All Manuals > CLIM 2.0 User Guide > 9 Defining Application Frames

9.2 Defining CLIM Application Frames

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:

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.

*application-frame* Variable

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 Macro

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.

9.2.1 The Application Frame Protocol

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 Function

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.

9.2.2 Using the :pane Option

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))) 

9.2.3 Using the :panes and :layouts Options

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:

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)))) 

9.2.4 Example of the :pane Option to define-application-frame

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)))))

9.2.5 Examples of the :panes and :layout Options to define-application-frame

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)))))

The Default Layout for the Graphic-Demo Example When No Explicit :layout Is Specified

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)))))

The Layout for the Graphic-Demo Example With an Explicit :layout

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)))))

The Two Layouts of the Mini-CAD Demo

9.2.6 Using an :accept-values Pane in a CLIM Application Frame

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:


CLIM 2.0 User Guide - 01 Dec 2021 19:38:58