Command Processing Contents Index Panes




28 Application Frames

28.1 Overview of Application Frames

Application frames (or simply, 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 visual aspect of an application frame is established by defining a hierarchy of panes . CLIM panes are interactive objects that are analogous to the windows, gadgets, or widgets of other toolkits. Application builders can compose their application's user interface from a library of standard panes or by defining and using their own pane types. Application frames can use a number of different types of panes including layout panes for spatially organizing panes, user panes for presenting application specific information, and gadget panes for displaying data and obtaining user input. Panes are describe in greater detail in Chapter Panes and Chapter Gadgets .

Frames are managed by special applications called 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 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. Note that by default command execution and display will not occur simultaneously, so user-defined functions need not have to cope with multiprocessing. Of course, the programmer can use multiple processes, but CLIM neither directly supports nor precludes doing so.

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

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 (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, dialogs, or by typing full command lines.

28.2 Defining and Creating Application Frames

application-frame[Protocol Class]
The protocol class that corresponds to an application frame. If you want to create a new class that behaves like an application frame, it should be a subclass of application-frame. Subclasses of application-frame must obey the application frame protocol.All application frame classes are mutable.

application-frame-pobject[Predicate]
Returns true if object is an application frame , otherwise returns false .

:name[Init arg]
:pretty-name[Init arg]
:command-table[Init arg]
:disabled-commands[Init arg]
:panes[Init arg]
:menu-bar[Init arg]
:calling-frame[Init arg]
:state[Init arg]
:properties[Init arg]
All subclasses of application-frame must handle these initargs, which are used to specify, respectively, the name, pretty name, command table, initial set of disabled commands, the panes, the menu bar, calling frame, state, and initial properties for the frame.

standard-application-frame[Class]
The instantiable standard class that implements application frames. By default, most application frame classes will inherit from this class, unless a non-nil value for superclasses is supplied to define-application-frame .

define-application-framename superclasses slots &rest options[Macro]
Defines a frame and CLOS class named by the symbol name that inherits from superclasses and has state variables specified by slots . superclasses is a list of superclasses that the new class will inherit from (as in defclass ). When superclasses is nil , it behaves as though a superclass of standard-application-frame was supplied. slots is a list of additional slot specifiers, whose syntax is the same as the slot specifiers in 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.

options is a list of defclass -style options, and can include the usual defclass options, plus any of the following:

The name , superclasses , and slots arguments are not evaluated. The values of each of the options are evaluated.

make-application-frameframe-name &rest options &key pretty-name frame-manager enable state left top right bottom width height save-under frame-class &allow-other-keys [Function]
Makes an instance of the application frame of type frame-class . If frame-class is not supplied, it defaults to frame-name .

The size options left , top , right , bottom , width , and height can be used to specify the initial size of the frame. If they are unsupplied and :geometry was supplied to define-application-frame , then these arguments default from the specified geometry.

options are passed as additional arguments to make-instance , after the pretty-name , frame-manager , enable , state , save-under , frame-class , and size options have been removed.

If save-under is true , then the sheets used to implement the user interface of the frame will have the ``save under'' property, if the host window system supports it.

If frame-manager is provided, then the frame is adopted by the specified frame manager. If the frame is adopted and either of enable or state are provided, the frame is pushed into the given state.

Once a frame has been create, run-frame-top-level can be called to make the frame visible and run its top-level function.

*application-frame*[Variable]
The current application frame. The global value is CLIM's default application, which serves only as a repository for whatever internal state is 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 with-slots or slot-value .

with-application-frame(frame) &body body[Macro]
This macro provides lexical access to the ``current'' frame for use with commands and the :pane , :panes , and :layouts options. frame is bound to the current frame within the context of one of those options.

frame is a symbol; it is not evaluated. body may have zero or more declarations as its first forms.

map-over-framesfunction &key port frame-manager[Function]
Applies the function function to all of the application frames that ``match'' port and frame-manager . If neither port nor frame-manager is supplied, all frames are considered to match. If frame-manager is supplied, only those frames that use that frame manager match. If port is supplied, only those frames that use that port match.

function is a function of one argument, the frame. It has dynamic extent.

destroy-frameframe[Generic function]
Destroys the application frame frame .

raise-frameframe[Generic function]
Raises the application frame frame to be on top of all of the other host windows by invoking raise-sheet on the frame's top-level sheet.

bury-frameframe[Generic function]
Buries the application frame frame to be underneath all of the other host windows by invoking bury-sheet on the frame's top-level sheet.

28.2.1 Specifying the Panes of a Frame

The panes of a frame can be specified in one of two different ways. If the frame has a single layout and no need of named panes, then the :pane option can be used. Otherwise if named panes or multiple layouts are required, the :panes and :layouts options can be used. Note that the :pane option is mutually exclusive with :panes and :layouts . It is meaningful to define frames that have no panes at all; the frame will simply serve as a repository for state and commands.

Panes and gadgets are discussed in detail in Chapter Panes and Chapter Gadgets .

The value of the :pane option is a form that is used to create a single (albeit arbitrarily complex) pane. For example:

(vertically ()
  (tabling ()
    ((horizontally ()
       (make-pane 'toggle-button)
       (make-pane 'toggle-button)
       (make-pane 'toggle-button))
     (make-pane 'text-field))
    ((make-pane 'push-button :label "a button")
     (make-pane 'slider)))
  (scrolling ()
    (make-pane 'application-pane
               :display-function 'a-display-function))
  (scrolling ()
    (make-pane 'interactor-pane)))
If the :pane option is not used, a set of named panes can be specified with the :panes option. Optionally, :layouts can also be used to describe different layouts of the set of panes.

The value of the :panes option is a list, each entry of which is of the form (name . body) . name is a symbol that names the pane, and body specifies how to create the pane. body is either a list containing a single element that is itself a list, or a list consisting of a symbol followed by zero or more keyword-value pairs. In the first case, the body is a form exactly like the form used in the :pane option. In the second case, body is a pane abbreviation where the initial symbol names the type of pane, and the keyword-value pairs are pane options. For gadgets, the pane type is the class name of the abstract gadget (for example, slider or push-button ). For CLIM stream panes, the following abbreviations are defined:

See Chapter Panes and Chapter Gadgets for more information on the individual pane and gadget classes, and the options they support.

An example of the use of :panes is:

(:panes
  (buttons (horizontally ()
             (make-pane 'push-button :label "Press me")
             (make-pane 'push-button :label "Squeeze me")))
  (toggle toggle-button 
          :label "Toggle me")
  (interactor :interactor
              :width 300 :height 300)
  (application :application
               :display-function 'another-display-function
               :incremental-redisplay t))
The value of the :layouts option is a list, each entry of which is of the form (name layout) . name is a symbol that names the layout, and layout specifies the layout. layout is a form like the form used in the :pane option, with the extension to the syntax such that the name of a named pane can be used wherever a pane may appear. (This will typically be implemented by using symbol-macrolet for each of the named panes.) For example, assuming a frame that uses the :panes example above, the following layouts could be specified:

(:layouts
  (default 
    (vertically ()
      button toggle 
      (scrolling () application)
      interactor))
  (alternate
    (vertically ()
      (scrolling () application)
      (scrolling () interactor)
      (horizontally ()
        button toggle))))
The syntax for :layouts can be concisely expressed as:

28.3 Application Frame Functions

The generic functions described in this section are the functions that can be used to read or modify the attributes of a frame. All classes that inherit from application-frame must inherit or implement methods for all of these functions.

frame-nameframe[Generic function]
Returns the name of the frame frame , which is a symbol.

frame-pretty-nameframe[Generic function]
Returns the ``pretty name'' of the frame frame , which is a string.

(setf frame-pretty-name)name frame[Generic function]
Sets the pretty name of the frame frame to name , which must be a string. Changing the pretty name of a frame notifies its frame manager, which in turn may change some aspects of the appearance of the frame, such as its title bar.

frame-command-tableframe[Generic function]
Returns the command table for the frame frame .

(setf frame-command-table)command-table frame[Generic function]
Sets the command table for the frame frame to command-table . Changing the frame's command table will redisplay the command menus (or menu bar) as needed. command-table is a command table designator .

frame-standard-outputframe[Generic function]
Returns the stream that will be used for *standard-output* for the frame frame . The default method (on standard-application-frame ) returns the first named pane of type application-pane that is visible in the current layout; if there is no such pane, it returns the first pane of type interactor-pane that is exposed in the current layout.

frame-standard-inputframe[Generic function]
Returns the stream that will be used for *standard-input* for the frame frame . The default method (on standard-application-frame ) returns the first named pane of type interactor-pane that is visible in the current layout; if there is no such pane, the value returned by frame-standard-output is used.

frame-query-ioframe[Generic function]
Returns the stream that will be used for *query-io* for the frame frame . The default method (on standard-application-frame ) returns the value returned by frame-standard-input ; if that is nil , it returns the value returned by frame-standard-output .

frame-error-outputframe[Generic function]
Returns the stream that will be used for *error-output* for the frame frame . The default method (on standard-application-frame ) returns the same value as frame-standard-output .

*pointer-documentation-output*[Variable]
This will be bound either to nil or to a stream on which pointer documentation will be displayed.

frame-pointer-documentation-outputframe[Generic function]
Returns the stream that will be used for *pointer-documentation-output* for the frame frame . The default method (on standard-application-frame ) returns the first pane of type pointer-documentation-pane . If this returns nil , no pointer documentation will be generated for this frame.

frame-calling-frameframe[Generic function]
Returns the application frame that invoked the frame frame .

frame-parentframe[Generic function]
Returns the object that acts as the parent for the frame frame . This often, but not always, returns the same value as frame-manager .

frame-panesframe[Generic function]
Returns the pane that is the top-level pane in the current layout of the frame frame 's named panes. This will typically be some sort of a layout pane.

frame-top-level-sheetframe[Generic function]
Returns the sheet that is the top-level sheet for the frame frame . This is the sheet that has as its descendents all of the panes of frame .

The value returned by frame-panes will be a descendents of the value of frame-top-level-sheet .

frame-current-panesframe[Generic function]
Returns a list of those named panes in the frame frame 's current layout. If there are no named panes (for example, the :pane option was used), only the single, top level pane is returned. This function returns objects that reveal CLIM's internal state; do not modify those objects.
get-frame-paneframe pane-name[Generic function]
Returns the named CLIM stream pane in the frame frame whose name is pane-name .

find-pane-namedframe pane-name[Generic function]
Returns the pane in the frame frame whose name is pane-name . This can return any type of pane, not just CLIM stream panes.

frame-current-layoutframe[Generic function]
Returns the current layout for the frame frame . The layout is named by a symbol.

(setf frame-current-layout)layout frame[Generic function]
Sets the layout of the frame frame to be the new layout specified by new-layout . 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 *standard-input* ). Some implementations of CLIM may cause the application to ``throw'' all the way back to run-frame-top-level in order to do this. After the new layout has been computed, the contents of each of the panes must be displayed to the degree necessary to ensure that all output is visible.

frame-all-layoutsframe[Generic function]
Returns a list of the names of all of the possible layouts for the frame.

layout-frameframe &optional width height[Generic function]
Resizes the frame and lays out the current pane hierarchy using the layout specified by frame-current-layout , according to the layout protocol. The basics of the layout protocols are described in Section The Layout Protocol . This function is automatically invoked on a frame when it is adopted, after its pane hierarchy has been generated.

If width and height are provided, then this function resizes the frame to the specified size. It is an error to provide just 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.

frame-exit[Condition]
The condition that is signalled when frame-exit is called. This condition will handle the :frame initarg, which is used to supply the frame that is being exited from.

frame-exit-framecondition[Generic function]
Returns the frame that is being exited from associated with the frame-exit condition.

frame-exitframe[Generic function]
Exits from the frame frame . The default method (on standard-application-frame ) signals a frame-exit condition, supplying frame as the :frame initarg.

pane-needs-redisplaypane[Generic function]
Returns two values, the first indicating whether the pane pane needs to be redisplayed, and the second indicating whether the pane needs to be cleared before being redisplayed. The first value is true when the pane is to be redisplayed. The second value is true when the pane is to be cleared.

(setf pane-needs-redisplay)value pane[Generic function]
Indicates that the pane pane should (or should not) be redisplayed the next time the owning frame executes the redisplay part of its command loop.

When value is nil , the pane will not require redisplay. When value is t , the pane will be cleared and redisplayed exactly once. When value is :command-loop , the pane will be cleared and redisplayed in each successive pass through the command loop. When value is :no-clear , the pane will be redisplayed exactly once without clearing it.

redisplay-frame-paneframe pane &key force-p[Generic function]
Causes the pane pane within the frame frame to be redisplayed immediately. pane is either a pane or the name of a named pane. When the boolean force-p is true , the maximum level of redisplay is forced (that is, the pane is displayed ``from scratch'').

redisplay-frame-panesframe &key force-p[Generic function]
redisplay-frame-panes causes all of the panes in the frame frame to be redisplayed immediately by calling redisplay-frame-pane on each of the panes in frame that are visible in the current layout. When the boolean force-p is true , the maximum level of redisplay is forced (that is, the pane is displayed ``from scratch'').

frame-replayframe stream &optional region[Generic function]
Replays the contents of stream in the frame frame within the region specified by the region region , which defaults to viewport of stream .

notify-userframe message &key associated-window title documentation exit-boxes name style text-style[Generic function]
Notifies the user of some event on behalf of the frame frame . message is a message string. This function provides a look and feel independent way for applications to communicate messages to the user.

associated-window is the window with which the notification will be associated, as it is for menu-choose . title is a title string to include in the notification. text-style is the text style in which to display the notification. exit-boxes is as for accepting-values ; it indicates what sort of exit boxes should appear in the notification. style is the style in which to display the notification, and is implementation-dependent.

frame-propertiesframe property[Generic function]
(setf frame-properties)value frame property[Generic function]
Frame properties can be used to associate frame specific data with frames without adding additional slots to the frame's class. CLIM may use frame properties internally to store information for its own purposes.

28.3.1 Interface with Presentation Types

This section describes the functions that connect application frames to the presentation type system. All classes that inherit from application-frame must inherit or implement methods for all of these functions.

frame-maintain-presentation-historiesframe[Generic function]
Returns true if the frame frame maintains histories for its presentations, otherwise returns false . The default method (on standard-application-frame ) returns true if and only if the frame has at least one interactor pane.

frame-find-innermost-applicable-presentationframe input-context stream x y &key event[Generic function]
Locates and returns the innermost applicable presentation on the window stream whose sensitivity region contains the point (x,y), on behalf of the frame frame in the input context input-context . event defaults to nil , and is as for find-innermost-applicable-presentation

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

frame-input-context-button-press-handlerframe stream button-press-event[Generic function]
This function is responsible for handling user pointer events on behalf of the frame frame in the input context *input-context* . stream is the window on which button-press-event took place.

The default implementation (on standard-application-frame ) unhighlights any highlighted presentations, finds the applicable presentation by calling frame-find-innermost-applicable-presentation-at-position , and then calls throw-highlighted-presentation to execute the translator on that presentation that corresponds to the user's gesture.

If frame-input-context-button-press-handler is called when the pointer is not over any applicable presentation, throw-highlighted-presentation must be called with a presentation of *null-presentation* .

frame-document-highlighted-presentationframe presentation input-context window x y stream[Generic function]
This function is responsible for producing pointer documentation on behalf of the frame frame in the input context input-context on the window window at the point (x,y). The documentation is displayed on the stream stream .

The default method (on standard-application-frame ) should produce documentation that corresponds to calling document-presentation-translator on all of the applicable translators in the input context input-context . presentation , window , x , y , and stream are as for document-presentation-translator .

Typically pointer documentation will consist of a brief description of each translator that is applicable to the specified presentation in the specified input context given the current modifier state for the window. For example, the following documentation might be produced when the pointer is pointing to a Lisp expression when the input context is form :

Left: '(1 2 3); Middle: (DESCRIBE '(1 2 3)); Right: Menu
frame-drag-and-drop-feedbackframe presentation stream initial-x initial-y new-x new-y state[Generic function]
The default feedback function for translators defined by define-drag-and-drop-translator , which provides visual feedback during the dragging phase of such translators on behalf of the frame frame . presentation is the presentation being dragged on the stream stream . The pointing device was initially at the position specified by initial-x and initial-y , and is at the position specified by new-x and new-y when frame-drag-and-drop-feedback is invoked. (Both positions are supplied for ``rubber-banding'', if that is the sort of desired feedback.) state will be either :highlight , meaning that the feedback should be drawn, or :unhighlight , meaning that the feedback should be erased.

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

28.4 The Generic Command Loop

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

    Prompts the user for input.

    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. Since commands may be read in any number of ways, the generic command loop enforces no particular interface style.

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

    Runs the display function for each pane in the frame as necessary. 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.


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 application-frame must inherit or implement methods for all of the following functions.

run-frame-top-levelframe &key &allow-other-keys [Generic function]
Runs the top-level function for the frame frame . The default method on application-frame simply invokes the top-level function for the frame (which defaults to default-frame-top-level ).

run-frame-top-level(frame application-frame ) &key [Method :around]
The :around method of run-frame-top-level on the application-frame class is responsible for establish the initial dynamic bindings for the application, including (but not limited to) binding *application-frame* to frame , binding *input-context* to nil , resetting the delimiter and activation gestures, and binding *input-wait-test* , *input-wait-handler* , and *pointer-button-press-handler* to nil .

default-frame-top-levelframe &key command-parser command-unparser partial-command-parser prompt[Generic function]
The default top-level function for application frames. This function implements a ``read-eval-print'' loop that displays a prompt, calls read-frame-command , then calls execute-frame-command , and finally redisplays all of the panes that need to be redisplayed.

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

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

command-parser , command-unparser , and partial-command-parser are the same as for read-command . command-parser defaults to command-line-command-parser if there is an interactor, otherwise it defaults to menu-only-command-parser . command-unparser defaults to command-line-command-unparser . partial-command-parser defaults to command-line-read-remaining-arguments-for-partial-command if there is an interactor, otherwise it defaults to menu-only-read-remaining-arguments-for-partial-command . default-frame-top-level binds *command-parser* , *command-unparser* , and *partial-command-parser* to the values of command-parser , command-unparser , and partial-command-parser .

read-frame-commandframe &key (stream *standard-input* )[Generic function]
Reads a command from the stream stream on behalf of the frame frame . The returned value is a command object.

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

execute-frame-commandframe command[Generic function]
Executes the command command on behalf of the frame frame . 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 standard-application-frame ) for execute-frame-command simply applies the command-name of command to command-arguments of command .

If process that execute-frame-command is invoked in is not the same process the one frame is running in, CLIM may need to make special provisions in order for the command to be correctly executed, since as queueing up a special ``command event'' in frame 's event queue. The exact details of how this should work is left unspecified.

command-enabledcommand-name frame[Generic function]
Returns true if the command named by command-name is presently enabled in the frame frame , otherwise returns false . If command-name is not accessible to the command table being used by frame , command-enabled returns 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.

(setf command-enabled)enabled command-name frame[Generic function]
If enabled is false , this disables the use of the command named by command-name while in the frame frame . Otherwise if enabled is true , the use of the command is enabled. After the command has been enabled (or disabled), note-command-enabled (or note-command-disabled ) is invoked on the frame manager and the frame in order to update the appearance of the interface, for example, ``graying out'' a disabled command.

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

display-command-menuframe stream &key command-table initial-spacing row-wise max-width max-height n-rows n-columns (cell-align-x :left ) (cell-align-y :top )[Generic function]
Displays the menu associated with the specified command table on stream by calling display-command-table-menu . If command-table is not supplied, it defaults to (frame-command-table stream ) . This function is generally used as the display function for panes that contain command menus.

initial-spacing , max-width , max-height , n-rows , n-columns , row-wise , cell-align-x , and cell-align-y are as for formatting-item-list .

28.5 Frame Managers

Frames may be 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: enabled , disabled , or 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.

frame-manager[Protocol Class]
The protocol class that corresponds to a frame manager. If you want to create a new class that behaves like a frame manager, it should be a subclass of frame-manager. Subclasses of frame-manager must obey the frame manager protocol.There are no advertised standard frame manager classes. Each port will implement one or more frame managers that correspond to the look and feel for the port.

frame-mananger-pobject[Predicate]
Returns true if object is a frame manager , otherwise returns false .

28.5.1 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.


Issue: SWM
How does one write a frame that supports an embedded frame, such as an editor frame within a documentation-writing frame?
The 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 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 *default-frame-manager* or *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.

find-frame-manager&rest options &key port &allow-other-keys [Function]
Finds an appropriate frame manager that conforms to the options, including the port argument. Furthermore, CLIM applications may set up dynamic contexts that affect what find-frame-manager will return.

port defaults to the value returned by find-port applied to the remaining options.

A frame manager is found using the following rules in the order listed:

    If a current frame manager has been established via an invocation of with-frame-manager , as is the case within a frame's top-level, and that frame manager conforms to the options, it is returned. The exact definition of ``conforming to the options'' varies from one port to another, but it may include such things as matching the console number, color or resolution properties, and so forth. If the options are empty, then any frame manager will conform.

    If *default-frame-manager* is bound to a currently active frame manager and it conforms to the options, it is returned.

    If port is nil , a port is found and an appropriate frame manager is constructed using *default-server-path* .

*default-frame-manager*[Variable]
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 *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 OpenLook frame manager and a Motif frame manager on a single port.

with-frame-manager(frame-manager) &body body[Macro]
Generates a dynamic context that causes all calls to find-frame-manager to return frame-manager if the where argument passed to it conforms to frame-manager . Nested calls to with-frame-manager will shadow outer contexts. body may have zero or more declarations as its first forms.

28.5.2 Frame Manager Operations

frame-managerframe[Generic function]
Returns the current frame manager of frame if it is adopted, otherwise returns nil .

(setf frame-manager)frame-manager frame[Generic function]
Changes the frame manager of frame to frame-manager . In effect, the frame is disowned from its old frame manager and is adopted into the new frame manager. Transferring a frame preserves its frame-state , for example, if the frame was previously enabled it will be enabled in the new frame manager.

frame-manager-framesframe-manager[Generic function]
Returns a list of all of the frames being managed by frame-manager . This function returns objects that reveal CLIM's internal state; do not modify those objects.
adopt-frameframe-manager frame[Generic function]
disown-frameframe-manager frame[Generic function]
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.

port(frame standard-application-frame )[Method]
If frame has been adopted by a frame manager, this returns the port with which frame is associated. Otherwise it returns nil .

port(frame-manager standard-frame-manager )[Method]
Returns the port with which frame-manager is associated.

frame-stateframe[Generic function]
Returns one of :disowned , :enabled , :disabled , or :shrunk , indicating the current state of frame.

enable-frameframe[Generic function]
disable-frameframe[Generic function]
shrink-frameframe[Generic function]
These functions force a frame into the enabled, disabled, or shrunken (iconified) 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.

These functions call the notification functions describe below to notify the frame manager that the state of the frame changed.

note-frame-enabledframe-manager frame[Generic function]
note-frame-disabledframe-manager frame[Generic function]
note-frame-iconifiedframe-manager frame[Generic function]
note-frame-deiconifiedframe-manager frame[Generic function]
Notifies the frame manager frame-manager that the frame frame has changed its state to the enabled, disabled, iconified, or deiconified state, respectively.

note-command-enabledframe-manager frame command-name[Generic function]
note-command-disabledframe-manager frame command-name[Generic function]
Notifies the frame manager frame-manager that the command named by command-name has been enabled or disabled (respectively) in the frame frame . 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.

frame-manager-notify-userframem message-string &key frame associated-window title documentation exit-boxes name style text-style[Generic function]
This is the generic function used by notify-user . The arguments are as for notify-user . The default method on standard-frame-manager will display a dialog or an alert box that contains the message and has exit boxes that allow the user to dismiss the notification.

generate-panesframe-manager frame[Generic function]
This function is invoked by a standard method of adopt-frame . define-application-frame automatically supplies a generate-panes method if either the :pane or :panes option is used in the define-application-frame .

It is the responsibility of this method to call setf on frame-panes on the frame in order to set the current

find-pane-for-frameframe-manager frame[Generic function]
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. define-application-frame automatically supplies a a method for this function if either the :pane or :panes option is used in the define-application-frame .

28.5.3 Frame Manager Settings

CLIM provides frame manager settings in order to allow a frame to communicate information to its frame manager.

(setf client-setting)value frame setting[Generic function]
Sets the setting setting to value for the frame frame .

reset-frameframe &rest client-settings[Generic function]
Resets the settings of frame. 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.

28.6 Examples of Applications

The following is an example that outlines a simple 4-by-4 sliding piece puzzle:

(define-application-frame puzzle ()
    ((puzzle-array :initform (make-array '(4 4))))
  (:menu-bar t)
  (:panes
    (display
      (outlining ()
        (make-pane 'application-pane
                   :text-cursor nil
                   :width :compute
                   :height :compute
                   :incremental-redisplay T
                   :display-function 'draw-puzzle))))
  (:layouts
    (:default display)))

(defmethod run-frame-top-level :before ((puzzle puzzle)) ;; Initialize the puzzle ...)

(define-presentation-type puzzle-cell () :inherit-from '(integer 1 15))

(defmethod draw-puzzle ((puzzle puzzle) stream &key max-width max-height) (declare (ignore max-width max-height)) ;; Draw the puzzle, presenting each cell as a PUZZLE-CELL ...)

(define-puzzle-command com-move-cell ((cell 'puzzle-cell :gesture :select)) ;; Move the selected cell to the adjacent open cell, ;; if there is one ...)

(define-puzzle-command (com-scramble :menu t) () ;; Scramble the pieces of the puzzle ...)

(define-puzzle-command (com-exit-puzzle :menu "Exit") () (frame-exit *application-frame*))

(defun puzzle () (let ((puzzle (make-application-frame 'puzzle :width 80 :height 80))) (run-frame-top-level puzzle)))

The following is an application frame with two layouts:

(define-application-frame test-frame () ()
  (:panes
    (a (horizontally ()
         (make-pane 'push-button :label "Press me")
         (make-pane 'push-button :label "Squeeze me")))
    (b toggle-button)
    (c slider)
    (d text-field)
    (e :interactor-pane
       :width 300 :max-width +fill+
       :height 300 :max-height +fill+))
  (:layouts
    (default 
      (vertically ()
        a b c (scrolling () e)))
    (other
      (vertically ()
        a (scrolling () e) b d))))

(define-test-frame-command (com-switch :name t :menu t) () (setf (frame-current-layout *application-frame*) (ecase (frame-current-layout *application-frame*) (default other) (other default))))

(let ((test-frame (make-application-frame 'test-frame))) (run-frame-top-level test-frame))




Command Processing Contents Index Panes