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.
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.
Returns true if object is a pane , otherwise returns
false .
The basic class on which all CLIM panes are built, a subclass of pane .
| make-pane | abstract-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-1 | realizer 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.
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.
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.
This option specifies the name of the pane. It defaults to nil .
29.2.2 Pane Properties
| pane-frame | pane | [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-name | pane | [Generic function] |
Returns the name of the pane.
| pane-foreground | pane | [Generic function] |
| pane-background | pane | [Generic function] |
| pane-text-style | pane | [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
All of the layout pane classes accept the :contents options, which is used
to specify the child panes to be laid out.
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 .)
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.
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 .
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
| 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:
| 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 .
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 .
| 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")))
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.
A pane that allows its children to be any size and lays them out wherever they
want to be (for example, a desktop manager).
| 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-viewport | pane | [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-region | pane | [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-scroller | pane | [Generic function] |
If the pane pane is part of a scroller pane, this returns the scroller
pane itself. Otherwise it returns nil .
| scroll-extent | pane 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).
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-width | space-req | [Generic function] |
| space-requirement-min-width | space-req | [Generic function] |
| space-requirement-max-width | space-req | [Generic function] |
| space-requirement-height | space-req | [Generic function] |
| space-requirement-min-height | space-req | [Generic function] |
| space-requirement-max-height | space-req | [Generic function] |
These functions read the components of the space requirement space-req .
| space-requirement-components | space-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-combine | function 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-space | pane &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-space | pane 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-requirements | pane &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-changed | sheet 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 .
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 .
| :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.
This option names the output record class to be used for the output history of
the pane. The default is standard-tree-output-history .
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 .
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-clear | window | [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-refresh | window | [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-viewport | window | [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-viewport | window | [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-position | window | [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))