% -*- Mode: LaTeX; Package: CLIM-USER -*-
\chapter {Gadget Panes}
\label {gadget-panes}

\section {Overview}

\concept{Gadget panes} are panes that implement such common toolkit components
as push buttons or scroll bars.  Each gadget pane class has a set of associated
generic functions that serve the role of ``callbacks'' in ``traditional''
toolkits.  For example, a push-button has a ``value change'' callback function
that is invoked when its button is ``pressed''.

\issue {Moon} {Doing gadgets as panes seems dangerous, since I thought panes are
statically laid out but one should be able to draw a knob anywhere in the
drawing plane and have it immediately start working.  I would have thought of
gadgets as presentations rather than panes.}

The gadget pane definitions supplied here are abstract.  That is, the gadget
definition does not specify the specific user interface of the gadget pane.  In
other words, it is not defined whether the user clicks on the button with the
mouse or moves the mouse over the button and presses some key on the keyboard to
invoke the ``value change'' callback.  Particular toolkit implementations will
specify the ``look and feel'' of their gadgets.

Each of the abstract gadget panes has at least one implementation, written in
Lisp using the CLIM input/output kernel capabilities.  Its appearance is
achieved via calls to the CLIM graphics functions, its interactive behavior
defined in terms of the CLIM input event processing mechanism.  Since these
gadget implementations are written entirely in terms of CLIM, they are portable
across all supported CLIM host window systems.  However, since the specific look
and feel of each such gadget is ``fixed'' in CLIM Lisp code, the gadget
implementation will look and behave the same in all environments.


\section {Interacting with Gadget Panes}

Every gadget has a \concept{client}.  The client is specified at gadget
creation.  The client is made aware of all important user interactions with the
gadget via the callback mechanism.   Each callback generic function is invoked
on both the gadget pane and its client.  Typically, a gadget pane's client will
be an application frame or a composite pane.

As an example, the argument list for \cl{value-change-callback} looks like
\arg{(gadget-pane client gadget-id value)}.  Assuming that programmer had
defined an application frame called \cl{button-test} that had a
\cl{clim-stream-pane} in its slot \cl{output-pane}, he could write the following
method:

\begin{verbatim}
(defmethod value-change-callback
           ((button push-button) (client button-test) gadget-id value) 
  (declare (ignore value))
  (with-slots (output-pane) client
    (format output-pane "A button was pressed.")))
\end{verbatim}

One problem with this particular example is that it differentiates on the gadget
class, not the gadget instance.  That is, the same method will run for every
push-button that has this frame as its client.  To help sort out the various
gadgets, each gadget pane has a \concept{gadget id} that can be initialized at
gadget creation.  The value of this gadget id is passed as the third argument to
each callback generic function.  In this case, if we had two buttons, we might
have installed \cl{start} and \cl{stop} as the respective gadget ids.  We could
then refine the above as:

\begin{verbatim}
(defmethod value-change-callback
           ((button push-button) (client button-test) (gadget-id (eql 'start)) value)
  (declare (ignore value))
  (start-test client))

(defmethod value-change-callback
           ((button push-button) (client button-test) (gadget-id (eql 'stop)) value)
  (declare (ignore value))
  (stop-test client))
\end{verbatim}

This scheme takes advantage of the multi-method facility in CLOS and frees the
programmer from having to subclass each gadget type before using it.

\section {Abstract Gadgets}

The class \cl{push-button} we introduced above is an \concept{abstract gadget
class}.  The callback interface to all implementations of the gadget is defined
by the abstract class.  In a frame pane layout specification, a gadget pane is
named by its abstract class name.  At pane realization time, this abstract class
must be resolved to a specific implementation class.  The individual
implementation classes specify the detailed look and feel of the gadget.  Every
implementation of an abstract gadget class is a subclass of the abstract class;
therefore they all share the same programmer interface.  The selection of a
specific implementation of an abstract gadget is handled by the frame manager.

\subsection {Implementation Strategy}

\begin{verbatim}
(defclass gadget-pane (pane)
  ((client :initarg :client :accessor gadget-client)
   (id :initarg :id gadget-id))
  (:default-initargs :id nil :client nil))

;; Abstract definition.
(defclass abstract-push-button () () )

;; For each callback, do this.
(defmethod value-change-callback
           ((gadget abstract-push-button) client gadget-id value)
  (declare (ignore client gadget-id value)) 
  nil)

;; Implementation side.
;; Associates implementation name with abstract name (somehow)
;; so that frame managers can select it.
(define-abstract-gadget-implementation motif-push-button-pane 
                                       (abstract-push-button . supers)
  (slots)
  . option-forms)

--->

(defclass motif-push-button-pane
          (abstract-push-button ,@supers gadget-pane)
  ,slots)

\end{verbatim}

As part of pane realization, a frame manager must select (and realize) a
specific implementation class for an abstract class.  If the abstract name isn't
``registered'', the abstract name is typically assumed to be the name of a
specific (portable) implementation.  If the abstract name is registered, the
frame manager selects one of the associated implementations.  This behavior is
implemented by a default method on \cl{realize-frame-pane} for the base
\cl{frame-manager} class.  Of course, any individual frame manager is free to
violate these conventions as part of establishing its peculiar look and feel.
It's unwise to shadow completely this default fallback method on
\cl{(pane-type t)}.

\Defgeneric {gadget-id} {gadget}

Returns the id of the gadget.  The id is typically a simple Lisp object that
uniquely identifies the gadgets.

\Defgeneric {gadget-client} {gadget}

Returns the client of the gadget.  The client is usually an application frame.

\Defgeneric {gadget-value} {gadget}

Returns the value of this gadget.  The interpretation of the value is
gadget-specific.  For example, a scroll bar's value might be a number between
0 and 1, while a toggle button's value is either \cl{t} or \cl{nil}.  See the
documentation of individual gadgets to find out how to interpret the value.

\Defgeneric {(setf gadget-value)} {value gadget \key (call-callbacks \cl{t})}

Sets the gadget's value to the specified value.  In addition, if
\arg{call-callbacks} is \term{true}, all the generic operations that would be
invoked if the gadget had been clicked upon in normal use will be run.  Note
that the syntax is:
\begin{verbatim}
(setf (gadget-value gadget :call-callbacks nil) new-value)
\end{verbatim}

\Defgeneric {activate-gadget} {gadget}

Causes the host gadget to become active, that is, available for input.

\Defgeneric {deactivate-gadget} {gadget}

Causes the host gadget to become inactive, that is, unavailable for input.  In
some environments this may cause the gadget to become grayed over; in others, no
visual effect may be detected.

\Defgeneric {note-gadget-activated} {client gadget}

This is invoked after a gadget is made active (available for input).

\Defgeneric {note-gadget-deactivated} {client gadget}

This is invoked after a gadget is made inactive (unavailable for input).

\Defgeneric {value-change-callback} {gadget-pane client gadget-id \optional value}

This is invoked when the value of a gadget is changed, either by the user or
programmatically.  For gadgets that do not have a value, the value of the
\arg{value} argument is unspecified and should be ignored.

Programmers will typically class-specialize the \arg{gadget-pane} and
\arg{client} arguments, and \cl{eql}-specialize the \arg{gadget-id} argument.

CLIM implementations must implement a default method for
\cl{value-change-callback} for every gadget class.

Most gadget classes have a set of additional callbacks, which are described
in detail in the description of the gadget class.


\section {Adaptive Gadget Panes}
\subsection {Overview}

CLIM supplies a set of gadgets that have been designed specifically to be
compatible with with a variety of user interface toolkits, including Xt
widget-based toolkits such as Motif, OpenLook, MacApp, and MS~Windows.

Each gadget maps to an implementation-specific object that is managed by the
underlying toolkit.  For example, while a CLIM program manipulates an object of
class \cl{scroll-bar}, the underlying implementation-specific object might be an
Xt widget of type \cl{Xm\_Scroll\_Bar}.  As events are processed on the
underlying object the corresponding generic operations are applied to the lisp
gadget.

Refer to \cl{realize-pane} to see how to construct and lay out a gadget.

\issue {ILA} {Do we want to define something like (adaptive-)gadget-handle?  A
documented way to get ahold of the underlying toolkit object?}


\subsection {Predefined Gadgets}

CLIM provides a standard set of adaptive gadgets.  This section documents the
predefined gadget types.   Note that not all operations will necessarily be
generated by particular toolkit implementations.  For example, a user interface
toolkit that is designed for a 3-button mouse may generate significantly more
gadget events than one designed for a 1-button mouse.  More on this below.

\comment{What graphic design do we want to use for this?  I'd like some horizontal rules
around each of these.  Maybe Ramana can whip something up.
I'm pretending that a set of TeX macros named Gadget, GadgetSupers, GadgetInits,
GadgetSMO, GadgetOperations, and GadgetComments have been defined.
---
Gadget takes one arg, the gadget name, and formats it nicely.
---
The rest introduce sections of the gadget's documentation.  Each should format its
associated text and then output its arg.
---
GadgetSupers' associated text is "Superclasses"
GadgetInits' associated text is Init Arguments
GadgetSMO's associated text is "State Manipulation Operations"
GadgetOperations' associated text is "Callbacks"
GadgetComments' associated text is "Comments"
---
I also use a macro "Callback" to format the description of the gadget generic operations.
}


\Gadget {push-button}

% For now we are NOT defining the logical "button" superclass
% that provides a common repository for the label and text-style.
% We will, however, use the button- prefix in the state manipulators
% for all buttons

The push button gadget provides press-to-activate switch behavior.

\GadgetInits {\cl{:label}---string

Specifies the label associated with the push button.

\cl{:label-text-style}---text-style

Specifies the text style that will be used when drawing the label.

\cl{:show-as-default-p}---boolean

When \arg{show-as-default-p} is \term{true}, the push button will be draw with a
heavy border, which indicates that this button is the ``default operation''.
}

\GadgetSMO{
\Defgeneric {button-label} {button}

Returns the label of the button.

\Defgeneric {(setf button-label)} {label button}

Changes the label of \arg{button} to the new label string \arg{label}.

\Defgeneric {button-text-style} {button}

Returns the text style of the button's label.

\Defgeneric {(setf button-text-style)} {text-style button}

Changes the text style of \arg{button}'s label to the new text style
\arg{text-style}.

% These state manipulators are specific to push buttons
\Defgeneric {push-button-show-as-default-p} {push-button}

Returns \term{true} if the push button will be shown as the default, otherwise
returns \term{false}.

\Defgeneric {(setf push-button-show-as-default-p)} {state push-button}

Changes the ``show as default'' state of \arg{push-button} to \arg{state}, which
must be \cl{t} or \cl{nil}.
}

\GadgetOperations {\Callback{value-change-callback} {button client gadget-id value}

Called when the toolkit determines that the button has been pushed.  The value
of \arg{value} is indeterminate for push buttons, and should be ignored.

\Callback {arm-callback} {push-button client gadget-id}

Called when the pointer is clicked on the push button gadget identified by
\arg{gadget-id}, preparatory to a value change.  (The exact time when this is
called may vary slightly from one toolkit to another.)

\Callback {disarm-callback} {push-button client gadget-id}

Called when the pointer button is released after an \cl{arm-callback}.  (The
exact time when this is called may vary slightly from one toolkit to another.)
}

\GadgetComments {The normal sequence of callbacks is \cl{arm-callback}, then
\cl{value-change-callback}, then \cl{disarm-callback}.
}


\Gadget {toggle-button}

The toggle button gadget provides ``on/off'' switch behavior.  This gadget
typically appears as a box that is optionally highlighted with a check-mark.
If the check-mark is present, the gadget's value is \cl{t}, otherwise it is
\cl{nil}.

\GadgetInits {\cl{:label}---string

Specifies the label associated with the toggle button.

\cl{:label-text-style}---text-style

Specifies the text style that will be used when drawing the label.

\cl{:indicator-type}---\cl{:one-of} or \cl{:some-of}

The indicator-type controls the appearance of the toggle button.  
For example, many toolkits present a one-of-many choice differently from
a some-of-many choice.
}

\GadgetSMO{
\Defgeneric {button-label} {button}

Returns the label of the button.

\Defgeneric {(setf button-label)} {label button}

Changes the label of \arg{button} to the new label string \arg{label}.

\Defgeneric {button-text-style} {button}

Returns the text style of the button's label.

\Defgeneric {(setf button-text-style)} {text-style button}

Changes the text style of \arg{button}'s label to the new text style
\arg{text-style}.

% These state manipulators are specific to toggle buttons
\Defgeneric {toggle-button-indicator-type} {toggle-button}

Returns the indicator type of \arg{toggle-button}.

\Defgeneric {(setf toggle-button-indicator-type)} {type toggle-button}

Changes the indicator type of \arg{toggle-button} to \arg{type}, which must be
\cl{:one-of} or \cl{:some-of}.
}

\GadgetOperations {\Callback{value-change-callback} {toggle-button client gadget-id value} 

Called when the toolkit determines that the toggle button has been toggled.  The
value of \arg{value} is indeterminate for toggle buttons, and should be ignored.

\Callback {arm-callback} {toggle-button client gadget-id}

Called when the pointer is clicked on the toggle button gadget identified by
\arg{gadget-id}, preparatory to a value change.  (The exact time when this is
called may vary slightly from one toolkit to another.)

\Callback {disarm-callback} {toggle-button client gadget-id}

Called when the pointer button is released after an \cl{arm-callback}.  (The
exact time when this is called may vary slightly from one toolkit to another.)
}

\GadgetComments {The normal sequence of callbacks is \cl{arm-callback}, then
\cl{value-change-callback}, then \cl{disarm-callback}.
}


\Gadget {scroll-bar}

\GadgetInits {\cl{:orientation}---\cl{:horizontal} or \cl{:vertical}

Specifies the orientation of the scroll bar, either horizontal or vertical.

\cl{:min-value}---real number, default 0

Specifies the minimum value of the scroll bar.

\cl{:max-value}---real number, default 1

Specifies the maximum value of the scroll bar.

\cl{:unit-increment}---real number, default 1

Specifies the increment between tick marks on the scroll bar.

\cl{:page-increment}---real number, default 1
}

\GadgetSMO{
\Defgeneric {scroll-bar-orientation} {scroll-bar}

Returns the orientation of the scroll bar.

\Defgeneric {(setf scroll-bar-orientation)} {orientation scroll-bar}

Changes the orientation of the scroll bar to \arg{orientation}.

\Defgeneric {scroll-bar-min-value} {scroll-bar}

Returns the minimum value of the scroll bar.

\Defgeneric {(setf scroll-bar-min-value)} {value scroll-bar}

Changes the minimum value of the scroll bar to \arg{value}.

\Defgeneric {scroll-bar-max-value} {scroll-bar}

Returns the minimum value of the scroll bar.

\Defgeneric {(setf scroll-bar-max-value)} {scroll-bar}

Changes the maximum value of the scroll bar to \arg{value}.

\Defgeneric {scroll-bar-unit-increment} {scroll-bar}

\Defgeneric {(setf scroll-bar-unit-increment)} {scroll-bar}

\Defgeneric {scroll-bar-page-increment} {scroll-bar}

\Defgeneric {(setf scroll-bar-page-increment)} {scroll-bar}
}

\GadgetOperations {\Callback{drag-callback} {scroll-bar client gadget-id value}

Invoked each time the ``thumb'' of the scroll bar is moved while dragging the
pointer.

\Callback {value-change-callback} {scroll-bar client gadget-id value}

Invoked when a pointer button is pressed a some point in the scroll bar.

All of the following callbacks are invoked when appropriate parts of the
scroll bar are clicked on.  Note that each implementation may not have ``hot
spots'' corresponding to each of these generic operations.

\callback {scroll-to-top-callback} {scroll-bar client gadget-id}
\callback {scroll-to-bottom-callback} {scroll-bar client gadget-id}
\callback {scroll-up-line-callback} {scroll-bar client gadget-id}
\callback {scroll-up-page-callback} {scroll-bar client gadget-id}
\callback {scroll-down-line-callback} {scroll-bar client gadget-id}
\Callback {scroll-down-page-callback} {scroll-bar client gadget-id}
}

\GadgetComments {\cl{value-change-callback} is invoked when the indicator is
released after dragging it.
}


\Gadget {slider}

\GadgetInits {\cl{:orientation}---\cl{:horizontal} or \cl{:vertical}

\cl{:min-value}---number, default 0

\cl{:max-value}---number, default 1

\cl{:show-value-p}---boolean, default NIL.

\cl{:show-value-p} controls whether or not a numeric display corresponding to the slider's
value is visible.
}

\GadgetSMO{
\Defgeneric {slider-orientation} {slider}

Returns the orientation of the slider.

\Defgeneric {(setf slider-orientation)} {orientation slider}

Changes the orientation of the slider to \arg{orientation}.

\Defgeneric {slider-min-value} {slider}

Returns the minimum value of the slider.

\Defgeneric {(setf slider-min-value)} {value slider}

Changes the minimum value of the slider to \arg{value}.

\Defgeneric {slider-max-value} {slider}

Returns the minimum value of the slider.

\Defgeneric {(setf slider-max-value)} {slider}

Changes the maximum value of the slider to \arg{value}.

\Defgeneric {slider-show-value-p} {slider}

\Defgeneric {(setf slider-show-value-p)} {slider}
}

\GadgetOperations {\Callback{drag-callback} {slider client gadget-id value}

Invoked each time the ``thumb'' of the slider is moved while dragging the
pointer.

\Callback {value-change-callback} {slider client gadget-id value}

Invoked when a pointer button is pressed a some point in the slider.
}

\GadgetComments {\cl{value-change-callback} is invoked when the indicator is
released after dragging it.
}


\Gadget {radio-box}

% flat gadget structure for now
%\GadgetSupers {Layout}

\GadgetInits {\cl{:current-selection}}

\GadgetSMO{
\Defgeneric {radio-box-current-selection} {gadget}
\Defgeneric {(setf radio-box-current-selection)} {selection gadget}
}

\GadgetOperations {\Callback{value-change-callback} {radio-box client gadget-id value}

\arg{value} is the newly-selected button gadget.}

\GadgetComments{The radio box enforces selection behavior like car radio
buttons.  Only one of the buttons managed by the radio box may be ``on'' at any
time.  As the current selection changes, the previously selected button and the
newly selected button both have their \cl{value-change-callback} handlers invoked.  The
radio box gadget can manage any other gadget whose gadget-value is constrained
to be a boolean.  At present, only the toggle button satisfies this criterion.
\cl{radio-box-current-selection} is the programmer interface to determining
which of the gadgets is selected.

%The Radio Box inherits from the Layout gadget class.  The same mechanism that is used by
%the Layout class to declare inferiors is used by the Radio Box to declare the set of
%managed buttons.

Note that the radio box is the client of its buttons.}


\Gadget {cascade-button}

%\GadgetSupers{Generic Button}

\GadgetInits {\cl{:menu-group}---a menu group}

\GadgetSMO{
\Defgeneric {cascade-button-menu-group} {gadget}
\Defgeneric {(setf cascade-button-menu-group)} {gadget}
}

%--- What exactly is this for?  What are the specifics of menu groups?  (Currently, they
%--- only have :command or :menu-group in them.  What's the right way to do the
%--- compuserve "One-of" selections?  A "specialization" of cascade-button?

\GadgetOperations {None}

\GadgetComments {When a cascade button is clicked upon, a menu containing its
menu group.

Note that the specific user interface to cascade buttons will differ in each
underlying toolkit.  For example, in some toolkits, merely dragging the mouse
across a cascade button is enough to cause its submenu to become visible.  In
other implementations, the mouse may have to leave the cascade button through a
particular boundary.  In others, a click may be necessary.  }
