Chapter 8: Interacting with the User
A program that just runs all by itself can be a useful thing. However, a program that interacts with the user is often much more interesting and flexible because it may not do the same thing every time, depending on the choices that the user makes. There are Logo commands, described in the Reference Manual, that let you get information from the user through the Listener window. Look up READ, READCHAR, READWORD and READLIST, for examples. This chapter describes the graphical controls available in Logo.
Controls in General
Graphical controls are used to
create a Graphical User Interface (or GUI presentation) for an
application program. The idea of “control” is from two points of view:
(1) GUI controls help a program control the actions of a user by
restricting choices and limiting selections to those defined and
understood by the application to prevent a user from supplying data that
does not compute; and (2) GUI controls allow users to pick and choose
which options they want when they want them - controls give users a
sense of power over the application instead of being controlled by it.
Eight different controls are available in the Controls panel of the Toolbox. In addition, you can select New Graphics Window from the File menu. This is often helpful to keep controls and drawings separated.
Controls are graphical and they respond to many of the same commands
that you use for bitmaps and turtles, but they are not bitmaps or
turtles. Controls have a Z.ORDER
property, but they don’t use it in
the same way that bitmaps and turtles use it. Controls always appear on
top of the bitmaps and turtles, regardless of the layer number they are
on. And, controls can be placed on top of each other, but the Z.ORDER
number has nothing to do with which one is on top - that depends on
which one was clicked last. So, you can ignore the Z.ORDER
for
controls - just remember that controls are always on top.
Controls can be dragged from the Controls panel of the Toolbox to the Graphics window. Each control created in this way is given a name based on its type. For example, open the Controls panel and drag out a button control and drop it on the Graphics window. Logo displays the message:
BUTTON.1 dropped.
When you drag a control to the Graphics window, some properties are
filled in with default values. For example, the “Click me” label on the
button is really the value of the button’s TEXT
property. Other
controls have different defaults, depending on the control. The
NEW and
DECLARE commands can be used to create
controls. The NEW command creates a control
with a name like the one created by dragging a control from the Toolbox.
The DECLARE command requires that you
choose a name. In either case, the control is placed at the center of
the Graphics window without the default values that are assigned when
you drag a control from the Toolbox. Type:
NEW "BUTTON
Result: BUTTON.2
To move a control to a new location, hold down the Shift key while you
click and drag on the control. You can also move a control by setting
the POSITION
property to a new coordinate point. Type:
PPROP "BUTTON.2 "POSITION [100 100]
Each type of control is a different classification. Type:
ASK EVERY "BUTTON [BACK 50]
You can get rid of a control with the ERASE command. Type:
ERASE "BUTTON.2
Be careful with the CLEARSCREEN
command (CS)
- it erases all of the controls from the Graphics window.
Use CLEAN or
DRAW unless you really want to get rid of
the controls.
Chances are, you’ve used every type of control in some application or
other, so you know how they work from the user’s point of view. Now,
you’ll learn what it takes to put them into your own programs. It’s not
difficult - most things are done with manipulations of the property
lists. The most important common properties are NAME
, POSITION
,
SIZE
and RUN
. Except for the scrollbar control, TEXT
is another
common property but it’s not used in the same way by each control. Some
controls have special properties as well as their own commands.
Button Control
The button control is typically used to run something. When you click on a button, you expect something to happen. Type:
EDP "BUTTON.1
The properties dialog for controls is not affected by the setting of the Extended property lists option of the Preferences dialog of the Edit menu. You always see the extended properties dialog. Of course, you can right-click (on a PC) or Ctrl-click (on a Mac) to bring up the properties dialog display, too. Change the following properties to the value shown:
RUN change to [MOVE]
SIZE change to [50 50]
TEXT change to Move
The TEXT
property of a button is the label you see on it. It’s a good
idea to use short but meaningful words for labels. By default, a button
is a long rectangle but it doesn’t have to be. When you click on the
button control, the instructions in the RUN
property are run as if you
had typed them in the Listener window. Click OK to close the dialog
and then define the MOVE
procedure.
TO MOVE
FORWARD 100 RIGHT 123
END
Click on the Move button a few times. You should see the turtle move and turn each time you click on the button.
Checkbox Control
The checkbox control is like a switch - it’s either on or off. Typically, a checkbox gives the user a choice between two conditions. Drag out a checkbox control and place it next to the Move button. Change the following properties to the value shown:
RUN change to [SWITCH.PEN]
SIZE change to [50 50]
TEXT change to Trail
In your program, it’s usually best to have a procedure that outputs the value of a control. A procedure with a meaningful name allows you to think in terms of what a control is for rather than how you have to manipulate it. Define the following procedure:
TO TRAIL?
GPROP "CHECKBOX.1 "STATE
END
For a checkbox control, the value is from the STATE
property. The
TEXT
property is just a label. You can put a lot of instructions in
the RUN
property of a control, but using a procedure is easier to deal
with, especially if you need to make changes later on. Define the
following procedure:
TO SWITCH.PEN
IF TRAIL? [PENDOWN] [PENUP]
END
This form of the IF command has two lists of
instructions that may be run, depending on the result of the condition
being tested. In this case, the condition is the output of the TRAIL?
procedure - it outputs either TRUE or FALSE. The first list is run if
the condition is true; the second list is run if the condition is false.
Now, when you click on the Move button, the Trail checkbox will determine whether or not the turtle leaves a trail (or draws lines). The checkmark indicates that a condition has been selected or turned on; removing the checkmark turns off the selection.
Radiobutton Control
The radiobutton control is a simulation of a mechanical button - like a channel selector on some radios. When you push on a real radiobutton, it selects a channel. To change channels, you have to push on a different radiobutton - pushing on the same radiobutton has no effect. This type of selection is called “mutually exclusive” in statistics - you can have one or the other, but not both at the same time.
Drag out two rabiobutton controls and place them next to the Trail
checkbox, one above the other. Change the following properties of
RAIDIOBUTTON.1
:
RUN change to [CHANGE.COLOR 1]
TEXT change to Red
Change the following properties of RADIOBUTTON.2
:
RUN change to [CHANGE.COLOR 2]
TEXT change to Black
Both radiobuttons run the same procedure, but they give it a different
input to identify themselves. The CHANGE.COLOR
procedure has to do two
things: turn off the other radiobutton and then change the color of
the turtle’s pen to the requested color. It’s best to turn off the other
button before doing anything else; otherwise, there may be a slight
delay - and you might think your radio is broken. Define the
CHANGE.COLOR
procedure:
TO CHANGE.COLOR :BUTTON
IF :BUTTON = 1 [TURN.OFF 2 SETPC "RED]
IF :BUTTON = 2 [TURN.OFF 1 SETPC "BLACK]
END
The TURN.OFF
procedure takes a button number as input. Using the
WORD command to build the actual name of the
radiobutton, it then sets the STATE
property to FALSE, which simulates
popping the button out. Define TURN.OFF
:
TO TURN.OFF :BUTTON
PPROP WORD "RADIOBUTTON. :BUTTON "STATE "FALSE
END
Editbox Control
The editbox control is for getting information from users. It’s normally
a free-form input which means users can type whatever they want. You can
control this, to some extent, by using the FILTER
property. Just put
in the characters you consider to be acceptable. For example, if you
want numeric input only, then put the string of digits 0123456789 in the
FILTER
property to restrict the users’ input to just numbers.
A maximum of 255 characters can be entered into an editbox. You can
control this with the LIMIT
property. It can be any number from 1 to
255.
How will your program know if a user has entered anything in an editbox
control? The MODIFIED
property gets set to “TRUE
whenever the user
types anything into the editbox. It does not get set to FALSE again.
However, your program can set MODIFIED
to FALSE after getting the
TEXT
value so that it can detect a new entry later on.
Since user input is (believe it or don’t) a very unreliable way of getting accurate data, be careful about what you expect to get from a user in an editbox control. The user’s name is not likely to cause a problem, but don’t ask a user to enter a command line to run - there’s a good chance your program will stop with an error message.
Statictext (Textbox) Control
The statictext (or textbox) control is typically used for displaying helpful information for the user, either as the label for a control or as an instruction panel. Drag out a statictext control and change the following property:
TEXT change to Velocity
Put three spaces in front of the word to make it appear more centered. This control will be used as the label for a scrollbar, since it doesn’t have a label of its own.
Scrollbar Control
The scrollbar control (also called a slider) is used to get numeric
input from a user. You can control the range of values with the
MINIMUM
and MAXIMUM
properties to make sure the number you get is
always in the proper range. The arrows at the ends of a scrollbar adjust
the value of the control in small increments, as defined by the
SMALLINC
property. The LARGEINC
property is used to adjust the
scrollbar value when the user clicks in the areas between the arrows and
the sliding mechanism. The position of the sliding mechanism of a
scrollbar is a visual representation of the control’s value as it
relates to the minimum and maximum values allowed.
The scrollbar does not have TEXT
property. You can use a statictext
control as a label. However, if you have checked the Show Hints option
of the Help menu, you can see the value of the TOOLTIP
property when
you put the mouse pointer over a scrollbar. The value of a scrollbar is
the VALUE
property. It may not be a whole number, even though the
minimum, maximum and increments are whole numbers, because the sliding
mechanism can be moved to any position between the arrows.
Drag out a scrollbar control, place it under the “Velocity” label, and change the following property:
RUN change to [CHANGE.VELOCITY]
Define the following procedure that outputs the value of the scrollbar:
TO CURRENT.VELOCITY
GPROP "SCROLLBAR.1 "VALUE
END
The CHANGE.VELOCITY
procedure will do two things: set the turtle’s
velocity to the value of the scrollbar and display the current velocity
in another statictext control. Drag out another statictext control,
place it next to the “Velocity” label, and change the following
property:
SIZE change to [20 16]
Use shift-drag to move the new statictext control close to the
“Velocity” label. Now, define the CHANGE.VELOCITY
procedure:
TO CHANGE.VELOCITY
SETVELOCITY CURRENT.VELOCITY
PPROP "STATICTEXT.2 "TEXT ROUND CURRENT.VELOCITY
END
The ROUND command takes a number as input and outputs a whole number. For example, if the input is 33.5, the output is 34; if the input is 22.4, the output is 22.
ListBox Control
Drag a listbox control from the Toolbox and place it under the scrollbar control. The listbox control is actually a table of text items. When you drag a listbox to the Graphics window, there are three items in the table, although you probably won’t want to use them. An easy way to get rid of them is to ask the listbox to remove them for you. Type:
REPEAT 3 [ASK "LISTBOX.1 [REMOVE 0] ]
REMOVE
is one of six special commands that are used by the listbox and
popup controls. It takes an index number as input and removes the
associated item from the table. Index number 0 is for the first item in
the table. When it is removed, the other items move up - index number 1
becomes the new index number 0, and so on.
The APPEND
command adds a new item to the end of the table. Type:
ASK "LISTBOX.1 [APPEND "HOME]
Result: 0
The output of APPEND
is the index number of the item that was added.
If you don’t need to use it, you can ignore it. The ADDSORTED
command
adds items in alphabetical order. It also outputs the index number of
the item that was added. Type:
IGNORE ASK "LISTBOX.1 [ADDSORTED "DRAW]
IGNORE ASK "LISTBOX.1 [ADDSORTED "CLEAN]
Type the following command to change the RUN
property:
PPROP "LISTBOX.1 "RUN [DO.COMMAND]
Define the following procedure:
TO DO.COMMAND
RUN (LIST GPROP "LISTBOX.1 "TEXT)
END
The parentheses are required because LIST
normally takes two inputs. When you click on one of the items in the
listbox control, the DO.COMMAND
will run the command.
You can change the items in a listbox control one at a time in the
properties dialog. The INDEX
property tells which of the items will be
reported as the TEXT
property of the control. When you enter a new
value in the INDEX
property, the TEXT
property changes to show the
associated value.
The other special commands for listbox and popup controls are INSERT
(to add an item in the middle of the table), REPLACE
(to change the
TEXT
property of the current item) and FIND
(to locate an item whose
TEXT
property matches the input). When a listbox has more items than
will fit in the current size, then a scrollbar is automatically
displayed to let you scroll through the items.
Popup Control
Drag a popup control from the Toolbox and place it above the Move button. The popup control is actually a table of text items very similar to the listbox control. It works in the same way but it takes up much less space on the Graphics window - only the currently selected item is shown. When you click on a popup control, a list of items appears (or pops up) so you can make a selection. The item you select is then duplicated in the top of the control and the list disappears.
When you drag a popup control to the Graphics window, there are three items in the table, although you probably won’t want to use them. An easy way to get rid of them is to ask the popup control to remove them for you. Type:
REPEAT 3 [ASK "POPUP.1 [REMOVE 0] ]
REMOVE
is one of six special commands that are used by the popup and
listbox controls. It takes an index number as input and removes the
associated item from the table. Index number 0 is for the first item in
the table. When it is removed, the other items move up - index number 1
becomes the new index number 0, and so on. The APPEND
command adds a
new item to the end of the table. Type:
ASK "POPUP.1 [APPEND "HOME]
Result: 0
The output of APPEND
is the index number the item that was added. If
you don’t need to use it, you can ignore it. The ADDSORTED
command
adds items in alphabetical order. It also outputs the index number of
the item that was added. Type:
IGNORE ASK "POPUP.1 [ADDSORTED "DRAW]
IGNORE ASK "POPUP.1 [ADDSORTED "CLEAN]
Type the following command to change the RUN
property:
PPROP "POPUP.1 "RUN [POP.COMMAND]
Define the following procedure:
TO POP.COMMAND
RUN (LIST GPROP "POPUP.1 "TEXT)
END
The parentheses are required because LIST
normally takes two inputs. When you click on one of the items in the
popup control, the POP.COMMAND
will run the command.
You can change the items in a popup control one at a time in the
properties dialog. The INDEX
property tells which of the items will be
reported as the TEXT
property of the control. When you enter a new
value in the INDEX
property, the TEXT
property changes to show the
associated value.
The other special commands for popup and listbox controls are INSERT
(to add an item in the middle of the table), REPLACE
(to change the
TEXT
property of the current item) and FIND
(to locate an item whose
TEXT
property matches the input). The SIZE
property is for the part
of the popup control that is always visible. The table’s display size is
automatically adjusted as more items are added. When a popup has more
items than will fit in the maximum table size, then a scrollbar is
automatically displayed to let you scroll through the items in the list.
Controls for STATES
Restart Logo and then load the STATES
workspace file. Define the
SETUP
procedure to add four controls to the Graphics window. The popup
control will have a table of all of the state abbreviations - and, you
won’t have to type them in! Since each state has a CAPITAL
property,
the GLIST command will find them all.
The FOREACH command will add each
abbreviation to the popup control by asking it to add each abbreviation
in alphabetical order. The three statictext controls will display the
full name, nickname and the baseball teams for the state that appears in
the popup control. The SETUP
procedure also loads the map and uses the
turtle to fill in the outer area with the SILVER
color.
When you select a state abbreviation in the popup control, the
UPDATE.INFO
procedure is run that sets the TEXT
property of the
three statictext controls. Define the UPDATE.INFO
procedure:
The CURRENT.STATE
procedure outputs the abbreviation currently
displayed in the popup control. Its definition is:
TO SETUP
DECLARE "POPUP "SELECT.STATE
PPROP "SELECT.STATE "POSITION [-250 -130]
PPROP "SELECT.STATE "RUN [UPDATE.INFO]
FOREACH GLIST "CAPITAL [IGNORE ASK "SELECT.STATE [ADDSORTED "?]]
DECLARE "STATICTEXT "STATE.NAME
PPROP "STATE.NAME "SIZE [150 16]
PPROP "STATE.NAME "POSITION [-125 -130]
DECLARE "STATICTEXT "STATE.NICKNAME
PPROP "STATE.NICKNAME "SIZE [150 16]
PPROP "STATE.NICKNAME "POSITION [30 -130]
DECLARE "STATICTEXT "BASEBALL.TEAMS
PPROP "BASEBALL.TEAMS "SIZE [150 16]
PPROP "BASEBALL.TEAMS "POSITION [185 -130]
UPDATE.INFO
END
TO UPDATE.INFO
PPROP "STATE.NAME "TEXT FULLNAME? CURRENT.STATE
PPROP "STATE.NICKNAME "TEXT NICKNAME? CURRENT.STATE
PPROP "BASEBALL.TEAMS "TEXT BASEBALL? CURRENT.STATE
END
TO CURRENT.STATE
GPROP "SELECT.STATE "TEXT
END
Save your workspace and then type:
SETUP
You can add more controls for other information. Add other statictext
controls for labels. Using the XY
property suggested earlier, you
could use the turtle to fill in selected state with a color; that could
serve as a visual reminder that you already looked at that state’s
information.
Controls for SIMON
Restart Logo and then load the SIMON
workspace file. With two
radiobutton controls, you can easily switch between turtle shapes and
the proper shapes. Define the SETUP
procedure to create the
radiobutton controls. The STATE
property of the TURTLE.SHAPES
control has been set to TRUE so it looks like it’s already been
selected.
Each radiobutton control runs its own procedure to turn off the other
control and then change the shapes of the turtles. Define USE.TURTLES
and USE.PROPER
.
The SIMON
procedure is shown below - all you should have to do is add
the call to SETUP
before the first guess is made.
TO SETUP
DECLARE "RADIOBUTTON "TURTLE.SHAPES
PPROP "TURTLE.SHAPES "TEXT "|Turtle shapes|
PPROP "TURTLE.SHAPES "RUN [USE.TURTLES]
PPROP "TURTLE.SHAPES "POSITION [210 10]
PPROP "TURTLE.SHAPES "SIZE [90 18]
PPROP "TURTLE.SHAPES "STATE TRUE
DECLARE "RADIOBUTTON "PROPER.SHAPES
PPROP "PROPER.SHAPES "TEXT "|Proper shapes|
PPROP "PROPER.SHAPES "RUN [USE.PROPER]
PPROP "PROPER.SHAPES "POSITION [210 -10]
PPROP "PROPER.SHAPES "SIZE [90 18]
END
TO USE.TURTLES
PPROP "PROPER.SHAPES "STATE "FALSE
ASK [1 2 3 4] [(SETSHAPE)]
END
TO USE.PROPER
PPROP "TURTLE.SHAPES "STATE "FALSE
ASK 1 [SETSHAPE "|~HOME/TOOLBOX/BIRDS/SPARROW2|]
ASK 2 [SETSHAPE "|~HOME/TOOLBOX/ANIMALS/BEE|]
ASK 3 [SETSHAPE "|~HOME/TOOLBOX/OTHER PICTURES/TELEPHONE|]
ASK 4 [SETSHAPE "|~HOME/TOOLBOX/VEHICLES/BEETLE|]
END
TO SIMON
CLEARSCREEN SETTURTLES 5 SETTSIZE 2
TELLALL 1 4 PENUP LEFT 45
EACH [RIGHT WHO * 90 FORWARD 100 SETHEADING 0]
SETTSIZE 5 SHOWTURTLE PPROP 0 "RUN [GUESS]
PPROP 1 "RUN [JOB 1] PPROP 2 "RUN [JOB 2]
PPROP 3 "RUN [JOB 3] PPROP 4 "RUN [JOB 4]
SETUP
GUESS
END
Controls for PUZZLE
The illustration for the puzzle game looks like it might be terribly complicated, but it’s not really very complicated at all. An extra Graphics window is used to separate the controls from the actual puzzle. This is done for two reasons: (1) the controls could get in the way of the puzzle pieces, and (2) the CLEARSCREEN command would erase all of the controls from the current window.
There is only one change needed to the original MAKE.PUZZLE
procedure.
You have to include the line SETACTIVEWINDOW “GRAPHICS
as the first
line. All of the activity in MAKE.PUZZLE
occurs in the window titled
Puzzle which is really the normal Graphics window.
; The SETUP procedure calls on other supporting procedures to do
; most of the work of setting up the windows and controls. The
; SETACTIVEWINDOW command is like a TELL command for windows -
; the following activity takes place in the current window (except
; SETBG, which applies to all windows at the same time).
TO SETUP
DO.WINDOWS
SETACTIVEWINDOW "GRAPHICS.1
CREATE.INFO
CREATE.PICTURES
CREATE.PIECES
CREATE.BUTTON
PPROP "PIECE.SLIDER "VALUE 8
PPROP "PIECES "TEXT 8
PPROP "PICTURES "INDEX 0
PPROP "LISTENER "VISIBLE "FALSE
END
; The DO.WINDOWS procedure creates a new Graphics window,
; arranges the windows and gives each one a new title.
TO DO.WINDOWS
IGNORE NEW "GRAPHICS
SETBG "SILVER
PPROP "GRAPHICS.1 "POSITION [0 0]
PPROP "GRAPHICS.1 "SIZE [196 483]
PPROP "GRAPHICS.1 "TITLE "|Puzzle Controls|
PPROP "GRAPHICS "POSITION [196 0]
PPROP "GRAPHICS "SIZE [434 483]
PPROP "GRAPHICS "TITLE "|Puzzle|
END
; The CREATE.INFO procedure uses a statictext control as an
; information display. Make sure you enter the information in the
; TEXT property as one long line.
TO CREATE.INFO
DECLARE "STATICTEXT "INFO
PPROP "INFO "POSITION [0 140]
PPROP "INFO "SIZE [150 60]
PPROP "INFO "TEXT (WORD "|Select a picture for your puzzle. |
"|Select the number of pieces. Then click PLAY and |
"|try to put it back together again.|)
END
; The CREATE.PICTURES procedure uses a listbox control to display
; the choices of pictures from the Animals folder. You can add more if
; you want.
TO CREATE.PICTURES
DECLARE "LISTBOX "PICTURES
PPROP "PICTURES "POSITION [0 20]
IGNORE ASK "PICTURES [ADDSORTED "|Elephant|]
IGNORE ASK "PICTURES [ADDSORTED "|Rhino|]
IGNORE ASK "PICTURES [ADDSORTED "|Zebra|]
IGNORE ASK "PICTURES [ADDSORTED "|Cat|]
IGNORE ASK "PICTURES [ADDSORTED "|Giraffe|]
IGNORE ASK "PICTURES [ADDSORTED "|Peacock|]
END
; The CREATE.BUTTON procedure uses a button control
; for starting the game.
TO CREATE.BUTTON
DECLARE "BUTTON "PLAY.BUTTON
PPROP "PLAY.BUTTON "POSITION [0 -140]
PPROP "PLAY.BUTTON "TEXT "PLAY
PPROP "PLAY.BUTTON "RUN [
MAKE.PUZZLE "ANIMALS GET.PICTURE GET.PIECES]
END
; The CREATE.PIECES procedure uses a scrollbar to set the number of
; puzzle pieces. You can adjust the minimum, maximum and increments to
; suit yourself. The statictext control is used to show the number of
; pieces selected.
TO CREATE.PIECES
DECLARE "SCROLLBAR "PIECE.SLIDER
PPROP "PIECE.SLIDER "POSITION [0 -80]
PPROP "PIECE.SLIDER "MINIMUM 3
PPROP "PIECE.SLIDER "MAXIMUM 20
PPROP "PIECE.SLIDER "LARGEINC 2
PPROP "PIECE.SLIDER "TOOLTIP "|Puzzle pieces|
PPROP "PIECE.SLIDER "RUN [CHANGE.PIECES]
DECLARE "STATICTEXT "PIECES
PPROP "PIECES "POSITION [0 -100]
PPROP "PIECES "SIZE [16 16]
END
; The following supporting procedures are used to get the values of
; controls and to display the number of pieces.
TO GET.PICTURE
OUTPUT GPROP "PICTURES "TEXT
END
TO GET.PIECES
OUTPUT GPROP "PIECES "TEXT
END
TO CHANGE.PIECES
PPROP "PIECES "TEXT ROUND CURRENT.PIECES
END
TO CURRENT.PIECES
GPROP "PIECE.SLIDER "VALUE
END
; These are the procedures from chapter 7: Bitmaps and Animation
TO MAKE.PUZZLE FOLDER PICTURE PIECES
; you need to switch the active window
SETACTIVEWINDOW "GRAPHICS
SETTURTLES 1 TELL 0 CS HT SETH 90 PU SETBG "SILVER
IGNORE LOADSNAP (WORD "|~HOME/TOOLBOX/| FOLDER "|/| PICTURE)
ASK "BITMAP.1 [HT]
SETXY GPROP "BITMAP.1 "SIZE
SETX -1 * XCOR SETY -1 * YCOR
(STAMP "BITMAP.1)
FOR "I 1 PIECES [
IGNORE SNAP SLICE.WIDTH PIECES SLICE.HEIGHT
FD SLICE.WIDTH PIECES
]
CLEAN ERASE "BITMAP.1
TELL EVERY "BITMAP
EACH [PPROP WHO "WINDOW "GRAPHICS]
EACH [SETH 90 FD RANDOM 150]
END
TO SLICE.WIDTH PIRCES
OUTPUT (FIRST GPROP "BITMAP.1 "SIZE) / PIECES
END
TO SLICE.HEIGHT
OUTPUT LAST GPROP "BITMAP.1 "SIZE
END
It may take a bit of time to get the hang of using Graphical controls, but the effort is well worth it. Trying to decide where to place them and getting them lined up properly is the most time-consuming part of it. It helps to play around interactively. Drag a control to where you want it to appear, then edit the properties to get the position coordinate. Using an extra Graphics window can be a big help.
Save your workspace. Next time you load it, just type SETUP
to get it
going. You could add other controls to select different folders.