% -*- Mode: LaTeX; Package: CLIM-USER -*-

\chapter {Defining New Pane Types}
\label {new-pane-types}

\section {Defining Leaf Panes}

To define a gadget pane implementation, first define the appearance and layout
behavior of the gadget, then define the callbacks, then define the specific user
interactions that trigger the callbacks.

For example, to define an odd new kind of button that displays itself as a
circle, and activates whenever the mouse is moved over it, proceed as follows:

\begin{verbatim}
;; A new kind of button
(defclass sample-button-pane (gadget-pane) ())

;; An arbitrary size parameter
(defparameter *sample-button-radius* 10)

;; Define the sheet's repaint method to draw the button.
(defmethod handle-repaint ((button sample-button-pane) region 
                           &key medium &allow-other-keys)
  (let ((radius *sample-button-radius*)
        (half (round  *sample-button-radius* 2)))
    ;; Larger circle with small one in the center.
    (draw-circle* medium radius radius radius
                  :filled nil)
    (draw-circle* medium radius radius half
                  :filled t)))

;;; Define the pane's compose-space method to always request the
;;; fixed size of the pane.
(defmethod compose-space ((pane sample-button-pane))
  (make-space-requirement :width  (* 2 *sample-button-radius*)
                          :height (* 2 *sample-button-radius*)))
\end{verbatim}

The above code is enough to allow you to instantiate the button pane in an
application frame.  It will fit in with the space composition protocol of, for
example, an \cl{hbox-pane}.  It will display itself as two nested circles.

The next step is to define the callbacks supported by this gadget, and the user
interaction that triggers them.

\begin{verbatim}
;; This default method is defined so that the callback can be invoked
;; on an arbitrary client value without error.
(defmethod value-change-callback
           ((button sample-button-pane) client id value)
  (declare (ignore client id value)))

;; This event processing method defines the rather odd interaction
;; style of this button, to whit: it triggers the activate callback
;; whenever the mouse moves into it.
(defmethod enter-region ((pane sample-button-pane) &key &allow-other-keys)
  (value-change-callback pane (gadget-client pane) (gadget-id pane) nil))
\end{verbatim}


\section {Defining Composite Panes} 

\subsection {Details of the Layout Protocol}
\label {detailed-layout}

The basics of layout protocol as needed by most application developers are
described in Section~\ref{basic-layout}.  That section should be read first.
This details of the layout protocol describe in this section are mostly of
interest to implementors of composite panes.

During the space composition pass, a composite pane will typically ask each of
its children how much space it requires using \cl{compose-space}.  They answer
by returning \cl{space-requirement} objects.  The composite will then form its
own space requirement by composing the space requirements of its children
according to its own rules for laying out its children.

During the space allocation pass, a composite pane will arrange its children
within the available space and allocate space to them according to their space
requirements and its composition rules.

\Defgeneric {compose-space} {pane}

This function is called on a pane to ask for its space requirements.  Methods
for this function must return a space requirement object.

\Defgeneric {allocate-space} {pane width height}

This function is called on a pane to inform it that it has been allocated space
that is \arg{width} by \arg{height}.

\Defgeneric {note-space-requirements-changed} {sheet pane}

This function should be invoked whenever \arg{pane}'s space requirements have
changed.  \arg{sheet} must be the parent of \arg{pane}.  Invoking this function
essentially means that \arg{compose-space} will be reinvoked on \arg{pane}, then
it will reply with a space requirement that is not equal to the reply that was
given on the last call to \arg{compose-space}.

This function is automatically invoked by \cl{change-space-requirements} in the
cases that \cl{layout-frame} isn't invoked.  In the case that \cl{layout-frame}
is invoked, it isn't necessary to call \cl{note-space-requirements-changed}
since a complete relayout of the frame will be executed.

\Defun {make-space-requirement} {\key (width \cl{0}) (max-width \cl{0}) (min-width \cl{0})
				      (height \cl{0}) (max-height \cl{0}) (min-height \cl{0})}

Constructs a space requirement object with the given characteristics, \cl{:width},
\cl{:height}, and so on.

\defun {space-requirement-width}             {space-req}
\defun {(setf space-requirement-width)}      {size space-req}
\defun {space-requirement-max-width}         {space-req}
\defun {(setf space-requirement-max-width)}  {size space-req}
\defun {space-requirement-min-width}         {space-req}
\defun {(setf space-requirement-min-width)}  {size space-req}
\defun {space-requirement-height}            {space-req}
\defun {(setf space-requirement-height)}     {size space-req}
\defun {space-requirement-max-height}        {space-req}
\defun {(setf space-requirement-max-height)} {size space-req}
\defun {space-requirement-min-height}        {space-req}
\Defun {(setf space-requirement-min-height)} {size space-req}

These functions read or modify the components of the space requirement
\arg{space-req}.
