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

\chapter {Application Frames}
\label {application-frames}

\issue {SWM} {Integrate the CLIM 0.9 stuff, but try to address the issues that
DCPL raises and all of the stuff in the mail as well.}

\issue {DCPL} {The Silica-based macrology for defining panes and layouts doesn't
easily allow, if it allows at all, for sharing panes between multiple layouts.
CLIM 1.0 seems to have this capability, but the syntax for the constraints is a
bit baroque.  Perhaps there just isn't a good one, since in all these years
we've never found it.  Another way to say all of this is that the functional
aspects of frames (panes and streams) needs to be separated from the layout
description.}

\issue {DCPL} {We need to decide how much of the pane, stream and layout
functionality we want to present in the API and/or SPEC, and how to present it.
For example, CLIM 0.9's \cl{frame-pane} isn't conceptually elegant because that
is how you get the current layout, and the layout is a pane, and you have to
know that.  Better is \cl{frame-current-layout} and then have layout-XXX
functions to interrogate the layout.  I think CLIM 1.0 does better here.}

\issue {DCPL} {CLIM 0.9's method of having panes names be slot names is poor
because it is implicit, and problematic because it uses \cl{slot-unbound}, which
while it may work, shoots up a red flag.  DW and presumably CLIM 1.0 have ways
to ask for the pane names and ways to retrieve a pane from a frame given its
name.  I think this is the right model.  The tricky thing, which Silica may
allow and that we probably want to preserve if possible, is for a named pane to
have another named pane as one of its descendants.  Also have a named pane have
a named stream as one of its descendants (in the event we have streams that
aren't panes).  This is important for viewport panes pointing at streams.}

\issue {DCPL} {The concept of a frame manager is an important one, as it is the
entity that bridges the gap between the application and the host windowing
system.}

\issue {DCPL} {The concept of server paths from CLIM 0.9 is superior to the
explicit \cl{open-root-window} paradigm of CLIM 1.0.  CLIM 0.9 has some problems
in this regard, but I have some saved mail from an ILA conversation a while that
goes a long way toward removing those problems.}


\section {Overview}

\concept{Application frames} (or simply, \concept{frames}) are the central
abstraction defined by CLIM for presenting an application's user interface.
Many of the other features and facilities provided by CLIM (for example, the
generic command loop, gadgets, look and feel independence) can be conveniently
accessed through the frame facility.  Frames can be displayed as either
top-level windows or regions embedded within the space of the user interfaces of
other applications.  In addition to controlling the screen real estate managed
by an application, a frame keeps track of the Lisp state variables that contain
the state of the application.

The contents of frame is established by defining a hierarchy of \concept{panes}.
CLIM panes are interactive objects that are analogous to the gadgets or widgets
of other toolkits.  Applications builders can compose their application's user
interface from a library of standard panes or by defining and using their own
pane types.  Application frame can use a number of different types of panes
including \concept{layout panes} for spatially organizing panes, \concept{user
panes} for presenting application specific information, and \concept{abstract
gadget panes} for displaying data and obtaining user input.  Panes are describe
in greater detail in Chapter~\ref{panes}.

Frames are managed by special applications called \concept{frame managers}.
Frame managers control the realization of the look and feel of a frame.  The
frame manager interprets the specification of the application frame in the
context of the available window system facilities, taking into account
preferences expressed by the user.  In addition, the frame manager takes care of
attaching the pane hierarchy of an application frame to an appropriate place in
a window hierarchy.  The most common type of frame manager is one that allows
the user to manipulate the frames of other applications.  This type of
application is typically called a desktop manager, or in X Windows terminology,
a window manager.  In many cases, the window manager will be a non-lisp
application.  In these cases, the frame manager will act as a mediator between
the lisp application and the host desktop manager.

Some applications may act as frame managers that allow the frames of other
applications to be displayed with their own frames.  For example, a text editor
might allow figures generated by a graphic editor to be edited in place by
managing the graphics editor's frame within its own frame.

Application frames provide support for a standard interaction processing loop,
like the Lisp ``read-eval-print'' loop, called a \concept{command loop}.  The
application programmer has to write only the code that implements the
frame-specific commands and output display functions.  A key aspect of the
command loop is the separation of the specification of the frame's commands from
the specification of the end-user interaction style.

The standard interaction loop consists of reading an input ``sentence'' (the
command and all of its operands), executing the command, and updating the
displayed information as appropriate.  CLIM implementations are free to run the
display update part of the loop at a lower priority than command execution, for
example, some implementations may choose not to update the display if there is
typed-ahead input.  Also, command execution and display will not occur
simultaneously, so user-defined functions need not have to cope with
multiprocessing.

To write an application that uses the standard interaction loop provided by
CLIM, an application programmer does the following:

\begin{itemize}
\item Defines the presentation types that are specific to the application.

\item Defines the application frame's commands, specifying the presentation
types of the operands involved in each command.

\item Defines the set of frames needed to support the application.

\item Defines the output display functions associated with the frames (possibly
using other facilities such as the incremental redisplay).
\end{itemize}

Taking as an example a simple ECAD program, the programmer would first define
the appropriate presentation types, such as wires, input and output signals,
gates, resistors, and so forth.  He would then define the program's commands in
terms of these types.  For example, the ``Connect'' command might take two
operands, one of type ``component'' and the other of type ``wire''.  The
programmer may wish to specify the interaction style for invoking each command,
for example, direct manipulation via translators, or selection of commands from
menus.  After defining an application frame that includes a CLIM stream pane,
the programmer then writes the frame-specific display routine that displays the
circuit layout.  Now the application is ready to go.  The end-user selects a
command (via a menu or command-line, or whatever), the top-level loop takes care
of collecting the operands for that command (again, via a variety of user
gestures), and then the application invokes the command.  The command may have a
side-effect on the frame's ``database'' of information, which can in turn affect
the output displayed by the redisplay phase.

Note that this definition of the standard interaction loop does not constrain
the interaction style to be a command-line interface.  The input sentence may be
entered via single keystrokes, pointer input, menu selection, or by typing full
command lines.


\section {Defining and Creating Application Frames}

\Defprotoclass {application-frame}

The protocol class that corresponds to an application frame.
\IfYouWantClass {an} {application frame} {application-frame}

All application frame classes are mutable.

\Defun {application-frame-p} {object}

Returns \term{true} if \arg{object} is an \term{application frame}, otherwise
returns \term{false}.

\definitarg {:name}
\definitarg {:pretty-name}
\definitarg {:panes}
\definitarg {:command-table}
\Definitarg {:disabled-commands}

All subclasses of \cl{application-frame} must handle these initargs, which are
used to specify, respectively, the name, pretty name, sequence of panes, command
table, and initial set of disabled commands for the frame.

\Defclass {standard-application-frame}

The standard class that implements application frames.  By default, most
application frame classes will inherit from this class, unless a non-\cl{nil}
value for \arg{superclasses} is supplied to \cl{define-application-frame}.


\Defmacro {define-application-frame} {name superclasses slots \rest options}

Defines a frame and CLOS class named by the symbol \arg{name} that inherits from
\arg{superclasses} and has state variables specified by \arg{slots}.
\arg{superclasses} is a list of superclasses that the new class will inherit
from (as in \cl{defclass}).  When \arg{superclasses} is \cl{nil}, it behaves as
though a superclass of \cl{standard-application-frame} was supplied.
\arg{slots} is a list of additional slot specifiers, as in \cl{defclass}.  Each
instance of the frame will have slots as specified by these slot specifiers.
These slots will typically hold any per-instance frame state.

\arg{options} is a list of \cl{defclass}-style options, and can include the
usual \cl{defclass} options \cl{defclass}, plus any of the following:

\begin{itemize}
\item \cl{:pane} \arg{form}, where \arg{form} specifies the single pane in the
application.  There is no default for this option.  This is the simplest way to
define a pane hierarchy.  The \cl{:pane} and \cl{:panes} options are mutually
exclusive.  See below for a complete description of the \cl{:pane} option.

\item \cl{:panes} \arg{form}, where \arg{form} specifies the panes of the
application.  There is no default for this option.  The \cl{:pane} and
\cl{:panes} options are mutually exclusive.  See below for a complete
description of the \cl{:panes} option.

\item \cl{:layout} \arg{form}, where \arg{form} specifies the layout.  The
default layout is to lay the panes out in horizontal strips.  See below for a
complete description of the \cl{:layout} option.

\item \cl{:command-table} \arg{name-and-options}, where
\arg{name-and-options} is a list consisting of the name of the application
frame's command table followed by some keyword-value pairs.  The keywords can be
\arg{inherit-from} or \arg{menu} (which are as in \cl{define-command-table}).
The default is to create a command table with the same name as the application
frame.

\item \cl{:command-definer} \arg{value}, where \arg{value} either \cl{nil},
\cl{t}, or another symbol.  When it is \cl{nil}, no command-defining macro is
defined.  When it is \cl{t}, a command-defining macro is defined, whose name is
of the form \cl{define-{\it name}-command}.  When it is another symbol, the
symbol names the command-defining macro.  The default is \cl{t}.

\item \cl{:disabled-commands} \arg{commands}, where \arg{commands} is a list
of command names that are initially disabled in the application frame.

\item \cl{:command-menu} \arg{command-table} specifies a set of commands that
the user can directly invoke from the frame in some frame manager specific way,
such as a menu bar on a Macintosh.  In other words, it specifies the top-level
commands of the application.  \arg{command-table} is the command table whose
menu will be used in the ``menu bar''.  If defaults to the command table for the
application.

\item \cl{:top-level} \arg{form}, where \arg{form} is a list whose first
element is the name of a function to be called to execute the top-level loop.
The function must take at least one argument, the frame.  The rest of the list
consists of additional arguments to be passed to the function.  The default
function is \cl{default-frame-top-level}.

\item \cl{:resize-frame} \arg{resize-p}, where if \arg{resize-p} is \term{true},
this indicates that the frame is willing to be resized when panes in its current
hierarchy change their space requirements or when a new hierarchy is selected by
changing the frame's current layout.
\end{itemize}

\issue {SWM} {Explain what gets evaluated when.}

\issue {SWM} {What does \cl{:layout} look like?  TeX-like?  Genera constraint
frames?} 

The value of the \cl{:panes} option is a list of pane descriptions.  Each pane
descriptions is a cons consisting of a pane name (which is a symbol), a pane
type, and a list of keyword-value pairs.

The pane options usable by all panes types are:

\begin{itemize}
\item \cl{:default-text-style} \arg{text-style}.

\item \cl{:scroll-bars} \arg{scroll-bar-spec}.

\item \cl{:default-size} \arg{size-spec}.

\item \cl{:display-function} \arg{display-spec}, where \arg{display-spec} is
a list whose first element is the name of a function to be applied to the
application frame, the pane, and the rest of \arg{display-spec}.  Two predefined
display functions are \cl{display-command-menu} (in which case a typical
display-spec would be \cl{`(display-command-menu ,\arg{command-table})}), and
\cl{incremental-redisplay-display-function} (in which case a typical
display-spec would be \cl{'(incremental-redisplay-display-function
\arg{display-function})}).

\item \cl{:display-time} \arg{time} controls when the pane's displayer function
is called.  When \arg{time} is \cl{nil}, the pane's displayer is not called.
When \arg{time} is \cl{t}, the displayer is called the ``next time'', and then
the display time is set to \cl{nil}.  When \arg{time} is \cl{:command-loop}, the
displayer is run each time around the application frame's command loop.
\end{itemize}

When a pane uses incremental redisplay (via
\cl{incremental-redisplay-display-function}), CLIM supplies the outermost call
to \cl{updating-output}, saves the incremental redisplay record, and calls
\cl{redisplay}.  The function that does the output performs only the nested
calls to \cl{updating-output}.  If an application pane uses incremental
redisplay without using the \cl{incremental-redisplay-display-function}, it must
perform the outermost call to \cl{updating-output}, save the incremental
redisplay record, and call \cl{redisplay} itself.

\issue {SWM} {\cl{:panes} is wrong, get the real scoop from Dennis or Bill.
Their description is that the \cl{:panes} option is used to define multiple
named top-level panes.  Its format is a list of two element lists.  The first
element of each sublist is a symbol naming the layout.  The second element is a
form that evaluates to a pane.  Using \cl{setf} on \cl{frame-current-layout} can
be used to switch between the defined layouts.  The \cl{generate-pane} method
supplied will also take into account the current frame layout though it will use
the first layout as a default.}

\issue {SWM} {ILA seems to have flushed pane types altogether and hand all of
that stuff to the \cl{:display-function} and \cl{:display-time}?  Not a bad
idea.  On the other hand, it's nice to be able to specify a name for a canned
set of pane options instead of specifying the options individually.}

\issue {SWM} {What are the defaults for the pane options?}

\Defmacro {with-application-frame} {(frame) \body body}

This macro provides lexical access to the ``current'' frame for use with the
\cl{:pane}, \cl{:panes}, and \cl{:layout} options.  \arg{frame} is bound to the
current frame within the context of one of those options.  \arg{body} may have
zero or more declarations as its first forms.

\Defun {make-application-frame} {frame-type \rest options
                                 \key frame-manager enable shrink state 
                                      left top right bottom width height
                                 \allow} 

Makes an instance of the application frame of type \arg{frame-type}.
\arg{options} are passed as additional arguments to \cl{make-instance}, after
the frame manager and sizing options have been removed.

\arg{left}, \arg{top}, \arg{right}, \arg{bottom}, \arg{width}, and \arg{height}
can be used to specify the size of the frame.

If \arg{frame-manager} is provided, then the frame is adopted by the specified
frame manager.  If the frame is adopted and any of \arg{enable}, \arg{shrink},
or \arg{state} are provided, the frame is pushed into the given state.

\issue {SWM} {Are there standard options, such as what display to put the window
on?}

\issue {SWM} {What is the documented interface for selecting/exposing the frame?
Should there be a way to find-or-create a frame for a given application?  Or is
that too much into the window-manager field?}


\Defvar {*application-frame*}

The current application frame.  The global value is CLIM's default application,
which serves only as a repository for whatever internal state needed by CLIM to
operate properly.  This variable is typically used in the bodies of command to
gain access to the state variables of the application frame, usually in
conjunction with \cl{with-slots} or \cl{slot-value}.


\section {The Application Frame Protocol}

The generic functions described in this section describe the application frame
protocol.  All classes that inherit from \cl{application-frame} must inherit or
implement methods for all of these functions.

\Defgeneric {frame-name} {frame}

Returns the name of the \term{frame} \arg{frame}, which is a symbol.

\Defgeneric {(setf frame-name)} {new-name frame}

Sets the name of the \term{frame} \arg{frame} to \arg{new-name}, which must be a
symbol.


\Defgeneric {frame-pretty-name} {frame}

Returns the ``pretty name'' of the \term{frame} \arg{frame}, which is a string.

\Defgeneric {(setf frame-pretty-name)} {new-name frame}

Sets the pretty name of the \term{frame} \arg{frame} to \arg{new-name}, which
must be a string.


\Defgeneric {frame-command-table} {frame}

Returns the command table for the \term{frame} \arg{frame}.

\Defgeneric {(setf frame-command-table)} {command-table frame}

Sets the command table for the \term{frame} \arg{frame} to \arg{command-table}.
Changing the frame's command table will redisplay the command menus (or menu
bar) as needed.  \arg{command-table} is a \term{command table designator}.


\Defgeneric {frame-standard-output} {frame}

Returns the stream that will be used for \cl{*standard-output*} for the
\term{frame} \arg{frame}.  The default method (on \cl{standard-application-frame})
returns the first pane of type \cl{:application} that is exposed in the current
layout; if there is no such \cl{:application} pane, it returns the first pane of
type \cl{:interactor} that is exposed in the current layout.

\Defgeneric {frame-standard-input} {frame}

Returns the stream that will be used for \cl{*standard-input*} for the
\term{frame} \arg{frame}.  The default method (on \cl{standard-application-frame})
returns the first pane of type \cl{:interactor} that is exposed in the current
layout; if there is no \cl{:interactor} pane, the value returned by
{frame-standard-output} is used.

\Defgeneric {frame-query-io} {frame}

Returns the stream that will be used for \cl{*query-io*} for the \term{frame}
\arg{frame}.  The default method (on \cl{standard-application-frame}) returns
the value returned by \cl{frame-standard-input}; if that is \cl{nil}, it returns
the value returned by \cl{frame-standard-output}.

\Defgeneric {frame-error-output} {frame}

Returns the stream that will be used for \cl{*error-output*} for the
\term{frame} \arg{frame}.  The default method (on \cl{standard-application-frame})
returns the same value as \cl{frame-standard-output}.

\issue {SWM} {How can the above four functions find a meaningful pane given the
Silica model of describing frame panes?}

\Defvar {*pointer-documentation-output*}

This will be bound either to \cl{nil} or to a stream to which pointer
documentation should be written.

\Defgeneric {frame-pointer-documentation-output} {frame}

Returns the stream that will be used for \cl{*pointer-documentation-output*}
for the \term{frame} \arg{frame}.  If this returns \cl{nil}, no pointer
documentation will be generated for this frame.


\Defgeneric {frame-top-level-sheet} {frame}

Returns the sheet that is the top-level sheet for the \term{frame} \arg{frame}.
This is the sheet that has as descendents all of the panes of \arg{frame}.

\Defgeneric {frame-panes} {frame}

Returns a list of all of the \term{frame} \arg{frame}'s named panes.  This
includes panes in the current layout, and panes in other layouts as well.
\ReadOnly

\Defgeneric {frame-current-panes} {frame}

Returns a list of those named panes in the \term{frame} \arg{frame}'s current
layout.
\ReadOnly

\Defgeneric {get-frame-pane} {frame pane-name}

Returns the named pane in the \term{frame} \arg{frame} whose name is
\arg{pane-name}.

\Defgeneric {frame-current-layout} {frame}

Returns the current layout for the \term{frame} \arg{frame}.  The layout is
named by a symbol.

\Defgeneric {(setf frame-current-layout)} {new-layout frame}

Sets the layout of the \term{frame} \arg{frame} to be the new layout specified
by \arg{new-layout}.  \arg{new-layout} must be a symbol that names one of the
possible layouts.

Changing the layout of the frame must recompute what panes are used for the
bindings of the standard stream variables (such as \cl{*standard-input*}).  Some
implementations of CLIM may cause the application to ``throw'' all the way back
to \cl{run-frame-top-level} in order to do this.  After the new layout has been
made computed, the contents of each of the panes must be displayed to the degree
necessary to ensure that all output is visible.

\Defgeneric {layout-frame-panes} {frame top-level-sheet}

Lays out all of the panes in the \term{frame} \arg{frame} using the sheet
\arg{top-level-sheet} as the parent sheet of the frame's panes.  The panes are
layed out according to the layout specified by \cl{frame-current-layout}.


\Defrestart {frame-exit}

The restart that is invoked when \cl{frame-exit} is called.

\Defgeneric {frame-exit} {frame}

Exits from the \term{frame} \arg{frame}.  The default method (on
\cl{standard-application-frame}) invokes the \cl{frame-exit} restart.


\defgeneric {panes-need-redisplay} {frame}
\Defgeneric {pane-needs-redisplay} {frame pane}

\cl{panes-need-redisplay} causes all of the panes in the \term{frame}
\arg{frame} to be redisplayed the next time around the command loop.
\cl{pane-needs-redisplay} causes only \arg{pane} within \arg{frame} to be
redisplayed the next time around the command loop; in this case, \arg{pane} is
either a pane or the name of a named pane.

\Defgeneric {redisplay-frame-panes} {frame \key force-p}

\cl{redisplay-frame-panes} causes all of the panes in the \term{frame}
\arg{frame} to be redisplayed immediately by calling \cl{redisplay-frame-pane}
on each of the panes in \arg{frame} that are visible in the current layout.
When the boolean \arg{force-p} is \term{true}, the maximum level of redisplay is
forced.

\Defgeneric {redisplay-frame-pane} {frame pane \key force-p}

Causes the pane \arg{pane} within the \term{frame} \arg{frame} to be redisplayed
immediately.  \arg{pane} is either a pane or the name of a named pane.  When the
boolean \arg{force-p} is \term{true}, the maximum level of redisplay is forced.


\Defgeneric {frame-replay} {frame stream \optional region} 

Replays the contents of \arg{stream} in the \term{frame} \arg{frame} within the
region specified by the region \arg{region}, which defaults to viewport of
\arg{stream}.


\Defgeneric {redisplay-frame-command-menu} {frame}

When a command table gets modified (by adding or removing a command, or adding
or removing a menu item, or by enabling or disabling a command), the command
menus for application frames may need to be redisplayed.
\cl{redisplay-frame-command-menu} is responsible for doing this.


\Defgeneric {notify-user} {frame format-string \rest format-args}

Notifies the user of some event on behalf of the \term{frame} \arg{frame}.
\arg{format-string} and \arg{format-args} are arguments allowable by
\cl{format}.

This function is intended to provide a look and feel independent way for
applications to communicate messages to the user.  For example, a frame manager
might provide a top-level message window or a message window for each frame, or
might pop up an alert box.


\subsection {Interface with Presentation Types}

All classes that inherit from \cl{application-frame} must inherit or implement
methods for all of these functions.

\Defgeneric {frame-maintain-presentation-histories} {frame}

Returns \term{true} if the \term{frame} \arg{frame} maintains histories for its
presentations, otherwise returns \term{false}.  The default method (on
\cl{standard-application-frame}) returns \term{true} if and only if the frame
has at least one interactor pane.


\Defgeneric {frame-find-innermost-applicable-presentation} {frame input-context stream x y}

Locates and returns the innermost applicable presentation on the window
\arg{stream} whose sensitivity region contains the point indicated by \arg{x}
and \arg{y}, on behalf of the \term{frame} \arg{frame} in the input context
\arg{input-context}.

The default method (on \cl{standard-application-frame}) will simply call
\cl{find-innermost-applicable-presentation}.

\Defgeneric {frame-input-context-button-press-handler} {frame stream button-press-event}

This function is responsible for handling user pointer events on behalf of the
\term{frame} \arg{frame}.  \arg{stream} is the window on which
\arg{button-press-event} took place.

The default implementation (on \cl{standard-application-frame}) unhighlight any
highlighted presentations, find the applicable presentation with
\cl{frame-find-innermost-applicable-presentation-at-position}, and then call
\cl{throw-highlighted-presentation} to execute the translator that corresponds
to the user's gesture.

\Defgeneric {frame-document-highlighted-presentation} {frame presentation input-context window x y stream}

This function is responsible for producing pointer documentation on behalf of
the \term{frame} \arg{frame}.  The default method (on
\cl{standard-application-frame}) should produce documentation that corresponds
to calling \cl{document-presentation-translator} on all of the applicable
translators in the input context \arg{input-context}.  \arg{presentation},
\arg{window}, \arg{x}, \arg{y}, and \arg{stream} are as for
\cl{document-presentation-translator}.


\Defgeneric {frame-click-and-drag-feedback} {frame presentation stream
                                             initial-x initial-y new-x new-y state} 

The default feedback function for translators defined by
\cl{define-click-and-drag-translator}, which provides visual feedback during the
``dragging'' phase of such translators on behalf of the \term{frame}
\arg{frame}.  \arg{presentation} is the presentation being dragged on the stream
\arg{stream}.  The pointing device was initially at the position specified by
\arg{initial-x} and \arg{initial-y}, and is at the position specified by
\arg{new-x} and \arg{new-y} when \cl{frame-click-and-drag-feedback} is invoked.
(Both position are supplied for rubber-banding, if that is the sort of desired
feedback.)  \arg{state} will be either \cl{:highlight}, meaning that the
feedback should be drawn, or \cl{:unhighlight}, meaning that the feedback should
be erased.

\Defgeneric {frame-click-and-drag-highlighting} {frame presentation stream state}

The default highlighting function for translators defined by
\cl{define-click-and-drag-translator}, which is invoked when a ``to object''
should be highlighted during the ``dragging'' phase of such translators on
behalf of the \term{frame} \arg{frame}.  \arg{presentation} is the presentation
over which the pointing device is located on the stream \arg{stream}.
\arg{state} will be either \cl{:highlight}, meaning that the highlighting for
the presentation should be drawn, or \cl{:unhighlight}, meaning that the
highlighting should be erased.


\subsection {The Generic Command Loop}

The default application command loop provided by CLIM performs the following
steps:

\begin{enumerate}
\item Prompts the user for input.

\item Reads a command.  Each application frame has a command table that contains
those commands that the author of the application wishes to allow the user to
invoke at a given time.  Commands may be read in any number of ways.  The
generic command loop enforces no particular interface style.

\item Executes the command.  The definition of each command may refer to (and
update) the state variables of the frame, to which \cl{*application-frame*} will
be bound.

\item Runs the display function for each pane in the frame.  The display function
may refer to the frame's state variables.  Display functions are usually written
by the application writer, although certain display functions are supplied by
CLIM itself.  Note that an application frame is free to have no panes.
\end{enumerate}


\issue {SWM} {RWK has a reasonable proposal for breaking down command loops into
their component pieces.  It should be integrated here.}

All classes that inherit from \cl{application-frame} must inherit or implement
methods for all of these functions.


\Defgeneric {run-frame-top-level} {frame}

Runs the top-level function for the \term{frame} \arg{frame}.  The default
method on \cl{application-frame} simply invokes the top-level function for the
frame (which defaults to \cl{default-frame-top-level}).

\Defaroundmethod {run-frame-top-level} {(frame \cl{application-frame})}

The \cl{:around} method of \cl{run-frame-top-level} on the
\cl{application-frame} class is responsible for binding \cl{*application-frame*}
to \arg{frame}.


\Defgeneric {default-frame-top-level} {frame \key command-parser command-unparser 
                                                  partial-command-parser
                                                  prompt}

The default top-level function for application frames.  This function implements
a ``read-eval-print'' loop that displays a prompt, calls
\cl{read-frame-command}, then calls \cl{execute-frame-command}, and finally
redisplays all of the panes that need to be redisplayed.

\cl{default-frame-top-level} will also establish a simple restart for
\cl{abort}, and bind the standard stream variables as follows.
\cl{*standard-input*} will be bound to the value returned by
\cl{frame-standard-input}.  \cl{*standard-output*} will be bound to the value
returned by \cl{frame-standard-output}.  \cl{*query-io*} will be bound to the
value returned by \cl{frame-query-io}.  \cl{*error-output*} will be bound to the
value returned by \cl{frame-error-output}.  It is unspecified what
\cl{*debug-io*} will be bound to.

\arg{prompt} is either a string to use as the prompt (defaulting to
\cl{"Command: "}, or a function of two arguments (a stream and the frame).

\arg{command-parser}, \arg{command-unparser}, and \arg{partial-command-parser}
are the same as for \cl{read-command}.  \arg{command-parser} defaults to
\cl{command-line-command-parser} if there is an interactor, otherwise it
defaults to \cl{menu-only-command-parser}.  \arg{command-unparser} defaults to
\cl{command-line-command-unparser}.  \arg{partial-command-parser} defaults to
\cl{command-line-read-remaining-arguments-for-partial-command} if there is an
interactor, otherwise it defaults to
\cl{menu-only-read-remaining-arguments-for-partial-command}.


\Defgeneric {read-frame-command} {frame stream}

Reads a command from the stream \arg{stream} on behalf of the \term{frame}
\arg{frame}.  The returned value is a command object.

The default method (on \cl{standard-application-frame}) for
\cl{read-frame-command} simply calls \cl{read-command}, supplying \arg{frame}'s
current command table as the command table.

\Defgeneric {execute-frame-command} {frame command}

Executes the command \arg{command} on behalf of the \term{frame} \arg{frame}.
\arg{command} is a command object, that is, a cons of a command name and a list
of the command's arguments.

The default method (on \cl{standard-application-frame}) for
\cl{execute-frame-command} simply applies the \cl{command-name} of \arg{command}
to \cl{command-arguments} of \arg{command}.


\Defgeneric {command-enabled} {command-name frame}

Returns \term{true} if the command named by \arg{command-name} is presently
enabled in the \term{frame} \arg{frame}, otherwise returns \term{false}.  If
\arg{command-name} is not accessible to the command table being used by
\arg{frame}, \cl{command-enabled} returns \term{false}.

Whether or not a particular command is currently enabled is stored independently
for each instance of an application frame; this status can vary between frames
that share a single command table.

\Defgeneric {(setf command-enabled)} {enabled command-name frame}

If \arg{enabled} is \term{false}, this disables the use of the command named by
\arg{command-name} while in the \term{frame} \arg{frame}.  Otherwise if
\arg{enabled} is \term{true}, the use of the command is enabled.  After the
command has been enabled (or disabled), \cl{note-command-enabled} is invoked on
the frame manager in order to update the appearance of the interface.

If \arg{command-name} is not accessible to the command table being used by
\arg{frame}, using \cl{setf} on \cl{command-enabled} does nothing.


\Defgeneric {display-command-menu} {frame stream
                                    \key command-table initial-spacing
                                         max-width max-height n-rows n-columns
                                         (cell-align-x \cl{:left}) (cell-align-y \cl{:top})}

Displays the menu associated with the specified command table on \arg{stream} by
calling \cl{display-command-table-menu}.  If \arg{command-table} is not
supplied, it defaults to \cl{(frame-command-table \arg{stream})}.  This function
is generally used as the display function for panes that contain command menus.

\arg{initial-spacing}, \arg{max-width}, \arg{max-height}, \arg{n-rows}, \arg{n-columns},
\arg{cell-align-x}, and \arg{cell-align-y} are as for \cl{formatting-item-list}.


\section {Window Viewport Management}

The \concept{viewport} of a window is the area of the window's drawing plane
that is currently visible in the window.

\issue {SWM} {Where does this discussion of viewports really belong?}

\Defgeneric {window-clear} {window}

Clears the entire drawing plane by filling it with the background design of the
window stream \arg{window}.  If \arg{window} has an output history, that is
cleared as well.  The text cursor position of \arg{window}, if there is one, is
reset to the upper left corner.

\Defgeneric {window-refresh} {window}

Clears the visible part of the drawing plane of \arg{window}, and then if the
window stream is an output recording stream, the output records in the visible
part of the window are replayed.

\Defgeneric {window-viewport} {window}

Returns the viewport of \arg{window}, which is an object of type \cl{area}.
Usually the viewport will be a \cl{standard-rectangle}.

\Defgeneric {window-erase-viewport} {window}

Clears the visible part of the drawing plane of \arg{window} by filling it with
the background design.

\Defgeneric {window-viewport-position*} {window}

Returns two values, the $x$ and $y$ position of the top-left corner of
\arg{window}'s viewport.

\Defgeneric {(setf window-viewport-position*)} {x y window}

Sets the position of \arg{window}'s viewport to \arg{x} and \arg{y}.


\section {Frame Managers}

Frames may be \concept{adopted} by a frame manager, which involves invoking a
protocol for generating the pane hierarchy of the frame.  This protocol provides
for selecting pane types for abstract gadget panes based on the style
requirements imposed by the frame manager.  That is, the frame manager is
responsible for the ``look and feel'' of a frame.

After a frame is adopted it can be in any of the three following states:
\concept{enabled}, \concept{disabled}, or \concept{shrunk}.  An enabled frame is
visible unless it is occluded by other frames or the user is browsing outside of
the portion of the frame manager's space that the frame occupies.  A shrunken
frame provides a cue or handle for the frame, but generally will not show the
entire contents of the frame.  For example, the frame may be iconified or an
item for the frame may be placed in a special suspended frame menu.  A disabled
frame is not visible, nor is there any user accessible handle for enabling the
frame.

Frames may also be disowned, which involves releasing the frame's panes as well
as all associated foreign resources.


\subsection {Finding Frame Managers}

Most frames need only deal directly with frame managers to the extent that they
need to find a frame manager into which they can insert themselves.  Since
frames will usually be invoked by some user action that is handled by some frame
manager, finding an appropriate frame manager is usually straightforward.

Some frames will support the embedding of other frames within themselves.  Such
frames would not only use frames but also act as frame managers, so that other
frames could insert frames.  In this case, the embedded frames are mostly
unaware that they are nested within other frames, but only know that they are
controlled by a particular frame manager.  Writing frames that support embedding
is described more in the section on Frame Manager Protocols.

The \cl{find-frame-manager} function provides a flexible means for locating an
frame manager to adopt an application's frames into.  There are a variety of
ways that the user or the application can influence where an application's frame
is adopted.

An application can establish an application default frame manager using
\cl{with-frame-manager}.  A frame's top-level loop automatically establishes the
frame's frame manager.

The programmer or user can influence what frame manager is found by setting
\cl{*default-frame-manager*} or \cl{*default-server-path*}.

Each frame manager is associated with one specific port.  However, a single port
may have multiple frame managers managing various frames associated with the
port.


\Defun {find-frame-manager} {\key where}

Finds an appropriate frame manager that conforms to the values of a number of
parameters including the \arg{where} argument, special dynamic contexts
established by the application or CLIM on the application's behalf, and global
variables established by the programmer or user.

The value of the \arg{where} option can be a port or a server path or \cl{nil},
which is its default.  This value is used to screen candidate frame managers to
ensure that they are associated with the correct port.  A frame manager is found
using the following rules in the order listed:

\begin{enumerate}
\item If a current frame manager has been established via an invocation of
\cl{with-frame-manager}, as is the case within a frame's top-level, and that
frame manager conforms to \arg{where}, it is returned.  Any frame managers
conforms if \arg{where} is \cl{nil}.

\item If \cl{*default-frame-manager*} is bound to a currently active frame
manager and it conforms to \arg{where}, it is returned.

\item If \arg{where} is a port, then a frame manager that conforms to the
default look and feel of the port is found or constructed and returned.

\item If \arg{where} is a server path, then a port is found for that server, and
then a frame manager that conforms the default look and feel of the port is
found or constructed and returned.

\item If \arg{where} is \cl{nil}, a port is found and an appropriate
frame manager is constructed using \cl{*default-server-path*}.
\end{enumerate}


\Defvar {*default-frame-manager*}

This variable provides a convenient point for allowing a programmer or user to
override what frame manager type would normally be selected.  Most users will
not set this variable since they can set \cl{*default-server-path*} to indicate
which host window system they want to use and are willing to use whatever frame
manager is the default for the particular port.  However, some users may want to
use a frame manager that isn't the typical frame manager.  For example, a user
may want to use both an Open Look frame manager and a Motif frame manager on a
single port.

\Defmacro {with-frame-manager} {(frame-manager) \body body}

Generates a dynamic context that causes all calls to \cl{find-frame-manager} to
return \arg{frame-manager} if the \arg{where} argument passed to it conforms to
\arg{frame-manager}.  Nested calls to \cl{with-frame-manager} will shadow outer
contexts.  \arg{body} may have zero or more declarations as its first forms.


\subsection {Frame Manager Operations}

\Defgeneric {frame-manager} {frame} 

Returns the current frame manager of \arg{frame} if it is adopted, otherwise
returns \cl{nil}.

\Defgeneric {(setf frame-manager)} {manager frame}

Changes the frame manager of \arg{frame} to \arg{manager}.  Effectively, the
frame is disowned from its old frame manager and is adopted into the new frame
manager.  Transferring a frame preserves its \cl{frame-state}, for example, if
the frame was previously enabled it will be enabled in the new frame manager.


\Defgeneric {frame-state} {frame}

Returns one of \cl{:disowned}, \cl{:enabled}, \cl{:disabled}, or \cl{:shrunk}
indicating the current state of frame.


\defgeneric {adopt-frame} {frame-manager frame}
\Defgeneric {disown-frame} {frame-manager frame} 

These functions insert or remove a frame from a frame manager's control.  These
functions allow a frame manager to allocate and deallocate resources associated
with a frame.  For example, removing a frame from a frame manager that is
talking to a remote server allows it to release all remote resources used by the
frame.


\defgeneric {frame-pane} {frame}
\Defgeneric {pane-frame} {pane}

These functions return the pane of the frame and the frame of the pane,
respectively.  \cl{pane-frame} can be invoked on any pane in a frame's pane
hierarchy, not just its single root pane.


\defgeneric {enable-frame} {frame}
\defgeneric {disable-frame} {frame}
\Defgeneric {shrink-frame} {frame}

These functions force a frame into the enabled, disabled, or shrunken states.  A
frame in the enabled state may be visible if it is not occluded or placed out of
the user's focus of attention.  A disabled frame is never visible.  A shrunk
frame is accessible to the user for re-enabling, but may be represented in some
abbreviated form, such as an icon or a menu item.


\Defgeneric {generate-panes} {frame frame-manager}

This function is invoked by a standard method of \cl{adopt-frame}.  It is the
responsibility of the frame implementor to provide a method that invokes
\cl{setf} of \cl{frame-pane} on the frame with a value of type \cl{pane}.
\cl{define-application-frame} automatically supplies a \cl{generate-panes}
method if the \cl{:panes} option is used.

\Defgeneric {layout-frame} {frame \optional width height}

Resizes the frame and layouts out the current pane hierarchy according to the
layout protocol.  The basics of the layout protocols are described in
Section~\ref{basic-layout}.  This function is automatically invoked on a frame
when it's adopted, after its pane hierarchy is generated.

If \arg{width} and \arg{height} are provided, then this function resizes the
frame to this size.  It is an error to provide just \arg{width}.

If no optional arguments are provided, this function resizes the frame to the
preferred size of the top-level pane as determined by the space composition pass
of the layout protocol.

In either case, after the frame is resized, the space allocation pass of the
layout protocol is invoked on the top-level pane.

\Defgeneric {reconfigure-frame} {frame pane-name \key resize-frame}

Switches the top-level pane to the pane specified by \arg{pane-name}.  This
function can only be used in conjunction with the \cl{:panes} options to
\cl{define-application-frame}, which is used to name panes.

If \arg{resize-frame} is nil, then the frame is not resized to accommodate the
new pane hierarchy.


\Defgeneric {frame-named-panes} {frame}

Returns the list of possible top-level pane names.  This is the set of valid
inputs to the \arg{pane-name} argument of \cl{reconfigure-frame}.

\Defgeneric {frame-pane-name} {frame}

Returns the name of the current top-level pane of the frame.

\Defgeneric {find-pane-for-frame} {frame frame-manager}

This function is invoked by a standard method of adopt-frame.  It must return
the root pane of the frame's layout.  It is the responsibility of the frame
implementor to provide a method that constructs the frame's top-level pane.
\cl{define-application-frame} automatically supplies a a method for this
function if the \cl{:panes} option is used.


\defgeneric {frame-properties} {frame property}
\Defgeneric {(setf frame-properties)} {new-value frame property} 

Frame properties can be used to associate frame specific data with frames
without adding additional slots to the frame's class.  However, for important
properties, the frame developer want to add slots to store highly utilized
information.


\Defgeneric {note-command-enabled} {frame-manager frame command-name enabled}

Notifies the frame manager \arg{frame-manager} that the command named by
\arg{command-name} has been enabled or disabled in the frame \arg{frame}.
\arg{enabled} is a boolean that indicates whether the command was enabled or
disabled.  The frame manager can update the appearance of the user interface as
appropriate, for instance, by ``graying out'' a newly disabled command from a
command menu or menu bar.


\subsection {Frame Manager Settings}

The Frame Manager Settings facility provides a mechanism for communicating
information from frames to their frame managers in a way that users can control
or override decisions.

\Defgeneric {(setf client-setting)} {new-value frame setting}

Sets the setting \arg{setting} to \arg{new-value} for the frame \arg{frame}.

\Defgeneric {reset-frame} {frame \rest new-client-settings}

Resets the settings of frame.  \cl{reset-frame} invokes a protocol that forces
the frame manager to notice that the settings have changed, where the setf
generic function just updates the frame data.  For example, the width and height
can be reset to force resizing of the window.

\newpage
\section {Examples of Applications}

\begin{verbatim}
;; Define the mapping between the top-level command names and
;; the commands they invoke.
(define-menu-group insdel-menu
  (("Insert Pane" com-insdel-frame-insert-pane)
   ("Remove Pane" com-insdel-frame-remove-pane)))

;; Simple application frame
(define-application-frame insdel-frame ()
  (vbox 
    (added-panes :initform nil))
  (:pane
    ;; Get access to vbox slot
    (with-frame-slots (vbox)
      ;; Macro to create a vertical stack of panes.
      (vertically
        (realize-pane 'line-editor-pane 
                      :width '(30 :character) :text "This is a line editor") 
        (realize-pane 'horizontal-divider :size :large)
        (restraining
          (setf vbox
                (vertically
                  (realize-pane 'label-pane 
                                :spacing 3 :label "This is a label pane")
                  (realize-pane 'horizontal-divider :size :medium)
                  :fill))))))
  (:menu-group insdel-menu))

;; The :COMMAND-DEFINER T option implied by use of :MENU-GROUP
;; caused the following macro to be defined.  It is basically like
;; DEFINE-COMMAND, but automatically associates the command with this
;; particular application.
(define-insdel-frame-command com-insdel-frame-insert-pane () 
  (with-frame-slots (added-pane vbox)
    ;; This command creates a new label pane (and divider) and pushes
    ;; it onto the panes list.  Each invocation adds one more pane
    ;; Inserting after :fill.
    (push (realize-pane 'hline-pane :size :small)
          added-panes)
    (push (realize-pane 'label-pane 
                        :label "Another ...")
          added-panes)
    ;; Not exported from CLIM yet
    (ws:insert-panes vbox 
                     (list
                       (cadr added-panes)
                       (car added-panes)))
    (repaint-sheet vbox (sheet-region vbox))
    (notify-user (pane-frame vbox) "Pane Inserted")))

;; Remove one of the previously-added panes.
(define-insdel-frame-command com-insdel-frame-remove-pane () 
  (declare (ignore button))
  (with-slots (added-pane vbox) frame
    (if added-panes
        (progn
          (ws:remove-pane vbox (pop added-panes))
          (ws:remove-pane vbox (pop added-panes))
          (repaint-sheet vbox (sheet-region vbox))
          (notify-user (pane-frame vbox) "Pane removed"))
        (notify-user (pane-frame vbox) "Trying to delete my panes, eh?"))))

(defun insdel (&rest settings)
  (make-frame 'insdel-frame
              :title "Insdel" :width 400 :height 200
              :user-settings settings
              :frame-manager (find-frame-manager)
              :enable t))

\end{verbatim}
