It often happens that the programmer wants to present a dialog where the individual fields of the dialog depend on one another. For example, consider a spreadsheet with seven columns representing the days of a week. Each column is headed with that day's date. If the user inputs the date of any single day, the other dates can be computed from that single piece of input.
If you build CLIM dialogs using accepting-values , you can achieve this effect by using the :resynchronize-every-pass argument to accepting-values in conjunction with the :default argument to accept . There are three points to remember:
The entire body of the accepting-values runs each time the user modifies any field. The body can be made to run an extra time by specifying :resynchronize-every-pass t . Code in the body may be used to enforce constraints among values.
If the :default argument to accept is used, then every time that call to accept is run, it will pick up the new value of the default.
Inside accepting-values , accept returns a third value, a boolean that indicates whether the returned value is the result of new input by the user or is just the previously supplied default.
In this example we show a dialog that accepts two real numbers, delimiting an interval on the real line. The two values are labelled
, but we wish to allow the user to supply a
that is greater than the
, and automatically exchange the values rather than signalling an error.
(defun accepting-interval (&key (min -1.0) (max 1.0)
(clim:accepting-values (stream :resynchronize-every-pass t)
'clim:real :default min
:prompt "Min" :stream stream))
'clim:real :default max
:prompt "Max" :stream stream))
(when (< max min)
(rotatef min max)))
(values min max))
(You may want to try this example after dropping the :resynchronize-every-pass and see the behavior. Without :resynchronize-every-pass , the constraint is still enforced, but the display lags behind the values and doesn't reflect the updated values immediately.)