SML PROGRAMMING

Nonmodal Dialog Boxes

Actually, by default dialog boxes created by WIN DB C are nonmodal. That means that if multiple dialog boxes are created within a particular group (more on that later), WIN DB R will read from all of them. What's important to keep in mind is that widget IDs must be unique for all active dialog boxes. Let's create a few toolboxes as an example:

EDITF.DLG:

BEGIN     0  5.00  5.00  4.50 16.00 v Edit Feature
PBUT   -101  0.00  0.00  1.50  8.00 v Add
PBUT   -102  0.00  8.00  1.50  8.00 v Delete
PBUT   -103  1.50  0.00  1.50  8.00 v Move
PBUT   -104  1.50  8.00  1.50  8.00 v Copy
PBUT   -105  3.00  0.00  1.50  8.00 v
PBUT   -106  3.00  8.00  1.50  8.00 v Change...
ARC.DLG:

BEGIN     0 11.25  5.00  4.50 16.00 v Arc
PBUT   -111  0.00  0.00  1.50  8.00 v Split
PBUT   -112  0.00  8.00  1.50  8.00 v Unsplit
PBUT   -113  1.50  0.00  1.50  8.00 v Reshape
PBUT   -114  1.50  8.00  1.50  8.00 v Spline
PBUT   -115  3.00  0.00  1.50  8.00 v Flip
PBUT   -116  3.00  8.00  1.50  8.00 v Vertex...
VERTEX.DLG:

BEGIN     0 11.25 22.00  3.00 16.00 v Vertex
PBUT   -121  0.00  0.00  1.50  8.00 v Draw
PBUT   -122  0.00  8.00  1.50  8.00 v Move
PBUT   -123  1.50  0.00  1.50  8.00 v Add
PBUT   -124  1.50  8.00  1.50  8.00 v Delete
ANNO.DLG:

BEGIN     0 11.25  5.00  3.00 16.00 v Anno
PBUT   -111  0.00  0.00  1.50  8.00 v Adjust
PBUT   -112  0.00  8.00  1.50  8.00 v Text...
PBUT   -113  1.50  0.00  1.50  8.00 v SetArrow
PBUT   -114  1.50  8.00  1.50  8.00 v DelArrow
To keep things simple we'll ignore the possible presence of any drawing or selection tools. Now let's assume that these dialog definition files are already sitting in %WKSP% waiting to be used. The following routine contains the necessary code to support them:

&routine etool

&define resp -1 &var
&define editf -11 &var
&define wksp -19 &var
&define winrtn 1 &var
SHOW EDITFEATURE [editf]
&if &eq [editf] NONE &do
   &return
&end
&value [wksp] WKSP
WIN DB C [wksp]editf.dlg
&if &eq [editf] ARC &do
   WIN DB C [wksp]arc.dlg 2
   WIN DB C [wksp]vertex.dlg 3
&elseif &eq [editf] ANNOTATION &do
   WIN DB C [wksp]anno.dlg 2
&end
&sv [resp] 1
&while &ne [resp] -1 &do
   &if &eq [editf] ANNOTATION &do
      &sv -2 ANNO...
      &sv -3 E
   &elseif &eq [editf] ARC &do
      &sv -2 ARC...
      &sv -3 E
   &else
      &sv -2 [editf]
      &sv -3 G
   &end
   &openw [wksp]t$ef.cmd
   &write "S 105 %-2"
   &write "%-3 105"
   &closew
   WIN DB R [wksp]t$ef.cmd
   &sv [resp] [winrtn]
   &if &eq [resp] 101 &do
      SHOW ANNOITEM -2 0
      &if &eq [editf] ANNOTATION &and &eq %-2 KEYBOARD &do
         &r annoadd
      &else
         ADD
      &end
   &elseif &eq [resp] 102 &do
      DELETE
   &elseif &eq [resp] 103 &do
      MOVE
   &elseif &eq [resp] 104 &do
      COPY
   &elseif &eq [resp] 105 &do
      &if &eq [editf] ARC &do
         WIN DB C [wksp]arc.dlg 2
         WIN DB C [wksp]vertex.dlg 3
      &else
         WIN DB C [wksp]anno.dlg 2
      &end
   &elseif &eq [resp] 106 &do
      &r setfeat
      SHOW EDITFEATURE [editf]
      &if &eq [editf] NONE &do
         &sv [resp] -1
      &elseif &eq [editf] ARC &do
         WIN DB C [wksp]arc.dlg 2
         WIN DB C [wksp]vertex.dlg 3
      &elseif &eq [editf] ANNOTATION &do
         WIN DB C [wksp]anno.dlg 2
         WIN DB D 3
      &else
         WIN DB D 2
         WIN DB D 3
      &end
   &elseif &eq [resp] 111 &do
      &if &eq [editf] ARC &do
         SPLIT
      &else
         REPOS
      &end
   &elseif &eq [resp] 112 &do
      &if &eq [editf] ARC &do
         UNSPLIT
      &else
         &r annotext
      &end
   &elseif &eq [resp] 113 &do
      &if &eq [editf] ARC &do
         RESHAPE
      &else
         SETARROW
      &end
   &elseif &eq [resp] 114 &do
      &if &eq [editf] ARC &do
         SPLINE
      &else
         DELETEARROW
      &end
   &elseif &eq [resp] 115 &do
      FLIP
   &elseif &eq [resp] 116 &do
      WIN DB C [wksp]vertex.dlg 3
   &elseif &eq [resp] 121 &do
      V DRAW
   &elseif &eq [resp] 122 &do
      V MOVE
   &elseif &eq [resp] 123 &do
      V ADD
   &elseif &eq [resp] 124 &do
      V DELETE
   &end
&end
WIN DB D 3
WIN DB D 2
WIN DB D 1
& DEL [wksp]t$ef.cmd
&return
In the first part of the routine, the "Edit Feature" toolbox and any feature-associated toolboxes are invoked. For edit feature ARC the collection looks like this:

Figure 1

The "ARC..." and "Vertex..." buttons restore the respective toolboxes should they be closed. For edit feature ANNO the collection looks like this:

Figure 2

The "ANNO..." button restores the annotation toolbox. For other edit features, the feature toolbox button is grayed:

Figure 3

The main drawback of the above example is that if the "Edit Feature" toolbox is closed, there is no way to recover it within the routine. Typically, a menu-driven application will embed code to handle all the possible menu entries and nonmodal return widgets in a master handling routine[1], and might have a "Tools" submenu to enable the user to reinvoke killed toolboxes at will.

Question: So what do I do if I want to create a modal dialog box (i.e. having sole focus) without having to dismiss and then recreate the existing (nonmodal) ones? Answer: Use dialog box groups.[2]

Dialog Box Groups

When you use WIN DB BH or WIN DB BI to create a new dialog box group, the box numbers, widget ids, and box positions are saved. The previous group is either hidden (BH) or rendered inactive (BI)[3]. You may then work with a new set of dialog boxes, and when you issue WIN DB E the current group is erased and the previous group restored.

If pin mode is set (WIN DB P), dialog boxes created in the new group will be positioned according to the corresponding boxes in the previous group. To force positioning according to the BEGIN line, you may issue the WIN DB U command; you will, however, want to set WIN DB P again after WIN DB E is issued.

Note that WIN DB B and WIN DB E will work even if there are no current dialog boxes. Thus a routine (e.g. to change the edit feature) may be written using those commands and launched from different routine levels without worry.

In the above example, there are three routines called by ETOOL that create a new dialog box group. Let's look at routine ANNOADD and see how it handles the situation:

&routine annoadd

&define just -5 &var
&define line -6 &var
&define pos -7 &var
&define type -8 &var
&define coo -9 &var
&define x -11 &var
&define y -12 &var
&define wksp -18 &var
&define temp -19 &var
&define winrtn 1 &var
SHOW ANNOSIZE [line]
SHOW ANNOPOSITION [pos]
SHOW ANNOTYPE [type]
SHOW COORDINATE [coo]
&value [wksp] WKSP
&rem **** hide current db group
WIN DB BH
&rem **** create annotation dialog box
&openw [wksp]t$anno.dlg
&write "BEGIN    0  5.00  5.00 10.00 34.00 v Add Anno"
&write "LTEXT    0  0.50  1.00  1.00 5.00 v Text:"
&write "EBOX   101  0.50  6.00  1.50 27.00 v"
&write "CBOX   102  2.50  1.00  1.00 12.00 v Add Arrow"
&write "CBOX   103  3.50  1.00  1.00 12.00 v Keep Text"
&write "RTEXT    0  3.50 15.00  1.00 8.00 v Spacing:"
&write "EBOX   104  3.00 24.00  1.50 6.00 v"
&write "GBOX     0  4.75  1.00  2.75 26.00 v Justification"
&write "RBUT  -105  6.00  2.00  1.00 6.00 v Left"
&write "RBUT  -106  6.00  9.00  1.00 8.00 v Center"
&write "RBUT  -107  6.00 18.00  1.00 8.00 v Right"
&write "PBUT  -108  8.00  1.00  1.50 8.00 v Place"
&write "PBUT  -109  8.00  9.00  1.50 8.00 v Add Line"
&write "PBUT  -110  8.00 17.00  1.50 8.00 v Set..."
&write "PBUT  -111  8.00 25.00  1.50 8.00 v Done"
&write "END"
&rem **** set justification according to current annopos
&value [temp] [pos] 2 2
&if &eq [temp] L &do
   &write "C 105"
&elseif &eq [temp] C &do
   &write "C 106"
&else
   &write "C 107"
&end
&write "S 104 1.5"
&write "G 109"
&closew
WIN DB C [wksp]t$anno.dlg
& DEL [wksp]t$anno.dlg
&rem **** process responses
&while &do
   WIN DB R [wksp]t$anno.cmd
   &if &fn [wksp]t$anno.cmd &do
      & DEL [wksp]t$anno.cmd
   &end
   &if &eq [winrtn] 105 &do
      &value [temp] [pos] 1 1
      &sv [pos] [temp]L
      ANNOPOS [pos]
   &elseif &eq [winrtn] 106 &do
      &value [temp] [pos] 1 1
      &sv [pos] [temp]C
      ANNOPOS [pos]
   &elseif &eq [winrtn] 107 &do
      &value [temp] [pos] 1 1
      &sv [pos] [temp]R
      ANNOPOS [pos]
   &elseif &eq [winrtn] 108 &and &ne "x%101" "x" &do
      &openw [wksp]t$anno.cmd
      &rem **** annotype must be POINT1 and annosize > 0
      &rem **** to enable stacked anno
      &if &eq [type] POINT1 &and &ne [line] 0 &do
         &type "Enter starting coordinate:"
         &getxym [x] [y] [temp]
         WIN FOCUS T
         COO KEY
         &sv [temp]
         ADD
         %101
         1 [x] [y]
         [temp]
         COO [coo]
         &write "E 109"
      &else
         &sv [temp]
         ADD
         %101
         [temp]
      &end
      &if &eq %102 1 &do
         SETARROW
      &end
      &if &eq %103 0 &do
         &write "S 101"
      &end
      &write "F 101"
      &closew
   &elseif &eq [winrtn] 109 &and &ne "x%101" "x" &do
      &openw [wksp]t$anno.cmd
      &sv [temp]
      &cv [y] [y] - ( [line] * %104 ) - ( [line] * 0.2 )
      COO KEY
      ADD
      %101
      1 [x] [y]
      [temp]
      COO [coo]
      &if &eq %103 0 &do
         &write "S 101"
      &end
      &write "F 101"
      &closew
   &rem **** begin modal code block
   &elseif &eq [winrtn] 110 &do
      WIN DB BI
      &r annoinit 1
      &openw [wksp]t$init.cmd
      &write "G 127"
      &closew
      WIN DB R [wksp]t$init.cmd
      & DEL [wksp]t$init.cmd
      &if &eq [winrtn] 128 &do
         ANNOTYPE %121
         ANNOPOS %122
         ANNOFIT %123
         ANNOLEVEL %124
         ANNOSYMBOL %125
         &if &eq "%126" "*" &do
            &type "ANNOSIZE:"
         &end
         ANNOSIZE %126
      &end
      WIN DB E
      SHOW ANNOSIZE [line]
      SHOW ANNOPOSITION [pos]
      SHOW ANNOTYPE [type]
      &openw [wksp]t$anno.cmd
      &if &ne [type] POINT1 &or &eq [line] 0 &do
         &write "G 109"
      &end
      &value [temp] [pos] 2 2
      &if &eq [temp] L &do
         &write "C 105"
      &elseif &eq [temp] C &do
         &write "C 106"
      &else
         &write "C 107"
      &end
      &closew
   &rem **** end modal code block
   &else
      WIN DB E
      &return
   &end
&end
&return
After querying current annotation parameters, WIN DB BH is executed to save and hide the current dialog box group. Then the dialog box is created:

Figure 4

Note the "Set..." button (ID 110), which calls yet another modal dialog box to set annotation parameters:

Figure 5

The "Item" edit box is grayed because ANNOADD only works with ANNOITEM KEYBOARD. Routine ANNOINIT creates and initializes the dialog box:

&routine annoinit

&define num -1 &var
&define wksp -18 &var
&define temp -19 &var
&define winrtn 1 &var
&value [wksp] WKSP
&openw [wksp]annoenv.dlg
&write "BEGIN    0  5.00 40.00  8.50 33.00 v Anno Environment"
&write "LTEXT    0  0.25  1.00  1.00 5.00 v Type"
&write "DROP   121  1.50  1.00  5.00 9.00 f"
&write "LTEXT    0  0.25 11.00  1.00 6.00 v Posit."
&write "DROP   122  1.50 11.00 11.00 6.00 f"
&write "LTEXT    0  0.25 18.00  1.00 4.00 v Fit"
&write "DROP   123  1.50 18.00  4.00 6.00 f"
&write "LTEXT    0  0.25 25.00  1.00 7.00 v Level"
&write "EBOX   124  1.50 25.00  1.50 7.00 f"
&write "LTEXT    0  3.25  1.00  1.00 7.00 v Symbol"
&write "EBOX   125  4.50  1.00  1.50 7.00 v"
&write "LTEXT    0  3.25  9.00  1.50 8.00 v Size"
&write "EBOX   126  4.50  9.00  1.50 8.00 f"
&write "LTEXT    0  3.25 18.00  1.50 8.00 v Item"
&write "EBOX   127  4.50 18.00  1.50 14.00 f"
&write "PBUT  -128  6.50  1.00  1.50 8.00 v Apply"
&write "END"
&rem **** fill in values
&write "L 121"
&write "POINT1"
&write "POINT2"
&write "LINE"
&write " "
SHOW ANNOTYPE [temp]
&write "S 121 [temp]"
&write "L 122"
&write "LL"
&write "LC"
&write "LR"
&write "CL"
&write "CC"
&write "CR"
&write "UL"
&write "UC"
&write "UR"
&write " "
SHOW ANNOPOS [temp]
&write "S 122 [temp]"
&write "L 123"
&write "ON"
&write "OFF"
&write " "
SHOW ANNOFIT [temp]
&write "S 123 [temp]"
&write "B 124 3 4"
SHOW ANNOLEVEL [temp]
&write "S 124 [temp]"
&write "B 125 3 4"
SHOW ANNOSYMBOL [temp]
&write "S 125 [temp]"
&rem &write "B 126 12 4"
SHOW ANNOSIZE [temp]
&write "S 126 [temp]"
&sv -2
SHOW ANNOITEM [temp] -2
&sv [temp] "[temp] %-2"
&write "S 127 [temp]"
&closew
WIN DB C [wksp]annoenv.dlg [num]
& DEL [wksp]annoenv.dlg
&return
It is possible to revise ANNOADD to support the "Anno Environment" dialog box nonmodally by replacing the "modal code block" with the following:

   &rem **** begin nonmodal code block
   &elseif &eq [winrtn] 110 &do
      &r annoinit 2
      &openw [wksp]t$anno.cmd
      &write "G 127"
      &closew
   &elseif &eq [winrtn] 128 &do
      ANNOTYPE %121
      ANNOPOS %122
      ANNOFIT %123
      ANNOLEVEL %124
      ANNOSYMBOL %125
      &if &eq "%126" "*" &do
         &type "ANNOSIZE:"
      &end
      ANNOSIZE %126
      SHOW ANNOSIZE [line]
      SHOW ANNOPOSITION [pos]
      SHOW ANNOTYPE [type]
      &openw [wksp]t$anno.cmd
      &if &ne [type] POINT1 &or &eq [line] 0 &do
         &write "G 109"
      &end
      &value [temp] [pos] 2 2
      &if &eq [temp] L &do
         &write "C 105"
      &elseif &eq [temp] C &do
         &write "C 106"
      &else
         &write "C 107"
      &end
      &rem **** reset annoenv editboxes
      SHOW ANNOLEV [temp]
      &write "S 124 [temp]"
      SHOW ANNOSYM [temp]
      &write "S 125 [temp]"
      &write "S 126 [line]"
      &closew
   &rem **** end nonmodal code block
Most notable is the addition of lines to reset the edit box widgets in the "Anno Environment" dialog box. This is especially useful for viewing instantly the results of an ANNOSIZE * command.

Handling multiple dialog boxes can be a challenge. It takes careful deliberation to implement nonmodal and modal dialog boxes, and to avoid widget collision. It can be especially difficult to design code to handle adequately all of the possible widgets in a given situation. Fortunately, there is an excellent utility included with PC ARC/INFO 3.5.X that greatly simplifies the task of testing and coding application interfaces.

Next: GUITOOL


[1]In that case WIN MENU R would either return a string value corresponding to the menu entry or a numeric value corresponding to the return widget.

[2]Commands such as WIN FILE and WIN MB automatically create a modal dialog box, so dialog box groups are not necessary. Any active dialog boxes will be set idle until the modal box is dismissed.

[3]Optionally, you may specify the number of a current dialog box to pass on to the new group as the initial dialog box.


Return to ArcTips page