Creating a Custom Dialog in xlisp-stat

Interactive dialogs can be used in xlisp-stat to create flexible and interesting dynamic graphics, allowing a user to specify options or values in a convenient way. However, the default commands which are provided in the system sometimes make it difficult or impossible to acheive the flexibility that's required for some applications. For example, consider the choose-item-dialog function. This function presents a list of choices to a user; after making a choice the user then clicks ``OK'', the dialog box disappears, and the program continues. But there are many applications where it would be more desirable to perform some action as soon as a choice is made, leaving the dialog box in place for future interaction. To clarify this point, suppose we are building an application where the user can choose among three four different kernel types. Using built-in defaults, the following command could be used to build the dialog box shown in Figure 1:
           (choose-item-dialog "Kernel:" 
           (list "Box" "Triangular" "Biweight" "Epanechinokov"))

Figure 1: Default Choose-Item-Dialog box

This default is composed of several different pieces; the list of kernel choices, a button for ``OK'' and a button for ``Cancel''. xlisp-stat provides primitives (prototypes) for each of these pieces, providing more control than is available for the defaults. In our current example, we want to eliminate the need for an ``OK'' choice by incorporating an action into the selection of the button. We can send a :new message to the choice-item-proto, telling it to create a choice-item (a set of buttons where exactly one is on and the others are off), with an action associated with the choice. In this case, we wish to change the value of the variable ktype each time a different button is selected.

(def choices (send choice-item-proto :new
	(list "Box" "Triangular" "Biweight" "Epanechinokov")
	:action #'(lambda () (def ktype (send choices :value)))))
In the default ( choose-item-dialog), there was no action associated with the choice-item itself; the action was tied to the ``OK'' button. Since we've modified this behavior, we no longer need an ``OK'' button, but we do need a ``Cancel'' button. We can create this button with the send-button-proto in a fashion similar to the above example:
(def close (send button-item-proto :new "Cancel"
	:action #'(lambda () (send kernel-chooser :close))))
Finally, by creating a list containing the different pieces, we can create the kernel-chooser dialog refered to above:
(def kernel-chooser 
     (send modal-dialog-proto :new 
     (list "Kernel:"
     (list choices)
     (list close))))
The resulting dialog box is shown in Figure 2.

Figure 2: Customized Choose-Item Dialog Box

Notice that the argument to the :new method of modal-dialog-proto consists of a list, containing either text (like "Kernel", or lists containing objects created by previous calls to the prototyping functions. Thus, this technique can be used to build very complex dialog boxes! The following is a list of functions available for creating dialogs:

dialog-protodialog with built-in ``Close'' button.
modal-dialog-protodialog with just the items you define
toggle-item-proto``on/off'' checkbox item
text-item-protostatic text
edit-text-item-protoeditable text
button-item-protobutton with associated action
modal-button-protobutton with default ``Close'' behavior
choice-item-protoradio buttons allowing exactly one choice

Suppose we wish to create a dialog box that not only allows us to select the kernel, but also a filename to open for data reading. First, we construct each item separately using the prototypes as in the previous example. We can create a text entry field for a filename with the edit-text-item-proto:

  (def file (send edit-text-item-proto :new "" :text-length 20))
The file object can now be incorporated into the kernel chooser using the following code; the result is shown in Figure 3.
(def kernel-chooser
     (send modal-dialog-proto :new
     (list "Kernel:" (list choices))
     (list "Filename" (list file))
     (list close))))

Figure 3: Customized Dialog Box with Filename input

To retrieve the name of the file entered into the dialog box, send the :text message to the file object.

Phil Spector
Fri Feb 28 11:18:56 PST 1997