define-application-frame Macro
define-application-frame name superclasses slots &rest options
Summary: 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:
:pane
form, where form specifies the single pane in the application. The default is nil
, meaning that there are either no panes or there are multiple panes. This is the simplest way to define a pane hierarchy. The :pane
option cannot be used with the :panes
and :layouts
options. See 9.2.2 Using the :pane Option for a complete description of the :pane
option.:panes
form, where form is an alist that specifies names and panes of the application. The default is nil
, meaning that there are no named panes. The :panes
and :pane
options are mutually exclusive. See 9.2.3 Using the :panes and :layouts Options for a complete description of the :panes
option.:layouts
form, where form specifies the layout. The default layout is to lay out all of the named panes in horizontal strips. The :layouts
and :pane
options are mutually exclusive. See 9.2.3 Using the :panes and :layouts Options for a complete description of the :layouts
option.:command-table
name-and-options, where 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 :inherit-from
or :menu
(which are as in define-command-table). The default is to create a command table with the same name as the application frame.:menu-bar
form is used to specify what commands will appear in a "menu bar." It typically specifies the top-level commands of the application. form is either nil
, meaning there is no menu bar; t
, meaning that the menu from frame's command table (from the :command-table
option) should be used; a symbol that names a command table, meaning that that command table's menu should be used. The default is t
.:disabled-commands
commands, where commands is a list of command names that are initially disabled in the application frame.:command-definer
value, where value either nil
, t
, or another symbol. When it is nil
, no command-defining macro is defined. When it is t
, a command-defining macro is defined, whose name is of the form define-name-command
. When it is another symbol, the symbol names the command-defining macro. The default is t
.:top-level
form, where 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 default-frame-top-level.
The name, superclasses, and slots arguments are not evaluated. The values of each of the options are evaluated.
make-application-frame Function
make-application-frame frame-name &rest options &key pretty-name frame-manager enable state left top right bottom width height save-under frame-class &allow-other-keys
Summary: 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 size of the frame.
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 t
, 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 enable or state is provided, the frame is pushed into the given state. See 9.9 Frame Managers.
Once a frame has been created, run-frame-top-level can be called to make the frame visible and run its top-level function.
Summary: 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 commands 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
Summary: This macro provides lexical access to the "current" frame for use with 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.
application-frame Protocol Class
Summary: 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-p object
Summary: Returns t
if object is an application frame; otherwise, it returns nil
.
:name
:pretty-name
:command
:disabled
:panes
:menu-bar
:calling-frame
:state
:properties Initargs
Summary: All subclasses of application-frame must handle these initargs, which specify, respectively, the name, pretty name, command table, initial set of disabled commands, panes, menu bar, calling frame, state, and initial properties for the frame.
standard-application-frame Class
Summary: The 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.
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 cannot be used 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.
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 an alist, 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 extended stream panes, the following abbreviations are defined:
:interactor
—a pane of type interactor-pane:application
—a pane of type application-pane:command-menu
—a pane of type command-menu-pane:pointer-documentation
—a pane suitable for displaying pointer documentation, if the host window system does not provide this.:title
—a pane suitable for displaying the title of the application. If the host window system provides this, the title will be displayed with the window decorations supplied by the window manager, and the CLIM title pane will be omitted.:accept-values
—a pane that can hold a "modeless" accepting-values dialog.
See 10 Panes and 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 an alist, 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. For example, assuming a frame that uses the :panes
example, the following layouts could be specified:
(:layouts (default (vertically () button toggle (scrolling () application) interactor)) (alternate (vertically () (scrolling () application) (scrolling () interactor) (horizontally () button toggle))))
Here is an example of how to use the :pane
option of define-application-frame:
(define-application-frame test-frame () () (:pane (vertically () (make-clim-interactor-pane :foreground +green+ :background +red+) (make-pane 'push-button :label "press me" :background +black+ :foreground +purple+ :activate-callback #'(lambda (button) (frame-exit *application-frame*)) :text-style (make-text-style :serif :roman 20)))))
Here are some examples of how to use the :panes
and :layouts
options of define-application-frame to describe the appearance of your application.
We begin by showing The Default Layout for the Graphic-Demo Example When No Explicit :layout Is Specified, an example of how CLIM supplies a default layout when you don't explicitly specify one in your frame definition. The default layout is a single column of panes, in the order (top to bottom) that you specified them in the :panes
option. Command menus are allocated only enough space to display their contents, while the remaining space is divided among the other types of panes equally.
(define-application-frame test () () (:panes (main :application :incremental-redisplay NIL :display-function 'display-main) (test-menu :command-menu) (listener :interactor)) (:layouts (:default (vertically () main test-menu listener))) (:command-table (test-menu :inherit-from (user-command-table) :menu (("EXIT" :command cmd-exit)))))
Now we take the same example as before and in The Layout for the Graphic-Demo Example With an Explicit :layout add an explicit :layout
option to the frame definition. The pane named explanation
occupies the bottom sixth of the screen. The remaining five-sixths are occupied by the demo
and commands
panes, which lie side by side, with the command pane to the right. The commands pane is only as wide as is needed to display the command menu.
(define-application-frame graphics-demo () () (:menu-bar nil) (:panes (commands :command-menu) (demo :application) (explanation :application :scroll-bars nil)) (:layouts (:default (vertically () (:fill (horizontally () (:fill demo) (1/5 commands))) (1/6 explanation)))))
Finally, here is a stripped-down version of the application frame definition for the CAD demo (in the file <release-directory>/demo/cad-demo.lisp
) which implements an extremely simplistic computer-aided logic circuit design tool.
There are four panes defined for the application. The pane named title
displays the string "Mini-CAD" and serves to remind the user which application is running. The pane named menu provides a menu of commands for the application. The pane named design-area
is the actual "work surface" of the application on which various objects (logic gates and wires) can be manipulated. A pane named documentation is provided to inform the user about what actions can be performed using the pointing device (typically the mouse) and is updated based on what object is currently being pointed to.
The application has two layouts, one named main
and one named other
. Both layouts have their panes arranged in vertical columns. At the top of both layouts is the title
pane, which is of the smallest height necessary to display the title string "Mini-CAD." Both layouts have the documentation pane at the bottom.
The two layouts differ in the arrangement of the menu and design-area
panes. In the layout named main
, the menu pane appears just below the title
pane and extends for the width of the screen. Its height will be computed so as to be sufficient to hold all the items in the menu. The design-area
pane occupies the remaining screen real estate, extending from the bottom of the menu pane to the top of the documentation pane, and is as wide as the screen.
To see the layout named other
, enter (setf (frame-current-layout *application-frame*) :other)
. This differs from the main
layout in the shape of the design-area
pane. Here the implementor of the CAD demo realized that, depending on what was being designed, either a short, wide area or a narrower but taller area might be more appropriate. The other
layout provides the narrower, taller alternative by rearranging the menu and design-area
panes to be side by side (forming a row of the two panes). The menu and design-area
panes occupy the space between the bottom of the title
pane and the top of the documentation pane, with the menu pane to the left and occupying as much width as is necessary to display all the items of the menu and the design-area
occupying the remaining width.
(define-application-frame cad-demo () () (:menu-bar nil) (:panes (title :title :display-string "Mini-CAD") (menu :command-menu) (design-area :application) (documentation :pointer-documentation)) (:layouts (:main (vertically () (1/8 title) (1/8 menu) (:fill design-area) (1/8 documentation))) (:other (vertically () (1/8 title) (:fill (horizontally () (1/4 menu) (:fill design-area))) (1/8 documentation)))))
Frame :accept-values
panes are used when you want one of the panes of your application to be in the form of an accepting-values dialog.
There are several things to remember when using an :accept-values
pane in your application frame:
:accept-values
pane to work, your frame's command table must inherit from the accept-values-pane command table.:display-function
option for an accepting-values pane will typically be something like:
(clim:accept-values-pane-displayer :displayer my-acceptor-function)
where my-acceptor-function
is a function that you write. It contains calls to accept just as they would appear inside a accepting-values for a dialog. It takes two arguments, the frame and a stream. my-acceptor-function
does not need to call accepting-values itself, since that is done automatically.
See 12 Menus and Dialogs especially the function accept-values-pane-displayer.
:accept-values
pane, *application-frame* is not bound to your application. Instead, it is bound to an application that implements accepting-values. Therefore, you cannot use with-frame-state-variables
in the display function for an :accept-values
pane. Use with-slots on the frame argument instead.display-after-commands
with :accept-values
panes, because the redisplay for those panes is managed at a slightly lower level for efficiency.
CLIM 2.0 User Guide - 01 Dec 2021 19:38:58