&routine getitems &rem arg1 = C or R (check box or radio button) &rem arg2 = title for dialog box &rem **** define variable names &define arg1 -1 &var &define arg2 -2 &var &define wksp -3 &var &define resp -4 &var &define i -11 &var &define wtype -12 &var &define title -13 &var &define wid -14 &var &define row -15 &var &define text -16 &var &define temp -19 &var &define winrtn 1 &var &rem **** generate item widget list &value [wtype] [arg1] &value [title] [arg2] &value [wksp] WKSP &openw [wksp]t$temp1.lis ITEMS LIST &closew &open [wksp]t$temp1.lis error &openw [wksp]t$temp2.lis &sv [wid] 100 &sv [row] 0 &sv [text] 200 &while &do &read [temp] [break] &inc [wid] &inc [row] &inc [text] &if &eq [wtype] C &do &write "CBOX [wid] [row] 1.5 1 1.5 v" &write "LTEXT [text] [row] 4 1 12 v [temp]" &else &write "RBUT [wid] [row] 1.5 1 1.5 v" &write "LTEXT [text] [row] 4 1 12 v [temp]" &end &end &close &closew &if &eq [row] 0 &do WIN MB 1 'No attributes.' &sv [resp] CANCEL &return [resp] &end &rem **** generate dialog box &openw [wksp]t$items.dlg &write "BEGIN 0 5 5 %<[row] + 4> 18 v [title]" &if &eq [wtype] R &do &write "GBOX 100 0 1 %<[row] + 1.5> 16 v" &end &closew & TYPE [wksp]t$temp2.lis >>[wksp]t$items.dlg &openw [wksp]t$items.dlg A &write "PBUT -98 %<[row] + 2> 1 1.5 8 v OK" &write "PBUT -99 %<[row] + 2> 9 1.5 8 v Cancel" &write "END" &closew WIN DB C [wksp]t$items.dlg WIN DB R &sv [temp] [winrtn] WIN DB D & DEL [wksp]t$items.dlg & DEL [wksp]t$temp*.lis &rem **** evaluate response &if &eq [temp] -1 &do &sv [resp] CANCEL &elseif &eq [temp] 49 &do &sv [resp] CANCEL &elseif &eq [temp] 99 &do &sv [resp] CANCEL &else &rem **** build list of items &sv [resp] &sv [i] 1 &while &rn [i] 1 [row] &do &value [wid] %<[i] + 100> &if &eq [wid] 1 &do &value [text] %<[i] + 200> &sv [resp] "[resp] [text]," &end &inc [i] &end &end &return "[resp]" &rem **** I/O error trap &label error &type "I/O Error" &sv [resp] CANCEL &return [resp]Initially, the output of the ITEMS LIST command is captured and the item names copied over to widget definitions. This file is appended to a dialog file containing the BEGIN header, and then OK and CANCEL push buttons are appended. Finally, the widget list is scanned for checks and the appropriate text appended to the response variable. Note that the list of selected items cannot exceed 80 characters or it will be cropped, and that if no items are checked, a null string is returned to the parent routine.
The "R" (radio button) option is used for single picks, as for a JOIN command. If executed as follows:
&r getitems R "Join Item" &rv -5
the value " TYPE," is returned to variable -5 (the JOIN command ignores the comma). The "C" (check box) option is used for multiple picks, as for a LIST command. If executed as follows:
&r getitems C "List Item(s)" &rv -5
the value " TYPE, NAME, #ACRES," is returned to variable -5.
In dedicated applications, item descriptions may be displayed, with the actual item names hidden beyond the width of the text widget (in this example, columns 30-36):
BEGIN 0 5 5.0 10.0 20.0 v Modify: CBOX 101 1 1.5 1.0 1.5 v LTEXT 201 1 4.0 1.0 15.0 v CBOX 102 2 1.5 1.0 1.5 v LTEXT 202 2 4.0 1.0 15.0 v CBOX 103 3 1.5 1.0 1.5 v LTEXT 203 3 4.0 1.0 15.0 v CBOX 104 4 1.5 1.0 1.5 v LTEXT 204 4 4.0 1.0 15.0 v CBOX 105 5 1.5 1.0 1.5 v LTEXT 205 5 4.0 1.0 15.0 v CBOX 106 6 1.5 1.0 1.5 v LTEXT 206 6 4.0 1.0 15.0 v PBUT -98 8 1.0 1.5 8.0 v OK PBUT -99 8 9.0 1.5 8.0 v Cancel END S 201 Vegetation Class VEG S 202 Signature Index INDEX S 203 Data Source SOURCE S 204 Catalog Number CATALOG S 205 Resolution RES S 206 Reference Date REF_DAT
Note the use of the S dialog command to set the values of the text widgets. The desired item name would be extracted as follows:
&value [text] %<[i] + 200> 30 36
&routine popup &rem Argument = text file &rem **** define variable names &define arg1 -1 &var &define pin -2 &var &define file -11 &var &define wksp -12 &var &define size -13 &var &define winrtn 1 &var &rem **** generate command file &sv [file] [arg1] &value [wksp] WKSP &sv [size] 40 &openw [wksp]t$popup.cmd &write "L 101 |EOL|" &closew & TYPE [file] >>[wksp]t$popup.cmd &openw [wksp]t$popup.cmd A &write "|EOL|" &closew &rem **** generate dialog box &r genpopup [size] WIN DB P &value [pin] [winrtn] &while &do WIN DB R [wksp]t$popup.cmd &rem **** process response &if &eq [winrtn] 103 &do WIN CB W '%101' &elseif &eq [winrtn] 104 &do WIN FILE 2 * 'Enter Save File' &if &ne "x[winrtn]" "x" &do & COPY [file] [winrtn] &end &elseif &eq [winrtn] 105 &do &cv [size] [size] - 20 &r genpopup [size] &elseif &eq [winrtn] 106 &do &cv [size] [size] + 20 &r genpopup [size] &else &goto [break] &end &end WIN DB D & DEL [wksp]t$popup.cmd &if &eq [pin] U &do WIN DB U &end &return &routine genpopup &define size -1 &var &define wksp -2 &var &value [wksp] WKSP &openw [wksp]t$popup.dlg &write "BEGIN 0 5 5 16 %<[size] + 2> v Text" &write "LBOX 101 1 1 12.0 [size] f" &write "PBUT 102 14 1 1.5 8 v OK" &write "PBUT 103 14 9 1.5 8 v Copy" &write "PBUT 104 14 17 1.5 8 v Save" &write "PBUT 105 14 25 1.5 4 v <<" &write "PBUT 106 14 29 1.5 4 v >>" &write "END" &if &eq [size] 40 &do &write "G 105" &end &closew WIN DB C [wksp]t$popup.dlg & DEL [wksp]t$popup.dlg &return
Note the use of the L dialog command to populate the list box. The "Copy" push button uses the WIN CB W command to write the text of a selected list entry to the Windows clipboard. The "Save" push button uses the WIN FILE command to allow the user to save to a new file (generally used when capturing output to a temporary file). Because a list box cannot scroll horizontally, the "<<" and ">>" push buttons allow the user to expand or contract the dialog box width by 20 column increments:
Also note the use of the WIN DB P command. This sets what is known as "pin mode", which prevents the position of the dialog box from being reset to the BEGIN values when it is recreated (which is undesirable if the dialog box has been moved by the user). If pin mode is not active at the time the WIN DB P command is issued, the value "U" is returned to variable 1. The value is stored in variable [pin] and examined at the end of the routine to see if pin mode needs to be turned off again using WIN DB U. (More about these commands when we get to nonmodal dialog boxes.)
Routines "getitems" and "popup" may be combined to construct a simple LIST routine for ARCEDITW:
&routine list &r getitems C "List Item(s)" &rv -1 &if &ne "%-1" "CANCEL" &do &value -2 WKSP &openw %-2t$temp.lis LIST %-1 &closew &r popup %-2t$temp.lis & DEL %-2t$temp.lis &end &returnOf course, an even simpler (but not as fun) alternative is to use the WIN RUN command to bring up a text editor instead of using the popup routine:
&routine list &r getitems C "List Item(s)" &rv -1 &if &ne "%-1" "CANCEL" &do &value -2 WKSP &openw %-2t$temp.lis LIST %-1 &closew WIN RUN notepad %-2t$temp.lis &end &returnThe chief disadvantage of a list box widget is that more than one entry cannot be selected[3]. One way to work around this is to maintain two lists and transfer entries between them. The following example is useful in situations involving large numbers of attribute items:
&routine getitem2 &rem **** define variable names &define resp -1 &var &define wksp -2 &var &define num_in -3 &var &define num_out -4 &var &define i -11 &var &define shift -12 &var &define temp -19 &var &define winrtn 1 &var &rem **** generate item list &value [wksp] WKSP &sv [num_in] 0 &sv [num_out] 0 &openw [wksp]t$temp1.lis ITEMS LIST &closew &open [wksp]t$temp1.lis error &while &do &read [temp] [break] &inc [num_in] &value %<1000 + [num_in]> [temp] &end &close &if &eq [num_in] 0 &do WIN MB 1 'No attributes.' &sv [resp] CANCEL &return [resp] &end &rem **** generate dialog box &openw [wksp]t$items.dlg &write "BEGIN 0 5.0 5 16.0 42 v List Item(s)" &write "LTEXT 0 0.5 1 1.0 18 v Available Items" &write "LBOX -1101 1.5 1 12.0 18 v " &write "LTEXT 0 0.5 23 1.0 18 v List Item(s)" &write "LBOX -1102 1.5 23 12.0 18 v " &write "PBUT -103 5.0 20 1.5 2 v >" &write "PBUT -104 7.5 20 1.5 2 v <" &write "PBUT -105 14.0 1 1.5 8 v OK" &write "PBUT -106 14.0 9 1.5 8 v Cancel" &write "PBUT -107 14.0 17 1.5 8 v Clear" &write "END" &rem **** generate command file &openw [wksp]t$items.cmd &r genlist 101 1000 [num_in] &write "G 104" &closew &rem **** open dialog and process response WIN DB C [wksp]t$items.dlg &while &do WIN DB R [wksp]t$items.cmd &if &fn [wksp]t$items.cmd &do & DEL [wksp]t$items.cmd &end &if &eq [winrtn] 101 &or &eq [winrtn] 103 &do &rem **** add entry to 102 &if &ne "x%101" "x" &do &inc [num_out] &value %<[num_out] + 2000> 101 &openw [wksp]t$items.cmd &r genlist 102 2000 [num_out] &write "E 104" &closew &end &elseif &eq [winrtn] 102 &or &eq [winrtn] 104 &do &rem **** remove entry from 102 &if &ne "x%102" "x" &do &sv [i] 1 &sv [shift] FALSE &dec [num_out] &while &rn [i] 1 [num_out] &do &value [temp] %<[i] + 2000> &if &eq "x[temp]" "x%102" &do &sv [shift] TRUE &end &if &eq [shift] TRUE &do &value %<[i] + 2000> %<[i] + 2001> &end &inc [i] &end &openw [wksp]t$items.cmd &r genlist 102 2000 [num_out] &if &eq [num_out] 0 &do &write "G 104" &end &closew &end &elseif &eq [winrtn] 105 &or &eq [winrtn] 50 &do &rem **** build item list &sv [resp] &sv [i] 1 &while &rn [i] 1 [num_out] &do &value [temp] %<[i] + 2000> &sv [resp] "[resp] [temp]," &inc [i] &end &goto [break] &elseif &eq [winrtn] 107 &do &rem **** clear 102 &sv [num_out] 0 &openw [wksp]t$items.cmd &r genlist 102 2000 [num_out] &write "G 104" &closew &else &sv [resp] CANCEL &goto [break] &end &end WIN DB D &return "[resp]" &rem **** I/O error trap &label error &type "I/O Error" &sv [resp] CANCEL &return [resp] &routine genlist &rem **** populate lists &define i -11 &var &define temp -19 &var &write "L %-1 |EOF|" &sv [i] 1 &while &rn [i] 1 %-3 &do &value [temp] %<[i] + %-2> &write "[temp]" &inc [i] &end &write "|EOF|" &return
Note that the LBOX widgets are assigned IDs of -1101 and -1102: assigning a negative ID and adding -1000 causes a list box to act as a return widget if an entry is double-clicked. For example, should a user double-click an available item entry, the value returned to variable 1 would be "101" and the contents of that entry would be assigned to variable 101.
In the above example, the user could also select an available item and click the ">" button to add it to the second list. Similarly, the user could remove an item from the second list either by double-clicking the entry or selecting the entry and clicking the "<" button. Clicking the "Clear" button clears the second list; note that a list box may be emptied by following the L dialog command immediately with the {EOF} line.
One feature of list boxes to beware of: the S dialog command will select the first entry of the list box that begins with the value. For example, if list box 101 contains:
PARCELS_I BOOK MAP PARCELand the command "S 101 PARCEL" is issued, PARCELS_I will be selected.
Finally, as was noted for text widgets above, verbose descriptions may be stored in the visible portion of list box entries, with system values hidden beyond.
[2]The path to the file must stated fully or relative to the current directory.
[3]A list box supporting multiple selects would make a very tasty future SML enhancement. MBOX and SMBOX statements could specify a starting ID, and selected entries would map to corresponding variables (the remainder in the range being assigned blank values).