The
popup-confirmer
function creates a dialog with predefined implementations of
OK
and
Cancel
buttons and a user specified pane in a layout with the buttons.
popup-confirmer pane message &rest interface-args &key modal title title-font value-function exit-function apply-function apply-check apply-button ok-function ok-check ok-button no-button no-function all-button all-function cancel-button help-button help-function buttons print-function callbacks callback-type button-position buttons-uniform-size-p foreground background font screen focus owner x y position-relative-to button-container button-font continuation callback-error-handler => result , successp
A CAPI pane or interface.
A string or
nil
.
modal , screen , focus , owner , x , y , and position-relative-to
These are passed to display-dialog.
A string specifying the title of the dialog window.
The font used in the title.
Controls the value returned, and whether a value can be returned.
Called on exiting the dialog.
apply-function , apply-check , apply-button
Define the callback, check function and title an Apply button.
ok-function, ok-check, ok-button
Define the callback, check function and title of an OK button.
Define the title and callback of a No button.
Define the title and callback of an All button.
Defines the title of a Cancel button.
Define the title and callback of a Help button.
Defines extra buttons.
Displays ok-button , no-button , cancel-button , apply-button and all-button as button titles.
Defines callbacks for buttons .
Specifies the callback-type of buttons .
One of
:bottom
,
:top
,
:left
,
:right
.
Controls relative button sizes.
A font or a font description.
A font or a font description.
A layout controlling where the buttons of the dialog appear.
A function or
nil
.
The result of
value-function
, or
pane
, or
nil
.
nil
if the dialog was cancelled,
t
otherwise.
The function
popup-confirmer
provides the quickest means to create new dialogs, as it will create and implement
OK
,
Cancel
and other buttons as required by your dialog, and will place a user-specified pane in a layout along with the buttons.
Generally the
Return
key selects the dialog's
OK
button and the
Escape
key selects the
Cancel
button, if there is one.
The argument
value-function
should provide a callback which is passed
pane
and should return the value to return from
popup-confirmer
. If
value-function
is not supplied, then
pane
itself will be returned as
result
. If the
value-function
wants to indicate that the dialog cannot return a value currently, then it should return a second value that is non-nil.
The
ok-check
function is passed the result returned by the
value-function
and should return true if it is acceptable for that value to be returned. These two functions are used by
popup-confirmer
to decide when the
OK
button should be enabled, thus stopping the dialog from returning with invalid data. The
OK
button's state can be updated by a call to redisplay-interface on the top-level, so the dialog should call it when the button may enable or disable.
The arguments
ok-button
,
no-button
and
cancel-button
are the text strings for each button, or
nil
meaning do not include that button. The
ok-button
returns successfully from the dialog (with the result of
value-function
), the
no-button
means continue but return
nil
, and the
cancel-button
aborts the dialog. Note that there are clear expectations on the part of users as to the functions of these buttons -- check the style guidelines of the platform you are developing for.
apply-button , if passed, specifies the title of an extra button which appears near to the OK button. apply-check and apply-function define its functionality.
all-button , if passed, specifies the title of an extra button which is always enabled and which appears near to the apply-button (if that exists) or the OK button. all-function defines its functionality.
help-button , if passed, specifies the title of a help button which appears to the right of the Cancel button. help-function defines its functionality.
print-function is called on the various button arguments to generate a string to display for each button title.
button-position
specifies where to put the buttons. The default is
:bottom
.
buttons-uniform-size-p
specifies whether the buttons are all the same size, regardless of the text on them. The default is
t
, but
nil
can be passed to make each button only as wide as its text.
foreground and background specify colors to use for the parts of the dialog other than pane , including the buttons
font specifies the font to use in the message .
button-font specifies the font to use in the buttons.
button-container indicates where the buttons of the dialog appear. It must be a layout which is a descendent of pane . The description of this layout is automatically set to the button-panel containing the buttons.
The arguments
exit-function
,
ok-function
and
no-function
are the callbacks that get done when exiting, pressing
OK
and pressing
No
respectively. The
exit-function
defaults to exit-confirmer, the
ok-function
defaults to the
exit-function
and the
no-function
defaults to a function exiting the dialog with
nil
.
The arguments
buttons
,
callbacks
and
callback-type
are provided as a means of extending the available buttons. The buttons provided by
buttons
will be placed after the buttons generated by
popup-confirmer
, with the functions in
callbacks
being associated with them. Finally
callback-type
will be provided as the callback type for the buttons.
If any of callbacks need to access pane , you could use confirmer-pane together with a callback-type that passes the interface.
If
continuation
is non-nil, then it must be a function with a lambda list that accepts two arguments. The
continuation
function is called with the values that would normally be returned by
popup-confirmer
. On Cocoa, passing
continuation
causes the dialog to be made as a window-modal sheet and
popup-confirmer
returns immediately, leaving the dialog on the screen. The with-dialog-results macro provides a convenient way to create a
continuation
function.
callback-error-handler
, if non-nil, should be a function designator for a function of one argument which is a condition, like the
handler-function
in
cl:handler-bind
. The handler is established (by
cl:handler-bind
with type
cl:error
) around each callback call inside the scope of
popup-confirmer
or display-dialog. In recursive calls, only the handler of the innermost call to
popup-confirmer
or display-dialog is established.
callback-error-handler
can use current-popup to find the popup (first argument to the innermost call of display-dialog or
popup-confirmer
).
If callback-error-handler wants to do a non-local exit, it should either call abort-callback to abort the callback but leave the dialog, or exit-dialog (or abort-dialog) to exit (or abort) the dialog.
All other arguments will be passed to the call to
make-instance
for the interface that will be displayed using display-dialog. Thus geometry information, colors, and so on can be passed in here as well. By default, the dialog will pick up the foreground, background and font of
pane
.
cl:handler-bind
around the call to display-dialog or
popup-confirmer
(the handler will also handle errors during raising the dialog, but these are not expected to happen). On Cocoa, using such an error handler does not necessarily work, because the callback may happen in another process.
callback-error-handler
ensures that the callback is in the scope of the handler on all plaforms. From the same reason the handler should not rely on the dynamic environment (including catchers and restarts), and needs to use current-popup to find its "context" and use abort-callback, exit-dialog or abort-dialog for non-local exit.
popup-confirmer
or display-dialog, the
callback-error-handler
handler will stay until the callback returns. Unless the recursive call handles the error, the handler of the outer call may be called to handle it, and needs to be written to deal with this possibility correctly. If the handler inside a recursive call needs to access the popup that was used in the same call that the handler was used, it should close over it, because current-popup returns the innermost one.
cl:handler-bind
or
cl:handler-case
) is inside the scope of the
callback-error-handler
, and therefore will be called first.
Here are two simple examples which implement the basic functionality of two CAPI prompters: the first implements a simple
prompt-for-string
, while the second implements
prompt-for-confirmation
.
(capi:popup-confirmer
(make-instance 'capi:text-input-pane
:callback
'capi:exit-confirmer)
"Enter some text:"
:value-function 'capi:text-input-pane-text)
(capi:popup-confirmer nil
"Yes or no?"
:callback-type :none
:ok-button "Yes"
:no-button "No"
:cancel-button nil
:value-function #'(lambda (dummy) t))
This example demonstrates the use of
:redisplay-interface
to make the
OK
button enable and disable on each keystroke.
(defun pane-integer (pane)
(ignore-errors (values
(read-from-string
(capi:text-input-pane-text
pane)))))
(capi:popup-confirmer
(make-instance 'capi:text-input-pane
:callback 'capi:exit-confirmer
:change-callback :redisplay-interface)
"Enter an integer"
:value-function 'pane-integer
:ok-check 'integerp)
An example illustrating the use of
:button-container
:
(let* ((bt (make-instance 'capi:simple-layout
:title "Button Container"
:title-position :left))
(tip1 (make-instance 'capi:text-input-pane
:title "Top"))
(tip2 (make-instance 'capi:text-input-pane
:title "Bottom"))
(layout (make-instance 'capi:column-layout
:description
(list tip1
bt
tip2))))
(capi:popup-confirmer layout nil
:title
"Dialog using button-container"
:button-container bt))
An example with all the defined buttons in use:
(defun all-buttons-dialog (&optional (num 20))
(let ((pane
(make-instance 'capi:list-panel
:items
(loop for ii from 1
to num
collect
(format nil "~r" ii))
:visible-min-width
'(character 20))))
(capi:popup-confirmer
pane
"All Buttons"
:callback-type :none
:button-position :right
:cancel-button "Cancel Button"
:ok-button "OK Button"
:ok-function #'(lambda (x)
(declare (ignorable x))
(capi:exit-dialog
(capi:choice-selected-item pane)))
:no-button "No Button"
:no-function
#'(lambda ()
(capi:exit-dialog
(cons :no
(capi:choice-selected-item pane))))
:apply-button "Apply Button"
:apply-function
#'(lambda ()
(capi:display-message
"Applying to ~a"
(capi:choice-selected-item pane)))
:help-button "Help Button"
:help-function
#'(lambda ()
(capi:display-message
"~a is ~:[an odd~;an even~] number"
(capi:choice-selected-item pane)
(oddp (capi:choice-selection pane))))
:all-button "All Button"
:all-function
#'(lambda()
(capi:exit-dialog
(capi:collection-items pane))))))
(all-buttons-dialog)
A dialog with arbitrary buttons:
(capi:popup-confirmer
(make-instance 'capi:text-input-pane)
"Dialog with arbitrary buttons"
:buttons '(:abc :xyz)
:callbacks
(list #'(lambda (data)
(capi:display-message
"Button ~A was pressed" data))
#'(lambda (data)
(capi:display-message
"Button with ~A was pressed, exiting with ~S" data data)
(capi:exit-dialog data)))
:callback-type :data)
This example illustrates the use of callback-error-handler :
(defun my-error-handler (condition)
(let ((pane (capi:current-popup)))
(capi:display-message
"Error inside dialog: ~a : ~a"
(capi:capi-object-name pane)
condition)
(capi:abort-callback)))
(let*
((foo-callback
(lambda ()
(let ((md (make-instance
'capi:push-button
:text "Error inside Callback-Error-Handler"
:name "Chicken"
:callback-type :data
:data "Twisted ankle."
:callback 'error)))
(capi:popup-confirmer
md nil
:callback-error-handler 'my-error-handler))))
(foo (make-instance
'capi:push-button
:text
"Popup confirmer with Callback-Error-Handler"
:callback-type :none
:callback foo-callback))
(bar (make-instance
'capi:push-button
:text "Error without a handler"
:callback-type :data
:data "Broken leg."
:callback 'error)))
(capi:contain (list foo bar)))