Every gadget has a client that is specified when the gadget is created. The client is notified via the callback mechanism when any important user interaction takes place. Typically, a gadget's client will be an application frame or a composite pane. Each callback generic function is invoked on the gadget, its client, the gadget id, and other arguments that vary depending on the callback.
For example, the argument list for activate-callback looks like (gadget client gadget-id) . Assuming the programmer has defined an application frame called button-test that has a CLIM stream pane in the slot output-pane , she could write the following method:
(defmethod activate-callback
((button push-button) (client button-test) gadget-id)
(with-slots (output-pane) client
(format output-pane
"The button ~S was pressed, client ~S, id ~S."
button client gadget-id)))
One problem with this example is that it differentiates on the class of the gadget, not on the particular gadget instance. That is, the same method will run for every push button that has the button-test frame as its client.
One way to distinguish between the various gadgets is via the gadget id , which is also specified when the gadget is created. The value of the gadget id is passed as the third argument to each callback generic function. In this case, if we have two buttons, we might install start and stop as the respective gadget ids and then use eql specializers on the gadget ids. We could then refine the previous method as:
(defmethod activate-callback
((button push-button) (client button-test)
(gadget-id (eql 'start)))
(start-test client))
(defmethod activate-callback
((button push-button) (client button-test)
(gadget-id (eql 'stop)))
(stop-test client))
;; Create the start and stop push buttons
(make-pane 'push-button
:label "Start"
:client frame :id 'start)
(make-pane 'push-button
:label "Stop"
:client frame :id 'stop)
Another way to distinguish between gadgets is to specify explicitly what function should be called when the callback is invoked. This is done by supplying an appropriate initarg when the gadget is created. The previous example could then be written as follows:
;; No callback methods needed; just create the push buttons.
(make-pane 'push-button
:label "Start"
:client frame :id 'start
:activate-callback
#'(lambda (gadget)
(start-test (gadget-client gadget))))
(make-pane 'push-button
:label "Stop"
:client frame :id 'stop
:activate-callback
#'(lambda (gadget)
(stop-test (gadget-client gadget))))
Common Lisp Interface Manager 2.0 User's Guide - 3 Mar 2015