26 Dialog Facilities

Major issue: There is a general issue about how these dialogs fit in with the dialogs that might be provided by the underlying toolkit. For example, under what circumstances is CLIM allowed to directly use the dialog facility provided by the host? --- SWM [annotate]

accepting-values  (&optional stream &key own-window exit-boxes initially-select-query-identifier modify-initial-query resynchronize-every-pass resize-frame align-prompts label scroll-bars x-position y-position width height command-table frame-class) &body body [Macro]

Builds a dialog for user interaction based on calls to accept within body. The user can select the values and change them, or use defaults if they are supplied. The dialog will also contain some sort of "end" and "abort" choices. If "end" is selected, then accepting-values returns whatever values the body returns. If "abort" is selected, accepting-values will invoke the abort restart. [annotate]

stream is an interactive stream that accepting-values will use to build up the dialog. The stream argument is not evaluated, and must be a symbol that is bound to a stream. If stream is t (the default), *standard-input* is used. [annotate]

body is the body of the dialog, which contains calls to accept that will be intercepted by accepting-values and used to build up the dialog. body may have zero or more declarations as its first forms. [annotate]

An accepting-values dialog is implemented as an application frame with a looping structure. First, body is evaluated in order to collect the output. While the body is being evaluated, all calls to accept call the accept-present-default presentation methods instead of calling the accept presentation methods. The output is then displayed, preferably using incremental redisplay in order to avoid unnecessary redisplay of unchanged output. If align-prompts is true (the default is nil), then the fields of the dialog will be displayed within a call to formatting-table so that the prompts are aligned vertically on their right-hand sides and the input fields are aligned on their left-hand sides. This option is intended to support toolkits where users expect dialogs to have this sort of layout. [annotate]

Note: The requirement that accepting-values be defined as a frame appears to have been dropped; the Franz user guide doesn't mention it. In any event, it would imply that extended output streams be able to adopt frames, which is rather onerous. [edit]-- Tim Moore 2003-05-08 06:17Z

After accepting-values has displayed all of the fields, it awaits a user gesture, such as clicking on one of the fields of the dialog. When the user clicks on a field, accepting-values reads a new value for that field using accept and replaces the old value with the new value. Then the loop is started again, until the user either exits or aborts from the dialog. [annotate]

Because of its looping structure, accepting-values needs to be able to uniquely identify each call to accept in the body of the dialog. The query identifier is used to identify the calls to accept. The query identifier for a call to accept is computed on each loop through the dialog, and should therefore be free of side-effects. Query identifiers are compared using equal. Inside of accepting-values, programmers should supply the :query-identifier argument to each call to accept. If :query-identifier is not explicitly supplied, the prompt for that call to accept is used as the query identifier. Thus, if :query-identifier is not supplied, programmers must ensure that all of the prompts are different. If there is more than one call to accept with the same query identifier, the behavior of accepting-values is unspecified. [annotate]

While inside accepting-values, calls to accept return a third value, a boolean ("changed-p") that indicates whether the object is the result of new input by the user, or is just the previously supplied default. The third value will be true in the former case, false in the latter. [annotate]

Implementation note: each invocation of accepting-values will probably need to maintain a table that maps from a query identifier to the output record for the field that used the query identifier, and the output record for each field in the dialog will probably need a mapping back to the query identifier. A mediating object (a "query object") is also useful, for instance, as a place to store the "changed-p" flag. [annotate]

The class of the application frame created by accepting-values will be accept-values or a subclass of accept-values. Programmers can use a class of their own by supplying the name of a class via the frame-class argument. CLIM will use the command table accept-values as the command table for accepting-values. Programmers can supply a command table of their own by supplying the command-table argument. [annotate]


This description of the command table argument is not very useful. If we default to accept-values, then we drop all translators from the command table associated with the application. On the other hand when we supply "our" command table, then accept-values translators and commands are not available.

One solution is to merge the application's command table and the supplied command table (by dynamically creating a new command table that inherits from both).

[edit]-- Daniel Kochmanski 2023-10-26 09:49Z

When own-window is non-nil, the dialog will appear in its own "popped-up" window. In this case the initial value of stream is a window with which the dialog is associated. (This is similar to the associated-window argument to menu-choose.) Within the body, the value of stream will be the "popped-up" window. own-window is either t or a list of alternating keyword options and values. The accepted options are :right-margin and :bottom-margin; their values control the amount of extra space to the right of and below the dialog (useful if the user's responses to the dialog take up more space than the initially displayed defaults). The allowed values for :right-margin are the same as for the :x-spacing option to formatting-table; the allowed values for :bottom-margin are the same as for the :y-spacing option. [annotate]

Minor issue: When the programmer supplies :right-margin or :bottom-margin options in the own-window argument, how is he supposed to determine what's needed? How about providing an option to permit the window to resize itself dynamically? There really needs to be a hook into note-space-requirements-changed or something. --- barmar, SWM [annotate]

exit-boxes specifies what the exit boxes should look like. The default behavior is though the following were supplied: [annotate]

'((:exit "<End> uses these values")
  (:abort "<Abort> aborts"))

Minor issue: We need to describe the interpretation of the exit-boxes argument. Are other keywords beside :exit and :abort permitted, such as :help? It's pretty common for a dialog to have multiple ways to exit; perhaps accepting-values should return a second value that indicates which exit box was selected. This alist looks sort of like a menu item list; perhaps the full generality should be permitted (so that the style of the exit box messages can be specified). The text strings that are shown in the default value look more like documentation than button labels; I think both are necessary, and the programmer must be able to find out what the default labels are so that he can include them in the documentation (rather than hard-coding "<End>" and "<Abort>"). --- barmar [annotate]

initially-select-query-identifier specifies that a particular field in the dialog should be pre-selected when the user interaction begins. The field to be selected is tagged by the :query-identifier option to accept. When the initial display is output, the input editor cursor appears after the prompt of the tagged field, just as if the user had selected that field by clicking on it. The default value, if any, for the selected field is not displayed. When modify-initial-query is true, the initially selected field is selected for modification rather than for replacement; the default is nil. [annotate]

resynchronize-every-pass is a boolean option specifying whether earlier queries depend on later values; the default is false. When it is true, the contents of the dialog are redisplayed an additional time after each user interaction. This has the effect of ensuring that, when the value of some field of a dialog depends on the value of another field, all of the displayed fields will be up to date. [annotate]

When resize-frame is true, own-window dialogs will be resized after each pass through the redisplay loop. The default is nil. [annotate]

label is as for menu-choose. x-position and y-position are as for menu-choose-from-drawer. width and height are real numbers that specify the initial width and height of own-window dialogs. [annotate]


accept-values   [Application Frame]

accepting-values must be implemented as a CLIM application frame that uses accept-values as the name of the frame class. [annotate]


display-exit-boxes  frame stream view [Generic Function]

Displays the exits boxes for the accepting-values frame frame on the stream strea, in the view view. The exit boxes specification is not passed in directly, but is a slot in the frame. The default method (on accept-values) simply writes a line of text associating the Exit and Abort strings with presentations that either exit or abort from the dialog. [annotate]

The frame, stream, and view arguments may be specialized to provide a different look-and-feel for different host window systems. [annotate]


accept-values-resynchronize  stream [Generic Function]

Causes accepting-values to resynchronizes the dialog once on the accepting values stream stream before it restarts the dialog loop. [annotate]


accept-values-command-button  (&optional stream &key documentation query-identifier cache-value cache-test resynchronize) prompt &body body [Macro]

Displays the prompt prompt on the stream stream and creates an area (the "button"). When a pointer button is clicked in this area at runtime, body will be evaluated. [annotate]

accept-values-command-button must be implemented by expanding into a call to invoke-accept-values-command-button, supplying a function that executes body as the continuation argument to accept-values-command-button. [annotate]

The stream argument is not evaluated, and must be a symbol that is bound to a stream. If stream is t (the default), *standard-input* is used. body may have zero or more declarations as its first forms. [annotate]


invoke-accept-values-command-button   [Method]

stream continuation view prompt &key documentation query-identifier cache-value cache-test resynchronize [annotate]

Displays the prompt prompt on the stream stream and creates an area (the "button"). When a pointer button is clicked in this area at runtime, the continuation will be called. continuation is a function that takes no arguments. view is a view. [annotate]

prompt may be either a string (which will be displayed via write-string), or a form that will be evaluated to draw the button. [annotate]

documentation is an object that will be used to produce pointer documentation for the button. It defaults to prompt. If it is a string, the string itself will be used as the pointer documentation. Otherwise it must be a function of one argument, the stream to which the documentation should be written. [annotate]

When resynchronize is true, the dialog will be redisplayed an additional time whenever the command button is clicked on. See the resynchronize-every-pass argument to accepting-values. [annotate]

cache-value and cache-test are as for updating-output. That is, cache-value should evaluate to the same value if and only if the output produced by prompt does not ever change. cache-test is a function of two arguments that is used to compare cache values. cache-value defaults to t and cache-test defaults to eql. [annotate]

This function may only be used inside the dynamic context of an accepting-values. [annotate]