The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
Accept
The goal is to create a text field and arrange its letters in an area of the screen. The letters have an order from first to last.
lay out text
Accept
To layout the text in the field, place the next letter just to the right of the previous one. The red arrow points to the letter that was just placed, in this case an "r". That letter extends beyond the right margin, so we need to move its entire word to the next line.
Place each letter just to the right of the previous letter on the current line. Then, look for special cases. If the letter follows a carriage return, move it to the next line. (This is done inside placeIfAfterReturn). The letter has the goal of not being clipped by the right margin. When a letter is not white space and finds that it is being clipped, run the backToWordStart rule. It looks backwards to find the start of the current word, and moves that letter to the next line.
Place
placeIfAfterReturn
backToWordStart
to the next letter. For all other letters, it returns false, which signals the place rule to go further and test whether the current letter is over the right margin. maxHeight and missingHeight are used to move the line down when a tall letter is in the middle of the line. We will hook this up later in the essay.
placeIfAfterReturn When my predecessor shape notNil and [my predecessor shape isNewline] Do "start of the next line" my pivotPosition 0 , (my predecessor pivotPosition y + maxHeight + maxDescent + 2). my pivotPosition ((whole shape leftAtY my pivotPosition y) + inset x) , my pivotPosition y. maxDescent := my descent. missingHeight := 0. return true. When Always Do return false.
my predecessor shape notNil and [my predecessor shape isNewline]
and
"start of the next line" my pivotPosition 0 , (my predecessor pivotPosition y + maxHeight + maxDescent + 2). my pivotPosition ((whole shape leftAtY my pivotPosition y) + inset x) , my pivotPosition y. maxDescent := my descent. missingHeight := 0. return true.
pivotPosition
pivotPosition
leftAtY
Always
return false.
How To Make A Text Field From Ants
*
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
Introduction
startOfWord travels back along the word to find the first letter. We are looking for a letter that is not white space. If we happen come to the first letter of the text, return it instead. startOfWord considers just one letter. If that letter is not the start of a word, it calls itself again to consider the preceeding letter.
startOfWord travels back along the word to find the first letter. We are looking for a letter that is not white space. If we happen come to the first letter of the text, return it instead. startOfWord considers just one letter. If that letter is not the start of a word, it calls itself again to consider the preceeding letter.
travels back along the word to find the first letter. We are looking for a letter that is not white space. If we happen come to the first letter of the text, return it instead.
considers just one letter. If that letter is not the start of a word, it calls itself again to consider the preceeding letter.
lay out text
Ted Kaehler, Yoshiki Ohshima
To see the default situation with no layout rules, press the blue button "layout". Since there are no rules, all of the letters pile up at the upper left of the field. A mouse click or drag on a letter does nothing.
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
layout
Letters In A Box With No Rules
Accept
startOfWord When my predecessor isNil Do return me. When my predecessor shape isWhiteSpace Do return me. When Always Do return rule startOfWord my predecessor.
my predecessor isNil
return me.
my predecessor shape isWhiteSpace
return me.
Always
return rule startOfWord my predecessor.
startOfWord
Figure 2: Simulation showing diffusion
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
Accept
Accept
Move that letter to the next line. Resume placing letters to the right of the "o", as indicated by the red arrow. Notice that all letters in the word "over" are placed more than once during the layout.
For example, could we program a text layout and editing system just using a “field of messages” that individual text characters can sense and respond to? Laying out a “paragraph” of “ants” seems like a good place to start because it will have to work continuously while the editor is being used.
backToWordStart When Always Do letterToMove := self startOfWord me. When self isStartOfLine letterToMove index Do "Word takes entire line, break at the clipped character" letterToMove := me. When Always Do maxHeight := letterToMove ascent. letterToMove pivotYIncreaseBy maxHeight + maxDescent + 2. letterToMove pivotPosition ((whole shape leftAtY letterToMove pivotPosition y) + inset x) , letterToMove pivotPosition y. missingHeight := 0. rule tell letterToMove successor to 'place'.
Always
letterToMove := self startOfWord me.
startOfWord
self isStartOfLine letterToMove index
isStartOfLine
"Word takes entire line, break at the clipped character" letterToMove := me.
Always
maxHeight := letterToMove ascent. letterToMove pivotYIncreaseBy maxHeight + maxDescent + 2. letterToMove pivotPosition ((whole shape leftAtY letterToMove pivotPosition y) + inset x) , letterToMove pivotPosition y. missingHeight := 0. rule tell letterToMove successor to 'place'.
pivotYIncreaseBy
pivotPosition
leftAtY
tell
to
lay out text
Accept
kedama
place When I amNil Do return me When Always Do my positionBecomes whole width atRandom, whole height atRandom. rule tell my successor to 'place'.
I amNil
return me
Always
my positionBecomes whole width atRandom, whole height atRandom. rule tell my successor to 'place'.
positionBecomes
tell
to
Text Field Specification
Place each letter just to the right of the previous letter on the current line. Then, look for special cases. If the letter follows a carriage return, move it to the next line. (This is done inside placeIfAfterReturn). The letter has the goal of not being clipped by the right margin. When a letter is not white space and finds that it is being clipped, run the backToWordStart rule. It looks backwards to find the start of the current word, and moves that letter to the next line.
Place
placeIfAfterReturn
backToWordStart
Noticing a Carriage Return The rule placeIfAfterReturn actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line. placeIfAfterReturn always returns true or false. This allows it to be used in a guard clause. You can see this in the place rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on
The rule placeIfAfterReturn actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line. placeIfAfterReturn always returns true or false. This allows it to be used in a guard clause. You can see this in the place rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on
The rule placeIfAfterReturn actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line. placeIfAfterReturn always returns true or false. This allows it to be used in a guard clause. You can see this in the place rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on
placeIfAfterReturn
placeIfAfterReturn
place
to the next letter. For all other letters, it returns false, which signals the place rule to go further and test whether the current letter is over the right margin. maxHeight and missingHeight are used to move the line down when a tall letter is in the middle of the line. We will hook this up later in the essay.
Noticing the right margin isClipped is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
isClipped is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
isClipped is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
isClipped
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
Ants are a “distributed hive animal” whose “cells” communicate by a variety of means including laying down trails of chemicals which can help ants get to discovered food sources.
Viewpoints Research Institute, Glendale, CA
Finding the Start of a Word We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line. backToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line. backToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line. backToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
backToWordStart
startOfWord,
Text Field Specification
Finding the Start of a Word We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line. backToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line. backToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
We know that the current letter hangs over the right margin. We need to move the entire word to the start of the next line. backToWordStart first calls startOfWord, which finds the first letter of the current word. If that letter is already at the start of a line, we should not move it. The line is wider than the field and has no white space in it. The original clipped character should be forced to start a new line. Otherwise, use the start of the word as the letter to be moved. Once we have the proper letter in letterToMove, put it at the start of the next line.
backToWordStart
startOfWord,
startOfWord travels back along the word to find the first letter. We are looking for a letter that is not white space. If we happen come to the first letter of the text, return it instead. startOfWord considers just one letter. If that letter is not the start of a word, it calls itself again to consider the preceeding letter.
startOfWord travels back along the word to find the first letter. We are looking for a letter that is not white space. If we happen come to the first letter of the text, return it instead. startOfWord considers just one letter. If that letter is not the start of a word, it calls itself again to consider the preceeding letter.
travels back along the word to find the first letter. We are looking for a letter that is not white space. If we happen come to the first letter of the text, return it instead.
considers just one letter. If that letter is not the start of a word, it calls itself again to consider the preceeding letter.
Is a Letter at the Start of a Line? Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
lay out text
reset
If the walk back (blue arrow) gets all the way to the left margin, a single word covers the entire line. Which letter should be moved to the next line? The original clipped letter (red arrow) is the proper letter to move. A single word that covers the entire line is a special case, and we must test for it.
Noticing a Carriage Return The rule placeIfAfterReturn actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line. placeIfAfterReturn always returns true or false. This allows it to be used in a guard clause. You can see this in the place rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on
The rule placeIfAfterReturn actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line. placeIfAfterReturn always returns true or false. This allows it to be used in a guard clause. You can see this in the place rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on
The rule placeIfAfterReturn actually ignores the return character itself. It only takes action when the previous letter is a carriage return. If so, it moves the current letter to the beginning of the next line. placeIfAfterReturn always returns true or false. This allows it to be used in a guard clause. You can see this in the place rule. When placeIfAfterReturn has moved a letter, it returns true, which signals to go on
placeIfAfterReturn
placeIfAfterReturn
place
isClipped When my shape isWhiteSpace Do return false. When Always Do return my right + inset x > (whole shape rightAtY my pivotPosition y)
my shape isWhiteSpace
return false.
Always
return my right + inset x > (whole shape rightAtY my pivotPosition y)
rightAtY
layout When whole contents isEmpty not Do rule tell whole contents first to 'place'. rule processActions.
whole contents isEmpty not
rule tell whole contents first to 'place'. rule processActions.
tell
to
All in One Line Now let's redefine place to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the place rule. The line is clipped by the edge of the field.
Now let's redefine place to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the place rule. The line is clipped by the edge of the field.
Now let's redefine place to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the place rule. The line is clipped by the edge of the field.
place
place
Wrapping the Text to a New Line When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general layout rule. It moves the first letter to the upper left. Then, it the tells the next letter to place itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to place.
When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general layout rule. It moves the first letter to the upper left. Then, it the tells the next letter to place itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to place.
When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general layout rule. It moves the first letter to the upper left. Then, it the tells the next letter to place itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to place.
layout
place
place
Accept
reset
How to Break the Line of Text
Is a Letter at the Start of a Line? Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
Finally, we need a little test to tell if the current letter is at the start of a line of text. 'me' is the index of a letter. Return true if the letter is at the left margin. This only works on letters that have been placed.
Figure 1: Ants swarming around food
What if the text is too long and goes over the margin?
Walk back with the blue arrow until we reach the first letter of the word.
Any costume that has those properties can be placed in text, even if it is not really a letter. A letter object is rendered into the composition area on the screen using the system's normal costume rendering programs.
Accept
layout
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
In the most general case, each letter can be any costume that has shape, color, and a bounding rectangle.
Text Field Specification
We want to investigate whether the “particles and fields” style of distributing messages as intrinsic parts of environments can work well for some programming problems.
layout When whole contents isEmpty not Do maxHeight := whole first ascent. maxDescent := whole first descent. missingHeight := 0. whole first pivotBecomes ((whole shape leftAtY 0) , maxHeight) + inset. rule tell whole first successor to 'place'. When Always Do rule tellLater rule to 'showSelection'. rule processActions.
whole contents isEmpty not
maxHeight := whole first ascent. maxDescent := whole first descent. missingHeight := 0. whole first pivotBecomes ((whole shape leftAtY 0) , maxHeight) + inset. rule tell whole first successor to 'place'.
pivotBecomes
leftAtY
tell
to
Always
rule tellLater rule to 'showSelection'. rule processActions.
tellLater
to
Text Field Specification
How to Break the Line of Text
To layout the text in the field, place the next letter just to the right of the previous one. The red arrow points to the letter that was just placed, in this case an "r". That letter extends beyond the right margin, so we need to move its entire word to the next line.
Walk back with the blue arrow until we reach the first letter of the word.
Move that letter to the next line. Resume placing letters to the right of the "o", as indicated by the red arrow. Notice that all letters in the word "over" are placed more than once during the layout.
If the walk back (blue arrow) gets all the way to the left margin, a single word covers the entire line. Which letter should be moved to the next line? The original clipped letter (red arrow) is the proper letter to move. A single word that covers the entire line is a special case, and we must test for it.
Wrapping the Text to a New Line When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general layout rule. It moves the first letter to the upper left. Then, it the tells the next letter to place itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to place.
When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general layout rule. It moves the first letter to the upper left. Then, it the tells the next letter to place itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to place.
When a line of text is longer than the width of the text field, we want to wrap it to the next line. The goal of text wrapping is to determine where to break the text to start a new line. Each letter follows its prececessor on the current horizontal line. When a letter hangs over the right margin, its entire word needs to be moved to the next line. A carriage return causes the next letter to start a new line. A single word can be wider than entire line. Break it where it touches the right margin. We also need to handle the cases when a letter has no prececessor (it is the first), and has no successor (it is the last). We start with a general layout rule. It moves the first letter to the upper left. Then, it the tells the next letter to place itself in the field. (Ignore the part about maxHeight and missingHeight for the moment.) When each letter is finished being placed, it must tell its successor to place.
layout
place
place
Start
*This project is funded by NSF and private donors
isStartOfLine When Always Do return (whole at me) pivotPosition x - inset x <=? "left margin" (whole shape leftAtY (whole at me) pivotPosition y)
Always
return (whole at me) pivotPosition x - inset x <=? "left margin" (whole shape leftAtY (whole at me) pivotPosition y)
at
leftAtY
at
Accept
With such a general notion of a letter, we are freed from dealing with the details of families of fonts, emphasis (bold, italic), construction of a letter of the desired size, or text color. When a glyph arrives at the layout stage, it already has the proper shape, style, size and color.
Stop
place When I amNil Do return me When my index = 1 Do my position (whole shape leftAtY 0)+4 , 4. return rule tell my successor to 'place'. When Always Do pred := my predecessor. my pivotPosition pred left + pred pivotOffset x + pred width , pred pivotPosition y. rule tell my successor to 'place'.
I amNil
return me
my index = 1
my position (whole shape leftAtY 0)+4 , 4. return rule tell my successor to 'place'.
position
leftAtY
tell
to
Always
pred := my predecessor. my pivotPosition pred left + pred pivotOffset x + pred width , pred pivotPosition y. rule tell my successor to 'place'.
pivotPosition
tell
to
place When I amNil Do return me. When Always Do pred := my predecessor. my pivotPosition pred right + pred pivotOffset x , pred pivotPosition y. When rule placeIfAfterReturn me Do return rule tell my successor to 'place'. When rule isClipped me Do rule tell me to 'backToWordStart'. When (rule isClipped me) not Do rule tell my successor to 'place'.
I amNil
return me.
Always
pred := my predecessor. my pivotPosition pred right + pred pivotOffset x , pred pivotPosition y.
pivotPosition
rule placeIfAfterReturn me
placeIfAfterReturn
return rule tell my successor to 'place'.
tell
to
rule isClipped me
isClipped
rule tell me to 'backToWordStart'.
tell
to
(rule isClipped me) not
isClipped
rule tell my successor to 'place'.
tell
to
Noticing the right margin isClipped is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
isClipped is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
isClipped is the most important rule for specifying word wrap. It returns true if current letter overlaps the right margin. It does this by comparing the letter's right x-value with the margin's x. The margin can be curved, so we ask the text field box for the margin's actual x value at this y. Containers can have irregular shapes, and line lengths can be different. White space such as a space or a tab are allowed to extend beyond the margin. Return false for white space letters.
isClipped
Rules The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the When. If the guard is true, then execute the Do part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses. Extremely Simple Layout Methods Random Layout As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for layout and place. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the When. If the guard is true, then execute the Do part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses.
The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the When. If the guard is true, then execute the Do part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses.
When
Do
As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for layout and place. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for layout and place. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
layout
place
Building a Text Field from “Ants”
Text Field Specification
Rules The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the When. If the guard is true, then execute the Do part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses. Extremely Simple Layout Methods Random Layout As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for layout and place. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the When. If the guard is true, then execute the Do part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses.
The behavior of the letters is defined by a set of rules. Each rule is in a rule editor window. At the top is the name of the rule, followed by the rule itself. The rule has a list of clauses. Each clause has a guard after the When. If the guard is true, then execute the Do part. "return" means evaluate the expression and hand it back to the place where the rule was called. We exit the rule at the return and do not perform the later clauses.
When
Do
As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for layout and place. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
As a simple first experiment, we will put each letter in a random place in the text field. Set the x,y position of each letter to a random value within the field's width and height. Press Accept in the rules for layout and place. Press the layout button below. What happens when you press it a second time? Press reset to put all letters at the upper left.
layout
place
All in One Line Now let's redefine place to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the place rule. The line is clipped by the edge of the field.
Now let's redefine place to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the place rule. The line is clipped by the edge of the field.
Now let's redefine place to arrange all letters in one long line. Position each letter just to the right of its predecessor. The one line example inherits the rules of the random layout and overrides the place rule. The line is clipped by the edge of the field.
place
place
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
lay out text
reset
lay out text
reset
The main problem is to do "word wrap" so that each word is entirely on one line. We don't want half the word at the end of one line and the other half on the next line.
reset
In the most general case, each letter can be any costume that has shape, color, and a bounding rectangle.
Accept
reset