Application Frames Contents Index Gadgets




29 Panes

29.1 Overview of Panes

CLIM panes are similar to the gadgets or widgets of other toolkits. They can be used by application programmers to compose the top-level user interface of their applications, as well as auxiliary components such as menus and dialogs. The application programmer provides an abstract specification of the pane hierarchy, which CLIM uses in conjunction with user preferences and other factors to select a specific ``look and feel'' for the application. In many environments a CLIM application can use the facilities of the host window system toolkit via a set of adaptive panes , allowing a portable CLIM application to take on the look and feel of a native application user interface.

Panes are rectangular objects that are implemented as special sheet classes. An application will typically construct a tree of panes that divide up the screen space allocated to the application frame. The various CLIM pane types can be characterized by whether they have children panes or not: panes that can have other panes as children are called composite panes , and those that don't are called leaf panes . Composite panes are used to provide a mechanism for spatially organizing (``laying out'') other panes. Leaf panes implement gadgets that have some appearance and react to user input by invoking application code. Another kind of leaf pane provides an area of the application's screen real estate that can be used by the application to present application specific information. CLIM provides a number of these application pane types that allow the application to use CLIM's graphics and extended stream facilities.

Abstract panes are panes that are defined only in terms of their programmer interface, or behavior. The protocol for an abstract pane (that is, the specified set of initargs, accessors, and callbacks) is designed to specify the pane in terms of its overall purpose, rather then in terms of its specific appearance or particular interactive details. The purpose of this abstract definition is to allow multiple implementations of the abstract pane, each defining its own specific look and feel. CLIM can then select the appropriate pane implementation based on factors outside the control of the application, such as user preferences or the look and feel of the host operating environment. A subset of the abstract panes, the adaptive panes , have been defined to integrate well across all CLIM operating platforms.

CLIM provides a general mechanism for automatically selecting the particular implementation of an abstract pane selected by an application based on the current frame manager. The application programmer can override the selection mechanism by using the name of a specific pane implementation in place of the abstract pane name when specifying the application frame's layout. By convention, the name of the basic, portable implementation of an abstract pane class can be determined by adding the suffix ``-pane '' to the name of the abstract pane class.

29.2 Basic Pane Construction

Applications typically define the hierarchy of panes used in their frames using the :pane or :panes options of define-application-frame . These options generate the body of methods on functions that are invoked when the frame is being adopted into a particular frame manager, so the frame manager can select the specific implementations of the abstract panes.

There are two basic interfaces to constructing a pane: make-pane of an abstract pane class name, or make-instance of a ``concrete'' pane class. The former approach is generally preferable, since it results in more portable code. However, in some cases the programmer may wish to instantiate panes of a specific class (such as an hbox-pane or a vbox-pane ). In this case, using make-instance directly circumvents the abstract pane selection mechanism. However, the make-instance approach requires the application programmer to know the name of the specific pane implementation class that is desired, and so is inherently less portable. By convention, all of the concrete pane class names, including those of the implementations of abstract pane protocol specifications, end in ``-pane ''.

Using make-pane instead of make-instance invokes the ``look and feel'' realization process to select and construct a pane. Normally this process is implemented by the frame manager, but it is possible for other ``realizers'' to implement this process. make-pane is typically invoked using an abstract pane class name, which by convention is a symbol in the CLIM package that doesn't include the ``-pane '' suffix. (This naming convention distinguishes the names of the abstract pane protocols from the names of classes that implement them.) Programmers, however, are allowed to pass any pane class name to make-pane , in which case the frame manager will generally instantiate that specific class.

pane[Protocol Class]
The protocol class that corresponds to a pane, a subclass of sheet . A pane is a special kind of sheet that implements the pane protocols, including the layout protocols. If you want to create a new class that behaves like a pane, it should be a subclass of pane. Subclasses of pane must obey the pane protocol.All of the subclasses of pane are mutable.

panepobject[Predicate]
Returns true if object is a pane , otherwise returns false .

basic-pane[Class]
The basic class on which all CLIM panes are built, a subclass of pane .

make-paneabstract-class-name &rest initargs[Function]
Selects a class that implements the behavior of the abstract pane abstract-class-name and constructs a pane of that class. make-pane must be used either within the scope of a call to with-look-and-feel-realization , or within the :pane or :panes options of a define-application-frame (which implicitly invokes with-look-and-feel-realization ).

It is permitted for this function to have lexical scope, and be defined only within the body of with-look-and-feel-realization .

make-pane-1realizer frame abstract-class-name &rest initargs[Generic function]
The generic function that is invoked by a call to make-pane . The object that realizes the pane, realizer , is established by with-look-and-feel-realization . Usually, realizer is a frame manager, but it could be another object that implements the pane realization protocol. frame is the frame for which the pane will be created, and abstract-class-name is the type of pane to create.

with-look-and-feel-realization(realizer frame) &body forms[Macro]
Establishes a dynamic context that installs realizer as the object responsible for realizing panes. All calls to make-pane within the context of with-look-and-feel-realization result in make-pane-1 being invoked on realizer . This macro can be nested dynamically; inner uses shadow outer uses. body may have zero or more declarations as its first forms.

Typically realizer is a frame manager, but in some cases realizer may be some other object. For example, within the implementation of pane that is uses its own subpanes to achieve its functionality, this form might be used with realizer being the pane itself.

29.2.1 Pane Initialization Options

The following options must be accepted by all pane classes.

:foreground[Option]
:background[Option]
These options specify the default foreground and background inks for a pane. These will normally default from window manager resources. If there are no such resources, the defaults are black and white, respectively.

Client code should be cautious about passing values for these two options, since the window manager's look and feel or the user's preferences should usually determine these values.

:text-style[Option]
This option specifies the default text style that should be used for any sort of pane that supports text output. Panes that do not support text output ignore this option.

Client code should be cautious about passing values for this option, since the window manager's look and feel or the user's preferences should usually determine this value.

:name[Option]
This option specifies the name of the pane. It defaults to nil .

29.2.2 Pane Properties

pane-framepane[Generic function]
Returns the frame that ``owns'' the pane. pane-frame can be invoked on any pane in a frame's pane hierarchy, but it can only be invoked on ``active'' panes, that is, those panes that are currently adopted into the frame's pane hierarchy.

pane-namepane[Generic function]
Returns the name of the pane.

pane-foregroundpane[Generic function]
pane-backgroundpane[Generic function]
pane-text-stylepane[Generic function]
Return the default foreground and background inks and the default text style, respectively, for the pane pane . These will be used as the default value for medium-foreground and medium-background when a medium is grafted to the pane.

29.3 Composite and Layout Panes

This section describes the various composite and layout panes provided by CLIM, and the protocol that the layout panes obey.

The layout panes describe in this section are all composite panes that are responsible for positioning their children according to various layout rules. Layout panes can be selected in the same way as other panes using make-pane or make-instance . For convenience and readability of application pane layouts, many of these panes also provide a macro that expands into a make-pane form, passing a list of the panes created in the body of the macro as the :contents argument (described below). For example, you can express a layout of a vertical column of two label panes either as:

(make-instance 'vbox-pane
  :contents (list (make-instance 'label-pane :text "One")
                  (make-instance 'label-pane :text "Two")))
or as:

(vertically ()
  (make-instance 'label-pane :text "One")
  (make-instance 'label-pane :text "Two"))

29.3.1 Layout Pane Options

:contents[Option]
All of the layout pane classes accept the :contents options, which is used to specify the child panes to be laid out.

:width[Option]
:max-width[Option]
:min-width[Option]
:height[Option]
:max-height[Option]
:min-height[Option]
These options control the space requirement paramaters for laying out the pane. The :width and :height options specify the preferred horizontal and vertical sizes. The :max-width and :max-height options specify the maximum amount of space that may be consumed by the pane, and give CLIM's pane layout engine permission to grow the pane beyond the preferred size. The :min-width and :min-height options specify the minimum amount of space that may be consumed by the pane, and give CLIM's pane layout engine permission to shrink the pane below the preferred size.

If either of the :max-width or :min-width options is not supplied, it defaults to the value of the :width option. If either of the :max-height or :min-height options is not supplied, it defaults to the value of the :height option.

:max-width , :min-width , :max-height , and :min-height can also be specified as a relative size by supplying a list of the form (number :relative) . In this case, the number indicates the number of device units that the pane is willing to stretch or shrink.

The values of these options are specified in the same way as the :x-spacing and :y-spacing options to formatting-table . (Note that :character and :line may only be used on those panes that display text, such as a clim-stream-pane or a label-pane .)

+fill+[Constant]
This constant can be used as a value to any of the relative size options. It indicates that pane's willingness to adjust an arbitrary amount in the specified direction.

:align-x[Option]
:align-y[Option]
The :align-x option is one of :right , :center , or :left . The :align-y option is one of :top , :center , or :bottom . These are used to specify how child panes are aligned within the parent pane. These have the same semantics as for formatting-cell .

:x-spacing[Option]
:y-spacing[Option]
:spacing[Option]
These spacing options apply to hbox-pane , vbox-pane , table-pane , and grid-pane , and indicate the amount of horizontal and vertical spacing (respectively) to leave between the items in boxes or rows and columns in table. The values of these options are specified in the same way as the :x-spacing and :y-spacing options to formatting-table . :spacing specifies both the x and y spacing simultaneously.

29.3.2 Layout Pane Classes

hbox-pane[Layout Pane]
horizontally(&rest options &key spacing &allow-other-keys ) &body contents[Macro]
The hbox-pane class lays out all of its child panes horizontally, from left to right. The child panes are separated by the amount of space specified by spacing .

The horizontally macro serves as a convenient interface for creating an hbox-pane .

contents is one or more forms that are the child panes. Each form in contents is of the form:

vbox-pane[Layout Pane]
vertically(&rest options &key spacing &allow-other-keys ) &body contents[Macro]
The vbox-pane class lays out all of its child panes vertically, from top to bottom. The child panes are separated by the amount of space specified by spacing .

The vertically macro serves as a convenient interface for creating an vbox-pane .

contents is as for horizontally .

hrack-pane[Layout Pane]
vrack-pane[Layout Pane]
Similar to the hbox-pane and vbox-pane classes, except that these ensure that all children are the same size in the minor dimension. In other words, these panes are used to create stacks of same-sized items, such as menu items.

An hrack-pane is created when the :equalize-height option to horizontally is true . A vrack-pane is created when the :equalize-width option to vertically is true .

table-pane[Layout Pane]
tabling(&rest options) &body contents[Macro]
This pane lays out its child panes in a two-dimensional table arrangement. Each of the table is specified by an extra level of list in contents . For example,

(tabling ()
  (list
    (make-pane 'label :text "Red")
    (make-pane 'label :text "Green")
    (make-pane 'label :text "Blue"))
  (list
    (make-pane 'label :text "Intensity")
    (make-pane 'label :text "Hue")
    (make-pane 'label :text "Saturation")))
grid-pane[Layout Pane]
A grid-pane is like a table-pane , except that each cell is the same size in each of the two dimensions.

spacing-pane[Layout Pane]
spacing(&rest options &key thickness &allow-other-keys ) &body contents[Macro]
This pane reserves some margin space of thickness thickness around a single child pane. The space requirement keys that are passed in indicate the requirements for the surrounding space, not including the requirements of the child.

outlined-pane[Layout Pane]
outlining(&rest options &key thickness &allow-other-keys ) &body contents[Macro]
This layout pane puts a outline of thickness thickness around its contents.

The :background option can be used to control the ink used to draw the background.

restraining-pane[Layout Pane]
restraining(&rest options) &body contents[Macro]
Wraps the contents with a pane that prevents changes to the space requirements for contents from causing relayout of panes outside of the restraining context. In other words, it prevents the size constraints of the child from propagating up beyond this point.

bboard-pane[Layout Pane]
A pane that allows its children to be any size and lays them out wherever they want to be (for example, a desktop manager).

label-pane[Service Pane]
labelling(&rest options &key label label-alignment &allow-other-keys ) &body contents[Macro]
Creates a pane that consists of the specified label label , which is a string. label-alignment may be either :bottom or :top , which specifies whether the label should appear at the top or the bottom of the labelled pane. The default for label-alignment is left unspecified.

29.3.3 Scroller Pane Classes

CLIM defines the following additional pane classes, each having at least one implementation.

scroller-pane[Service Pane]
scrolling(&rest options) &body contents[Macro]
Creates a composite pane that allows the single child specified by contents to be scrolled. options may include a :scroll-bar option. The value of this option may be t (the default), which indicates that both horizontal and vertical scroll bars should be created; :vertical , which indicates that only a vertical scroll bar should be created; or :horizontal , which indicates that only a horizontal scroll bar should be created.

The pane created by the scrolling will include a scroller-pane that has as children the scroll bars and a viewport . The viewport of a pane is the area of the window's drawing plane that is currently visible to the user. The viewport has as its child the specified contents.

pane-viewportpane[Generic function]
If the pane pane is part of a scroller pane, this returns the viewport pane for pane . Otherwise it returns nil .

pane-viewport-regionpane[Generic function]
If the pane pane is part of a scroller pane, this returns the region of the pane's viewport. Otherwise it returns nil .

pane-scrollerpane[Generic function]
If the pane pane is part of a scroller pane, this returns the scroller pane itself. Otherwise it returns nil .

scroll-extentpane x y[Generic function]
If the pane pane is part of a scroller pane, this scrolls the pane in its viewport so that the position (x,y) of pane is at the upper-left corner of the viewport. Otherwise, it does nothing.

x and y are coordinates.

29.3.4 The Layout Protocol

The layout protocol is triggered by layout-frame , which is called when a frame is adopted by a frame manager.

CLIM uses a two pass algorithm to lay out a pane hierarchy. In the first pass (called called space composition ), the top-level pane is asked how much space it requires. This may in turn lead to same the question being asked recursively of all the panes in the hierarchy, with the answers being composed to produce the top-level pane's answer. Each pane answers the query by returning a space requirement (or space-requirement ) object, which specifies the pane's desired width and height as well as its willingness to shrink or grow along its width and height.

In the second pass (called space allocation ), the frame manager attempts to obtain the required amount of space from the host window system. The top-level pane is allocated the space that is actually available. Each pane, in turn, allocates space recursively to each of its descendants in the hierarchy according to the pane's rules of composition.


Issue: ILA
It isn't alway possible to allocate the required space. What is the protocol for handling these space allocation failures? Some kind of error should be signalled when the constraints can't be satisfied, which can be handled by the application. Otherwise the panes will fall where they may. The define-application-frame macro should provide an option that allows programmers to conveniently specify a condition handler.
For many types of panes, the application programmer can indicate the space requirements of the pane at creation time by using the space requirement options (described above), as well as by calling the change-space-requirements function (described below). For example, application panes are used to display application-specific information, so the application can determine how much space should normally be given to them.

Other pane types automatically calculate how much space they need based on the information they need to display. For example, label panes automatically calculate their space requirement based on the text they need to display.

A composite pane calculates its space requirement based on the requirements of its children and its own particular rule for arranging them. For example, a pane that arranges its children in a vertical stack would return as its desired height the sum of the heights of its children. Note however that a composite is not required by the layout protocol to respect the space requests of its children; in fact, composite panes aren't even required to ask their children.

Space requirements are expressed for each of the two dimensions as a preferred size, a mininum size below which the pane cannot be shrunk, and a maxium size above which the pane cannot be grown. (The minimum and maximum sizes can also be specified as relative amounts.) All sizes are specified as a real number indicating the number of device units (such as pixels).

space-requirement[Class]
The protocol class of all space requirement objects. There are one or more subclasses of space-requirement with implementation-dependent names that implement space requirements. The exact names of these classes is explicitly unspecified. If you want to create a new class that behaves like a space requirement, it should be a subclass of space-requirement. Subclasses of space-requirement must obey the space requirement protocol.All of the instantiable space requirement classes provided by CLIM are immutable.

make-space-requirement&key (width 0 ) (max-width 0 ) (min-width 0 ) (height 0 ) (max-height 0 ) (min-height 0 )[Function]
Constructs a space requirement object with the given characteristics, :width , :height , and so on.

space-requirement-widthspace-req[Generic function]
space-requirement-min-widthspace-req[Generic function]
space-requirement-max-widthspace-req[Generic function]
space-requirement-heightspace-req[Generic function]
space-requirement-min-heightspace-req[Generic function]
space-requirement-max-heightspace-req[Generic function]
These functions read the components of the space requirement space-req .

space-requirement-componentsspace-req[Generic function]
Returns the components of the space requirement space-req as six values, the width, minimum width, maximum width, height, minimum height, and maximum height.

space-requirement-combinefunction sr1 sr2[Function]
Returns a new space requirement each of whose components is the result of applying the function function to each the components of the two space requirements sr1 and sr2 .

function is a function of two arguments, both of which are real numbers. It has dynamic extent.

space-requirement+sr1 sr2[Function]
Returns a new space whose components are the sum of each of the components of sr1 and sr2 . This could be implemented as follows:

(defun space-requirement+ (sr1 sr2)
  (space-requirement-combine #'+ sr1 sr2))
space-requirement+*space-req &key width min-width max-width height min-height max-height[Function]
Returns a new space requirement whose components are the sum of each of the components of space-req added to the appropriate keyword argument (for example, the width component of space-req is added to width ).

This is intended to be a more efficient, ``spread'' version of space-requirement+ .

compose-spacepane &key width height[Generic function]
During the space composition pass, a composite pane will typically ask each of its children how much space it requires by calling compose-space . They answer by returning space-requirement objects. The composite will then form its own space requirement by composing the space requirements of its children according to its own rules for laying out its children.

The value returned by compose-space is a space requirement object that represents how much space the pane pane requires.

width and height are real numbers that the compose-space method for a pane may use as ``recommended'' values for the width and height of the pane. These are used to drive top-down layout.

allocate-spacepane width height[Generic function]
During the space allocation pass, a composite pane will arrange its children within the available space and allocate space to them according to their space requirements and its own composition rules by calling allocate-space on each of the child panes. width and height are the width and height of pane in device units.

change-space-requirementspane &key resize-frame &rest space-req-keys[Generic function]
This function can be invoked to indicate that the space requirements for pane have changed. Any of the options that applied to the pane at creation time can be passed into this function as well.

resize-frame determines whether the frame should be resized to accommodate the new space requirement of the hierarchy. If resize-frame is true , then layout-frame will be invoked on the frame. If resize-frame is false , then the frame may or may not get resized depending on the pane hierarchy and the :resize-frame option that was supplied to define-application-frame .

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

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

changing-space-requirements(&key resize-frame layout) &body body[Macro]
This macro supports batching the invocation of the layout protocol by calls to change-space-requirements . Within the body, all calls to change-space-requirements change the internal structures of the pane and are recorded. When the body is exited, the layout protocol is invoked appropriately. body may have zero or more declarations as its first forms.

29.4 CLIM Stream Panes

In addition to the various layout panes and gadgets, an application usually needs some space to display application-specific output and receive application-specific input from the user. For example, a paint program needs a ``canvas'' pane on which to display the picture and handle the ``mouse strokes''. An application frame can use the basic CLIM input and output services in an application-specific way through use of a CLIM stream pane .

This section describes the basic CLIM stream pane types. Programmers are free to customize pane behavior by defining subclasses of these pane classes writing methods to change the repaint or event-handling behavior.

29.4.1 CLIM Stream Pane Options

CLIM application frames accept the :foreground , :background , :text-style , and layout pane options. The space requirement options (:width , :height , and so forth) can also take a size specification of :compute , which causes CLIM to run the display function for the pane, and make the pane large enough to hold the output of the display function.

In addition to the above, CLIM stream panes accept the following options:

:display-function[Option]
This is used to specify a function to be called in order to display the contents of a CLIM stream pane. CLIM's default top level function, default-frame-top-level , function will invoke the pane's display function at the appropriate time (see the :display-time option). The value of this option is either the name of a function to invoke, or a cons whose car is the name of a function and whose cdr is additional arguments to the function. The function will be invoked on the frame, the pane, and the additional function arguments, if any. The default for this option is nil .

:display-time[Option]
This is used to indicate to CLIM when the pane's display function should be run. If it is :command-loop , CLIM will clear the pane and run the display function after each time a frame command is executed. If it is t , the pane will be displayed once and not again until (setf~pane-needs-redisplay) is called on the pane. If it is nil , CLIM will never run the display function until it is explicitly requested, either via pane-needs-redisplay or redisplay-frame-pane . The default for this option varies depending on the type of the pane.

:incremental-redisplay[Option]
When true , the redisplay function will initially be executed inside of an invocation to updating-output and the resulting output record will be saved. Subsequent calls to redisplay-frame-pane will simply use redisplay to redisplay the pane. The default for this option is nil .

:text-margin[Option]
:vertical-spacing[Option]
These options specify the default text margin (that is, how much space is left around the inside edge of the pane) and vertical spacing (that is, how much space is between each text line) for the pane. The default for :text-margin is the width of the window, and the default for :vertical-spacing is 2.

:end-of-line-action[Option]
:end-of-page-action[Option]
These options specify the end-of-line and end-of-page actions to be used for the pane. The default for these options are :wrap and :scroll , respectively.

:output-record[Option]
This option names the output record class to be used for the output history of the pane. The default is standard-tree-output-history .

:draw[Option]
:record[Option]
These options specify whether the pane should initially allow drawing and output recording. The default for both options is t .

29.4.2 CLIM Stream Pane Classes

clim-stream-pane[Service Pane]
This class implements a pane that supports the CLIM graphics, extended input and output, and output recording protocols. Most CLIM stream panes will be subclasses of this class.

interactor-pane[Service Pane]
The pane class that is used to implement ``interactor'' panes. The default method for frame-standard-input will return the first pane of this type.

For interactor-pane , the default for :display-time is nil and the default for :scroll-bars is :vertical .

application-pane[Service Pane]
The pane class that is used to implement ``application'' panes. The default method for frame-standard-output will return the first pane of this type.

For application-pane , the default for :display-time is :command-loop and the default for :scroll-bars is t .

command-menu-pane[Service Pane]
The pane class that is used to implement command menu panes that are not menu bars. The default display function for panes of this type is display-command-menu .

For command-menu-pane , the default for :display-time is :command-loop , the default for :incremental-redisplay is t , and the default for :scroll-bars is t .

title-pane[Service Pane]
The pane class that is used to implement a title pane. The default display function for panes of this type is display-title .

For title-pane , the default for :display-time is t and the default for :scroll-bars is nil .

pointer-documentation-pane[Service Pane]
The pane class that is used to implement the pointer documentation pane.

For pointer-documentation-pane , the default for :display-time is nil and the default for :scroll-bars is nil .

29.4.3 Making CLIM Stream Panes

Most CLIM stream panes will contain more information than can be displayed in the allocated space, so scroll bars are nearly always desirable. CLIM therefore provides a convenient form for creating composite panes that include the CLIM stream pane, scroll bars, labels, and so forth.

make-clim-stream-pane&rest options &key type label label-alignment scroll-bars borders display-after-commands &allow-other-keys [Function]
Creates a pane of type type , which defaults to clim-stream-pane .

If label is supplied, it is a string used to label the pane. label-alignment is as for the labelling macro.

scroll-bars may be t to indicate that both vertical and horizontal scroll bars should be included, :vertical (the default) to indicate that vertical scroll bars should be included, or :horizontal to indicate that horizontal scroll bars should be included.

If borders is true , the default, a border is drawn around the pane.

display-after-commands is used to initialize the :display-time property of the pane. It may be t (for :display-time :command-loop ), :no-clear (for :display-time :no-clear ), or nil (for :display-time nil ).

The other options may include all of the valid CLIM stream pane options.

make-clim-interactor-pane&rest options[Function]
Like make-clim-stream-pane , except that the type is forced to be interactor-pane .

make-clim-application-pane&rest options[Function]
Like make-clim-stream-pane , except that the type is forced to be application-pane .

29.4.4 CLIM Stream Pane Functions

The following functions can be called on any pane that is a subclass of clim-stream-pane . (Such a pane is often simply referred to as a window .) These are provided purely as a convenience for programmers.

window-clearwindow[Generic function]
Clears the entire drawing plane by filling it with the background design of the CLIM stream pane window . If window has an output history, that is cleared as well. The text cursor position of window , if there is one, is reset to the upper left corner.

window-refreshwindow[Generic function]
Clears the visible part of the drawing plane of the CLIM stream pane window , and then if the window stream is an output recording stream, the output records in the visible part of the window are replayed.

window-viewportwindow[Generic function]
Returns the viewport region of the CLIM stream pane window . If the window is not scrollable, and hence has no viewport, this will region sheet-region of window .

The returned region will generally be a standard-bounding-rectangle .

window-erase-viewportwindow[Generic function]
Clears the visible part of the drawing plane of the CLIM stream pane window by filling it with the background design.

window-viewport-positionwindow[Generic function]
Returns two values, the x and y position of the top-left corner of the CLIM stream pane window 's viewport. If the window is not scrollable, this will return the two values 0 and 0.

(setf* window-viewport-position)x y window[Generic function]
Sets the position of the CLIM stream pane window 's viewport to x and y . If the window is not scrollable, this will do nothing.

For CLIM implementations that do not support setf* , the ``setter'' function for this is window-set-viewport-position .

29.4.5 Creating a Standalone CLIM Window

The following function can be used to create a standalone window that obeys CLIM's extended input and output stream and output recording protocols.

open-window-stream&key port left top right bottom width height foreground background text-style (vertical-spacing 2 ) end-of-line-action end-of-page-action output-record (draw t ) (record t ) (initial-cursor-visibility :off ) text-margin save-under input-buffer (scroll-bars :vertical ) borders label[Function]
Creates and returns a sheet that can be used as a standalone window that obeys CLIM's extended input and output stream and output recording protocols.

The window will be created on the port port at the position specified by left and top , which default to 0. right , bottom , width , and height default in such a way that the default width will be 100 and the default height will be 100.

foreground , background , and text-style are used to specify the window's default foreground and background inks, and text style. vertical-spacing , text-margin , end-of-line-action , end-of-page-action , output-record , draw , and record are described in Section CLIM Stream Pane Options .

scroll-bars specifies whether scroll bars should be included in the resulting window. It may be one of nil , :vertical (the default), :horizontal , or :both . borders is a booleans that specifies whether or not the resulting window should have a border drawn around it. The default is t . label is either nil or a string to use as a label for the window.

initial-cursor-visibility is used to specify whether the window should have a text cursor. :off (the default) means to make the cursor visible if the window is waiting for input. :on means to make the cursor visible immediately. nil means the cursor will not be visible at all.

When save-under is true , the result window will be given a ``bit save array''. The default is nil .

If input-buffer is supplied, it is an input buffer or event queue to use for the resulting window. Programmers will generally supply this when they want the new window to share its input buffer with an existing application. The default is to create a new input buffer.

29.5 Defining New Pane Types

This section describes how to define new pane classes. The first section shows a new kind of leaf pane (an odd kind of push-button). The second section shows a new composite pane that draws a dashed border around its contents.

29.5.1 Defining a New Leaf Pane

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

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

;; A new kind of button.
(defclass sample-button-pane
          (action-gadget
           space-requirement-mixin
           leaf-pane)
    ())

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

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

;; Define the pane's compose-space method to always request the ;; fixed size of the pane. (defmethod compose-space ((pane sample-button-pane) &key width height) (declare (ignore width height)) (make-space-requirement :width (* 2 *sample-button-radius*) :height (* 2 *sample-button-radius*)))

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

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

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

;; This event processing method defines the rather odd interaction ;; style of this button, to wit, it triggers the activate callback ;; whenever the mouse moves into it. (defmethod handle-event ((pane sample-button-pane) (event pointer-enter-event)) (activate-callback pane (gadget-client pane) (gadget-id pane)))

29.5.2 Defining a New Composite Pane

To define a new layout pane implementation, the programmer must define how the much space the pane takes, where its children go, and what the pane looks like.

For example, to define a new kind of border pane that draws a dashed border around its child pane, proceed as follows:

;; The new layout pane class.
(defclass dashed-border-pane (layout-pane)
    ((thickness :initform 1 :initarg :thickness))
  (:default-initargs :background +black+))

;; The specified contents are the sole child of the pane. (defmethod initialize-instance :after ((pane dashed-border-pane) &key contents) (sheet-adopt-child pane contents))

;; The composite pane takes up all of the space of the child, plus ;; the space required for the border. (defmethod compose-space ((pane dashed-border-pane) &key width height) (let ((thickness (slot-value pane 'thickness)) (child (sheet-child pane))) (space-requirement+ (compose-space child :width width :height height) (make-space-requirement :width (* 2 thickness) :height (* 2 thickness)))))

;; The child pane is positioned just inside the borders. (defmethod allocate-space ((pane dashed-border-pane) width height) (let ((thickness (slot-value pane 'thickness))) (move-and-resize-sheet (sheet-child pane) thickness thickness (- width (* 2 thickness)) (- height (* 2 thickness))))) (defmethod handle-repaint ((pane dashed-border-pane) region) (declare (ignore region)) ;not worth checking (with-sheet-medium (medium pane) (with-bounding-rectangle* (left top right bottom) (sheet-region pane) (let ((thickness (slot-value pane 'thickness))) (decf right (ceiling thickness 2)) (decf bottom (ceiling thickness 2)) (draw-rectangle* medium left top right bottom :line-thickness thickness :filled nil :ink (pane-background pane))))))

(defmacro dashed-border ((&rest options &key thickness &allow-other-keys) &body contents) (declare (ignore thickness)) `(make-pane 'dashed-border-pane :contents ,@contents ,@options))




Application Frames Contents Index Gadgets