ToC DocOverview CGDoc RelNotes FAQ Index PermutedIndex
Allegro CL version 11.0

Common Graphics classes


app

class, cg package

The class of an application under development or being run. It is unlikely that programmers need to use this class. Most of the methods are intended for potential future enhancements and unused in the current release.


audio-player

Class, cg package

A widget that plays audio files, typically mp3 files. It is currently implemented only for CG/JS mode, though it could also be implemented for Windows desktop mode as a widget on top of the mci-wave-audio API. It shares the media-player API with the video-player widget. The value property of the widget is the file path namestring of the audio file that the widget is currently playing or ready to play.


audio-player-pane

Class, cg package

The class of the pane of an audio-player widget.


bar-chart-view

Class, cg package

The class of a bar-chart-view. The unique properties of bar-chart-view are:

The bar-chart-view inherits additional properties from chart-view.

See chart-widget and also cg-chart-widget.html.


basic-pane

class, cg package

The class of all windows (excluding menus, which are not usually regarded as windows). A basic-pane instance by default appears on the screen as a simple rectangular blank area with no border or title-bar, but may have any of the standard window attributes by specifying them explicitly when calling make-window.

Windows are Common Lisp streams, and so various standard stream functions may be applied to them. For example, stream output functions such as print and format will draw text on a window, and a window is closed by calling close on it. (See also user-close.) The devide-open generic function may be extended with custom methods that do additional setup when a window is created. The function windowp will return true if its argument is a window and it is currently open.

This class is suitable to use as the superclass of custom application window classes when it is desirable to start with the simplest type of window, adding particular default attributes as needed. For windows that have borders and title-bars, it may be simpler to instead subclass frame-window. If backing-store is desired, instead use a bitmap-pane or bitmap-window. If controls are to be added to the window, a dialog is recommended.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


bitmap-pane

class, cg package

A class of window that provides automatic backing-store. When things are drawn on a bitmap-pane, the window stores everything that has been drawn in an unseen memory bitmap (which is similar to a bitmap-stream). When the window is later uncovered, the built-in redisplay-window method for bitmap-panes copies the stored image back to the visible window.

This built-in behavior refreshes the window more quickly than would a non-trivial custom redisplay-window method that redraws everything from scratch. It also allows the application to add to the drawing at any time rather than encapsulating the drawing code into a custom redisplay-window method as usual. (An application should never add a redisplay-window method to a bitmap-pane class.)

The drawback is that significant memory is required for the memory bitmap. Usually it is best to instead use a more general type of window such as a frame-window or non-refreshing-window, unless the quicker redisplay provided by the backing-store is needed. Creating a bitmap-pane or increasing its page size with set-page-size could signal an error of type memory-bitmap-not-created if there is not enough memory for the memory bitmap.

A special technique for switching a bitmap-pane to a completely new drawing very quickly is described under with-delayed-redraw, with an example. An alternate technique for quick redisplay is the double-buffered property (which works with arbitrary windows, rather than with bitmap-panes only).

Typically this class is instantiated indirectly by creating a bitmap-window, whose frame-with-single-child features are recommended when a toolbar or status-bar is to be added to the window. Otherwise, a title-bar and/or border could be added directly to a standalone bitmap-pane if these options are explicitly specified when calling make-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


bitmap-stream

class, cg package

A class of object similar to windows in that you can draw onto it but it is never visible on the screen. Its contents, however, can be copied onto a visible window using copy-stream-area. A bitmap-window (or bitmap-pane) has the functionality of a bitmap-stream hardwired into it, implementing the backing-store for automatically refreshing and redisplaying the window. Bitmap-stream is provided in case you want to manage the drawings stored in memory independently. For an example using bitmap-streams, choose the Help menu | CG Examples and look for Bitmap-streams: custom backing store.

One creates a bitmap-stream by calling open-stream, passing the desired size as the value of page-width and page-height keyword arguments. Below is an example expression that creates a bitmap-stream; the two nil arguments are required due to the two deprecated optional parameters of open-stream.

(open-stream 'bitmap-stream nil nil
  :page-width 600 :page-height 400
  :background-color yellow)

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


bitmap-window

class, cg package

A class of window that automatically adds a bitmap-pane child window. The bitmap-pane provides backing-store for automatic redisplay of the window's contents without writing a redisplay-window method, and the automatic instantiation of the child window (supplied by the superclass frame-with-single-child) makes this class suitable for windows that are also to have a toolbar or status-bar.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


box

class, cg package

The class of box objects. A box is created with make-box, and indicates a rectangular area in some coordinate system by specifying its left, top, right, and bottom coordinates. Boxes are useful for determining such things as a window's location and size or where to draw something on a graphical stream.

While boxes are geometric shapes, that can be drawn with drawing functions like draw-box, they are also used as data structures.

See also box-bottom, box-bottom-center, box-bottom-right, box-bottom-left, box-center, box-center-x, box-center-y, box-height, box-intersect, box-intersect-p, box-left, box-left-center, box-move, box-right, box-right-center, box-top, box-top-center, box-top-left, box-top-right, box-union, box-width, box=, boxp, center-to-box, center-to-box-x-y, copy-box, draw-box, erase-box, erase-contents-box, fill-box, and nbox-move.


build-module

class, cg package

The symbol naming this class has been moved to the :ide package. Please see build-module.


button

class, cg package

Class

The class of a standard button control having the title attribute displayed on the face of the button. Subclasses include default-button and cancel-button.

Control

Instance of the button class. This is a standard button control displaying text. The on-change function begins any action initiated by the button being clicked.

Adding a button control to your form

Click the button tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Notes

The displayed name of the button is the value of the title property. If the wrapping property is true, the title will wrap text to a second line if necessary. If wrapping is nil, text that does not fit will not be displayed.

This button doesn't stay pressed in when clicked. It gives a little jump and then returns to its resting state.

The background color is inherited from Windows. Use a picture-button if you want more control over the appearance.

Creating an instance of a button control

This call to make-instance returns an instance of button. Properties and event-handlers can be initialization keyword arguments (the keyword has the same name as the property, with a prepended colon, e.g. :width for width). Additional arguments could be provided. Their absence indicates the default value will be used.

(make-instance 'button
               :font
                 (make-font-ex nil "MS Sans Serif" 11 nil)
               :left 263
               :name :button4
               :on-click 'form1-button4-on-click
               :title "Here"
               :top 160
               :width 33))

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


button-info

class, cg package

Class

The class of individual button on a multi-picture-button control.

Creating a button-info instance

This call to make-instance returns an instance of a button-info. Properties can be initialization keyword arguments (the keyword has the same name as the property, with a prepended colon, e.g. :width for width). Additional arguments could be provided. Their absence indicates the default value will be used.

(make-instance 'button-info
               :name :new
               :pixmap-name :new
               :pixmap-source nil
               :pixmap-icon nil
               :background-color nil
               :foreground-color nil
               :title nil
               :width nil
               :height nil
               :stretching t
               :tooltip nil
                :help-string "Open a blank editor window")

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code. The example above came from placing a multi-picture-button on a form and looking at the resulting .bil file.


button-pane

class, cg package

The class of widget-windows that are instantiated whenever a button is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a button subclass or otherwise add methods to the widget-window of a button. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


calendar

class, cg package

This widget displays a calendar that always has a particular date selected. The user can select a different date in a variety of ways.

The value property of the widget always contains a universal time integer for the currently-selected date. (Due to using Lisp universal times, dates before 1900 cannot be selected.) You can set the slected date with (setf value) applied to a calendar instance. The new value must be an integer representing a universal time.

If you set the selected date programmatically by passing a universal time to (setf value), it may be prudent to use a universal time whose time of day is not within an hour of one AM to avoid any possible confusion related to daylight savings time. Internally the widget arbitrarily always specifies 4 AM to encode-universal-time when the user selects a date interactively. Other than that, the time (hour, minute, second) of the universal time which is the value is ignored.

In the main mode, all of the dates of a single month are displayed at any one time, with a row for each week. The user can browse to other months, and also switch to three alternate modes that display an entire year, decade, or century.

The user can click any "cell" in the calendar to select a date when a month is displayed, or to select a month when a year is displayed, and so on. The arrow buttons in the top right and left corners can be clicked to display the next or previous "page", such as the next month when a month is displayed or the next year when a year is displayed. Clicking the title displays the next higher level, such as the year that contains the month that was displayed. Clicking a value in a higher level displays the selected value at the next lower level; for example, clicking July when a year is displayed displays the dates of July of that year. This allows selecting any date by "zeroing in" on it in a top-down manner.

Here are the keyboard alternatives for navigating the calendar (letters should be entered un-shifted -- they are shown uppercase because that is the standard was to identify keyboard letters):

Action Equivalent key or letter
Select the cell to the right R or RightArrow
Select the cell to the left L or LeftArrow
Select the cell above U or UpArrow
Select the cell below D or DownArrow
Display the next page N or PageDown or Control-RightArrow
Display the previous page P or PageUp or Control-LeftArrow
Move to the next higher level H or Control-UpArrow
Move to the next lower level G or Control-DownArrow or Spacebar

Some calendar cells are displayed in a special way. By default, the currently-selected date displays a light-blue background and a blue border. The date that's currently under the mouse has a similar style using fainter colors. Today's date is drawn with red text. And dates for the next and previous month (which share the first and last week of the displayed month) are drawn with gray text. Any of these styles may be modified by using the cell-style, cell-style-selected, cell-style-under-mouse, cell-style-current-date, and cell-style-other-month properties of the widget, respectively. And you can avoid drawing today's date in a different way by simply turning off the highlight-current-date property.

Here are some other calendar properties that control the layout and drawing style of the widget:

The following properties may be read to retrieve the individual parts of the currently selected date, as an alternative to parsing the universal time that's in the value property. A new date can be selected programmatically only by setting the value property, though.


cancel-button

class, cg package

Class

The class of the cancel-button control. A subclass of button.

Control

Instance of the cancel-button class. This control is typically used to cancel an action in a modal dialog using return-nil-from-pop-up-dialog. Cancel buttons intercept the ESC key as a mouse click.

Usually this type of control has the name CANCEL, but you can change the title property to anything you like.

Adding a cancel-button control to your form

Click the cancel-button tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Notes

It is an error to place more than one cancel-button on a dialog.

This button doesn't stay pressed in when clicked. It gives a little jump and then returns to its resting state.

The displayed name of the button is the value of the title property. If the wrapping property is true, the title will wrap text to a second line if necessary. If wrapping is nil, text that does not fit will not be displayed.

Creating an instance of a cancel-button control

This call to make-instance returns an instance of a cancel-button. Properties can be initialization keyword arguments (the keyword has the same name as the property, with a prepended colon, e.g. :left for left). Additional arguments could be provided. Their absence indicates the default value will be used.

(make-instance 'cancel-button
               :font
                 (make-font-ex nil "MS Sans Serif" 11 nil)
               :left 189
               :name :cancel-button-1
               :title "Cancel"
               :top 146)

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


caret-mixin

class, cg package

Mix this class in with each of your window classes to create windows that have carets. You must create a class that has both caret-mixin and some instantiable window class as its superclasses, and then create an instance of that class.

This is a non-instantiable class.

Carets are specific to Microsoft Windows, and caret code in an application will have no effect in CG/JS mode.


cell-style

class, cg package

This class is used to specify the style in which one of the cell types of a calendar widget is drawn. A calendar widget will create the instances of this class that it needs by default, though an application can completely replace a default style by creating a cell-style instance and passing it when creating the calendar widget. Alternately, an application can modify any of the existing cell-style instances of a calendar widget after the widget has been created.

The various cell-styles used by a calendar instance are accessed with the generic functions cell-style, cell-style-selected, cell-style-under-mouse, cell-style-current-date, and cell-style-other-month.

A cell-style has the properties background-color, foreground-color, border-color, border-width, and bold-text. Here are examples of the two alternate ways to specify a custom cell style.

;; Make a calendar widget, and then modify its built-in cell-style
;; for the date that's under the mouse to have blue text.
(let* ((calendar (make-instance 'calendar)))
  (setf (foreground-color (cell-style-under-mouse calendar)) blue)
  calendar)

;; Create a calendar widget with a custom cell-style object
;; for the date that's currently under the mouse.
(make-instance 'calendar
  :cell-style-under-mouse
  (make-instance 'cell-style
    :foreground-color (make-rgb :red 0 :green 128 :blue 192)
    :background-color light-gray   ;; nil means no background
    :border-color dark-blue
    :border-width 2                ;; nil or zero means no border
    :bold-text t))    

cg-configuration

class, cg package

The class of the Common Graphics configuration object, which contains a variety of options for the way that Common Graphics behaves, either in the IDE or in a standalone application. Most of the options appear on the Tools | Options dialog, chiefly on the CG tab. The complete set of Common Graphics options may be viewed or modified in the IDE Inspector by using the Tools | Inspect System Data | CG Configuration Options menu command.

The Common Graphics configuration object may also be accessed programmatically with the expression (configuration *system*) (see configuration and *system*). For example, to set the global tooltip delay in a Common Graphics application to 500 milliseconds (the default is 1000), the application's startup code should include the following form:

(setf (tooltip-delay (configuration *system*)) 500)

The IDE normally saves all Common Graphics and IDE configuration options in an allegro-ide-options.cl file, so that future IDE sessions will retain option settings that were made in earlier sessions. (See save-options-on-exit.) In a standalone Common Graphics application, on the other hand, Common Graphics options must be set programmatically in application code, and IDE options are of course not available.

See also ide-configuration, which covers IDE options.


cg-stream

class, cg package

The class of all Common Graphics streams, which include windows, menus, bitmap-streams, printer streams, and the screen (see screen). These objects are instances of the Common Lisp stream class (specifically of the simple-stream class) because, like other output streams, these objects are opened and closed, and a stream of output may be written to them while they are open (and only then). (An exception is that stream output may not be written to a menu, but it still is usable only while it is open.)

While conventional streams deal with a one-dimensional sequence of characters or bytes, most cg-streams deal with two-dimensional graphical output. This output is still ordered in time though, and therefore can still be thought of as a flowing stream of graphical output.

In addition to using Common Graphics drawing functions such as draw-line and copy-to-stream to draw on cg-streams, the text output functions of Common Lisp such as print and format may also be used to draw text to a cg-stream. These functions will draw at the current-position of the stream and update the current-position to the end of the text. Text is simply one kind of graphical output that may be sent to a cg-stream.

All windows and the screen are always interactive streams (see interactive-stream-p), not because the user may prompt for stream input in them, but because output to these streams is often intended to be visible to the user immediately in interactive user interfaces. Since interactive streams always call force-output automatically after each call to text output functions, it should never be necessary for an application to call force-output or finish-output on a window or the screen. For other cg-streams, all of the Common Graphics graphical drawing functions will do a force-output just before they do their drawing, and so it should not be necessary to call force-output or finish-output between drawing Common Lisp text output and drawing Common Graphics graphical output to the same cg-stream in order to ensure that everything is drawn in the correct order.

The text-edit-pane (along with its subclasses such as rich-edit-pane) is the only cg-stream class that can do input. This window is actually a control. It is usually used only for text input and output, as a file stream might be used, but arbitrary graphical drawing may also be done to it as well. (Being a control, graphical output to a text-edit-pane must be surrounded by a call to with-device-context.)

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


cgjs-options

Class, cg package

The class of an object that holds the CG/JS server options for a project. See the cgjs-options accessor function of a project.


character-format

class, cg package

A class of objects that contains a set of character format parameters. A character-format instance has these slots:

face, point-size, bold, italic, underline, color, same-face, same-point-size, same-bold, same-italic, same-underline, same-color.

These properties correspond to the multiple values returned by get-character-format. The first six properties take the same kinds of values as the same arguments to set-character-format, while the remaining same-foo properties are boolean values.

A character-format instance may be used to copy character-formatting from one place to another. Alternately, a set of several character formats may be managed in order to apply particular styles to various places in a rich-edit-pane.

When applying a character-format, the face of the text will be changed only if same-face is non-nil, and likewise for the other corresponding properties. Therefore, if a character-format retrieved from a section of text by calling character-format is applied to another section of text by calling (setf character-format), only those attributes that were uniform over the entire copied text will be changed in the target text. For example, if the copied text includes some bold text as well as some non-bold text, then the boldness of the target text will not change.

See cg-rich-text.html for information about rich text editing in Common Graphics.


chart-axis

Class, cg package

The class of the chart-axis. This is the superclass of item-axis and value-axis. This class is not instantiable. Here are the properties that are unique to chart axes and common to both types of chart axis:

See chart-widget and also cg-chart-widget.html.


chart-legend

Class, cg package

The class of the chart-legend. The following properties are unique to chart-legends:

See chart-widget and also cg-chart-widget.html.


chart-or-plot

Class, cg package

The non-instantiable superclass of chart-widget and plot-widget. Properties defined on this class may be used with either a chart-widget or a plot-widget instance.

Here are the properties that are supplied by the chart-or-plot class:

See cg-chart-widget.html for an introduction to the chart-widget, much of which also applies to the plot-widget.


chart-or-plot-pane

Class, cg package

The class of the pane of a chart or a plot.

See chart-widget and also cg-chart-widget.html.


chart-or-plot-view

class, cg package

The class of a chart-or-plot-view. This is a non-instantiable superclass of chart-view and plot-view. It provides properties that are common to all "view" objects that are used by the chart-widget and plot-widget controls. The unique properties of chart-or-plot-view are:

See chart-widget, plot-widget, and also cg-chart-widget.html.


chart-view

Class, cg package

The class of a chart-view. This is the non-instantiable superclass of line-graph-view and bar-chart-view. It provides properties that are specific to the chart-widget. The unique property of chart-view is values-are-stacked.

The chart-view inherits additional properties from chart-or-plot-view.

See chart-widget and also cg-chart-widget.html.


chart-widget

Class, cg package

The class of the chart-widget.

The chart-widget is a versatile facility for creating two-dimensional line graphs and bar charts. (To plot X/Y coordinate pairs instead, see the plot-widget class.)

The chart widget could be used to present static information or to dynamically monitor information as it changes. The widget will automatically lay out its axes and other parts (according to style properties that you can modify) and can also autocompute a rounded value range that encloses all of the data values. A long sequence of data items can be scrolled into view by dragging the mouse or using the usual scrolling keys.

Chart subobjects

The following classes are used to create secondary objects that are used by a chart-widget:

Each of these classes has its own properties (that is, slots and accessors).

Properties of the chart-widget class

These properties are unique to the chart-widget class.

Additional chart-widget properties are provided by the chart-or-plot superclass.

chart-widget example

Below is a quick chart-widget example. See the chart-widget tutorial (cg-chart-widget.html) for more examples with more extensive explanations. The tutorial is probably the best way to learn the widget. There is also an example in the IDE's Navigator dialog that generates random charts to show off the variety of its styles.

The following example code demonstrates the two main alternate techniques for supplying the data for a chart: (1) calling set-chart-value once for each datum, and (2) supplying a chart-value-returner function that will be called as needed to return each value.

For both techniques we will use the following sample data. Each of the entries in this list will become one "chart item" for a bowling event, and each person that is mentioned in the plists of bowling scores will become one "chart object".

(defparameter *scores*
  '(((2005 dec 12) :doris 164 :tal 152)
    ((2006 feb 3) :doris 168 :tal 145 :hubert 103)
    ((2006 feb 18) :doris 160 :tal 173 :hubert 110 :myrtle 124)
    ((2006 jun 17) :doris 172 :tal 160 :myrtle 142)
    ((2006 aug 31) :tal 170 :myrtle 135)))

The first version of the example code uses the approach of calling set-chart-value for each datum, after creating the chart-widget.

(let* ((width 300)
       (height 400)
       (chart-widget
        (make-instance 'chart-widget
          :title "Bowling Scores"
          :chart-view :line
          :fit-chart-items t
          :item-axis (make-instance 'item-axis
                       :on-print-major-label
                       (lambda (date)
                         (format nil "~:(~a~) ~a ~a"
                           (second date)(third date)(first date))))
          :chart-legend (make-instance 'chart-legend
                          :on-print-chart-object 'capitalize-object)
          :right-attachment :right
          :bottom-attachment :bottom
          :left 0 :top 0 :width width :height height))
       (dialog (make-window :bowling-scores
                 :class 'dialog
                 :title "Bowling Scores"
                 :scrollbars nil
                 :interior (make-box-relative 40 40 width height)
                 :dialog-items (list chart-widget)))
       item-id)
  (dolist (item *scores*)
    (setq item-id (pop item))
    (loop (unless item (return))
          (set-chart-value
           chart-widget
           :item-id item-id
           :object-id (first item)
           :value (second item))
          (setq item (cddr item))))
  dialog)

The second version builds the same chart by supplying a chart-value-returner function rather than by calling set-chart-value in a loop. When using a chart-value-returner, you generally need to supply a list of chart-objects and a chart-items-max-index to tell the widget the range of items and objects for which it should query values.

(let* ((width 300)
       (height 400)
       (chart-widget
        (make-instance 'chart-widget
          :title "Bowling Scores"
          :chart-view :line
          :fit-chart-items t
          :item-axis (make-instance 'item-axis
                       :on-print-major-label
                       (lambda (date)
                         (format nil "~:(~a~) ~a ~a"
                           (second date)(third date)(first date))))
          :chart-legend (make-instance 'chart-legend
                          :on-print-chart-object 'capitalize-object)
          :chart-objects '((:id :doris)(:id :hubert)(:id :myrtle)(:id :tal))
          :chart-items-max-index (1- (length *scores*))
          :chart-value-returner
          (lambda (chart-widget value-type item-index
                                object-index object-id)
            (declare (ignore chart-widget object-index))
            (let* ((item (nth item-index *scores*)))
              (case value-type
                (:id (first item))
                (:value (getf (rest item) object-id)))))
          :right-attachment :right
          :bottom-attachment :bottom
          :left 0 :top 0 :width width :height height)))
  (make-window :bowling-scores
    :class 'dialog
    :title "Bowling Scores"
    :scrollbars nil
    :interior (make-box-relative 40 40 width height)
    :dialog-items (list chart-widget)))

See cg-chart-widget.html.


chart-widget-pane

Class, cg package

The class of the pane of a chart-widget.

See chart-widget and also cg-chart-widget.html.


check-box

class, cg package

Class

The class of the check-box control.

Control

Instance of the check-box class. This is a standard check-box control. A check-box is a control which permits two of three states (depending on the value of the three-state property).

A two-state check-box is either toggled on or off by clicking it. When it is on, the value field of the dialog item is set to t and the box is filled with a check mark. When it is off, the value field of the dialog item is set to nil and the box is blank.

A three-state check-box will show a third grayed-out state when its value is :gray. This intermediate state is typically used either to indicate that a true-or-false value is unknown or undetermined, or that some but not all of a set of subchoices are selected. Clicking on or otherwise selecting the check-box will cycle its value between nil, t, and :gray (in that order). The value can also be :except-interactively, which allows :gray to be specified programmatically but not by clicking it or by pressing the spacebar when it has the keyboard focus.

You can have as many check-boxes on a dialog as you wish. Each one works independently of the others; that is, they aren't defined in groups via the :cluster property as radio-buttons are.

The title field of the dialog item is used as the label of the check-box, and is displayed immediately to the right of the check-box itself. The title will wrap or not as the wrapping property is true or nil.

Adding a check-box control to your form

Click the check-box tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size. Note: resizing the check-box control changes the size of the bounding-box, but not the size of the actual check-box inside. Resize the label for the box by changing the font property.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Creating an instance of a check-box control

This call to make-instance returns an instance of a check-box. Properties can be initialization keyword arguments (the keyword has the same name as the property, with a prepended colon, e.g. :left for left). Additional arguments could be provided. Their absence indicates the default value will be used.

(make-instance 'check-box
                :font
                 (make-font-ex nil "MS Sans Serif" 11 nil)
                :left 242
                :three-state nil ;; a two-state check-box
                                 ;; specify t for a three-state
                                 ;; check-box. Note that the three-state
                                 ;; property cannot be changed after
                                 ;; a check box is created.
                :name :check-box-1
                :title "Check Box"
                :top 180)

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


check-box-column

class, cg package

A grid-column subclass whose superclasses are check-box-column-mixin and grid-column. This class may be instantiated directly when no further subclassing is needed, and therefore is convenient when creating a grid-widget interactively on a form window and then editing its properties in the inspector (see cg-grid-widget-simplified-tutorial.html). In the inspector, you could move to an existing grid-column and then set its class property to check-box-column to turn it into this type of column (where the class choices are available in the drop-down list for the class property). See check-box-column-mixin for the widget behavior.


check-box-column-mixin

class, cg package

A non-instantiable class that can be mixed with the grid-column class to create grid columns whose cells act like check-box controls. Each cell in the column will implement the pseudo-control if the row of that cell is an instance of a grid-row subclass that mixes in the widget-row-mixin class. See check-box-column for an instantiable subclass that you can use directly when no further subclassing is needed, even specifying it interactively.

To ensure that this mixin class' methods take precedence over other methods that specialize on grid-column, this mixin class generally should appear first in a defclass expression's list of superclasses, as in:

(defclass my-check-box-column
  (check-box-column-mixin my-subclass-of-grid-column) ...)

The draw-cell method provided by this mixin will call read-cell-value to determine whether to draw the check mark. If read-cell-value returns nil, it will not draw a check mark, and otherwise it will.

When the user clicks the check-box gadget displayed in the cell, the cell-click method provided by this mixin calls write-cell-value with a value of either t or nil so as to change the domain value represented by the cell. Alternately the user may press the spacebar or the enter key to simulate clicking the check-box.

The title-reader property of the column should be used to determine the string to display in each check-box cell. The click-must-be-on-gadget property may be used to determine where the user must click within the cell to activate the cell's gadget.

See the section Built-In Grid Cell Widgets on the page for the grid-widget class for an overview of the grid column mixins.

A quicker but less object-oriented alternative to using the widget-column-mixin classes is to write cell-widget methods.


check-box-pane

class, cg package

The class of widget-windows that are instantiated whenever a check-box is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a check-box subclass or otherwise add methods to the widget-window of a check-box. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


class-grid

Class, cg package

A class-grid is a specialized grid-widget subclass that makes it easier to create grids that edit instances of classes. Rather than defining row and column classes and then instantiating those classes and adding them to a grid-widget, you instead specify a single expression that parametrically describes the slots to be edited, and then the class-grid will automatically create grid columns for those slots. It will also automatically create grid rows for a set of instances when you set its value property to be a list of instances.

A class-grid always has a single body section with other sections for column and row headers, and there are other limitations to the style of the grid. In exchange for those limitations, a class-grid is much easier to set up than a general grid-widget.

Using a Class-Grid

To use a class-grid, there are three main properties that you need to set:

Other Class-Grid Properties

A class-grid has all of the properties of a grid-widget, but you shouldn't set the column-sections and row-sections properties because they are created automatically from the edited-slots property. Since you cannot specify properties of a class-grid's sections and subsections directly at creation time, some high-level properties are defined on the class-grid class itself that will affect its subobjects. These properties include:

To reject invalid slot values as soon as the user enters them, write one or more validate-edited-slot-value methods.

For advanced use, after a class-grid has been created you could find the automatically created column and row sections and their subsections and modify them as with any other grid-widget. To do so, you may want to know that the two column-sections are named :header and :body (in that order), and so are the two row-sections. The single subsection of each header section is also named :header. The name of each column in the body is the name of the slot that it edits.

See also class-grid-top-pane and class-grid-drawing-pane.


class-grid-body-column

Class, cg package

The subclass of class-grid-column that is used in the body of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-body-column-section

Class, cg package

The subclass of class-grid-column-section that is used in the body of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-body-row

Class, cg package

The subclass of widget-row-mixin and class-grid-row that is used in the body of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-body-row-section

Class, cg package

The subclass of class-grid-row-section that is used in the body of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-check-box-column

Class, cg package

A subclass of check-box-column-mixin and class-grid-body-column that is used by a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-column

Class, cg package

The subclass of grid-column that is used for all columns of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-column-header-row

Class, cg package

The subclass of column-sizing-row-mixin, column-selecting-row-mixin, and class-grid-row that is used by the column headers of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-column-header-row-section

Class, cg package

The subclass of row-section-with-sort-gadget-mixin and class-grid-row-section that is used for the column headers of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-column-section

Class, cg package

The subclass of grid-column-section that is used for all column-sections of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-combo-box-column

Class, cg package

A subclass of combo-box-column-mixin and class-grid-body-column that is used by a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-drawing-pane

Class, cg package

The subclass of grid-drawing-pane that is used for a class-grid.


class-grid-editable-text-column

Class, cg package

A subclass of editable-text-column-mixin and class-grid-body-column that is used by a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-lisp-text-column

Class, cg package

A subclass of editable-text-column-mixin and class-grid-body-column that is used by a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-numeric-editable-text-column

Class, cg package

A subclass of class-grid-editable-text-column that is used by a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-pixmap-column

Class, cg package

A subclass of pixmap-column-mixin and class-grid-body-column that is used by a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-row

Class, cg package

The subclass of grid-row that is used for all rows of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-row-header-column

Class, cg package

The subclass of row-sizing-column-mixin, row-selecting-column-mixin, and class-grid-column that is used for the row headers of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-row-header-column-section

Class, cg package

The subclass of class-grid-column-section that is used for the row headers of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-row-section

Class, cg package

The subclass of grid-row-section that is used for all row-sections of a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-static-text-column

Class, cg package

A subclass of static-text-column-mixin and class-grid-body-column that is used by a class-grid.

A class-grid creates instances of this class automatically, so an application should not do so directly.


class-grid-top-pane

Class, cg package

The class of lisp-widget-window that is used as the main window of a class-grid widget. A subclass of grid-top-pane.


client-port

class, cg package

The symbol naming this class has been moved to the dde package. Please see client-port.


column-defaults

class, cg package

The class of the subsection-defaults of a grid-column-section.


column-header-defaults

class, cg package

The class of the object that is returned by calling column-header-defaults on a grid-widget. See that function for more information.


column-header-row

class, cg package

A sub-class of grid-row that is handy for implementing a row of column header cells. Specifically, this class mixes together the classes column-sizing-row-mixin, column-selecting-row-mixin, and grid-row. Using this class is simply a shortcut for making a subclass of those classes yourself. See those superclasses for more information.

See also the Navigator dialog example (on the Examples tab) entitled "Grid-Widget: a more sophisticated employee chart".


column-selecting-row-mixin

class, cg package

A grid-row that is an instance of this class allows the user to select and/or move grid-columns by clicking the cells where they cross the grid-row. The selectable property of a column must also be true before the column may be interactively selected, and the movable property of a column must also be true before the column may be interactively moved. In other words, a column may be interactively selected at a particular cell if the column is a selectable one and the row at that cell is an instance of column-selecting-row-mixin; and (likewise) a column may be interactively moved (among the columns in its grid-column-section) at a particular cell if the column is a movable one and the row at that cell is an instance of column-selecting-row-mixin.

This feature is typically used only in a grid-row that serves as a set of column headers, so that the special column-selecting and/or -moving behavior does not override other cell-click behavior in the body of the grid-widget. Nevertheless, it may sometimes be desirable to use this class for multiple rows of a grid.

The user uses this feature by moving the mouse cursor into a cell in a selectable or movable grid-column where it crosses a column-selecting-row-mixin row. The user may click and drag horizontally in this cell to reposition the grid-column, or click and release without moving the mouse more than *start-drag-slack* pixels to toggle the selected property of the column. When the mouse button is released after a drag, the column is positioned among the columns in its grid-column-section so that it is just to the right of all of the columns whose vertical centers are to the left of the final vertical center of the drag box (this should be intuitive). A drag may be canceled either by pressing the Escape key before releasing the mouse button or by releasing the mouse button while the drag box is positioned where the column would snap back to where it was already.

An individual selectable grid-column may be added to the current set of selected columns in its grid-column-section by holding down the Control key while clicking the column; if the column is already selected, then this deselects the column instead. If the Shift key is held down while clicking a selectable column, then the range of columns that just encompasses all of the columns that were already selected plus the column that was clicked are then left in a selected state (regardless of their selected state beforehand).

This class must be mixed with grid-row (or one of its subclasses) to make an instantiable class. It is best to specify such mixin classes ahead of the grid-row class in the list of superclasses for a new class, so that the small amount of special behavior from the mixin class will override the more general behavior of the grid-row class. For example:

(defclass my-column-selecting-row (column-selecting-row-mixin grid-row)())

The above default mouse click behavior may be overridden by custom cell-click methods.

For an example of column-selecting-row-mixin, see the Navigator dialog example (on the Examples tab) entitled "Grid-Widget: a basic replicated editable-text column". See also the class column-header-row, which combines this class with column-sizing-row-mixin and grid-row for use as a typical row of column headers.

See also slide-subsection.


column-sizing-row-mixin

class, cg package

A grid-row that is an instance of this class allows the user to interactively change the width of grid-columns where they cross the grid-row. The resizable property of a column must also be true before interactive resizing is possible for that column. In other words, a column may be interactively resized at a particular cell if the column is a resizable one and the row at that cell is an instance of column-sizing-row-mixin.

This feature is typically used only in a row that serves as a set of column headers, so that the special column-sizing mouse cursor does not appear frequently as the user moves the mouse over the body of the grid (which might be distracting), and/or to prevent the user from inadvertantly resizing a column slightly if they click too near a cell's border when they mean to click in its interior. Nevertheless, it may sometimes be desirable to use this class for multiple rows, or even every row, of a grid.

The user uses this feature by moving the mouse cursor to the righthand border of a cell in a resizable column where it crosses a column-sizing-row-mixin row. The mouse cursor will change to indicate where resizing may be initiated; this area ranges from the rightmost edge of the border to *grid-border-mouse-slack* pixels to the left of that. The user may click and drag horizontally in this area to resize the grid-column. If the uniform-resizing property of the grid section is true, then all of the columns in the clicked grid-column-section will be sized to the specified size, though if the Control key is held down then the behavior of the uniform-resizing property is reversed. The drag may be canceled either by pressing the Escape key before releasing the mouse button or by releasing the mouse button to the left of the left side of the column (which would otherwise makes its width be negative).

This class must be mixed with grid-row (or one of its subclasses) to make an instantiable class. It is best to specify such mixin classes ahead of the grid-row class in the list of superclasses for a new class, so that the small amount of special behavior from the mixin class will override the more general behavior of the grid-row class. For example:

(defclass my-column-sizing-row (column-sizing-row-mixin grid-row)())

The above default mouse click behavior may be overridden by custom cell-click methods.

The width of a grid-column is stored as its section-size property. See also stretch-subsection.

See the grid-widget class for an overview of writing grid-widget code.


combo-box

class, cg package

Class

The class of the combo-box control

Control

Instance of the combo-box class. This control is similar to pop-up-menu except that it can be operated from the keyboard using the arrow keys.

Adding a combo-box control to your form

Click the combo-box tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size. Note: resizing the combo-box means horizontal resizing only. Changing the size of the combo-box won't mean proportional changes in the size of the characters inside the box. Change the font property if you want to change the size of the actual characters displayed.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Customizing combo-box behavior

To allow users to type directly in the box instead of pulling down and selecting a value, set the value of the typable property. If it is specified non-nil, users may type a new value directly into the edit-box of a combo-box rather than being forced to select a value from the drop-down list.

Comparing values in a combo-box range

Combo-boxes use on-change-test to compare their value to elements in their rangerange. The initial value of the on-change-teston-change-test is eql. That value is inappropriate if the values in the range are strings: equal would be more appropriate for strings (two strings with the same characters may not be eql but are equal.

Displaying all the box values either all at once or one at a time

The dropping property is no longer supported. (It was supposed to control whether all values of the combo-box were always displayed or not.)

Scrollbars

Combo-box controls cannot have a horizontal scrollbar, so the valid choices are :vertical and nil for the scrollbars property. If a horizontal scrollbar is needed on a combo-box, an outline control could be used instead, using only top-level items in the range and turning off the draw-icons property to simulate a combo-box.

Creating an instance of a combo-box control

This call to make-instance returns an instance of a combo-box. Properties can be initialization keyword arguments (the keyword has the same name as the property, with a prepended colon, e.g. :left for left). Additional arguments could be provided. Their absence indicates the default value will be used.

(make-instance 'combo-box
               :font
                (make-font-ex nil "MS Sans Serif" 11 nil)
               :left 238
               :name :combo-box-1
               :range '(:one :two :three)
               :top 106
               :value :one)

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


combo-box-column

class, cg package

A grid-column subclass whose superclasses are combo-box-column-mixin and grid-column. This class may be instantiated directly when no further subclassing is needed, and therefore is convenient when creating a grid-widget interactively on a form window and then editing its properties in the inspector (see cg-grid-widget-simplified-tutorial.html). In the inspector, you could move to an existing grid-column and then set its class property to combo-box-column to turn it into this type of column (where the class choices are available in the drop-down list for the class property). See combo-box-column-mixin for the widget behavior.


combo-box-column-mixin

class, cg package

A non-instantiable class that can be mixed with the grid-column class to create grid columns whose cells act like combo-box controls. Each cell in the column will implement the pseudo-control if the row of that cell is an instance of a grid-row subclass that mixes in the widget-row-mixin class. Instances of this may use real combo-boxes or simulations (such as pop-up menus). Which is used depends on the value of the use-real-combo-box property. See combo-box-column for an instantiable subclass that you can use directly when no further subclassing is needed, even specifying it interactively.

To ensure that this mixin class' methods take precedence over other methods that specialize on grid-column, this mixin class generally should appear first in a defclass expression's list of superclasses, as in:

(defclass my-combo-box-column
  (combo-box-column-mixin my-subclass-of-grid-column) ...)

The draw-cell method provided by this mixin will call read-cell-value to find the value to draw in the cell, and then call the column's data-read-converter function to convert the value to the actual string to draw.

When the user clicks on the down-arrow gadget displayed in the cell, the cell-click method provided by this mixin displays a list of choices and calls write-cell-value with the new choice if the user selects one. When the user clicks anywhere else in the cell, other properties of the grid-column determine whether this gesture displays the list of choices, initiates type-in, or does nothing. The user may alternately press the spacebar to emulate clicking on the down-arrow or the enter key to emulate clicking elsewhere in the cell.

The typable property of the column may be used to indicate whether the user may optionally type in a new value directly. When the typable property is true, the edit-start-trigger and edit-end-trigger properties of the column may be used to determine what gesture the user must make to initiate and complete the typing in of a new value for the cell. This type of column may also be given a template-string to restrict what the user may enter.

The range-reader property should be used to determine the set of choices that will be presented in each cell's drop-down list. The on-print property may be used to convert the choices to strings to be displayed in the cell's drop-down list (though the column's data-read-converter is called to convert the cell's actual value to the string displayed in the cell).

The click-must-be-on-gadget property may be used to determine where the user must click within the cell to display the list of choices when the typable property is nil. (When typable is true, the user must always click on the drop-down arrow to show the list of choices, since clicking elsewhere in the cell initiates type-in instead.)

See the section Built-In Grid Cell Widgets on the page for the grid-widget class for an overview of the grid column mixins.

A quicker but less object-oriented alternative to using the widget-column-mixin classes is to write cell-widget methods.


combo-box-pane

class, cg package

The class of widget-windows that are instantiated whenever a combo-box is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a combo-box subclass or otherwise add methods to the widget-window of a combo-box. See widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


common-status-bar

class, cg package

The class of the common status bar. See add-common-status-bar.


comtab

class, cg package

A class of objects which control keyboard behavior. Also called command tables or keystroke command tables. Comtabs are often used in editor implementations; they associate Lisp functions with certain key combinations.

See set-event-function, whose description includes a comtab example.


comtab-mixin

class, cg package

This is a non-instantiable class which must be a superclass of any window class whose instances are to be given comtabs. text-edit-pane is the only built-in instantiable window class that has comtab-mixin as a superclass. If comtabs are desired on other windows, then a subclass must first be created with comtab-mixin as one of the superclasses.

See set-event-function, whose description includes a comtab example.


configuration

class, cg package

The class of objects which are data structures that hold configuration options of the system.


cursor

class, cg package

The class of mouse cursor objects. Any window, widget (dialog-item), or hotspot may be given its own mouse cursor by calling (setf cursor). See the section on mouse cursors in cg-pixmaps.html for more infomation.


default-button

class, cg package

Class

The class of the default-button control. A subclass of button.

Control

Instance of the default-button class. Default buttons are used in modal dialogs as the OK button. This button usually appears with a double-thickness black line around it to mark it as the primary choice on a dialog.

Rename your default-buttons (Yes, Continue, Find, and Accept are all common names for them) by changing the title property.

Why use a default button control instead of a button control?

The default button differs from the regular button and cancel-button controls by its on-change function. Default buttons have their on-change event-handler set to return-t-from-pop-up-dialog. They catch the ENTER or RETURN keystroke as a button press when they have the keyboard focus. Use this control when you want your software users to be able to click a button to continue the dialog's process by default.

Adding a default-button control to your form

Click the default-button tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Notes

It is an error to place more than one default-button on a dialog.

Although a dialog contains a default-button, the actual default button (the one invoked if ENTER is pressed and the one surrounded by a thick black border) can be set dynamically with set-default-button.

The displayed name of the button is the value of the title property. If the wrapping property is true, the title will wrap text to a second line if necessary. If wrapping is nil, text that does not fit will not be displayed.

This button doesn't stay pressed in when clicked. It gives a little jump and then returns to its resting state.

Creating an instance of a default-button control

This call to make-instance returns an instance of a default-button. Properties can be initialization keyword arguments (the keyword has the same name as the property, with a prepended colon, e.g. :left for left). Additional arguments could be provided. Their absence indicates the default value will be used.

(make-instance 'default-button
               :font
                (make-font-ex nil "MS Sans Serif" 11 nil)
               :left 321
               :title "Default"
               :name :default-button-1
               :top 193)

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


development-main-window

class, cg package

The class of the unseen IDE owner window that allows the separate top-level IDE windows to behave as a single application.


dialog

class, cg package

A class of window that is suitable for displaying controls (also called widgets and dialog-items). Controls may actually be added to any window, but dialogs are the only windows that have special behavior for moving the keyboard focus among the controls. This behavior includes pressing the TAB key to move to the next widget, or pressing a letter key while holding down the Alt key to move to the widget whose label underlines that character. (To be precise, this behavior is defined on the non-instantiable dialog-mixin class, and dialog is the only built-in instantiable class that inherits this behavior.)

dialogs are often shown modally by calling pop-up-modal-dialog. When this is the purpose of a dialog, it is typically useful to specify the pop-up property of the dialog as true. This property coerces various other properties to their conventional values for modal dialogs. dialogs are created by calling make-window just as other windows are.

An application can draw on a dialog just as it would on other windows. Drawing that would intersect controls (or other child windows) will not cover the controls, and instead will appear to be covered by the controls.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


dialog-item

class, cg package

A non-instantiable class which is a superclass of various control classes.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


dialog-mixin

class, cg package

A non-instantiable class that provides specific behavior for using the keyboard to move the keyboard focus among the controls on a window by pressing the TAB key (or arrow keys in a group of buttons) or the various Alt key shortcuts for each widget. This mixin also provides the behavior where pressing the Enter key emulates pushing the default-button that's on the window (if any), and pressing the Escape key emulates pressing the cancel-button (if any).

Usually this behavior is obtained by instantiating the built-in dialog class to create a window that is to have controls on it, but this mixin class exists separately in case this special dialog behavior needs to be mixed with other window classes.


drawable

class, cg package

Class

A vanilla control for drawing arbitrary custom drawings. The drawing can either be performed at will or by an on-redisplay handler function whenever a redisplay is needed. A bitmap-stream may optionally be used by the control, either to remember what currently should be drawn on the control or to draw updates with less flashing.

A drawable control allows a drawing field in a dialog. Other ways to combine drawing with controls is to use a window with one pane a bitmap-pane and another a dialog, or to use a bitmap-window with a toolbar (on which controls can be placed). It is also possible to place controls directly on a bitmap-pane, though in that case certain features are lost, such as using the TAB key to move focus from one control to another. (However, if that feature is less important, putting controls directly on a bitmap-pane does allow for faster redisplay.)

This widget has page-width, page-height, and scrollbars properties, which are usually properties of windows rather than widgets. For a drawable widget, these properties work just as they do with windows.

There are two issues with images on a drawable control: displaying them in the first place and refreshing them when necessary (when, for example, the control is covered and uncovered, or iconified and expanded).

If use-bitmap-stream is nil, drawing is done by the on-redisplay function. This function (an example is given on the on-redisplay page) should do all drawing necessary. Whenever redisplay is necessary, this function will be called. Redisplay is forced by a call to update-drawable. It is also forced when a drawable is covered and uncovered or when it is iconified and expanded.

Whenever a drawable control needs to be redrawn, such as when it is uncovered, redisplay-event is called on it. The default redisplay-event method essentially just calls the on-redisplay handler of the drawable if it has one, and the on-redisplay handler is the more typical place to place custom drawing code.

If use-bitmap-stream is true, there will be a bitmap-stream associated with the drawable control, returned by the function bitmap-stream applied to the drawable. Drawing should be done to this bitmap-stream, and then the drawable should be refreshed with a call to update-drawable. The drawable will also be updated when it is covered and uncovered, or iconified and expanded. (Note that drawing is not done directly on the drawable. The bitmap-stream is not visible. It must be copied to the drawable. Note that this copying can become expensive if the image is large and redisplays are frequent.)

The function drawable-stream returns the bitmap-stream of a drawable if there is one and the window of the drawable otherwise.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

The Navigator has an example (on the Examples tab) of the drawable widget called "An Animated 'Drawable' Control". It illustrates smooth animation using the use-bitmap-stream option of the widget and a timer to control the speed of the animation. Display the Navigator dialog with the Help menu | Navigator menu command.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


drawable-pane

class, cg package

The class of lisp-widget-windows that are instantiated whenever a drawable is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a drawable subclass or otherwise add methods to the lisp-widget-window of a drawable. See lisp-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


dropping-outline

class, cg package

Class

The class of the dropping-outline control. This is a special subclass of outline that can drop the outline itself down from a single-line widget that simply displays the current value, similar to a drop-down list widget or combo-box.

A dropping outline does not change its selection when its pixmaps are clicked to expand or collapse items. This feature allows users to expand or condense the outline hierarchy without making a selection, since making a selection un-drops the outline.

Control

An instance of the dropping-outline class. This control is similar to a combo-box, only when you open it, you expose an outline rather than a list. It is a special subclass of the outline class.

Users can only see one outline item at a time in the dropping-outline display, but when the down-arrow portion of the control is clicked the outline will drop (open up) to the size you define when sizing the control. Note that the outline may be clipped by the boundaries of the dialog containing the dropping-outline control. Whether of not it is clipped is controlled by the top-level-dropper property.

Once dropped, arrow keys can be used to navigate in the outline.

Adding a dropping-outline control to your form

Click the dropping-outline tool on of the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size.

Resizing this control horizontally changes the size of the un-dropped form of the control.

Resizing the control vertically defines the full size of the window displaying the dropped version of the control. If you need a taller window to display the dropped-outline items in a running form, go back to the layout and resize the control vertically.

Resizing the dropping-outline won't mean proportional changes in the size of the characters inside the list. Change the font property if you want to change the size of the actual characters displayed.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Creating an instance of a dropping-outline control

See the example form creating an outline widget in the description of the outline class. Replace the first five lines with

(make-window 'dropping-outline-dialog  ;; new name for window
  :class 'dialog
  :interior (make-box-relative 100 200 240 140)
  :dialog-items
  (list (make-instance 'dropping-outline  ;; instead of 'outline
  ...
  )))

The example will now create a dropping outline rather than an outline.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


editable-text

class, cg package

Class

The class of the editable-text control (and super class of a multi-line-editable-text control). These controls can accept text which can be edited by the user, and which is displayed surrounded by a box. The edited text is stored as a simple string in the value field of the dialog item.

The text initially displayed can be specified by storing a simple string in the value field. The delayed property controls whether the dialog-item value is updated after every keystroke or only when the user moves to another item.

You can constrain the number of characters, the types of characters that can be entered, and add characters that display but cannot be modified in an editable-text widget with template-string and *template-chars*.

Control

An instance of the editable-text class. This control contains editable text displayed surrounded by a box.

The edited text is stored as a simple string in the value field of the dialog item. The text initially displayed can be specified by storing a simple string in the value field.

editable-text controls do not have titles. If you want to add a title to your editable-text control, pair it with a static-text control.

Adding an editable-text control to your form

Click the editable-text tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size. Note: resizing the control changes the size of the bounding-box, but not the size of the actual characters inside. Change the font property if you want to change the size of the characters.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Customizing editable-text control behavior

When user-generated changes appear: the delayed option controls whether the dialog-item value is updated after every keystroke or only after the user moves to another item on the dialog.

Number, type, and read-only qualities of characters: you can constrain the number of characters, constrain the types of characters that can be entered, and add characters that display but cannot be modified in an editable-text widget with template-string and *template-chars*.

Adding a password: the password property can be set with a non-nil value, and the widget will echo asterisks (or another character, if desired) for each typed character (preventing others who see the screen from knowing what was typed).

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


editable-text-column

class, cg package

A grid-column subclass whose superclasses are editable-text-column-mixin and grid-column. This class may be instantiated directly when no further subclassing is needed, and therefore is convenient when creating a grid-widget interactively on a form window and then editing its properties in the inspector (see cg-grid-widget-simplified-tutorial.html). In the inspector, you could move to an existing grid-column and then set its class property to editable-text-column to turn it into this type of column (where the class choices are available in the drop-down list for the class property). See editable-text-column-mixin for the widget behavior.


editable-text-column-mixin

class, cg package

A non-instantiable class that can be mixed with the grid-column class to create grid columns whose cells act like multi-line-editable-text controls. Each cell in the column will implement the pseudo-control if the row of that cell is an instance of a grid-row subclass that mixes in the widget-row-mixin class. See editable-text-column for an instantiable subclass that you can use directly when no further subclassing is needed, even specifying it interactively.

To ensure that this mixin class' methods take precedence over other methods that specialize on grid-column, this mixin class generally should appear first in a defclass expression's list of superclasses, as in:

(defclass my-editable-text-column
  (editable-text-column-mixin my-subclass-of-grid-column) ...)

The edit-start-trigger and edit-end-trigger properties of the column may be used to determine what gesture the user must make to initiate and complete the typing-in of a new value for the cell. The user may press either the spacebar or the enter key to emulate clicking on a cell in this column, and so that will initiate type-in in the same cases that clicking will. This type of column may also be given a template-string to restrict what the user may enter. The scrollbars property determines whether a vertical scrollbar will appear during editing; when true (the default) a scrollbar will appear, and when nil it will not appear (to save space in the cell).

When the user initiates type-in according to the edit-start-trigger property, the user is allowed to edit the string displayed in the cell. The user may then either press the escape key to cancel the edit, or accept the edit by pressing the enter key or by moving the keyboard focus out of the cell. If the edit is accepted and the text has changed, then the column's data-write-converter function is called to convert the typed string to a meaningful data object, which is then written by calling write-cell-value.

The read-cell-value method supplied by this mixin calls the column's data-read-converter to convert the actual domain data value represented by this cell into a string to be drawn in the cell. This string is also the initial string to be edited when the user initiates type-in.

See the section Built-In Grid Cell Widgets on the page for the grid-widget class for an overview of the grid column mixins.

A quicker but less object-oriented alternative to using the widget-column-mixin classes is to write cell-widget methods.


editable-text-pane

class, cg package

The class of widget-windows that are instantiated whenever an editable-text is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of an editable-text subclass or otherwise add methods to the widget-window of an editable-text. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


font

class, cg package

The class of font objects. See make-font and make-font-ex.


font-face-combo-box

class, cg package

A subclass of combo-box, used for changing the font face of an associated rich-edit control. The control's range is always the set of font faces that are currently installed in the operating system at runtime. When the end user selects a font face, the selected text in the associated rich-edit control is changed to the selected face. The control's value will also update automatically to display the font face of the text that is currently selected in the associated rich-edit control, if that face is installed.

If there are any rich-edit controls on the same parent window as the font-face-combo-box, and at least one of them has had the keyboard focus, then the combo-box will affect the rich-edit that most recently had (or still has) the focus; otherwise it will do nothing. If a rich-edit is not found on the same parent window, then the grandparent window is searched, followed by the great-grandparent and so on; this allows a font-face-combo-box to be placed on the toolbar of a dialog that contains a rich-edit control in its main area, for example.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


font-size-combo-box

class, cg package

A subclass of combo-box, used for changing the font height of an associated rich-edit control. This control's range is always a standard list of typical font sizes, though any size may be typed in. When the end user selects a font face (see font-face-combo-box), the selected text in the associated rich-edit control is changed to the selected font height. The control's value will also update automatically to display the font size of the text that is currently selected in the associated rich-edit control.

If there are any rich-edit controls on the same parent window as the font-size-combo-box, and at least one of them has had the keyboard focus, then the combo-box will affect the rich-edit that most recently had (or still has) the focus; otherwise it will do nothing. If a rich-edit is not found on the same parent window, then the grandparent window is searched, followed by the great-grandparent and so on; this allows a font-size-combo-box to be placed on the toolbar of a dialog that contains a rich-edit control in its main area, for example.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


fontmetrics

class, cg package

The class of fontmetrics objects. Some functions that return attributes of fonts may be passed the font object directly, but most of them must instead be passed a fontmetrics object that reflects the font as it is used on a particular graphical stream.

A fontmetrics is created by calling either make-fontmetrics or fontmetrics, and is returned by each of those functions as well as by nfontmetrics. Once a fontmetrics object is returned by a call to either fontmetrics or nfontmetrics, it holds the values of various attributes of the current font of the window. Various accessor functions such as font-leading and font-fixed-width-p can then be called on the fontmetrics object to obtain information about the font as used on that stream.

Most of the fontmetrics accessors return the size (in pixels) of various parts of a character cell, such as font-descent to return the part of each character cell that is reserved for the parts of characters that descend below the baseline. These values may be different on different streams, even for a font of a particular declared pixel size (see font-size and make-font-ex). This might even be true among different kinds of windows on a single screen at a particular resolution. Therefore, these accessor functions do not work on a font object by itself, and must instead by passed a fontmetrics object that reflects the current font of a particular stream on which it may be used.

Example

In this example, the form will return the internal font leading of the specified font when it is used on the window "my-window".

(let* ((font-37 (make-font-ex nil "Arial" 24)))
  (with-font (my-window font-37)
    (font-internal-leading (fontmetrics my-window))))

Here is an example function that collects all of the attributes of a font and returns them as a plist. It allows you to pass in the stream where the font might be used, in case any measurements may differ based on the stream, and otherwise uses the screen for measurements. The function illustrates how some font attribute functions must be passed a fontmetrics object, while others take the font itself.

(defun font-attributes (font &key (stream (screen *system*)))
  
  ;; This is needed if the stream is the screen or an instance
  ;; of os-widget-window, since these streams do not have permanent
  ;; device-contexts as "regular" windows do.
  (with-device-context (hdc stream)
    
    ;; Assign the font to the stream, and THEN retrieve a
    ;; fontmetrics object for the stream, which will then reflect
    ;; that font as used on that stream.
    (with-font (stream font)
      (let* ((fm (fontmetrics stream))
             (plist nil))
        
        ;; Collect every attribute that requires a fontmetrics
        ;; object from our fontmetrics object that reflects the font.
        (dolist (accessor
                 '#.(reverse
                     '(font-height
                       font-ascent font-descent font-leading
                       font-external-leading font-internal-leading
                       font-fixed-width-p font-average-char-width
                       font-max-char-width font-vector-p
                       font-truetype-p font-device-p font-direction)))
          (push (funcall accessor fm) plist)
          (push accessor plist))
        
        ;; Add to the list the other font attributes that can be
        ;; called directly on the font object itself.
        (dolist (accessor
                 '#.(reverse
                     '(font-family
                       font-face font-size font-style
                       font-style-word font-size-is-char-height)))
          (push (funcall accessor font) plist)
          (push accessor plist))
        
        ;; Return the list of all of the font's attributes.
        plist))))

;;; Try printing the attributes of an example font.
(pprint (font-attributes (make-font-ex nil "Arial" 24 '(:bold))))

==> (font-family nil font-face "Arial" font-size 24 font-style (:bold)
             font-style-word 1 font-size-is-char-height t
             font-height 30 font-ascent 23 font-descent 6
             font-leading 6 font-external-leading 1
             font-internal-leading 5 font-fixed-width-p nil
             font-average-char-width 11 font-max-char-width 64
             font-vector-p t font-truetype-p t font-device-p nil
             font-direction :left-right)

form

class, cg package

The class of forms, the windows used in projects to design application windows. See Designing a user interface using forms in the IDE User Guide.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


form-module

class, cg package

The symbol naming this class has been moved to the :ide package. Please see form-module.


form-pane

class, cg package

The symbol naming this class has been moved to the :ide package. Please see form-pane.


frame-window

class, cg package

A class of window that by default has a border, scrollbars, and a title-bar with the standard small buttons for iconizing, maximizing, and closing the window. Otherwise a frame-window is a general window similar to a basic-pane. Despite the name, which might suggest that the window is useful only for adding a frame around other windows, a frame-window can be drawn on directly.

This class is suitable to use as the superclass of custom application window classes that have borders and titlebars. frame-windows are also resizable by default, though this can be overridden, for example, by explicitly passing the resizable keyword argument to make-window as nil, or by specifying the :resizable :default-initarg of a subclass as nil. Any other window attributes that a particular window class provides by default may be turned off similarly, or additional attributes added.

For windows that are also to have a toolbar or status-bar, the non-refreshing-window class is recommended instead due to its frame-with-single-child properties that accomodate toolbars and status-bars. If backing-store is desired, instead use a bitmap-pane or bitmap-window. When adding controls, a dialog is recommended.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


frame-with-single-child

class, cg package

A non-instantiable superclass of the instantiable window classes non-refreshing-window, bitmap-window, and text-edit-window. When a frame-with-single-child subclass is instantiated by calling make-window, the frame window that is created directly serves only as a frame (consisting of a title-bar and/or a border), and a second window is created automatically as child pane that serves as the interior drawing area.

A frame-with-single-child window is most useful when a toolbar or status-bar is to be added to the window, especially if the window has scrollbars. The reason is that these auxilliary windows are created as siblings of the automatically-added child pane, and the scrollbars (if any) are created on the child pane rather than on the frame. This arrangement allows the application to draw in the entire page-box of the child pane without any of the drawing being covered by the toolbar or status-bar, and allows the drawing to scroll without scrolling the toolbar or status-bar along with it.

This double-window arrangement is also needed for a text-edit-window, because a text-edit-pane is actually a control internally and cannot have a frame itself. (For other window classes, frame attributes may be added even when the class excludes them by default for typical usage as a frameless pane.)

A default-pane-class method that specializes on the frame-with-single-child class determines what class is instantiated to make the child pane. When subclassing a frame-with-single-child class for use in an application, it is typically necessary to subclass both the frame class and the pane class, and then to define a trivial default-pane-class method to associate the two with each other. Several of the examples in the Examples tab of the Navigator dialog, including the "Custom Windows" example at the top of the list, illustrate this common technique.

The function frame-child returns the child pane that was automatically added to a frame-with-single-child window. The function owner, as usual, will return the frame window from the pane.

Note that any drawing that is done must be done on the pane window rather than on the frame window, because the frame's interior is covered by the pane. Until version 6.0, Common Graphics would automatically divert drawing to the pane window, but this is no longer done because it was deemed more confusing than useful. Various other functions must be called on the pane itself when it is the true object of interest, even though the two windows are conceptually a single window.

The frame-child pane window resizes itself as needed whenever the frame window (or its interior) is resized by always setting its right-attachment property to :right and its bottom-attachment to :bottom. Applications may use this techique for custom child panes that do not use the built-in frame-with-single-child facility. This may be necessary, for example, if multiple child panes are desired or a single child pane is desired that does not fill the frame window's interior.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


graphical-stream

class, cg package

This non-instantiable class is the superclass of all stream classes onto which graphics can be drawn. This includes windows (instances of basic-pane and its subclasses), the screen (whose class is screen), bitmap-stream, and printer streams. The class may be useful for specializing methods that should apply to any stream on which graphics can be drawn.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


grid-column

class, cg package

The class of a column in a grid-widget control.


grid-column-section

class, cg package

The class of a grid-column-section. It inherits from cg.grid:grid-section-any and grid-section. This is the top-level user class for creating column sections.

The cg.grid:grid-section-any class (which is named by a symbol not exported from the cg package and therefore not elsewhere documented) is a superclass of both grid-section (grid-row-sections and grid-column-sections) and grid-subsection (grid-rows and grid-columns) and provides functionality common to those classes.

See the grid-widget class for an overview of writing grid-widget code.


grid-drawing-pane

class, cg package

The class of a grid-drawing-pane window. A grid-drawing-pane is a child window of the main widget-window (of class grid-top-pane) that is associated with a grid-widget, and is where the entire grid is drawn except for the outermost grid border. The function grid-drawing-pane (when called on a grid-top-pane instance) returns the grid-drawing-pane child window just as the function window (when called on the grid-widget itself) returns the main widget-window.

See grid-drawing-pane-class-for-grid for information on subclassing the grid-drawing-pane of a grid-widget.


grid-row

class, cg package

The class of a row inside of a grid-widget control.


grid-row-section

class, cg package

The class of a grid-row-section. This class inherits from cg.grid:grid-section-any and grid-section. This is the top-level user class for creating row sections.

See the grid-widget class for an overview of writing grid-widget code.


grid-row-section-with-sort-gadget

class, cg package

A grid-row-section subclass whose superclasses are row-section-with-sort-gadget-mixin and grid-row-section. It can be instantiated directly when no further subclassing is needed. When creating a grid-widget interactively on a form window (see cg-grid-widget-simplified-tutorial.html), its row-section for column headers will be an instance of this class.


grid-section

class, cg package

The uninstantiable parent class for grid-row-sections and grid-column-sections.

See the grid-widget class for an overview of writing grid-widget code.


grid-subsection

class, cg package

The class of a grid-subsection, which can be either a row or column of a grid. See grid-widget for an overview of writing grid-widget code.


grid-top-pane

class, cg package

The class of lisp-widget-windows that are instantiated whenever a grid-widget is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a grid-widget subclass or otherwise add methods to the lisp-widget-window of a grid-widget. See lisp-widget-window, grid-drawing-pane (the generic function), grid-drawing-pane (the class), and grid-drawing-pane-class-for-grid.


grid-widget

class, cg package

Class

The class of all grid-widget controls.

Control

An instance of the grid-widget class. This is a very versatile (and therefore relatively complex) widget that is useful for implementing things such as spreadsheets and tables. Grid cells can either use built-in cell widgets or implement custom drawing and mouse/keyboard behavior.

A grid-widget may be divided into multiple sections, each of which may be independently scrollable and resizable. Within each section are rows and columns that are collectively known as subsections. (Sections are sometimes referred to as main sections to distinguish them from subsections.) Rows and columns may be interactively resized, moved (to change their order), selected, and deleted, whenever each of those options is enabled. Rows and columns may be added and removed programmatically at any time. A row or column can have its own individual stylistic properties, and can also be replicated to produce a set of identical visual rows or columns that are represented by a single row or column lisp object.

Each section, row, and column is implemented as a standard-object. A grid cell does not have a Lisp object to represent it because the number of cells increases quadratically as the rows and columns increase. Instead, a cell is accessed by methods that specialize on both the row and column whose intersection defines the cell.

Some illustrations

The Examples tab of the Navigator has several Grid widgets examples. We illustrate some here.

Here is Grid-widget: the simplest possible grid-widget-example. A simple grid. Left click on a cell and an X is marked (as we have done with several). Right click and the X goes away. Note the scroll bars. The widget is bigger than the window displaying it.

Here is a more complex example Grid-widget: using built-in cell widgets in ARBITRARY cells.

All these examples (and there are several more) are available to run and the code the generates them can be examined and adapted or reused. See the Examples tab of the Navigator.

Writing Grid-Widget Code

Using a grid-widget consists of constructing the grid-widget from sections and subsections, specifying various stylistic properties, and (the trickier part) writing methods that control how various grid cells read application data to display, draw themselves based on that data, respond to mouse clicks and keypresses, and finally write user-modified data back to the application.

Most of the grid-widget documentation describes this very general approach that offers the most flexibility and power. But for typical fairly simple grids, you may be able to use a simpler interactive approach where you place a grid-widget onto a form window (along with other widgets), and then use the inspector to specify the properties of the grid-widget and its child objects. And later you can still incorporate aspects of the more general programmatic approach as needed. See the cg-grid-widget-simplified-tutorial.html document, which has a worked out example of creating a grid-widget control in that way.

Constructing a Grid-Widget

Normally you will first define subclasses of various grid classes so that you can specialize methods on them. The basic classes to subclass are grid-widget, grid-row-section, grid-column-section, grid-row, and grid-column. When you create a grid-widget instance, specify its row-sections property as a list of instances of your grid-row-section subclasses, and its column-sections property as a list of your own grid-column-sections. When making each grid-row-section or grid-column-section, specify its subsections property as a list of instances of your grid-row or grid-column subclasses (respectively).

Optionally, you can also specify the section-count property of a row or column to make that single row or column lisp object produce multiple identical visual rows or columns, which are distinguished by an index only. Subsections can also be added and removed later by calling add-row, add-column, delete-row, and delete-column. Call make-instance as usual to create each object.

Grid sections and subsections have various properties that determine how they appear and behave mechanically. These may be specified when creating each object and/or changed anytime later. Some of these properties apply to both sections and subsections, including resizable, section-size, border-width, border-dashing, border-color, and proportional. Properties that apply only to sections include scrollbars, uniform-resizing, empty-color, default-cell-3d-border, default-cell-border-color, and default-cell-border-width. Properties that apply only to subsections include movable, deletable, and selectable.

Manipulating Application Data in a Grid-Widget

In addition to writing code to constuct a grid-widget and specify its mechanical behavior, you need to write methods that specify how it displays application data and optionally modifies it. (Further below we discuss some higher-level alternatives that can remove the need to write some or all of these methods.) Here are the basic generic functions to specialize in order to display data in a grid-widget:

And here are the basic generic functions to specialize if you also want to allow the user to modify the data interactively in the grid, rather than simply viewing it:

Higher-Level Alternatives

The above generic functions are all that you need to specialize in order to write your data-manipulating grid code from scratch. But there is some additional higher-level grid functionality that can reduce the number of grid methods that must be written for typical applications.

These alternatives are applicable to any application that uses grid rows to represent data objects and grid columns to represent their properties. For example, one of the Navigator grid examples uses grid rows to represent employees, and grid columns to represent properties such as employee name and department. We will discuss that example here.

This higher-level functionality falls into two camps: reader and writer properties, and cell widgets.

Reader and Writer Properties

The first higher-level alternative lets you avoid writing read-cell-value and write-cell-value methods. In an application such as the employee example, you would probably have an employee class that already has accessor functions such as employee-name and employee-department. When representing employees and their properties in a grid-widget, you could specify the data-object property of each grid-row as the employee that the row represents, and specify the data-reader property of each grid-column as the existing accessor function (such as employee-name or employee-department) for the property that the column represents. If you are allowing the user to modify data values in the grid, then you could also specify a function such as (setf employee-name) as the data-writerdata-writer property of the column.

It just so happens that the default read-cell-valueread-cell-value method calls the grid column's data-reader function on the row's data-object, if both of those exist. And the default write-cell-value method calls the column's data-writer function on the data-object. This means that by specifying data-object, data-reader, and data-writer properties for your grid subsections, you can avoid writing custom read-cell-value and write-cell-value methods for various types of cells. You can still write your own draw-cell methods that call the default read-cell-value method, though, and write custom cell-click and cell-key-down methods that call the default write-cell-value method. See also data-read-converter and data-write-converter.

Built-In Grid Cell Widgets

The other higher-level alternative lets you avoid writing custom draw-cell, cell-click, and cell-key-down methods. It consists of several types of built-in "cell widgets" that know how to draw themselves and how to respond to user gestures to modify the represented value. When using these built-in cell widgets, you can still write your own read-cell-value and write-cell-value methods that will be called automatically by the built-in cell widget code. Or use both of these higher-level alternatives together to avoid writing any custom methods.

Since there is not an object for each grid cell, the built-in cell widgets are defined as mixin classes that you combine with a grid-column class. The defined classes are editable-text-column-mixin, check-box-column-mixin, combo-box-column-mixin, static-text-column-mixin, static-text-and-button-column-mixin, pixmap-column-mixin, and lamp-column-mixin. The pseudo-widget will appear in any cell whose column is an instance of one of these mixin classes and whose row is an instance of the widget-row-mixin class. This design lets you specify a type of widget for some subset of the cells of a grid column. This is appropriate for applications that use a grid column to represent a property, since typically the same widget would be appropriate for editing a particular property regardless of which data object (grid row) is being edited.

Typically you would have a header row or row-section that does not have the widget-row-mixin, and then a number of "body" rows that do have it, so that the widget does not appear in the header row. See also row-header-column and column-header-row.

A quicker but less object-oriented way to use the built-in cell widgets is to write cell-widget methods. This bypasses the widget-column-mixin and widget-row-mixin classes altogether, and allows the widgets to be used in arbitrary cells rather than only in particular columns for each type of widget.

Controlling the Built-In Draw-Cell Methods

If you are using a built-in draw-cell method that's supplied by a cell widget, or the default method that displays any cell value as a string, then you can still exert some control over how a cell draws itself. You do this by writing trivial methods that return specific aspects of the drawing style. The generic functions to specialize include cell-font, cell-background-color, cell-foreground-color, cell-horizontal-padding, cell-vertical-padding, cell-horizontal-justification, cell-vertical-justification, cell-wrapped-p, cell-3d-border, and data-read-converter. Each built-in draw-cell method will call some subset of these generic functions and use the values that they return.

Caching Read-Cell-Value Values and Delaying Write-Cell-Value Calls

By default, an application's read-cell-value method (or a data-reader function that the default method calls) is called every time a cell is drawn to return the value to display. If this code takes significant time, then these calls can be minimized by setting the grid-widget's cache-cell-values property to true.

Similarly by default, an application's write-cell-value method (or a data-writer function that the default method calls) is called immediately whenever the user interactively edits the value in a grid cell. To delay these calls that modify application data until the user either confirms or rejects recent edits sometime later, set the grid-widget's delay-write-cell-value property to true.

Bypassing Read-Cell-Value and Write-Cell-Value Altogether

Perhaps it will be clear at this point that read-cell-value and write-cell-value exist primarily because the higher-level grid features uses them to separate the functionality that they provide from the methods that you still have to write. So if you are not using either higher-level alternative, then a draw-cell method actually would not need to call a separate read-cell-value method, and could instead fetch its application data to draw directly. Similarly, a cell-click or cell-key-down method would not need to call a separate write-cell-value method, and could instead modify the application's data directly. The "simple color editor" example in Navigator is an example of this.

Adding a Grid-Widget to a Form

A grid-widget can be added to a form interactively as with other widgets, but it is probably simpler to write all of its code programmatically, due to the need to define subclasses and properties for sub-components. To usefully add a grid-widget to a form interactively, you probably should first define the subclasses for your grid-widget, sections and subsections, and give them default-initargs that specify the properties that you would like for their instances, and then call add-to-component-toolbar to add your customized grid-widget class to the widget palette.

A higher-level alternative that is already in the widget palette is the class-grid. A class-grid works well when created interactively on a form because all of its customizable properties are at the top level rather than on grid sections.

Additional Grid-Widget Help

Please refer to the multiple grid-widget examples in Navigator for complete example code. And to look up additional grid functionality that was not covered here, look at the Allegro Tree of Knowledge (displayed with the Help | Tree of Knowledge menu command). In that dialog, do Search | Find Forward on the string "grid-widget".

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


group-box

class, cg package

Class

The class of a group-box control.

Control

Draws a black titled box of specified size. Used to group items. Note that though this widget appears as a simple line around other widgets, it is actually an opaque area. Therefore, you need to insure that any widgets appearing inside the group-box are displayed after the group-box is (since otherwise they will be buried behind the opaque group-box). The buried widgets will be invisible.

The order in which you need to list the widgets depends on when you create them. If you are passing in a list of widgets to make-window, the group-box should come after the items inside it. If, on the other hand, you are calling add-component to add individual widgets to a parent window that already exists, then you should either add the group-box before adding the widgets that are inside it, or else pass the optional behind argument to add-component when adding the group-box, so that it will be placed behind existing widgets rather than possibly burying them. When interactively placing widgets onto form windows in the IDE, the form window knows how to keep group-boxes behind any widgets that they encompass, and so you don't need to handle that yourself.

If the title property of a group-box is either nil or the null string, then no title is drawn and the border forms a complete rectangle. Also, the top edge of the group box will move up to the top edge of the group box's region (rather than being a bit lower as usual to align with the vertical center of the title text).

If either the width or the height of a group-box is less than 20, then the group box will be drawn as a single vertical or horizontal line (respectively) instead of as a narrow box, and the title will not be drawn. The single line will still have a 3D look as long as the border is :raised-edge or :sunken-edge.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

Note about releases prior to 6.1: this class was named lisp-group-box. The symbol lisp-group-box still names a class which is a subclass of group-box with nothing added.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


group-box-pane

class, cg package

The class of lisp-widget-windows that are instantiated whenever a group-box is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a group-box subclass or otherwise add methods to the lisp-widget-window of a group-box. See lisp-widget-window.

Note on name change: in earlier releases, this class was named lisp-group-box-pane. That name is no longer used and the symbol lisp-group-box-pane no longer exists.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


handle

class, cg package

The class named by this symbol is not for user code. cg:handle is exported because there is a function of that name.


header-cell

class, cg package

The class of the header cell child of any grid-subsection. It is returned by calling header-cell on any grid-row or grid-column. See that function for more information.


header-control

class, cg package

Class

The class of the header-control control.

Control

An instance of the header-control class. This control serves as a sorting tool for other controls.

This control will work only when running in Windows desktop mode, and it has not been found to be useful even there. The list-view widget has a similar header along with a body that the header works with out of the box.


header-control-pane

class, cg package

The class of widget-windows that are instantiated whenever a header-control is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a header-control subclass or otherwise add methods to the widget-window of a header-control. See os-widget-window.


header-defaults

class, cg package

The superclass of column-header-defaults and row-header-defaults.


header-defaults-or-cell

class, cg package

The non-instantiable superclass of header-cell and header-defaults. This is used internally for defining methods that apply to both of those classes.


header-info

class, cg package

The class of the individual headers in a header-control.


hls

class, cg package

The class of an hls (hue-lightness-saturation) color object. See make-hls.


horizontal-scroll-bar

class, cg package

Class

The class of a horizontal-scroll-bar control. Note this is unrelated to scrollbars placed in certain windows automatically by the system.

Control

An instance of the :horizontal-scrollbar class. This control is paired programmatically with other controls (static pictures, for instance) to permit horizontal scrolling when too much information prevents the viewer from seeing everything on their display simultaneously.

Scrollbars can also be used as sliders to affect another control by raising or lowering a number, intensifying or fading a color, or otherwise gradually increasing/decreasing some characteristic of the attached control. A good model of this appears in the Car Payments Example in the Examples tab of the Navigator dialog (display with Help menu | CG Examples).

The range property of the scrollbar is a list of two integers: for example, (0 100). The value of the scrollbar determines the position of the scrollbox along the length of the scrollbar. The value of the scrollbar is an integer within the range.

The delayed property controls whether the scrollbar's value is updated as the user scrolls or only at the end of the scrolling operation.

See the Navigator dialog example (on the Examples tab) entitled "Car Payments" for an example of basic usage of scroll-bar widgets.

Adding a horizontal-scroll-bar control to your form

Click the horizontal-scroll-bar icon on of the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Customizing the horizontal-scrollbar

Attaching a scrollbar to another control. Scrollbars are not attached to other controls (as the up-down-control is, e.g.) You have to customize the on-change (typically) event handler for the scrollbar to programmatically make whatever scrolling effect you want.

Attaching a scrollbar to a window. Scrollbars on windows and various components such as multi-line-editable-text or outline are implemented differently. They are added when needed when the scrollbars property is true.

Scrolling by logical objects rather than by pixels

In a typical custom scrolling scheme, an application does not need to worry about how much data is above the current scroll position, and so the redisplay-window method can simply start drawing whatever is known to be currently scrolled to the top of the window. This means that the application does not have to compute and/or cache the pixel sizes of everything above the scroll-position, which simplifies the coding and can also speed scrolling up quite a bit when there is a huge amount of data to be scrolled. The drawbacks are that (1) this approach may be applicable only if data is entirely arranged into "rows" or "columns", (2) scrolling is not as visually smooth since an individual data object is always aligned with the top and/or left side of the window, and (3) custom methods need to be written to override several CG generic functions that are exported for this purpose.

See the Navigator dialog example (on the Examples tab) entitled "Scrolling by arbitrary objects rather than pixels" for a complete example of this special alternative for custom scrolling by logical objects..

It is now possible to customize scrolling in this way by overriding the default methods of several generic functions. Typically this is useful for scrolling by some sort of logical objects such as lines of text or grid cells rather than by pixels, as the default methods do. The generic functions that may need to be modified are:

redisplay-window to decide what should be drawn based on a custom scroll-position and then draw it

nscroll-position to return a position object where a coordinate might be an index into a set of arbitrary objects rather than a pixel distance

scroll-range which may return a value indicating the number of objects to be scrolled into the window rather than a pixel size

update-scroll-bars-for-new-window-size to adjust the scroll-range after a window has been resized

scroll-to to interpret a new programmatic scroll position

user-scroll to interpret an interactive scrolling gesture

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


horizontal-scroll-bar-pane

class, cg package

The class of widget-windows that are instantiated whenever a horizontal-scroll-bar is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a horizontal-scroll-bar subclass or otherwise add methods to the widget-window of a horizontal-scroll-bar. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


hotspot

class, cg package

The class of a hotspot object. Hotspots are invisible regions on a window that can receive and respond to mouse events just as actual windows do. They can be used to overlay images drawn on a window in order to make the images behave as graphical objects without using a separate child window that would obscure overlapping images on the main window.

The mouse-in, mouse-out, and various mouse click methods such as mouse-left-down are invoked for hotspot instances just as it is for windows. If you define mouse click methods for hotspots, the methods should return nil if you want the click to be further processed by the hotspot's parent window, or non-nil to prevent further processing of the click by the window.

General steps for using hotspots

A hotspot's highlight-style may optionally be set to :invert or :outline to make the hotspot highlight itself whenever the mouse is inside its hotspot-region. If these two built-in highlight styles are not adequate, you can override the default highlight-hotspot method to highlight the hotspot however you like.

Other than highlighting themselves when under the mouse cursor, hotspots do not draw anything on their parent window. Typically a hotspot covers the same region where something is drawn, allowing the user to click on that thing. But since an application could draw any sort of graphic where the hotspot lies, the hotspot does not attempt to do this drawing itself; instead, the window's redisplay-window method should draw the "real" object that the hotspot is making active. For a polygon hotspot, for example, the redisplay-window method could pass the same vector of positions to draw-polygon to draw the "real" polygon as the corresponding hotspot uses to define its hotspot-region.

Here are some other properties that hotspots can be given, either by passing the keyword initarg such as :name to make-instance, or by calling the setf function such as (setf name) any time later.

The function hotspots returns a list of all of the hotspots that are currently on a window, and current-hotspot returns the one that is currently under the mouse, if any. Calling parent on a hotspot returns the window that it is on, if any.

The IDE's Navigator dialog includes a complete example of using hotspots. Look for Hotspots: mouse-active highlighting regions.


hotspot-mixin

class, cg package

Mix this class in with all your window classes to make them hotspot-enabled.


html-browser

class, cg package

A subclass of dialog that is designed for browsing web pages and HTML files. Creating an instance by calling make-window (or the convenience function html-browser) will automatically add an instance of html-widget to the dialog, plus a toolbar with common HTML-browsing widgets, and optionally a common-status-bar. You can call display-html on the dialog to display a web page or file in the html-widget child.

The toolbar contains a multi-picture-button that has buttons that call html-widget-go-back, html-widget-go-forward, html-widget-reload, and html-widget-stop-load. It also contains a combo-box where you can type in a URL or path namestring and press the Enter key to display that page. There is also a Go button that can be clicked instead of pressing the Enter key.

The name of the child html-widget will be :html, so you can pass that name to find-component to find the child html-widget of an html-browser. The multi-picture-button is named :multipic, the combo-box is named :combo, and the go button is named :go.

If this dialog is not adequate, you can instead create your own dialog that includes an html-widget.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


html-widget

class, cg package

A class of widget that renders HTML and handles clicking on links and so on. It can be used for visiting web pages or displaying HTML files in a window of a CG application.

The value property of this widget may be set to either the URL of a web site or to the pathname or path namestring of a file. Alternately you can call display-html on this widget.

In CJ/JS, this widget is simply an iframe HTML element. An unfortunate limitation with this widget (due to JavaScript security restrictions) is that CG cannot control what mouse and keyboard gestures do. Instead, those gestures will do the usual web browser operations, where for example a right-click will show the web browser's own menu of commands that it will apply to the entire CG application, and doing a string search will search over all of the text in the entire CG browser tab. So this widget is probably not suitable for general distribution.

On Windows, this widget is implemented on the InternetExplorer OCX control. (See def-cg-ocx-control for information on creating other Common Graphics widgets from OCX controls.) One limitation of this widget is that does not provide a way to search for a text string in the HTML. It also is able to display only relatively simple web pages, due to being based on the Internet Explorer browser that is no longer being updated.

With the Windows widget, you can navigate by calling functions such as html-widget-go-back, html-widget-go-forward, html-widget-reload, html-widget-command-change, and html-widget-stop-load. There is also an html-browser dialog that incorporates an html-widget along with other common browser widgets that call those functions.

Also with the Windows widget only, the function html-widget-copy will copy any selected text to the clipboard, html-widget-save will save the entire page of HTML to a file, and html-widget-print will print the page. And on-command-change specifies the function to be called when a command's availability status has changed.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


html-widget-for-browser

class, cg package

The subclass of html-widget that is used by the html-browser class. Methods on this class will print standard status-bar messages to the html-browser's common-status-bar (if it has one) and collect visited pages into the html-browser's history list. If you specify a subclass of html-widget when creating an html-browser (see the html-widget-class argument to the function html-browser), then it should probably be a subclass of html-widget-for-browser.


html-widget-pane

class, cg package

The ocx-widget-window class for the html-widget dialog-item.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


html-widget-pane-for-browser

class, cg package

The ocx-widget-window class for an html-widget-for-browser dialog-item.


icon-drawing-view

class, cg package

The class of an icon-drawing-view. This is a non-instantiable superclass of line-graph-view and plot-view. It provides properties that are specific to views that can draw icons at data points. The unique properties of icon-drawing-view are:

See chart-or-plot, chart-widget, and plot-widget.


image-list

class, cg package

An image-list object contains an ordered set of pixmaps, for use by certain kinds of widgets. Currently only the list-view widget uses image-lists, where the large-image-list, small-image-list, and state-image-list may each be an image-list object. (Alternately, these list-view properties may be simple lists of the names of cached pixmaps, in which case the list-view internally creates and manages its image-list objects, and so an application typically does not need to deal with image-lists directly itself.)

An image list can be created as simply as this:

(make-instance 'image-list
  :name :main-image-list
  :pixmaps (list butterfly-pixmap worm-pixmap))

where each item in the pixmaps list is an existing pixmap object, as created (for example) by load-pixmap. If the desired pixmaps have been cached by calling cache-pixmap on them, then the pixmaps can alternately be specified by their names, as in:

(make-instance 'image-list
  :name :main-image-list
  :pixmap-names (list :butterfly :worm))

If the name initarg is not passed, a unique default name such as :image-list-3 will be used.

Once an image-list has been created, it may be specified as the large-image-list, small-image-list, or state-image-list property of a list-view control.

All of the pixmaps in a single image-list must have the same width, height, and bits-per-pixel. It also must be the case that either all of the pixmaps have a mask or none of the pixmaps have a mask.

See also the description of the pixmap class and the essay on pixmaps, cg-pixmaps.html.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


item-axis

Class, cg package

The class of the item-axis, which, along with value-axis, is a subclass of chart-axis. See chart-axis for a list of properties these classes have in common. The properties unique to item-axis are:

See chart-widget and also cg-chart-widget.html.


item-list

class, cg package

The non-instantiable dialog-item class that encompasses the instantiable classes single-item-list and multi-item-list.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


item-list-pane

class, cg package

The widget-window class for the item-list dialog-item class.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


lamp

class, cg package

The class of the lamp control. The widget-window of the control is a member of the lamp-pane class.

The lamp control is a colored shape (a circle, rectangle, triangle, or diamond) which can be on or off, or can blink between on and off. The on and off colors may be any colors, and may be changed at any time. A single lamp widget can optionally display an entire rectangular array of lamp images, which may individually be on or off or blinking, and may be different colors.

The value property of the widget may be t (meaning the lamp is on), nil (meaning it is off), :blinking (meaning it switches between on and off, with the interval determined by blink-off-milliseconds and blink-on-milliseconds), or an array of such values. The lamp displays its on-color when it is on, and its off-color when it is off.

The off-color property value is nil by default, in which case the effective off-color is derived automatically from the on-color and the off-color-factor. The off-color-factor is a number between zero and one by which to multiply the on-color RGB values to produce a dimmer version of the same hue for the off state.

The lamp-shape property may be either :circle, :triangle, :rectangle, or :diamond to draw the lamp in a particular shape. The border around the lamp is controlled with the border-color and border-width properties (where a border-width of zero would draw no border).

The title property may be either a string to display on one side of the lamp, or else nil to display no string. The title-side property may be :left, :top, :right, or :bottom to position the title on a particular side of the lamp image, or :center to position the title within the (typically rectangular) lamp image. As with other widgets, the font property determines the font with which to draw the title string.

The size of the lamp image within the widget may be specified explicitly by setting the lamp-width and lamp-height properties to the desired pixel size. By default these properties are nil instead, which means to fit the lamp image to the current size of the widget. When fitting to the widget, the size of the lamp image is affected by the outer-horizontal-margin, inner-horizontal-margin, outer-vertical-margin, and inner-vertical-margin properties. The "outer" margins are between the image and the edge of the widget, while the "inner" margins are between the lamp image and the title, or between the multiple lamp images when the value property is an array (see below). The outer margins are particularly useful when laying out lamps on a form, allowing you to snap the widgets up against each other without the lamp images or title strings running into each other.

The size of the lamp image within the widget may be specified explicitly by setting the lamp-width and lamp-height properties to the desired pixel size. By default these properties are nil instead, which means use the size ten pixels. The positioning of a single lamp image or an array of them is affected by the outer-horizontal-margin, inner-horizontal-margin, outer-vertical-margin, and inner-vertical-margin properties. The "outer" margins are between the image and the edge of the widget, while the "inner" margins are between the lamp image and the title, or between the multiple lamp images when the value property is an array (see below). The outer margins are particularly useful when laying out lamps on a form, allowing you to snap the widgets up against each other without the lamp images or title strings running into each other.

By default, lamp images are placed near one or two sides of the widget to leave all remaining space for any labels. But if the center-all property is turned on, then all images and labels are centered as a group within the widget.

Making an array of lamps

To make a lamp widget display a rectangular grid of lamp images, set the value property to be a two-dimensional array, where the major dimension of the array indicates the row, and the minor dimension the column. Each value in the array should be either nil, t, or :blinking to specify the state of each lamp in the grid. When the value property is an array, then the title and title-side properties are not used, and the following properties are used instead: row-labels, column-labels, row-label-side, column-label-side, row-label-margin, column-label-margin, row-label-offset, column-label-offset, and column-label-orientation. The lamp shape will be the same for all lamps in the grid, and any blinking lamps will blink in unison. The on-color and off-color properties may be an array of the same dimensions as the value array to make each image use a different color; if off-color is nil then an off-color will be derived for each image individually.

Replacing any lamp property will automatically update the appearance of the widget, as usual, either on a form or at runtime. But when the value is an array, it is simpler and more efficient to modify the existing array object, rather than consing up a new array for each change. Since the value property remains the same object in this case, the widget will not update itself automatically. To cause the widget to update its appearance after modifying the array object, call update-lamp.

Using lamp widgets in grid-widget cells

A lamp widget can be displayed in one or more cells of a grid-widget. To do so, create the lamp dialog-item as usual, but do not place it onto a parent window (which you would normally do either by including the lamp widget in the list of dialog-items of the parent window, or by calling add-component). Instead, associate the lamp dialog-item with a grid-widget in one of the two following ways. Thereafter, whenever you modify properties of the lamp dialog-item, the changes will automatically be drawn in any grid cells that display that lamp.

Method 1 for placing lamps in a grid-widget

To make a column of lamp cells, use the lamp-column-mixin class along with the widget-row-mixin class, as usual when using the various widget-column-mixin classes in a grid-widget. The lamp-widget property of the grid-column will be the actual lamp dialog-item.

The Employee Grid example in the IDE's Navigator dialog includes a lamp column. That example has grown rather large, so search for lamp-column-mixin and then for the stressed-column class that uses that mixin. Below is the code from that example that makes the lamp column (with a few properties removed here). It uses the data-reader property to read a value from an employee's stressed slot, then the data-read-converter property to convert the user value :extremely from the stressed slot to the value :blinking for the lamp widget to handle in the usual way. The title-reader property is used to make a title string to display in each cell. A sort-predicate is specified in case the user sorts the grid rows by that grid column, to sort the blinking cells to the top, followed by the on cells, and finally the off cells at the bottom. And finally the lamp-widget property is set to be a real lamp widget. Its wrapping property is turned on to make the labels fit better in a narrow grid column.

  (make-instance 'stressed-column ;; a subclass of lamp-column-mixin
    :name :stressed
    :data-reader 'stressed
    :data-read-converter (lambda (user-value)
                           (case user-value
                             (:extremely :blinking)
                             (t user-value)))
    :title-reader (lambda (employee)
                    (format nil "Is ~:(~a~) stressed?"
                      (name employee)))
    :sort-predicate (lambda (a b)
                      (or (eq a :blinking)
                          (and a (not b))))
    :lamp-widget (make-instance 'lamp
                   :outer-horizontal-margin 8
                   :inner-horizontal-margin 10
                   :wrapping t))

Method 2 for placing lamps in a grid-widget xxxxxxxxx

To add a lamp to a single arbitrary grid cell, write a cell-widget method (as usual for widgets in individual cells). When the grid-row and grid-column arguments to the method indicate a cell that should contain a lamp, then the method should return two values, which are the keyword symbol :lamp and the actual lamp dialog-item to be displayed there. See cell-widget for more information. The cell-widget example in the IDE's Navigator Dialog also displays an arrayed lamp in one cell.

Lamp example

Here is an example that creates a simple lamp and an arrayed lamp on a dialog.

(let* ((simple-lamp (make-instance 'lamp
                      :value t
                      :on-color green
                      :title "Simple Lamp"
                      :left 20 :top 20 :width 160 :height 24))
       (array-lamp (make-instance 'lamp
                     :value #2a((nil t nil)
                                (t nil :blinking)
                                (:blinking t t))
                     :on-color #2a((#.yellow #.light-blue #.red)
                                   (#.yellow #.light-blue #.red)
                                   (#.yellow #.light-blue #.red))
                     :row-labels '("One" "Two" "Three")
                     :column-labels '("Apple" "Blueberry" "Cherry")
                     :column-label-orientation :vertical
                     :row-label-side :right
                     :lamp-shape :triangle
                     :lamp-height 12
                     :lamp-width 16
                     :row-label-margin 10
                     :column-label-margin 8
                     :inner-horizontal-margin 8
                     :center-all nil
                     :left 20 :top 60 :width 160 :height 120)))
  (make-window :lamp-example
    :class 'dialog
    :title "Lamp Example"
    :resizable nil
    :dialog-items (list simple-lamp array-lamp)
    :interior (make-box-relative 300 100 200 200)))

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


lamp-column

class, cg package

A grid-column subclass whose superclasses are lamp-column-mixin and grid-column. This class may be instantiated directly when no further subclassing is needed, and therefore is convenient when creating a grid-widget interactively on a form window and then editing its properties in the inspector (see cg-grid-widget-simplified-tutorial.html). In the inspector, you could move to an existing grid-column and then set its class property to lamp-column to turn it into this type of column (where the class choices are available in the drop-down list for the class property). See lamp-column-mixin for the widget behavior.


lamp-column-mixin

Class, cg package

A non-instantiable class that can be mixed with the grid-column class to create grid columns whose cells draw lamp widgets. Each cell in the column will display a lamp if the row of that cell is an instance of a grid-row subclass that mixes in the widget-row-mixin class. See lamp-column for an instantiable subclass that you can use directly when no further subclassing is needed, even specifying it interactively.

To ensure that this mixin class' methods take precedence over other methods that specialize on grid-column, this mixin class generally should appear first in a defclass expression's list of superclasses, as in:

(defclass my-lamp-column
  (lamp-column-mixin my-subclass-of-grid-column) ...)

The draw-cell method provided by this mixin will draw (in each cell) the single lamp widget that is the value of the lamp-widget property of the grid column. It will call read-cell-value to determine the state of the lamp (off, on, or blinking) in each cell. The grid column may be given a data-read-converter function to convert arbitrary application values into corresponding lamp state values (nil, t, and :blinking).

The grid column may be given a title-reader property to determine the string to display in each lamp cell. If there is no title-reader function or it returns nil, then no label will be displayed beside the lamp image (and the lamp image will be centered within the grid cell).

Here is a typical expression for creating a lamp grid column. It assumes that the data-object of each grid-row has a slot called danger-level containing one of the values :low, :moderate, or :high.

(make-instance 'my-lamp-column
  :name :danger-level
  :proportional nil
  :section-size 24
  :data-reader 'danger-level
  :data-read-converter (lambda (user-value)
                         (case user-value
                           (:low nil)
                           (:moderate t)
                           (:high :blinking)))
  :lamp-widget (make-instance 'lamp
                 :on-color red
                 :lamp-shape :triangle
                 :lamp-width 16
                 :lamp-height 12))

The Employee grid example in the Navigator includes a lamp column.

See the section Built-In Grid Cell Widgets on the page for the grid-widget class for an overview of the grid column mixins.

A quicker but less object-oriented alternative to using the widget-column-mixin classes is to write cell-widget methods.

See the lamp widget.


lamp-pane

class, cg package

The class of the the pane of a lamp control.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


layout-spacing

Class, cg package

The class of layout-spacing sub-objects of object-editor dialogs. If the default spacing that is used when an object-editor automatically lays out its widgets is not satisfactory, then the object-editor can be given a layout-spacing object whose properties specify custom spacing values.

The Class Interface Editor dialog does not include widgets for specifying this value interactively, but it could edited in the Inspect dialog after the Class Interface Editor sets up an object-editor form window.

Creating an object-editor programmatically with a layout-spacing sub-object would have this general format:

(make-window :my-object-editor
  :class 'object-editor
  :edited-class ...
  :edited-slots ...
  :layout-spacing (make-instance 'layout-spacing
                    :layout-widget-spacing 4
                    :layout-outer-margin 12
                    ...))

Here are the particular properties of a layout-spacing object:


library-module

class, cg package

The symbol naming this class has been moved to the :ide package. Please see library-module.


line-drawing-view

class, cg package

The class of a line-drawing-view. This is a non-instantiable superclass of line-graph-view and plot-view. It provides properties that are specific to views that can draw lines between data points. The unique properties of line-drawing-view are:

See chart-or-plot, chart-widget, and plot-widget.


line-graph-view

Class, cg package

The class of a line-graph-view. The unique properties of line-graph-view are:

The line-graph-view inherits additional properties from chart-view, line-drawing-view, and icon-drawing-view.

See chart-widget and also cg-chart-widget.html.


lisp-edit-pane

class, cg package

The class of widget-windows that are instantiated whenever a multi-line-lisp-text is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a lisp-text subclass or otherwise add methods to the widget-window of a lisp-text. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


lisp-edit-window

class, cg package

A frame-with-single-child class similar to the text-edit-window class, except that the frame-child pane will be a lisp-edit-pane rather than a text-edit-pane.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


lisp-group-box

class, cg package

The class named lisp-group-box is now named group-box. The class lisp-group-box is now a subclass (with no additions) of group-box. Users should convert code to make use of the new name.


lisp-text

class, cg package

Class and Control

Like an editable-text control, except that the value may be any lisp object rather than a string only. When the control's value is set programmatically to a new arbitrary lisp object, the on-print event handler function for the control takes the object as its argument and should return a string to be displayed in the control. When the end user types into the control, read-from-string is called internally on the new string to produce a new arbitrary lisp object that is then stored as the value of the control. Errors are trapped during the reading so that no break will occur; if an error is signaled during the reading then nil is stored as the value of the control.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


lisp-text-pane

class, cg package

The class of widget-windows that are instantiated whenever a lisp-text is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a lisp-text subclass or otherwise add methods to the widget-window of a lisp-text. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


lisp-widget

class, cg package

This is the class of all dialog-items that are implemented from scratch in Common Graphics, rather than utilizing controls that are supplied by the operating system. Common Graphics exports several such widgets, namely the outline, dropping-outline, grid-widget, multi-picture-button, drawable, and group-box widgets.

Applications may also write their own lisp-widgets. The basic procedure for defining a custom lisp-widget consists of the following:

  1. Creating a subclass of lisp-widget for the dialog-item itself.

  2. Creating a class that is a subclass of lisp-widget-top-window, to serve as the actual window that appears on the screen for the dialog-item.

  3. Adding a widget-device method to associate the two subclasses above with each other.

  4. Adding a device-open method for the lisp-widget-top-window subclass, which gets called automatically whenever an instance of the lisp-widget subclass is placed onto a parent window. This method should call open-lisp-widget-window on the stream object that is passed to device-open; this will create the actual window on the screen that is represented by the lisp-widget-window object. The device-open method should also do any needed initial setup of the widget, such as processing the initargs that were passed to make-instance to create the dialog-item instance. There is a built-in device-open method for lisp-widget-top-window that simply calls open-lisp-widget-window, so if that is sufficient then this step can be skipped.

  5. Adding a redisplay-window method for the lisp-widget-window subclass, to draw the widget whenever it is uncovered or its value changes.

  6. If the widget may have a value and needs to be redisplayed to reflect a new value, then adding a widget-set-value method for the lisp-widget-window subclass. This method should call invalidate on the lisp-widget-window, which causes its redisplay-window method to be called.

  7. If the widget should respond to user mouse or keyboard events, adding methods on the lisp-widget-window subclass for such generic functions as mouse-left-down, mouse-moved, or virtual-key-down. These methods will typically determine a new value for the widget and call (setf value) to update the widget according to the user gesture.

  8. Perhaps defining additional lisp-widget-window subclasses for any child windows that the widget may have. (Widgets usually do not have child windows.) These classes should NOT also be subclasses of lisp-widget-top-window. The device-open method should also create the needed child window instances, but by calling make-window rather than calling open-lisp-widget-window. The name of the lisp-widget-window subclass should be passed as the :class argument to make-window.

  9. Perhaps adding a lisp-widget-draw-focus method and a lisp-widget-clear-focus for the lisp-widget-window subclass that either draws or erases an indication that the widget currently has the keyboard focus. These methods are called automatically as the widget gains and loses the keyboard focus. If the widget does not need to visually indicate when it has the focus, then these methods are not needed.

Details of the above procedure may be found in the source code for the Navigator examples called "Custom Widgets: implementing in lisp" and "Circle Widget: a simpler lisp widget". Navigator examples are displayed by the Help menu | CG Examples menu command.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


lisp-widget-top-window

class, cg package

A non-instantiable class that is superclass to several classes related to lisp widgets.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


lisp-widget-window

class, cg package

The class of all widget-windows that are implemented within Lisp, rather than being provided by the underlying window system. This class is not instantiable.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


list-view

class, cg package

Class

The class of the list-view control.

Control

The list-view control displays a table of textual information. It may include a row of buttons along the top that serve as column headers and which may be clicked in order to sort the rows of the list-view by the values that appear in any column. The column headers may also be stretched to change the width of individual columns.

The range property of a list-view is a list of list-view-item instances, each of which represents one row of data. The columns property contains a list of list-view-column instances, each of which represents one column of data and its header. Each list-view-item has a value-plist property that contains a value for each column of that row --- this value-plist is of the form (column-name value column-name value ...).

The list-view control supports icons and alternate layout styles. (The alternate layout styles are supported on the Windows platform only.) Refer to the documentation for the following symbols for more information: image-list, large-image-list, small-image-list, state-image-list, icon-index, state-icon-index, layout-style, alignment, auto-arrange, arrange-icons, list-view-item-position, open-image-list, close-image-list, image-list-open-p, and share-image-lists. On Windows only, see draggable-headers, full-row-select, and show-grid-lines.

Check boxes

On Windows, check boxes are supported for list-views. See show-check-boxes, checked, and on-check.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

Example

Here is an example that shows how to create and modify a list-view widget programmatically. It creates a list-view with some initial items and displays it on a parent dialog, then adds a few more items and modifies the value of one of them.

(let* ((list-view
        
        ;; Make a list-view widget.
        (make-instance 'list-view
          
          ;; Where to place the list-view in its parent dialog.
          :left 20 :top 20 :width 300 :height 200
          
          ;; The initial columns of the list-view.
          :columns (list
                    (make-instance 'list-view-column
                      :name :flower
                      :title "Flower"
                      :justification :left
                      :width 144
                      :on-sort-predicate 'string<)
                    (make-instance 'list-view-column
                      :name :value
                      :title "Value"
                      :justification :center
                      :width 60
                      :on-sort-predicate '<)
                    (make-instance 'list-view-column
                      :name :rating
                      :title "Rating"
                      :width 80))
          
          ;; The initial rows of the list-view.
          :range (list
                  (make-instance 'list-view-item
                    :name :azalea
                    
                    ;; The value to display in each column
                    ;; for this row.
                    :value-plist
                    `(:flower "Azalea" :value 3700 :rating :low))
                  
                  (make-instance 'list-view-item
                    :name :dieffenbachia
                    :value-plist
                    `(:flower "Dieffenbachia" :value 23 :rating :high))
                  (make-instance 'list-view-item
                    :name :philodendron
                    :icon-index 1
                    :value-plist
                    `(:flower "Philodendron" :value 870 :rating :low))
                  (make-instance 'list-view-item
                    :name :spider-plant
                    :icon-index 1
                    :value-plist
                    `(:flower "Spider Plant" :value 9 :rating :medium)))
          
          ;; This row that will initially be selected.
          :value (list :dieffenbachia)
          
          ;; The set of icons that can be displayed at the left
          ;; of the rows.  The icon-index of each list-view-item
          ;; is an index into this set of pixmaps.
          ;; The :pixmap-names argument refers to pixmaps
          ;; that can be found from their names because
          ;; cache-pixmap was called on the pixmaps.
          :small-image-list (make-instance 'image-list
                              :name :sample-small
                              :pixmap-names
                              (list :default-closed-with-mask
                                    :default-leaf-with-mask))
          
          ;; The list-view will initially be sorted by this column.
          :sort-column :flower))
       
       ;; Make a parent dialog and put the list-view widget on it.
       (dialog (make-window :list-view-example
                 :class 'dialog
                 :interior (make-box-relative 200 200 340 240)
                 :dialog-items (list list-view))))
  (select-window dialog)
  
  ;; After the dialog has appeared, add a few more rows
  ;; one at a time.
  (dotimes (j 3)
    (sleep 1)
    (let* ((title (format nil "~:(~r~)" (1+ j))))
      (add-item list-view
                (make-instance 'list-view-item
                  :name (intern title :keyword)
                  :icon-index 0
                  :value-plist `(:flower ,title
                                 :value ,(* 10 (1+ j))
                                 :rating :medium)))))
  
  ;; Increase the value of the spider plant, and then select it.
  (sleep 1)
  (let* ((item (find-item list-view :spider-plant))
         (plist (value-plist item)))
    (incf (getf plist :value) 300)
    (setf (value-plist item) plist))
  (sleep 1)
  (setf (value list-view)(list :spider-plant))

  ;; Sort by the flower column again after adding the new items.
  (sleep 1)
  (setf (sort-column list-view) :flower)
  
  ;; Return the dialog.
  dialog)

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


list-view-column

class, cg package

The class of a list-view column. These are the elements of a list-view.


list-view-item

class, cg package

The class of a list-view-item, which are the things displayed in a list-view control.


list-view-pane

class, cg package

The class of widget-windows that are instantiated whenever a list-view is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a list-view subclass or otherwise add methods to the widget-window of a list-view. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


mci-animation

class, cg package

One of various classes that implement aspects of the MCI interface.

See cg-mci.html.


mci-cd-audio

class, cg package

One of various classes that implement aspects of the MCI interface.

See cg-mci.html.


mci-dat

class, cg package

One of various classes that implement aspects of the MCI interface.

See cg-mci.html.


mci-device

class, cg package

One of various classes that implement aspects of the MCI interface.

See cg-mci.html.


mci-overlay

class, cg package

One of various classes that implement aspects of the MCI interface.

See cg-mci.html.


mci-scanner

class, cg package

One of various classes that implement aspects of the MCI interface.

See cg-mci.html.


mci-sequencer

class, cg package

One of various classes that implement aspects of the MCI interface.

See cg-mci.html.


mci-video-disc

class, cg package

One of various classes that implement aspects of the MCI interface.

See cg-mci.html.


mci-wave-audio

class, cg package

One of various classes that implement aspects of the MCI interface.

See cg-mci.html.


media-player

Class, cg package

The parent class of audio-player and video-player. The API for those two classes is nearly identical and is therefore shared. These widgets are currently implemented only for CG/JS mode, though they could also be implemented for Windows.

Each player has interactive controls for the usual actions such as playing and pausing, moving the current time, and adjusting the volume. These actions and others can also be performed programmatically by calling the functions media-player-command and media-player-property.


media-player-pane

Class, cg package

The parent class of audio-player-pane and video-player-pane.


memory-bitmap-not-created

class, cg package

This condition will be signaled if an error occurs when creating the backing-store memory bitmap for a window. This typically indicates that not enough memory was available to create the memory bitmap. This may happen when creating a bitmap-pane if the page-width or page-height is very large, or when creating other windows if the double-buffered property is true and the window itself is very large.

An application could handle this situation by trapping this condition when calling make-window. The condition could also be signaled when resizing a double-buffered window with functions such as resize-window or (setf exterior), or when increasing the page size of a bitmap-pane with set-page-size.

This condition is a subclass of error.


menu

class, cg package

The class of menu objects. A menu is created by calling open-menu. See open-menu for more information.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

See also the menu chapter in the IDE User Guide.


menu-bar

class, cg package

The class of menu-bar objects.

Call menu to return the menu-bar of a window, or (setf menu) to add or remove a menu-bar to or from a window. See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

See also the menu chapter in the IDE User Guide.


menu-item

class, cg package

The class of menu-item objects. A menu-item is created by calling make-instance, specifying the menu-item class or some subclass of it.

Here is a list of the properties of a menu-item; each can be specified at creation time by passing the corresponding keyword initarg to make-instance:

Here is a typical menu-item creation form:

(make-instance 'menu-item
  :name :help
  :title "~Help"
  :value 'show-help
  :help-string "Shows help on the selected thing."
  :event-synonym 'vk-f1)

A menu-item may be added to a menu when the menu is created by calling open-menu, or added later by calling add-to-menu.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

See also the menu chapter in the IDE User Guide.


message-window

class, cg package

This is the window class that is instantiated by default by with-message-window. You can create a custom subclass with the appearance you wish if you do not like this default class. See with-message-window for more information.


module

class, cg package

The symbol naming this class has been moved to the :ide package. Please see module.


multi-item-list

class, cg package

Class

The class of the multi-item-list control.

Control

Instance of the multi-item-list class. This control is similar to single-item-list except that the user may select multiple items, in either continuous ranges or discontinuous ranges. multi-item-list and single-item-list are together called item-list widgets.

The value property is set to a list of the highlighted items; both sequential and non-sequential list items can be highlighted.

The range property contains all of the entries in the list; items appear in the order you enter them in the range. The items may be any type of object, though for some item types the on-change-test of the widget may need to be changed to a function that will return true for equivalent objects of that type.

The entire range may be set either by passing the :range initarg when calling make-instance to create the widget, or later by calling (setf range). Incremental changes to the range may be made by calling the functions list-widget-add-item, list-widget-remove-item, list-widget-replace-item, and list-widget-move-item.

An application should not destructively modify a list that it has passed as a :range initarg or to (setf range) for an item-list widget, because the widget retains this list object to determine which values are actually new when (setf range) is called again on the widget. To make small changes to the range, the incremental functions mentioned above may be used to avoid consing a new list to pass to (setf range).

The :key initarg to make-instance should be a function of one argument which should return the object to be displayed for each item in the range.

Navigating and selecting items from the multi-item-list

Continuous ranges are selected by holding down the Shift key and clicking on the beginning and end of the range (or each item if desired). Discontinuous ranges are selected by holding down the Control key and clicking on each item desired. Or, if a multi-item-list is created with the initarg :simple-click-toggle true, each item is toggled separately with a click, but Shift-click does not, in that case select several items (see simple-click-toggle).

Arrow keys can be used to navigate up and down the length of the list.

Adding a multi-item-list control to your form

Click the multi-item-list tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size. Note: resizing the multi-item list won't mean proportional changes in the size of the characters inside the list. Change the font property if you want to change the size of the actual characters displayed.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Scrollbars

In release 11.0, the following paragraph is no longer true, because a fix was found.

On Windows, this control will show a horizontal scrollbar only if its multi-column-p property is true (and the multiple columns extend beyond the width of the control). If a horizontal scrollbar is needed on an multi-item-list that does not use multiple columns, an outline control could be used instead, using only top-level items in the range and turning off the draw-icons property to simulate an item-list.

Notes

When list-items exceed the size of the display, a scroll-bar appears on the right side of the box automatically. Scroll bars don't appear when individual list entries are too long to fit in the width of the display, nor does the text wrap.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


multi-item-list-pane

class, cg package

The class of widget-windows that are instantiated whenever a multi-item-list is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a multi-item-list subclass or otherwise add methods to the widget-window of a multi-item-list. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


multi-line-editable-text

class, cg package

Class

The class of the multi-line-editable-text control.

Control

Instance of the :multi-line-editable-text. This control behaves similarly to editable-text, but covers more than one line and has vertical scrollbars whenever the size of the text block exceeds the size of the window. Text on long lines wraps to fit in the window when the horizontal scrollbar is not enabled, and continues to wrap even after resizing.

The edited text is stored as a simple string in the value field of the dialog item. The text initially displayed can be specified by storing a simple string in the value field.

Note that the TAB character cannot be entered when the tabstop property is on, since entering TAB causes the focus to move to the next control in the tab sequence.

multi-line-editable-text controls do not have titles. If you want to add a title to your multi-line-editable-text control, pair it with a static-text control.

Adding a multi-line-editable-text control to your form

Click the multi-line-editable-text tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size. Note: resizing the control changes the size of the bounding-box, but not the size of the actual characters inside. Change the font property if you want to change the size of the characters.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Customizing multi-line-editable-text control behavior

Adding scrollbars to multi-line-editable-text controls: set the scrollbars property to t (use both scrollbars), :vertical (use vertical scrollbar only), or :horizontal (use the horizontal scrollbar only). If the value of this property is nil, scrollbars will not appear.

Note: If the horizontal scrollbar is not enabled, then the text will wrap automatically at space boundaries to prevent the text from extending off the right edge of the control. This is done at display time by Windows without adding newline characters, so the text will re-wrap if the dialog-item is resized.

Making multi-line-editable-text controls read-only or not: set the read-only property. t means read-only, nil means editable. True, which prevents the user from typing into the widget, can be handy for displaying scrolling text that the user should not change.

When user-generated changes appear: the delayed property controls whether the dialog-item value is updated after every keystroke or only after the user moves to another item on the dialog.

Data in a multi-line-editable-text

The generic function text-range can be used to extract data from a multi-line-editable-text control.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


multi-line-lisp-text

class, cg package

Class and Control

This control is like a multi-line-editable-text control, except that the value may be any lisp object rather than a string only. When the control's value is set programmatically to a new arbitrary lisp object, pprint is called internally on the object to return a string to be displayed in the control. When the end user types into the control, read-from-string is called internally on the new string to produce a new arbitrary lisp object that is then stored as the value of the control. Errors are trapped during the reading so that no break will occur; if an error is signaled during the reading then nil is stored as the value of the control.

See also lisp-text

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


multi-picture-button

class, cg package

Class

The class of the multi-picture-button control.

Control

An instance of the multi-picture-button class. This control fills the need for toolbars and other instances of controls where many icons may need to appear on a form at once. Graphic lines and gaps separate the control icons into three main groupings in the initial version of the control. This control is capable of a non-momentary pressed-in state.

Using the multi-picture-button instead of many individual bitmaps can reduce application overhead. Controls are window-like objects; they can get focus and be affected by events. They are costly in terms of system resources. It is a better design strategy to use a multi-picture-button instead of a bank of individual picture-button controls and save the overhead for another part of the application where you might really want it.

Not every cell in the multi-picture button has to be clickable, some can be purely for display.

Various properties of multi-picture-button controls

Among the properties of this control are:

See also multi-picture-button-scroll, multi-picture-button-scroll-interval, and update-multi-picture-button.

Defining individual buttons on the control

The range of a multi-picture-button control is a list of button-info objects and optionally the keyword :gap. Each button-info is a CLOS object that describes one of the individual buttons of the multi-picture-button control. Setting the range (with setf) to a different list of button-infos will update the set of displayed buttons. The symbol :gap may also appear in the range list. That value inserts a gap (of size gap-size) between the buttons defined by the button-info instances on either side of :gap. When button-3d-border is :when-pressed in the multi-picture-button control, the gap is further indicated by a vertical line.

The value of a multi-picture-button is a list of the names of the buttons that are currently pressed. Setting the value to a different list of button names will cause those buttons to be pressed in and all other buttons released.

What happens when a button is clicked?

When a button is clicked by the user, the on-change event handler will be invoked.

The new-value argument is a list of all buttons that are pressed after the click. If it is a longer list than the old-value argument, then a button was pressed (rather than released) and it is guaranteed that the clicked button is the first one in the list. The new-value argument will be nil if a single button had been pressed and was clicked to release it.

See also unpress-automatically, which causes the button to be unpressed after the on-change function is run.

Creating an instance of a multi-picture-button control

This call to make-instance returns an instance of a multi-picture-button. Properties can be initialization keyword arguments (the keyword has the same name as the property, with a prepended colon, e.g. :top for top). Additional arguments could be provided. Their absence indicates the default value will be used. Note that the value of the range argument (the last one) is a long list of button-info instances.

(make-instance 'multi-picture-button
                   :font
                   (make-font-ex nil "MS Sans Serif" 11 nil)
                   :left 430
                   :name :multi-picture-button-1
                   :top 84
                   :unavailable-color-mapper
                    (list (cons black gray) (cons dark-gray gray)
                         (cons dark-blue gray) (cons dark-green gray)
                         (cons dark-red gray) (cons dark-cyan gray)
                         (cons dark-yellow gray)
                         (cons dark-magenta gray) (cons red dark-red)
                         (cons green dark-green) (cons blue dark-blue)
                         (cons yellow dark-yellow)
                         (cons cyan dark-cyan)
                         (cons magenta dark-magenta))
                   :range (list (make-instance 'button-info
                           :name :new
                           :pixmap-name :new
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string "Open a blank editor window")
                         (make-instance 'button-info
                           :name :open
                           :pixmap-name :open
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string "Edit a file")
                         (make-instance 'button-info
                           :name :save
                           :pixmap-name :save
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string "Save the selected window")
                         (make-instance 'button-info
                           :name :load
                           :pixmap-name :load
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string "Load a lisp file")
                         :gap
                         (make-instance 'button-info
                           :name :red
                           :pixmap-name nil
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color red
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string "Use red")
                         (make-instance 'button-info
                           :name :green
                           :pixmap-name nil
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color green
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string "Use green")
                         (make-instance 'button-info
                           :name :blue
                           :pixmap-name nil
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color blue
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string "Use blue")
                         (make-instance 'button-info
                           :name :yellow
                           :pixmap-name nil
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color yellow
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string "Use yellow")
                         (make-instance 'button-info
                           :name :cyan
                           :pixmap-name nil
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color cyan
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string "Use cyan")
                         (make-instance 'button-info
                           :name :magenta
                           :pixmap-name nil
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color magenta
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string "Use magenta")
                         (make-instance 'button-info
                           :name :one
                           :pixmap-name nil
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title "One"
                           :width 26
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :two
                           :pixmap-name nil
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title "Two"
                           :width 26
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :incremental-evaluation
                           :pixmap-name :incremental-evaluation
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :incremental-compile
                           :pixmap-name :incremental-compile
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :evaluate-clipboard
                           :pixmap-name :evaluate-clipboard
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :inspect
                           :pixmap-name :inspect
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :find-in-file
                           :pixmap-name :find-in-file
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :find-definition
                           :pixmap-name :find-definition
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         :gap
                         (make-instance 'button-info
                           :name :trace
                           :pixmap-name :trace
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :breakpoint
                           :pixmap-name :breakpoint
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :profile
                           :pixmap-name :profile
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :create
                           :pixmap-name :basic-pane
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :edit-file
                           :pixmap-name :edit-file
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :apropos
                           :pixmap-name :apropos
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil)
                         (make-instance 'button-info
                           :name :print
                           :pixmap-name :print
                           :pixmap-source nil
                           :pixmap-icon nil
                           :background-color nil
                           :foreground-color nil
                           :title nil
                           :width nil
                           :height nil
                           :stretching t
                           :tooltip nil
                           :help-string nil))
                 )

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code. The example above came from placing a multi-picture-button on a form and looking at the resulting .bil file.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


multi-picture-button-pane

class, cg package

The class of lisp-widget-windows that are instantiated whenever a multi-picture-button is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a multi-picture-button subclass or otherwise add methods to the lisp-widget-window of a multi-picture-button. See lisp-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


node-pane-mixin

class, cg package

This class can be mixed with a window class (basic-pane or some subclass of it) to provide functionality for drawing graphs and handling mouse events on the individual node and link objects (vertices and edges) in a graph.

There is an example of this facility in the Navigator dialog, called Custom Graphical Objects: A Nodes-and-Links Editor.


non-refreshing-pane

class, cg package

A class of basic window. It is actually equivalent to a basic-pane, having no title-bar or border by default, but is provided as a distinct class to serve as the default-pane-class of the non-refreshing-window class. This class is normally instantiated indirectly by creating a non-refreshing-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


non-refreshing-window

class, cg package

A class of window that has a frame and automatically adds a child pane. This is a subclass of frame-with-single-child, indicating that by default a non-refreshing-window has a title-bar and a border as a frame-window does, and also that it automatically adds a frame-child pane window, in this case a non-refreshing-pane, and is therefore suitable when a toolbar or status-bar is to be added to the window.

The name "non-refreshing" means that the window does not automatically know how to redraw itself when it is uncovered, and so an application must supply a redisplay-window method (on the child pane class) that will be called whenever the window needs to be redrawn. This is actually the case of every window class except for bitmap-window and bitmap-pane (and text-edit-pane, because it is actually a control internally). If backing-store is desired for automatic redisplay, use a bitmap-window instead. When adding controls, a dialog is recommended.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


object-editor

Class, cg package

An object-editor is a specialized dialog subclass that makes it easier to create dialogs that edit instances of classes. Rather than creating individual widgets and giving them on-change functions and adding them to a dialog, you instead specify a single expression that parametrically describes the slots to be edited, and then the object-editor will automatically create widgets for those slots and arrange them on the dialog. An object-editor also offers a set of standard command buttons for viewing other instances, reverting the current changes, and so on.

Creating an object-editor dialog interactively is described in the document for the IDE's Class Interface Editor dialog. An extended programmatic example can be found in the essay Creating an Object-Editor Dialog or Class-Grid Programmatically.

Using an Object-Editor

To use an object-editor, there are three main properties that you need to set:

An object-editor will sort its edited-instances by the primary-name-slot and secondary-name-slot of the edited-class, if any, or else by the usual print names of the instances. It will display the first instance in the sorted listed automatically. The user may then use the command-buttons on the dialog to display and edit various instances, or the application can call display-instance in some other way.

How Slot Values Are Read and Written

When reading and writing slot values, an object-editor will call reader and writer functions of any direct slots that have reader and writer functions, and otherwise will call slot-value and (setf slot-value). Using reader and writer functions allows applications to perform their usual side effects as an object-editor accesses the slots. This is not done for non-direct slots, though, because it is not straightforward to find the reader and writer functions.)

Automatic Saving of User Edits

An object-editor will save changes to the currently displayed instance whenever a different instance is displayed or when object-editor-save is called. It will also do a save when a different window is selected if the save-on-clear-focus property is true, and do a save whenever an individual widget's value is changed if the save-on-new-widget-value property is true.

Finding the Object-Editor that a Widget Is On

If you add custom widgets to an object-editor form window in an IDE project, and an on-change function of a custom widget needs to find the object-editor itself, then note that this will be the parent of the parent of the widget. The widget's parent will be an object-editor-pane, and it is the parent of that pane that would be the proper argument for functions that take an object-editor argument.

Other Object-Editor Functionality

To reject invalid slot values as soon as the user enters them, write one or more validate-edited-slot-value methods.

To customize the spacing of widgets on the dialog, create an instance of the layout-spacing class, specifying some of its spacing properties, and pass it as the value of the layout-spacing initarg when creating the object-editor.

See command-buttons for the list of standard command buttons that are available on an object-editor, and the exported functions that they call.

The function current-instance returns the instance that is currently being displayed.

A special table of all instances is included on the dialog if the include-table-of-all-instances property is true.


object-editor-pane

Class, cg package

The class of the frame-child of an object-editor dialog. An instance of this class is always created automatically for an object-editor dialog. This is mostly so that the object-editor can have a status-bar and be scrollable vertically (otherwise scrolling would move the status-bar). The parent of a widget on a object-editor will be this window, and the parent of this window will be an actual object-editor.


ocx-widget

class, cg package

The class of all Common Graphics dialog-items that implement OCX controls. Use the def-cg-ocx-control macro to define subclasses of this class.

See handle-ocx-shortcut, *ocx-classes-for-focus*, *suppressed-ocx-properties*, and ocx-control.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


ocx-widget-window

class, cg package

The class of all Common Graphics widget-windows that implement OCX controls. Use the def-cg-ocx-control macro to define subclasses of this class.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


os-widget

class, cg package

The class of all dialog-items that are provided by the underlying window system or operating system. This class is not instantiable.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


os-widget-window

class, cg package

The class of all widget-windows that are provided by the underlying window system or operating system. This class is not instantiable. An application can usually use the various instantiable dialog-item classes (also called controls or widgets) without concerning itself with their associated widget-window classes which are internally instantiated to create the actual windows that appear on the screen for the logical dialog-items created by the application.

But if an application needs to intercept low-level window events that are not exported as one or more of the dialog-item's event-handler properties, then the application should make subclasses of both the dialog-item class and the associated widget-window class, and then add the needed methods that specialize on the window subclass, such as virtual-key-down or mouse-left-down methods. A widget-device method also should be added to associate the window class with the dialog-item class.

In releases prior to 7.0, this class was named by the symbol widget-window. That symbol still exists and still names a class, the superclass of os-widget-window (and of lisp-widget-window).

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


outline

class, cg package

Class

The class of an outline control.

Control

Instance of the outline class. This control acts as a multiple-item list, with added functionality to display its items in a hierarchy and to display only selected subtrees of the hierarchy. The items displayed are instances of the outline-item class.

The outline can be navigated via the arrow keys and the PAGE UP/PAGE DOWN keys. Scrollbars appear along the length of the control when the list exceeds the size of the frame.

Adding an outline control to your form

Click the outline tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size. Note: resizing the outline won't mean proportional changes in the size of the characters inside the list. Change the font property if you want to change the size of the actual characters displayed.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Creating an outline widget programmatically

Here is an example of writing code from scratch to create an outline widget, rather than building one interactively on a form. The keyword arguments here such as :range correspond to properties such as the range property that would be displayed in the inspector for an outline on a form, and which you can modify by calling (setf range).

The nested tree of :range arguments shown here demonstrates how to specify the whole tree of outline-items at once; an alternative is to write range-on-open methods that create each item's child items lazily when the item is opened by the user. Another alternative would be to call (setf range) on individual outline-item objects. For more complete examples, see the "Outline Widget" examples in the Navigator dialog.

There are many functions for manipulating outline widgets. A good way to find documentation links to all of them is by searching for "outline" in the Allegro Tree of Knowledge dialog displayed by the Help menu | Tree of Knowledge menu command. One generic function for outline widgets is handle-home-key-shortcuts, which allows keys in the middle of the keyboard (J, K, D, F, T, and B) to have the same effect as keys often on the right, like the arrow keys, Home, and End.

(in-package :cg-user)
(make-window 'outline-dialog
  :class 'dialog
  :interior (make-box-relative 100 200 240 140)
  :dialog-items
  (list (make-instance 'outline
          :font (make-font-ex nil "MS Sans Serif" 11 nil)
          :left 20 :top 20 :width 200 :height 100
          :name :my-outline
          :value :top-1
          :range
          (list (make-instance 'outline-item
                  :value :top-1
                  :state :open
                  :selected t
                  :range
                  (list (make-instance 'outline-item 
                          :value :middle-1
                          :state :open
                          :range
                          (list
                           (make-instance 'outline-item 
                             :value :bottom-11
                             :state :closed)
                           (make-instance 'outline-item
                             :value :bottom-12
                             :available nil
                             :state :closed)
                           (make-instance 'outline-item
                             :value :bottom-13
                             :state :closed
                             :font
                             (make-font-ex
                              nil "Courier" 15 '(:bold :italic)))))
                        (make-instance 'outline-item
                          :value :middle-2
                          :state :open
                          :range
                          (list
                           (make-instance 'outline-item
                             :value :bottom-21
                             :state :closed
                             :foreground-color red)
                           (make-instance 'outline-item
                             :value :bottom-22
                             :state :closed)
                           (make-instance 'outline-item
                             :value :bottom-23
                             :state :closed
                             :background-color yellow)))))
                (make-instance 'outline-item
                  :value :top-2
                  :state :open
                  :range
                  (list (make-instance 'outline-item
                          :value :biff
                          :state :closed
                          :background-color cyan)
                        (make-instance 'outline-item
                          :value :boff
                          :state :closed
                          :range nil)))))))

See also About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


outline-display-pane

class, cg package

The class of lisp-widget-windows that are instantiated whenever a dropping-outline is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a dropping-outline subclass or otherwise add methods to the lisp-widget-window of a dropping-outline. See lisp-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


outline-dropping-pane

class, cg package

The class of the window that drops down from a dropping-outline widget to reveal the tree of outline-items.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


outline-item

class, cg package

The class of an outline-item, which denotes a single entry in an outline control.

Outline-items consist of a value to be displayed, an arbitrary "type", a state (:open or :closed or :partially-open) indicating whether its subitems are currently displayed, a list of subitems, and a plist that may contain other item-specific attributes. The range of an outline control is a Lisp tree of these items. A range-on-open method can be used to supply the range in a lazy fashion (determining it when the item is opened).

Outline-items can be displayed above their parents when above-parent is true and the outline's handle-above-parent property is also true.

Outlines may be opened or closed programmatically with open-outline-item-value and close-outline-item-value or using (setf state). For the latter, see the discussion under the heading State on outline-items on the page for state.

There are various functions for manipulating outline-items. Among them are outline-item-mouse-in, outline-item-mouse-out, select-on-typing, move-up-one-outline-item, move-down-one-outline-item, hide-outline-item-children, show-outline-item-children, outline-item-removed, outline-item-added, outline-items-reordered, remove-outline-item, add-sibling-outline-item, add-child-outline-item, and shift-outline-item.

Outline items can be selected. The select-on-right-click property, if true, cause right-clicking on an outline-item to select that item as well as displaying a right button menu.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.


outline-pane

class, cg package

The non-instantiable superclass for all windows that are used in outline widgets for drawing the tree of outline-items; the subclasses are outline-top-pane (used by the regular outline widget) and outline-dropping-pane (used by the dropping-outline widget).

A diagram of window and widget classes is shown in Widget and window classes in cgide.htmlWidget and window classes in cgide.html.


outline-top-pane

class, cg package

The class of lisp-widget-windows that are instantiated whenever an outline is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of an outline subclass or otherwise add methods to the lisp-widget-window of an outline. See lisp-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


outline-widget-pane

class, cg package

The non-instantiable superclass for all windows that are used in outline widgets; the direct subclasses are outline-pane and outline-display-pane.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


picture-button

class, cg package

Class

The class of a picture-button control

Control

Instance of the picture-button class. This control contains an icon that may be selected by the user. It is capable of a non-momentary pressed-in state.

The image that is to appear on a picture-button (or on a static-picture) widget may be specified with any one of the following properties (typically by passing the equivalent keyword argument such as :pixmap to make-instance when creating an instance of the widget):

If no pixmap or icon has been specified for the widget, then it will simply fill its interior with its background-color.

Further notes

If the :stretching option to make-instance is passed as non-nil, then the bitmapped image will stretch automatically to fit the size of the widget. If nil, it will be drawn at the size at which the image was defined. The default is t. See stretching.

Grouping picture-buttons in clusters

The :cluster entry on the dialog item plist can be used to group picture-button dialog items into clusters. If the user clicks on one button in the cluster, that button will be turned on, and all other buttons in the cluster turned off. For example, consider the following:

(make-instance 'picture-button ... :cluster 'cluster1) 
(make-instance 'picture-button ... :cluster 'cluster1) 
(make-instance 'picture-button ... :cluster 'cluster2) 
(make-instance 'picture-button ... :cluster 'cluster2)

It creates two picture-button clusters each with two picture buttons. :cluster entries are compared using eql.

Component overhead and clusters of picture-buttons

Using a multi-picture-button instead of clusters of picture-buttons will reduce the load on resources and reduce application size/complexity in most situations. Components are window-like objects and are relatively costly in terms of system resources.

Using click-off with picture-button controls

This control supports the click-off property. The :click-off option to make-instance can have the following values:

Note: :click-off affects only what happens when clicking on a button widget while it is selected; the state of the button can always be changed programmatically by calling (setf value).

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


picture-button-pane

class, cg package

The class of widget-windows that are instantiated whenever a picture-button is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a picture-button subclass or otherwise add methods to the widget-window of a picture-button. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


picture-widget

class, cg package

The non-instantiable dialog-item class for widgets that display a single pixmap. The subclasses are picture-button and static-picture.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


picture-widget-pane

class, cg package

The widget-window class for the picture-widget dialog-item class.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


pixmap

class, cg package

Class

The class of pixmap objects. See the essay on pixmaps: cg-pixmaps.html.


pixmap-column

class, cg package

A grid-column subclass whose superclasses are pixmap-column-mixin and grid-column. This class may be instantiated directly when no further subclassing is needed, and therefore is convenient when creating a grid-widget interactively on a form window and then editing its properties in the inspector (see cg-grid-widget-simplified-tutorial.html). In the inspector, you could move to an existing grid-column and then set its class property to pixmap-column to turn it into this type of column (where the class choices are available in the drop-down list for the class property). See pixmap-column-mixin for the widget behavior.


pixmap-column-mixin

Class, cg package

A non-instantiable class that can be mixed with the grid-column class to create grid columns whose cells draw pixmaps that represent user values. Each cell in the column will display a pixmap if the row of that cell is an instance of a grid-row subclass that mixes in the widget-row-mixin class. See pixmap-column for an instantiable subclass that you can use directly when no further subclassing is needed, even specifying it interactively.

To ensure that this mixin class' methods take precedence over other methods that specialize on grid-column, this mixin class generally should appear first in a defclass expression's list of superclasses, as in:

(defclass my-pixmap-column
  (pixmap-column-mixin my-subclass-of-grid-column) ...)

The draw-cell method provided by this mixin will draw (in each cell of the grid column) a pixmap that is associated with an application value, if a pixmap has been supplied for that value. First read-cell-value is called as usual to find the application value to display (this typically calls the column's data-reader function). Then the pixmap-alist of the grid-column is searched to find an entry whose first element is that user value. If a match is found, then the second element of the alist entry is taken to be the name of a pixmap. If find-pixmap finds a cached pixmap by that name, then it is displayed in the cell. Otherwise the cell will be drawn blank.

If the stretching property of the grid-column is true, then the pixmap will be expanded or shrunk as needed to exactly fit the cell. Otherwise the pixmap will be drawn at its natural size.

If the user-modifiable property of the grid-column is true, then the user may cycle through the set of pixmaps by clicking the grid cell or pressing the spacebar when it has the keyboard focus. Each time a new pixmap is displayed, write-cell-value is called to write the associated data-value back into the data-object of the grid-row (this typically calls the column's data-writer function).

Here is a typical expression for creating a pixmap grid column. It assumes that the data-object of each grid-row has a slot accessor called access containing one of the values :none, :partial, or :full.

(make-instance 'my-pixmap-column
  :name :access
  :proportional nil
  :section-size 24
  :data-reader 'access
  :data-writer '(setf access)
  :pixmap-alist '((:none nil)
                  (:partial :key)
                  (:full :key-special))

The Employee grid example in the Navigator dialog includes a pixmap column that displays pictures of keys as in the code snippet above.

See the section Built-In Grid Cell Widgets on the page for the grid-widget class for an overview of the grid column mixins.

A quicker but less object-oriented alternative to using the widget-column-mixin classes is to write cell-widget methods.


plot-value-axis

class, cg package

The class of a plot-value-axis. This is the class to instantiate for the x-axis, y-axis, x-axis-2, or y-axis-2 property of a plot-widget.

This class does not define any unique properties, and instead inherits all of its properties from value-axis and its superclass chart-axis.

See plot-widget.


plot-view

class, cg package

The class of a plot-view. This is the class to instantiate for the plot-view property of a plot-widget. It represents the actual plot of points inside the value axes of the widget.

This class does not define any unique properties, and instead inherits all of its properties from chart-or-plot-view, line-drawing-view, and icon-drawing-view.

The unique properties of plot-view are:


plot-widget

class, cg package

The class of the plot-widget.

The plot-widget is a facility for creating two-dimensional plots of X/Y coordinate pairs, such as scatter plots. (To instead create bar charts or line graphs for a sequence of items, see the chart-widget class.)

The plot-widget can be used to present static information or to dynamically monitor information as it changes. The widget will automatically lay out its axes and other parts (according to style properties that you can modify), and can also autocompute a rounded value range that encloses all of the data values.

Plot subobjects

The following classes are used to create secondary objects that are used by a plot-widget:

Each of those classes has its own properties that affect the style and behavior of the plot-widget itself.

Properties of the plot-widget class

These properties are unique to the plot-widget class.

Additional plot-widget properties are provided by the chart-or-plot superclass.

plot-widget examples

The following example code demonstrates the two main alternate techniques for supplying the data for a plot: (1) calling set-plot-value once for each datum, and (2) supplying a plot-value-returner function that will be called as needed to return each value.

For both techniques we will use the following sample data. This is an array of arbitrary X/Y coordinate pairs. The outermost dimension of the array represents two independent objects, each of which has its own set of X/Y pairs. Typically, different icons will be used in a plot to distinguish the data of different objects.

(defparameter *points*

  ;; Points for the first chart object.
  #3a(((51.68 18.49) (59.28 41.71) (10.26 130.29) (12.16 144.05)
       (20.14 136.31) (52.44 42.57) (49.4 59.77) (50.16 72.67)
       (41.42 76.97) (35.72 92.45) (33.06 112.23) (39.52 110.51)
       (47.88 95.89) (38.76 89.87) (25.84 131.15) (17.86 119.11)
       (30.4 104.49) (44.08 89.01) (55.86 70.09) (47.5 52.03)
       (44.08 70.95) (51.68 94.17) (36.86 105.35) (39.9 122.55)
       (23.94 120.83) (16.72 132.01) (31.92 124.27) (56.24 31.39)
       (53.58 55.47) (49.4 83.85) (43.32 105.35))

      ;; Points for the second chart object.
      ((37.0 123.0) (53.58 138.03) (45.98 140.61) (43.32 119.97)
       (25.08 75.25) (24.32 123.41) (37.24 89.01) (39.52 101.91)
       (34.96 107.93) (30.78 114.81) (24.32 112.23) (25.08 99.33)
       (25.08 89.87) (20.9 109.65) (18.24 87.29) (11.02 69.23)
       (12.54 58.05) (17.86 40.85) (19.38 58.05) (25.08 63.21)
       (21.66 81.27) (13.68 88.15) (29.64 128.57) (20.9 118.25)
       (16.72 113.09) (17.1 98.47) (22.42 101.91) (30.02 83.85)
       (33.82 101.05) (28.88 96.75) (27.36 119.11))))

The first version of the example code uses the approach of calling set-plot-value for each datum, after creating the plot-widget.

(let* ((width 500)
       (height 400)
       (plot-widget
        (make-instance 'plot-widget
          :title "Two Sets of Points"
          :chart-objects '((:id first :label "First Collection")
                           (:id second :label "Second Collection"))
          :plot-view (make-instance 'plot-view
                       :icon-images '(:square :circle)
                       :draw-lines nil)
          :x-axis (make-instance 'plot-value-axis
                    :axis-label "The X Axis")
          :y-axis (make-instance 'plot-value-axis
                    :axis-label "The Y Axis")
          :chart-legend (make-instance 'chart-legend
                          :layout-orientation :one-column)
          :right-attachment :right
          :bottom-attachment :bottom
          :left 0 :top 0 :width width :height height))
       (dialog (make-window :example-plot
                 :class 'dialog
                 :title "Example Plot"
                 :scrollbars nil
                 :interior (make-box-relative 40 40 width height)
                 :dialog-items (list plot-widget)))
       item-id)

  ;; This version copies your data to the plot-widget,
  ;; one element at a time.
  (dotimes (object-index (array-dimension *points* 0))
    (dotimes (value-index (array-dimension *points* 1))
      (set-plot-value plot-widget
                      :object-index object-index
                      :value-index value-index
                      :x (aref *points* object-index value-index 0)
                      :y (aref *points* object-index value-index 1))))
  dialog)

The second version builds the same plot by supplying a plot-value-returner function rather than by calling set-plot-value in a loop. This technique is typically more efficient because it accesses your data where it already lives, rather than first accumulating the data gradually into the plot-widget's own internal representation.

When using a plot-value-returner, you generally need to also supply a list of chart-objects and a plot-values-max-index value, to tell the widget the range of indexes over which it should call your plot-value-returner function.

(let* ((width 500)
       (height 400)
       (plot-widget
        (make-instance 'plot-widget
          :title "Two Sets of Points"

          ;; This version uses a plot-value-returner function, along
          ;; with a plot-values-max-index and a list of chart-objects.
          :plot-value-returner
          (lambda (plot-widget value-type value-index
                               object-index object-id)
            (declare (ignore plot-widget object-index))
            (case value-type
              (:x (aref *points* object-index value-index 0))
              (:y (aref *points* object-index value-index 1))))
          :plot-values-min-index 0
          :plot-values-max-index (1- (array-dimension *points* 1))
          :chart-objects '((:id first :label "First Collection")
                           (:id second :label "Second Collection"))
          
          :plot-view (make-instance 'plot-view
                       :icon-images '(:square :circle)
                       :draw-lines nil)
          :x-axis (make-instance 'plot-value-axis
                    :axis-label "The X Axis")
          :y-axis (make-instance 'plot-value-axis
                    :axis-label "The Y Axis")
          :chart-legend (make-instance 'chart-legend
                          :layout-orientation :one-column)
          :right-attachment :right
          :bottom-attachment :bottom
          :left 0 :top 0 :width width :height height))
       (dialog (make-window :example-plot
                 :class 'dialog
                 :title "Example Plot"
                 :scrollbars nil
                 :interior (make-box-relative 40 40 width height)
                 :dialog-items (list plot-widget))))
  dialog)

Here's one more example to illustrate a few more options. This one adds a second pair of axes with a different scale for a second chart object. It also specifies some additional properties of the plot-widget and its secondary objects, to give you a feel for some of the other modifiable attributes. And it uses a mathematical function to generate plot values in a circular manner, rather than using real data as an application typically would.

(let* ((width 500)
       (height 600)
       (plot-widget
        (make-instance 'plot-widget
          :title "Doris and Hubert"
          :subtitle #.(format nil "This pointless subtitle will wrap ~
                          automatically to avoid clipping at the sides ~
                          of the plot-widget.")
          :subtitle-color dark-red
          :footnote "There's really no need for this footnote."

          ;; This plot uses a different pair of axes for each object.
          ;; The :x-axis and :y-axis values for :hubert tell the plot-widget
          ;; to use the axes on the right and top sides of the plot for that
          ;; object, rather than the default axes along the left and bottom
          ;; sides.  And the :label properties are printed in the legend
          ;; to tell the user which objects go with which axes.
          :chart-objects (vector (list :id :doris
                                       :label "Doris Lurple (left and bottom axes)")
                                 (list :id :hubert
                                       :label "Hubert Murple (right and top axes)"
                                       :x-axis 2
                                       :y-axis 2))

          ;; Unlike the previous examples, we specify :draw-lines as true here,
          ;; to draw lines between the plotted points.  True is the default.
          ;; All of the lines in the plot data will be 2 pixels thick.
          :plot-view (make-instance 'plot-view
                       :icon-images '(:square :circle)
                       :icon-fill-colors (list blue green)
                       :line-widths (list 2)
                       :draw-lines t)

          ;; Here we create the usual primary axes that lie along the
          ;; left and bottom sides of the plot.
          :x-axis (make-instance 'plot-value-axis
                    :axis-label "Lower Axis"
                    :axis-color blue
                    :range-bottom 0
                    :range-top 10)
          :y-axis (make-instance 'plot-value-axis
                    :axis-label "Left Axis"
                    :axis-color blue
                    :range-bottom 3.0
                    :range-top 7.0)

          ;; Since we're using the second pair of axes for this plot,
          ;; we specify some attributes for those axes here.
          :x-axis-2 (make-instance 'plot-value-axis
                      :axis-label "Upper Axis"
                      :axis-color (make-rgb :green 192)
                      :draw-minor-tics t
                      :draw-minor-labels nil
                      :minor-tic-length 4
                      :range-bottom 0
                      :range-top 10)
          :y-axis-2 (make-instance 'plot-value-axis
                      :axis-label "Right Axis"
                      :axis-color (make-rgb :green 192)
                      :draw-minor-tics t
                      :minor-tic-length 4
                      :range-bottom 0
                      :range-top 8
                      :major-tic-increment 2
                      :minor-tics-per-major-tic 2)

          :chart-legend (make-instance 'chart-legend
                          :legend-font (make-font-ex :swiss "Arial / ANSI" 12))

          ;; This is a rather artificial plot-value-returner because
          ;; it uses a mathematical function to generate points to plot,
          ;; rather than looking up arbitrary real-world data as usual.
          ;; But it illustrates returning the various attributes of a
          ;; plotted point, such as :x-high for an error-range value to
          ;; the right of a plotted point.
          :plot-value-returner
          (lambda (plot-widget value-type value-index
                               object-index object-id)
            (declare (ignore plot-widget object-id))
            (let* ((factor 2.4)

                   ;; We use some trigonometry here to generate
                   ;; values that go around in a circle.  The plot-widget
                   ;; isn't limited to laying out a sequence of items in
                   ;; a single direction as the chart-widget is.
                   (x (+ 5 (* (+ object-index 2)
                              (cos (* value-index factor)))))
                   (y (+ 5 (* (1+ object-index)
                              (sin (* value-index factor))))))

              ;; The keywords here are all of the possible values of the
              ;; value-type argument that is passed to a plot-value-returner
              ;; function.  :x and :y are the coordinates of a point to plot.
              ;; The low and high values are typically used for an error
              ;; range, and this plot-widget will draw them as T-bars.
              (case value-type
                (:x x)
                (:y y)
                (:x-low nil) ;; Don't draw any T-bars toward the left.
                (:x-high (* x 1.07))
                (:y-low (* y .95))
                (:y-high (* y 1.05))

                ;; Here we artificially use larger icons for plotted points
                ;; that are farther to the right (with a larger X coordinate).
                (:icon-size (ceiling (+ x 1))))))

          ;; This tells the plot-widget to call the plot-value-returner
          ;; function a number of times with the value-index argument
          ;; varying from 0 through 12.
          :plot-values-min-index 0
          :plot-values-max-index 12

          :right-attachment :right
          :bottom-attachment :bottom
          :left 0 :top 0 :width width :height height))
       (dialog (make-window :example-plot
                 :class 'dialog
                 :title "More Complete Example"
                 :scrollbars nil
                 :interior (make-box-relative 40 40 width height)
                 :dialog-items (list plot-widget))))
  dialog)

plot-widget-pane

class, cg package

The class of the pane of a plot-widget.


pop-up-menu

class, cg package

The class of pop-up menus. See menu.


printer

class, cg package

Printing hardcopy is supported only when running in Windows desktop mode, and the printing functions should be called only in Windows desktop mode.

The class of printer objects. Open a printer with open-stream (not make-instance). For example, this form, if run, sets some values and pops up a printer job dialog for getting more instructions from the user:

(open-stream 'printer nil nil
             :output :units-per-inch 100
             :font (make-font-ex nil :arial 48)) 

The printer-specific arguments to open-stream are documented under pop-up-printer-job-dialog. Do not call that function directly, though, because it is called internally when you open a printer stream. To show the Page Setup dialog, which is independent of any particular print job, call pop-up-printer-setup-dialog at any time.

A higher-level alternative to open-stream is with-output-to-printer. This macro ensures that the printer stream gets closed after executing the macro body, and avoids executing the macro body at all if the user cancels the print job dialog. It also provides additional arguments for setting up the resolution and initial font of the printed output.

You can draw on a printer stream just as you would on a window, calling functions such as draw-line and draw-string-in-box. The pixel resolution of a laser printer is typically much finer than on a monitor, though, so first call stream-units-per-inch to find the resolution and then adjust your drawing code to it, or call (setf stream-units-per-inch) to adjust the stream's resolution to your preferred drawing coordinates. Call left-margin, top-margin, right-margin, and bottom-margin to find the coordinates within which you should draw on the current page, and call new-page to advance to the next printed page.

To find out attributes of a printer without actually printing anything, use with-printer.


progress-indicator

class, cg package

Class

The class of the progress-indicator control.

Control

An instance of the progress-indicator class. This control often appears where users make a request on a form and will have to wait for some hidden process to complete before proceeding with the rest of the possible functions on the form.

Adding a progress-indicator control to your form

Click the progress-indicator tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Adding a caption to the progress indicator

  1. Select the static-text control tool.

  2. Click on the form and drag the control to the place where you want the caption for the progress-indicator to appear.

  3. Double-click the static-text control to focus on it with the Inspector.

  4. Inspect the title property of the control by double-clicking on the value of the title and changing it in the Edit Expression dialog. Click the OK button when you are done editing the new caption.

    If the caption is small enough to see in the Inspector's right column, you can also click once on the title and delete and replace the text right in the Inspector without opening the Edit Expression dialog.

  5. If you want to change the alignment of the text with respect to the length of the progress-indicator, resize the text control to be the exact same length as the progress-indicator. Then change the justification property of the text-control to either :right or :center. The initial justification on a static-text control is :left.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

Example

The following code creates a dialog window with a progress indicator on it. The variable my-pi is set to the component, using find-component. The function foo runs through a loop of length 10, printing the fraction done and updating the progress indicator in each iteration, while also sleeping for one second between loop interations. The progress indicator is incremented with (setf value).

(in-package :cg-user)
(make-window :pi-dialog
  :class 'dialog
  :interior (make-box-relative 100 100 240 140)
  :dialog-items
  (list (make-instance 'progress-indicator
          :left 20 :top 20 :width 200 :height 20
          :name :my-pi
          :value 0
          :range '(0 100)
          )))

(defvar my-pi)
(setq my-pi (find-component :my-pi :pi-dialog))

(defun foo ()
  (declare (special my-pi))
  (setf (value my-pi) 0)
  (dotimes (i 10)
    (sleep 1)
    (format t "~D% done~%" (* 10 (+ i 1)))
    (setf (value my-pi) (* 10 (+ i 1)))
    ))

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


progress-indicator-pane

class, cg package

The class of widget-windows that are instantiated whenever a progress-indicator is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a progress-indicator subclass or otherwise add methods to the widget-window of a progress-indicator. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


project

class, cg package

The symbol naming this class has been moved to the :ide package. Please see project.


project-module

class, cg package

The symbol naming this class has been moved to the :ide package. Please see project-module.


property

class, cg package

The class of a property object. Properties are defined by the macros defproperties and define-property.


pull-down-menu

class, cg package

The class of a pull-down menu. See menu and the menu chapter in the IDE User Guide.


radio-button

class, cg package

Class

The class of a radio-button control.

Control

An instance of the radio-button class. This is a standard radio button control. The title field of the dialog item is used as the name of the radio button, and is displayed immediately to the right of the radio button itself. The value field of the dialog item is set to t if the radio button is on and is set to nil if it is off.

The behavior of radio buttons is to select one item in the cluster to the exclusion of all others. You are not required to place a group box around the set. Radio buttons are defined as being in a particular group via the :cluster property.

The displayed name of the button is the value of the title property. If the wrapping property is true, the title will wrap text to a second line if necessary. If wrapping is nil, text that does not fit will not be displayed.

Adding a radio-button control to your form

Click the radio-button tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size. Note: resizing the radio-button control changes the size of the bounding-box, but not the size of the actual radio button inside.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Grouping radio-buttons together

The :cluster entry on the dialog item plist is used to group radio button dialog items into clusters. If the user clicks on one button in the cluster, that button will be turned on, and all other buttons in the cluster turned off. For example, consider the following:

(make-instance 'radio-button ... :cluster 'cluster1) 
(make-instance 'radio-button ... :cluster 'cluster1) 
(make-instance 'radio-button ... :cluster 'cluster2) 
(make-instance 'radio-button ... :cluster 'cluster2)

It creates two radio button clusters with two radio buttons each. :cluster entries are compared using eql.

Using click-off with radio-button controls

Radio-button supports the click-off property. This property can have the following values:

Note: this option affects only what happens when clicking on a radio-button widget while it is in focus; the state of the radio-button can always be changed programmatically with value.

radio buttons and tabstop

Windows only allows you to tab to a radio-button when it is on. (Common Graphics supports tabbing to controls that have their tabstop property on.) The usual approach is to set the tab order of your dialog so that all of the radio-buttons that are in the same cluster will be adjacent in the tab order, and then make sure that the initial value of one of the radio-buttons in the cluster is non-nil. Then the user will be able to tab to the currently "on" radio-button in that cluster and then use the keyboard's arrow keys to move to the other radio-buttons in that cluster.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


radio-button-pane

class, cg package

The class of widget-windows that are instantiated whenever a radio-button is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a radio-button subclass or otherwise add methods to the widget-window of a radio-button. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


rgb

class, cg package

The class of an rgb (red-green-blue) color object. See make-rgb.


rich-edit

class, cg package

Class

The rich-edit widget is specific to Windows desktop mode, and should not be used in CG/JS mode.

The control built on rich-edit-pane. Shares its automatic linking-up features. This class is a subclass of multi-line-editable-text control class that can display so-called rich text, with multiple fonts, text colors, paragraph justifications, and other text formatting. The control can read and write standard .rtf (Rich Text Format) files. The formatting may be modified programmatically by calling functions such as set-character-format and set-paragraph-format, or interactively by the end user if any rich-edit "helper" controls exist on the same parent window or some descendent window of it (such as a toolbar). The rich-edit helper controls are the rich-edit-multipic, font-face-combo-box, font-size-combo-box, and rich-edit-ruler.

See cg-rich-text.html for information about rich text editing in Common Graphics.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


rich-edit-combo-box

class, cg package

The non-instantiable superclass of the two special types of combo-box (font-face-combo-box and font-size-combo-box) that are provided for use with a rich-edit control.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


rich-edit-dialog

class, cg package

The rich-edit widget and dialog are specific to Windows desktop mode, and should not be used in CG/JS mode.

A subclass of dialog intended for use with rich-edit controls. Currently the only functional differences between a dialog and a rich-edit-dialog are:

To create a rich-edit-dialog interactively, invoke the File | New Form menu-bar command and select rich-edit-dialog from the list of choices. This will make a rich-edit-dialog form and will automatically add a rich-edit control and an associated rich-edit-ruler just above it to the form, and also add auxiliary widgets in a toolbar for use with the rich-edit control.

This dialog will act as a complete WordPad(tm)-like application. If you would like to add additional controls to the form or toolbar, you can do so. The rich-edit controls appear at the right end of the component toolbar. Note that if multiple rich-edit controls are added to a single form, the single set of rich-edit helper controls works for all of the rich-edit controls on the same parent window, reflecting the rich-edit that most recently had the keyboard focus.

Try running the initial rich-edit form (with that form selected, click on Run | Run Form), then clicking the Open button in the toolbar and selecting the file examples\cg\rich-edit-sample.rtf (in the examples\cg\ subdirectory of the main Allegro directory). This should show some sample rich text.

Building Rich-Edit Forms from Scratch

To test making your own rich-edit dialog from scratch, invoke the File | New Form command, and select dialog from the list of window classes that you can create. Double click the interior of the new form to inspect it.

If you would like to start the menu-bar off with the special rich-edit commands, then go to the menu property of the form in the inspector and enter #.(rich-edit-menubar) in the inspector line for the menu property. (The #. reader macro is a trick to evaluate the expression typed directly into a line of the inspector.) This should add the standard rich-edit menu-bar to the form, and you can further edit this menu as you like.

Back in the inspector, toggle the toolbar property on to give the form a toolbar. Also toggle the status-bar property to give the form a status-bar for messages. Next, click on the Rich-Edit button of the Component Toolbar (the one with a big green "R"), and then click in the main interior of your form to create a rich-edit control. You may want to size the rich-edit control larger, since the default size is rather small. Now click on each of the next three rich-edit "helper" controls on the Component Toolbar and instantiate those widgets from left to right on the toolbar of your new form. (The helper controls consist of the rich-edit-multipic, the font-face-combo-box, and the font-size-combo-box. Finally, click on the Ruler button on the Component Toolbar, position it just above the rich-edit control, and then drag it or stretch it partly over the rich-edit as needed to make it snap into place along the top.

Having done this, you now have a dialog that is functionally similar to the one created by using the rich-edit-dialog class. You can customize either however you like by adding additional controls and editing the initial rich-edit menubar. Note that only a rich-edit-dialog has the built-in feature of prompting the user to save any unsaved rich-edit controls when a closing gesture is made.

Special Features

While the rich-edit functionality basically allows for custom WordPad--like applications, there are a couple of features that are somewhat unique:

If you place a menu bar on a rich-edit-dialog, you may want to use funcall-menu-item-with-rich-edit instead of funcall-menu-item-with-window as the on-click function for the menu-bar.

See cg-rich-text.html for information about rich text editing in Common Graphics.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


rich-edit-multipic

class, cg package

This class is a subclass of the multi-picture-button control class. rich-edit-multipic has a standard set of buttons for working with an associated rich-edit control. The buttons may be clicked by the end user to read or write .rtf files and to change the character format and paragraph justification of the selected text in the associated rich-edit control. The buttons also change their pressed or unpressed state automatically to reflect the state of the currently selected text in the associated rich-edit control.

If there are any rich-edit controls on the same parent window as the rich-edit-multipic, and at least one of them has had the keyboard focus, then the rich-edit-multipic will affect the rich-edit that most recently had (or still has) the focus; otherwise it will do nothing. If a rich-edit is not found on the same parent window, then the grandparent window is searched, followed by the great-grandparent and so on; this allows a rich-edit-multipic to be placed on the toolbar of a dialog that contains a rich-edit control in its main area, for example.

See cg-rich-text.html for information about rich text editing in Common Graphics.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


rich-edit-pane

class, cg package

A text-edit-pane that will automatically link up with any rich-edit formatting controls that are either on the same parent or on a toolbar of the parent. This is the class of widget-windows that are instantiated whenever a rich-edit is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a rich-edit subclass or otherwise add methods to the widget-window of a rich-edit. See os-widget-window.

The character index at a specific position is returned by character-index-at-position and the location of that character (given the index) is returned by position-of-character-index.

See cg-rich-text.html for information about rich text editing in Common Graphics.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


rich-edit-ruler

class, cg package

The rich-edit-ruler control allows the end user to interactively specify paragraph indentation and tab positions of an attached rich-edit control. The control will affect the paragraph that currently contains the text cursor, or the set of paragraphs that are wholly or partly selected.

Two small triangular gadgets may be dragged along the lower half of the ruler to set the main left and right indentations, and a third small triangular gadget may be dragged along the upper half to set the left indentation of the first line of each paragraph. Clicking elsewhere on the ruler adds a tab marker at the clicked position. A tab marker may be removed by clicking it and dragging it off the ruler.

A rich-edit-ruler must be attached to a particular rich-edit control in order to have any functionality. When building a form interactively, a rich-edit-ruler may be attached by placing it or dragging it so that it partly overlaps a rich-edit control. The ruler will then be positioned and sized so that it runs along the entire top side of the rich-edit control, and the two controls will be internally associated. When creating the controls programmatically instead, the name of the rich-edit should be specified as the rich-edit property of the ruler, and the name of the ruler should be specified as the ruler property of the rich-edit. This may be done at creation time using the associated initargs, like this:

(make-instance 'rich-edit
  :name 'my-rich-edit
  :ruler 'my-rich-edit-ruler
  ...)
...
(make-instance 'rich-edit-ruler
  :name 'my-rich-edit-ruler
  :rich-edit 'my-rich-edit
  ...)

See cg-rich-text.html for information about rich text editing in Common Graphics.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


rich-edit-ruler-pane

class, cg package

The class of lisp-widget-windows that are instantiated whenever a rich-edit-ruler is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a rich-edit-ruler subclass or otherwise add methods to the lisp-widget-window of a rich-edit-ruler. See lisp-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


row-defaults

class, cg package

The class of the subsection-defaults of a grid-row-section.


row-header-column

class, cg package

A sub-class of grid-column that is handy for implementing a column of row header cells. Specifically, this class mixes together the classes row-sizing-column-mixin, row-selecting-column-mixin, and grid-column. Using this class is simply a shortcut for making a subclass of those classes yourself. See those superclasses for more information.

See also the Navigator dialog example (on the Examples tab) entitled "Grid-Widget: a more sophisticated employee chart".


row-header-defaults

class, cg package

The class of the object that is returned by calling row-header-defaults on a grid-widget. See that function for more information.


row-section-with-sort-gadget-mixin

class, cg package

An application can mix this class into a grid-row-section subclass to give that row-section a default interactive interface to the row-sorting functionality of a grid-widget. The mixin will cause mouse clicks on cells in that row section to sort the grid and/or to select the current sort-column. Typically it is mixed into a row section that is used for column headers, containing a single grid-row.

Note that if the particular interactive interface provided by this mixin is not suitable, an application can instead define its own cell-click methods that initiate a call to sort-grid in a custom way, and also perhaps define draw-cell methods that indicate the current sort-column and/or sort-reverse status in a custom way. This mixin is simply a suggested interactive interface to the standard programmatic sorting functionality of grid-widgets.

In addition to implementing mouse clicks for sorting, this mixin draws a "sort gadget" at the very right end of the row section, in the space where the row section's scrollbar would be if it had one. (Therefore, this section's scrollbars property should be nil so as not to cover the scroll gadget. Normally this is not a problem since a row section used for sorting is a header row that would not scroll.) The sort gadget is drawn simply as a group of horizontal lines that are longer toward the bottom when the grid-widget's sort-reverse property is nil, and longer toward the top when sort-reverse is true. This provides a visual indication of the current sort direction.

Another visual cue provided by this mixin is to underline the text in the cell in the current sort-column. This is implemented by a cell-font method that calls vary-font on the usual font for the cell to add underlining to it.

The mouse click behavior of this mixin depends on the value of the sort-on-click property of the row section, which provides two alternate styles.

If sort-on-click is true (the default), then a simple left click in a cell of this row-section will set the sort-column of the grid to the column of the clicked cell, and then call sort-grid to sort the grid-row-section just below this row section by the values in the column. If the clicked column was already the sort-column of the grid, then the value of the sort-reverse property is first toggled so that the sort is done in the opposite direction. The sort gadget at the right always indicates the direction in which the most recent sort was done. Clicks on the sort gadget itself will do nothing. This sort-on-click option provides the more intuitive click behavior which is similar to how the list-view control works, for example. The drawback is that it overrides whatever left-click behavior the cells in this row section would otherwise have.

If sort-on-click is nil, then mouse clicks are handled in an alternate style that's provided mostly for backward compatibility, because it is less intuitive. The mixin was written this way originally so as not to override the usual left-click functionality of any grid cells. With this option, the user first sets the current sort-column by right-clicking on the cell where that column and this row-section intersect. Then the user left-clicks the sort gadget itself to do the sort. (If no current sort column has been set yet, a warning dialog is shown.) Right-clicking the sort gadget will reverse the order of the sort that is to be done (so with this option, the appearance of the sort gadget reflects the order of any subsequent sort, rather than the order of the most recent sort).

For either sort-on-click option, the click that sets a new current sort-column will do so only if that column's sortable property is true, as it is by default.


row-selecting-column-mixin

class, cg package

A grid-column that is an instance of this class allows the user to select and/or move grid-rows by clicking the cells where they cross the grid-column. The selectable property of a row must also be true before the row may be interactively selected, and the movable property of a row must also be true before the row may be interactively moved. In other words, a row may be interactively selected at a particular cell if the row is a selectable one and the column at that cell is an instance of row-selecting-column-mixin; and (likewise) a row may be interactively moved (among the rows in its grid-row-section) at a particular cell if the row is a movable one and the column at that cell is an instance of row-selecting-column-mixin.

This feature is typically used only in a grid-column that serves as a set of row headers, so that the special row-selecting and/or -moving behavior does not override other cell-click behavior in the body of the grid-widget. Nevertheless, it may sometimes be desirable to use this class for multiple columns of a grid.

The user uses this feature by moving the mouse cursor into a cell in a selectable or movable grid-row where it crosses a row-selecting-column-mixin column. The user may click and drag vertically in this cell to reposition the grid-row, or click and release without moving the mouse more than *start-drag-slack* pixels to toggle the selected property of the row. When the mouse button is released after a drag, the row is positioned among the rows in its grid-row-section so that it is just below all of the rows whose vertical centers are above the final vertical center of the drag box (this should be intuitive). A drag may be canceled either by pressing the Escape key before releasing the mouse button or by releasing the mouse button while the drag box is positioned where the row would snap back to where it was already.

An individual selectable grid-row may be added to the current set of selected rows in its grid-row-section by holding down the Control key while clicking the row; if the row is already selected, then this deselects the row instead. If the Shift key is held down while clicking a selectable row, then the range of rows that just encompasses all of the rows that were already selected plus the row that was clicked are then left in a selected state (regardless of their selected state beforehand).

This class must be mixed with grid-column (or one of its subclasses) to make an instantiable class. It is best to specify such mixin classes ahead of the grid-column class in the list of superclasses for a new class, so that the small amount of special behavior from the mixin class will override the more general behavior of the grid-column class. For example:

(defclass my-row-selecting-column (row-selecting-column-mixin grid-column)())

The above default mouse click behavior may be overridden by custom cell-click methods.

For an example of row-selecting-column-mixin, see the Navigator dialog example (on the Examples tab) entitled "Grid-Widget: a basic replicated editable-text column". See also the class row-header-column, which combines this class with row-sizing-column-mixin and grid-column for use as a typical column of row headers.

See also slide-subsection.


row-sizing-column-mixin

class, cg package

A grid-column that is an instance of this class allows the user to interactively change the height of grid-rows where they cross the grid-column. The resizable property of a row must also be true before interactive resizing is possible for that row. In other words, a row may be interactively resized at a particular cell if the row is a resizable one and the column at that cell is an instance of row-sizing-column-mixin.

This feature is typically used only in a column that serves as a set of row headers, so that the special row-sizing mouse cursor does not appear frequently as the user moves the mouse over the body of the grid (which might be distracting), and/or to prevent the user from inadvertantly resizing a row slightly if they click too near a cell's border when they mean to click in its interior. Nevertheless, it may sometimes be desirable to use this class for multiple columns, or even every column, of a grid.

The user uses this feature by moving the mouse cursor to the bottom border of a cell in a resizable row where it crosses a row-sizing-column-mixin column. The mouse cursor will change to indicate where resizing may be initiated; this area ranges from the bottom edge of the border to *grid-border-mouse-slack* pixels above that. The user may click and drag vertically in this area to resize the grid-row. If the uniform-resizing property of the grid section is true, then all of the rows in the clicked grid-row-section will be sized to the specified size, though if the Control key is held down then the behavior of the uniform-resizing property is reversed. The drag may be canceled either by pressing the Escape key before releasing the mouse button or by releasing the mouse button above the top of the row (which would otherwise makes its height be negative).

This class must be mixed with grid-column (or one of its subclasses) to make an instantiable class. It is best to specify such mixin classes ahead of the grid-column class in the list of superclasses for a new class, so that the small amount of special behavior from the mixin class will override the more general behavior of the grid-column class. For example:

(defclass my-row-sizing-column (row-sizing-column-mixin grid-column)())

The above default mouse click behavior may be overridden by custom cell-click methods.

The height of a grid-row is stored as its section-size property. See also stretch-subsection.

See the grid-widget class for an overview of writing grid-widget code.


scaling-stream

class, cg package

A mixin allowing modification of stream-units-per-inch and stream-units-per-mm. Scaling-stream is the parent of the printer class but not of any of the built-in window classes. To make a scalable window, you must create a class with the scaling-stream mixin and some window class as its superclasses.


screen

class, cg package

The class of screen objects. There is only a single screen instance, which is automatically created when Common Graphics is initialized with initialize-cg. (A possible future enhancement would support multiple monitors, each of which would have its own screen.)

The screen object is returned by the expression (screen *system*) (see screen and *system*). This object will be returned by parent when called on a top-level window, and by owner when called on a non-owned top-level window.

Drawing may be done on the screen as it is done on a window, though the drawing code must be wrapped in a with-device-context form. Care should be taken not to draw on other applications, which this allows.

This class was named windows-screen-device in releases prior to 7.0.


screen-stream

class, cg package

The class of all streams that display on the screen, which includes all windows (see basic-pane) and the screen itself. This is the class of objects that are valid as the owner of a window or menu.


scroll-bar

class, cg package

The non-instantiable dialog-item class that encompasses vertical-scroll-bar and horizontal-scroll-bar.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


scroll-bar-mixin

class, cg package

A non-instantiable mix-in class that groups together all dialog-items that select a value from a continuous range. The range property of these widgets is a list of a minimum and a maximum value.


scroll-bar-pane

class, cg package

The widget-window class for the scroll-bar dialog-item class.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


scroll-bar-pane-mixin

class, cg package

The widget-window mix-in class for the scroll-bar-mixin dialog-item class.


scrolling-static-text

Class, cg package

The class of a scrolling-static-text control.

This widget displays a block of non-editable text that wraps at spaces as needed to contain the text within the width of the widget, just as an ordinary static-text widget does. In addition, it will scroll vertically when not all of the text will fit within the height of the widget. A vertical scrollbar appears only when scrolling is needed. The widget can be scrolled as usual with the mouse on the scrollbar or with the Page Up, Page Down, and up and down arrow keys. This widget always uses the double-buffered property for smooth scrolling and updating.

The value property holds the string that the widget displays. The draw-focus property determines whether a rectangle is drawn around the text when the widget has the keyboard focus. If border-color is not nil, then a rectangle is drawn around the text at all times. The horizontal-justification, vertical-justification, and margin-around-text properties determine how the text is laid out within the widget. The text may be scrolled programmatically by calling set-first-visible-line.

Application code that precedes the scrolling-static-text widget may have emulated it by using a multi-line-editable-text widget with its read-only property set to true and perhaps its border set to :none. Using a scrolling-static-text in such cases may be more efficient.


scrolling-static-text-pane

Class, cg package

The class of the pane of a scrolling-static-text widget.

See chart-widget and also cg-chart-widget.html.


shortcut-menu

class, cg package

The class of shortcut-menus (also called right-button menus). See menu and the menu chapter in the IDE User Guide.

A menu of this class is invoked whenever pop-up-shortcut-menu is called and shortcut-commands returns a list of menu-items to show in the menu.


single-item-list

class, cg package

Class

The class of the single-item-list control. multi-item-list and single-item-list are together called item-list widgets.

Control

An instance of the single-item-list class. A list box highlighting a single item in its window. The list is navigable from the keyboard via the arrow keys. HOME and END keys take users to the top and bottom of the list, respectively.

The value field is set to the item selected by the user, and is shown highlighted in the list. If no item is highlighted, the value field is set to nil. The items may be any type of object, though for some item types the on-change-test of the widget may need to be changed to a function that will return true for equivalent objects of that type.

The range property holds the list of items to be displayed; list items appear in the order you enter them in the range. The items may be any type of object, though for some item types the on-change-test of the widget may need to be changed to a function that will return true for equivalent objects of that type.

The entire range may be set either by passing the :range initarg when calling make-instance to create the widget, or later by calling (setf range). Incremental changes to the range may be made by calling the functions list-widget-add-item, list-widget-remove-item, list-widget-replace-item, and list-widget-move-item.

An application should not destructively modify a list that it has passed as a :range initarg or to (setf range) for an item-list widget, because the widget retains this list object to determine which values are actually new when (setf range) is called again on the widget. To make small changes to the range, the incremental functions mentioned above may be used to avoid consing a new list to pass to (setf range).

Adding a single-item-list control to your form

Click the single-item-list tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size. Note: resizing the single item list won't mean proportional changes in the size of the characters inside the list. Change the font property if you want to change the size of the actual characters displayed.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Scrollbars

In release 11.0, the following paragraph is no longer true, because a fix was found.

On Windows, this control will show a horizontal scrollbar only if its multi-column-p property is true (and the multiple columns extend beyond the width of the control). If a horizontal scrollbar is needed on a single-item-list that does not use multiple columns, an outline control could be used instead, using only top-level items in the range and turning off the draw-icons property to simulate an item-list.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


single-item-list-pane

class, cg package

The class of widget-windows that are instantiated whenever a single-item-list is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a single-item-list subclass or otherwise add methods to the widget-window of a single-item-list. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


size

class, cg package

The class named by this symbol is not for user code. cg:size is improperly exported and will not be exported in later releases.


slot-editing-class-grid

Class, cg package

The subclass of class-grid that is created automatically on an object-editor for a slot that uses the :table-of-class-instances type. An application should not instantiate this class directly. This class name is exported mostly because it can appear in code that is generated for object-editor forms.


split-bar

class, cg package

The split-bar control can be used to allow the end user to interactively resize multiple tiled windows panes, or to move and resize groups of widgets.

This is done by creating a split-bar widget that lies between other sibling widgets or windows that it should affect. When used to resize window panes, typically you would leave just enough room between the panes to insert the split-bar like another tiled pane. (The parent window does not need to be a dialog, though the split-bar is always a dialog-item.) When used to move and/or resize groups of widgets instead, there may be additional space between the groups of widgets, with the split-bar placed midway in between.

A split-bar can extend across its parent window either horizontally or vertically by setting its orientation property to :horizontal or :vertical.

The simple bar that's drawn for the control can be either visible or invisible while idle, while under the mouse, or while being dragged, according to the properties color-when-idle, color-under-mouse, and color-when-dragging. (A split-bar that's on a form window will always be visible to facilitate laying out the form, so you would need to run the form to check the invisibility.)

The control will display a special mouse cursor when the mouse is over the bar to indicate that a drag can be done when clicking at that location. This allows the user to find a split-bar even when the widget itself is invisible.

You can specify what happens when the user drags a split-bar by setting up simple lists of the widgets or panes that should be resized or moved as the bar is dragged, if that is sufficient. See the widgets-to-move and widgets-to-resize properties. Otherwise an on-change function can be used for customized behavior. A split-bar can resize panes or widgets continuously during the drag, or only once at the end, according to its delayed property.

The split-bar's current position can be controlled programmatically by setting the value property. The widget's value should be a non-negative integer that indicates the distance of a horizontal split-bar from the top edge of the parent window's interior, or the distance of a vertical split-bar from the left edge of the parent window's interior.

When creating a split-bar programmatically and passing the orientation argument as :vertical, you will probably want to also pass the cursor-name argument as :vertical-splitbar-cursor (or the name of a custom cursor), since it will otherwise default to :horizontal-splitbar-cursor. (This is not an issue when creating a split-bar interactively on a form window.)

The Navigator dialog includes a split-bar example called Two Window-Panes with a Draggable Split-Bar Widget.

Here are the properties of the split-bar:

The class of widget-window that is displayed for a split-bar is split-bar-pane. Typically an application needs to deal only with the dialog-item class, though if you supply an on-redisplay function to draw a split-bar in a custom way, then you draw on the split-bar-pane.


split-bar-pane

class, cg package

The class of widget-window that is displayed for a split-bar dialog-item.

Typically an application needs to deal only with the dialog-item class, though if you supply an on-redisplay function to draw a split-bar in a custom way, then you will draw on this window.


spreadsheet

class, cg package

A subclass of grid-widget with some built-in basic spreadsheet functionality. For the full built-in functionality, it needs to be instantiated interactively by placing an instance onto a form window (see cg-grid-widget-simplified-tutorial.html). Its icon in the widget palette looks like the one for the standard grid-widget, except with a red "S" in the lower-right corner, identified by the red arrow in the illustration below. (The similar one with a C is for the class-grid.)

The built-in functionality may be too specific for most uses, but it may be feasible to adapt the initial spreadsheet that you place onto a form window. The code that gets generated into the .bil file for the form could be studied as an example, if needed. The built-in features are:


spreadsheet-column

class, cg package

The grid-column subclass that is used in the spreadsheet widget (when it is created interactively by placing it onto a form window).


spreadsheet-column-header-row

class, cg package

The column-header-row subclass that is used in the spreadsheet widget (when it is created interactively by placing it onto a form window) for the row of column headers along the top. It prints successive letters in the column header cells.


spreadsheet-row

class, cg package

The grid-row subclass that is used in the spreadsheet widget (when it is created interactively by placing it onto a form window).


spreadsheet-row-header-column

class, cg package

The row-header-column subclass that is used in the spreadsheet widget (when it is created interactively by placing it onto a form window) for the column of row headers on the left. It prints successive integers in the row header cells.


static-picture

class, cg package

Class

The class of a static-picture control.

Control

An instance of the :static-picture class. This control displays an icon which may not be changed by the user. It can act like a button; it may be set to receive mouse clicks via the on-click event handler.

The image that is to appear on a static-picture (or on a picture-button) widget may be specified with any one of the following properties (typically by passing the equivalent keyword argument such as :pixmap to make-instance when creating an instance of the widget):

If no pixmap or icon has been specified for the widget, then it will simply fill its interior with its background-color.

Mapping application values to multiple pixmaps

The pixmap-alist property of a static-picture may be set to an association list that maps arbitrary application values to pixmaps that represent them. Then whenever the value property of the widget is set to one of those application values, the associated pixmap will be displayed. And if the widget's user-modifiable property is true, then the user will be able to cycle through the pixmaps by clicking the widget or pressing the spacebar when the widget has the keyboard focus; selecting a new pixmap will set the value property of the widget to be the associated application value. See pixmap-alist for the format of the association list.

Further notes

Resizing a static-picture may mean that an aliasing (jaggies) problem appears in the pixmap. Go back to the program that created the graphic and re-save it at a higher resolution or a larger image size if you encounter this problem.

Customizing the static-picture control

The stretching property: if the :stretching option is passed as non-nil, then the bitmapped image will stretch automatically to fit the size of the widget. If nil, it will be drawn at the size at which the image was defined.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


static-picture-pane

class, cg package

The class of widget-windows that are instantiated whenever a static-picture is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a static-picture subclass or otherwise add methods to the widget-window of a static-picture. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


static-text

class, cg package

Class

The class of a static-text control.

Control

This control is displayed as a block of text that cannot be edited. For scrollable non-editable text, use a scrolling-static-text instead.

The text to be displayed should be stored as a simple string in the value field of the dialog item. See the description of the wrapping property for information on what happens when the text is longer than the control is wide.

Adding a static-text control to your form

Click the static-text tool on the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size. Note: resizing the static-text control changes the size of the bounding-box, but not the size of the actual text inside. Change the font property if you want to change the size of the actual characters displayed.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Using a Static-Text as a Keyboard Shortcut to Jump to a Control

A static-text control can provide a keyboard shortcut for moving the keyboard focus to the control that immediately follows the static-text in the tab order of the parent window. To effect this, place a tilde character (~) in the control's label just before the character that is to serve as a shortcut. (The label is the string in the value property of the static-text.) The tilde will not appear in the label, and the following character will be underlined to indicate the shortcut. Then whenever the end user holds down the Alt key and presses the shortcut character, the keyboard focus will move to the control after the static-text in the tab order, assuming that no other control on the same parent window uses the same shortcut character.

Note that this works only when the parent window is an instance of the dialog-mixin class (or some subclass of it). This behavior, along with the ability to move the keyboard focus from one control to another by pressing the tab key (or shift-tab for the reverse direction) is what distinguishes dialog-mixin instances from other windows.

The tab order is the order of the controls in the dialog-items property of a window, and is always the same as the occlusion order (that is, which controls are in front of which when they overlap). This order may be specified programmatically by the order of the list of controls passed as the :widgets initarg to make-window (or passed to update-dialog). Interactively, the tab order of controls on a form may be edited with the Form | Set Tab Order menu command or with the tab-position property on the individual controls.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


static-text-and-button-column

class, cg package

A grid-column subclass whose superclasses are static-text-and-button-column-mixin and grid-column. This class may be instantiated directly when no further subclassing is needed, and therefore is convenient when creating a grid-widget interactively on a form window and then editing its properties in the inspector (see cg-grid-widget-simplified-tutorial.html). In the inspector, you could move to an existing grid-column and then set its class property to static-text-and-button-column to turn it into this type of column (where the class choices are available in the drop-down list for the class property). See static-text-and-button-column-mixin for the widget behavior.


static-text-and-button-column-mixin

class, cg package

A non-instantiable class that can be mixed with the grid-column class to create grid columns whose cells act like static-text controls with button controls. Each cell in the column will implement the pseudo-controls if the row of that cell is an instance of a grid-row subclass that mixes in the widget-row-mixin class. See static-text-and-button-column for an instantiable subclass that you can use directly when no further subclassing is needed, even specifying it interactively.

To ensure that this mixin class' methods take precedence over other methods that specialize on grid-column, this mixin class generally should appear first in a defclass expression's list of superclasses, as in:

(defclass my-static-text-and-button-column
  (static-text-and-button-column-mixin my-subclass-of-grid-column) ...)

When the user clicks on the small button displayed in the cell, the cell-click method provided by this mixin calls the button-function of the grid-column (if non-nil) to perform some arbitrary action. Alternately the user can emulate clicking the button by pressing either the spacebar or the enter key, or by double-clicking anywhere in the cell.

The button-function property of the column should be used to determine what happens when the user presses the button.

The button-fills-cell property determines whether the button fills the cell or is small and in one corner of the cell.

The draw-cell method supplied by this mixin calls the column's data-read-converter to convert the data object represented by each cell into a string to display in the cell.

See the section Built-In Grid Cell Widgets on the page for the grid-widget class for an overview of the grid column mixins.

A quicker but less object-oriented alternative to using the widget-column-mixin classes is to write cell-widget methods.


static-text-column

class, cg package

A grid-column subclass whose superclasses are static-text-column-mixin and grid-column. This class may be instantiated directly when no further subclassing is needed, and therefore is convenient when creating a grid-widget interactively on a form window and then editing its properties in the inspector (see cg-grid-widget-simplified-tutorial.html). In the inspector, you could move to an existing grid-column and then set its class property to static-text-column to turn it into this type of column (where the class choices are available in the drop-down list for the class property). See static-text-column-mixin for the widget behavior.


static-text-column-mixin

class, cg package

A non-instantiable class that can be mixed with the grid-column class to create grid columns whose cells act like static-text controls. Each cell in the column will implement the pseudo-control if the row of that cell is an instance of a grid-row subclass that mixes in the widget-row-mixin class. See static-text-column for an instantiable subclass that you can use directly when no further subclassing is needed, even specifying it interactively.

To ensure that this mixin class' methods take precedence over other methods that specialize on grid-column, this mixin class generally should appear first in a defclass expression's list of superclasses, as in:

(defclass my-static-text-column
  (static-text-column-mixin my-subclass-of-grid-column) ...)

The draw-cell method supplied by this mixin calls the column's data-read-converter to convert the data object represented by each cell into a string to display in the cell.

See the section Built-In Grid Cell Widgets on the page for the grid-widget class for an overview of the grid column mixins.

A quicker but less object-oriented alternative to using the widget-column-mixin classes is to write cell-widget methods.


static-text-pane

class, cg package

The class of widget-windows that are instantiated whenever a static-text is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a static-text subclass or otherwise add methods to the widget-window of a static-text. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


status-bar

class, cg package

The class of a status-bar, a frameless child dialog lying along the bottom edge of its parent window, containing a single static-text widget for displaying messages pertaining to the parent window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


subsection-defaults

class, cg package

The class of the subsection-defaults of a grid-section.


system

class, cg package

Class of the system object. The current system (the value of *system*) contains information about the running IDE.


tab-control

class, cg package

Class

The class of tab-control controls.

Control

An instance of the tab-control class. This control allows you to create a set of pages of controls and group them in related sub-groups on each tab. The Options dialog is an example of a tab-control.

The individual tabs are instances of the tab-info class. The range property contains a list of tab-info objects, and the value property contains the name of the selected tab-info. Setting the value property to a different name will select a different tab. A tab can be added to an existing tab-control by calling add-tab, or removed by calling remove-tab. A widget can be added to an existing tab by calling add-component-to-tab, or removed by calling remove-component-from-tab.

Other properties that are unique to the tab-control include tab-height, tab-width, fixed-width, single-line, focus-on-click, ragged-right, tab-side, button-style, and tabs-are-draggable.

When creating tab-controls interactively on form windows, tab-controls allow overlap on their borders even when the option is turned off. Objects overlapping a tab may or may not appear in the range and tab-info(s) for the tabs they overlap, so use this feature with care.

In Windows, the tab-order of the controls on a parent window is always the same as the front-to-back occlusion order of the controls. This means that a tab-control must be positioned in the tab order after all of the widgets that are on it, or else it will cover those widgets. This is handled automatically when designing a form window interactively, but it must be handled by the application when creating a dialog programmatically. See tab-position.

The generic functions select-adjacent-tab and select-recent-tab are useful for keyboard shortcuts that select nearby or recently-selected tabs of a tab-control.

Adding a tab-control to your form

Click the tab-control tool on of the Component toolbar. Move the mouse cursor to the part of the form where you want to place the control, and click again. The control will appear with colored resizing handles.

Adding widgets to tabs programmatically

If you are creating a dialog programmatically rather than laying it out interactively as a form, then there are two ways to add widgets to tab-control tabs. One way is to associate the widgets with each other when creating all of them together. The other way is to call add-component-to-tab to add a widget to a pre-existing tab-control.

First we have is an example of the first approach. This code will create a window that contains a tab-control that has a button widget on its first tab. To make the button appear only when its tab is selected, the tab-control and the button must be associated with each other. So the button points to its tab by specifying a :tab-control initarg of (:my-tab-control :one), which is a list of the name of the tab-control followed by the name of the tab. Conversely, the first tab points to the button by specifying a :widgets initarg of (:first-button), which is a list of all of the widgets that are on that tab.

(setq my-window
      (make-window :my-window
        :class 'dialog :width 300 :height 300
        :dialog-items
        (list (make-instance 'button
                :left 80 :top 100 :width 100 :height 30
                :name :first-button :title "~First"
                :tab-control '(:my-tab-control :first-tab))
              (make-instance 'tab-control
                :left 50 :top 50 :width 200 :height 150
                :name :my-tab-control :value :first-tab
                :range
                (list (make-instance 'tab-info
                        :name :first-tab :label "One"
                        :widgets '(:first-button))
                      (make-instance 'tab-info
                        :name :second-tab :label "Two")
                      (make-instance 'tab-info
                        :name :third-tab :label "Three"))))))

The other way to add a widget to a tab programmatically is to call add-component-to-tab. This is useful if you want to create a tab-control and then add widgets to it later. (Similarly, remove-component-from-tab will remove a widget from a tab.)

This example would add another button widget to the tab-control that was created above, this time to the second tab.

(add-component-to-tab
  (find-component :my-tab-control my-window)
  :second-tab
  (make-instance 'button
    :left 100 :top 100 :width 100 :height 30
    :name :second-button :title "~Second"))

Resizing and moving the control

Controls can only be resized and moved on forms during the design stage; the size and location of everything is fixed on a running form.

Resize the control by clicking the mouse cursor and dragging one of the handles to the new size-point. Release the mouse key when you are satisfied with the new size.

Resizing the tab-control won't mean proportional changes in the size of the characters of the labels of the tabs. Change the font property if you want to change the size of the actual characters displayed.

Move the control by clicking anywhere on it except a resizing handle and dragging it to a new location on the form. Release the mouse key when you are ready to place the control.

Moving a tab-control means dragging all of the contained objects along with it.

Adding controls to the tab-control tabs

When designing a dialog using a form, drag controls onto the individual tabs and position them. After you have added controls to each tab, you will be able to see their names in the expanded portions of the Inspector. To see the names of the controls placed on each tab in the Inspector:

  1. Click on the tab-control to give it focus in the Inspector. (If no inspector is visible, double-click the widget to ensure that an Inspector window is created if needed and brought to the front.)

  2. Click on the range, making sure to click on the name of the range property (the left column) rather than the value (the right column). You will see a display of tab-info entries, one per line. There will be one tab-info for each tab in your tab-control. They will be numbered from 0 to n for (n+1) tabs.

  3. Double-click on the value (the right hand column) for one of the tab-infos. A dialog will appear displaying the contents of the tab-info. All of the controls on that tab will appear in the value expression displayed by the dialog.

  4. Click the OK button when you are done inspecting the expression to close the dialog.

You can also inspect the tab-infos programmatically by searching your code for calls to make-instance with tab-info for the particular tab-control you are working on.

Adding more tabs to the tab-control in the IDE

  1. Click on the tab-control to give it focus in the Inspector.
  2. Click on the extended editor button (the one with 3 dots) for the value of the range of the tab-control.
  3. The Edit Expression dialog will appear. You can either copy a make-info from one of the existing tabs in the dialog and paste it in another location and modify it, or just begin typing your own make-infos directly into the window.
  4. Click the OK button when you are satisfied with your new expression. The new tab-control will appear on your form with the changes you coded in the Edit Expression dialog.

Highlighting one or more specific tabs

The generic funcion highlight-tab allows you to highlight one or more tabs on a tab-control.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


tab-control-pane

class, cg package

The class of widget-windows that are instantiated whenever a tab-control is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a tab-control subclass or otherwise add methods to the widget-window of a tab-control. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


tab-info

class, cg package

The class of an individual tab on a tab-control. See highlight-tab for information on how a tab can be highlighted.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.


text-edit-pane

class, cg package

The class of windows that provide multi-line text-editing capabilities. This is an instantiable class, though it is more typically used either by creating a multi-line-editable-text dialog-item (since this is the widget-window class for that dialog-item class), or by creating a text-edit-window to provide a frame around the text-edit-pane that it automatically adds (because in Windows a text-edit-pane itself may not have a title-bar and does not work well as a top-level window).

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


text-edit-window

class, cg package

A frame-with-single-child class of windows whose frame-child pane is a text-edit-pane for editing text.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


text-widget

class, cg package

The non-instantiable class of dialog-items that display standalone text. The subclasses are editable-text, which provides text-editing functionality, and static-text, which merely displays text.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


text-widget-pane

class, cg package

The widget-window class for the text-widget dialog-item class.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


texture

class, cg package

The class of texture objects. A texture is a standard object that defines the array of pixel values for a pixmap. The data for a texture is stored internally as a lisp array, the platform- and version-independent interface to the texture is the nested set of lists of pixel values stored in its contents property. The array is the value of the texture-array property.


texture-info

class, cg package

A texture is a pixel-map or bitmap packaged up to work on a particular device. It is used to denote a pattern to fill an area of a stream or background, and to define cursors. A texture is not associated with a particular stream. If it is a pixel-map, the specified colors are used. In the case of a bitmap, value 1 is interpreted as the stream foreground color and the value 0 as its background color.

A texture-info is the structure associated with the texture.


timer

class, cg package

See cg-timers.html.

The class of timer objects. A timer can be used to cause an arbitrary piece of application code to be asynchronously invoked after a specified amount of time has elapsed. A timer can then be stopped in order to run its code a single time only, or it can be allowed to continue running in order to run its code an indefinite number of times at a regular time interval.

A single timer can be started and stopped a number of times, using various time intervals, to time a number of different activities. If multiple activities need to be timed simultaneously, then multiple timers can be created and run alongside each other. It is also convenient to create a separate timer for each piece of code that is to be invoked by timers, even when they do not need to run simultaneously.

A timer has the following properties. All of these except for id may be set by an application.

name: an arbitrary symbol that is used to find a timer (by calling find-timer), or to distinguish an individual timer during development and debugging.

active: a boolean value indicating whether a timer is currently running: an active timer "fires" each time its interval passes, while an inactive timer does nothing. This property of a timer will be non-nil if start-timer has been called on the timer more recently than stop-timer has. If the active property is explicitly modified by an application from nil to non-nil, then start-timer is called internally, and if the active property is explicitly modified from non-nil to nil, then stop-timer is called internally. Therefore, in order to wrap all starting and stopping of timers, it is sufficient to add start-timer and stop-timer methods.

id: a positive integer that is assigned and used by the operating system to uniquely identify a particular timer. Use of id is deprecated. An application should never modify this property. Any given timer object will always use the same id, and no other timer object will use that id.

interval: a positive integer indicating the number of milliseconds after a timer is started that it will "fire" by calling the generic function timer. The interval default-initarg for the timer class is 1000, which will fire the timer once a second.

on-timer: the name of a function that is invoked after the timer's interval has elapsed (assuming that the default timer method has not been overridden).

timer-count: a non-negative integer indicating the number of times that a timer's interval has elapsed since it was most recently started.

timer-info: a place for an application to store arbitrary information about its current use of a timer.

timer-universal-time: the universal time at which the timer is scheduled to fire, or nil if the timer is not active.


toggling-widget

class, cg package

The non-instantiable dialog-item class that groups together all widgets that have a value that can be toggled between true and nil. (An exception is the static-picture subclass, which does not have a true-or-nil value but which is grouped with the picture-button class for other reasons.)

The subclasses are button, check-box, radio-button, and picture-widget.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


toggling-widget-pane

class, cg package

The widget-window class for the toggling-widget dialog-item class.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


toolbar

class, cg package

The class of a toolbar. This is a frameless dialog window lying along the top edge of its parent window, and typically containing picture-button and combo-box widgets that implement functionality for the parent.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


touch-point

class, cg package

Instances of this structure class are passed in a vector in each call that Common Graphics makes to touch-event. See touch-event for a description of the information that this structure holds.


trackbar

class, cg package

The class of the trackbar control. This is a linear gauge displaying a pointer that indicates some value within a specified range, and allowing users to drag the pointer to other values within the range and thereby effect some arbitrary behavior. The value of the widget can increase in either direction, according to the widget's direction-of-increase property.

An example use of a trackbar would be the volume slider on a stereo.

When running in Windows desktop mode, tick marks may be displayed at some specified frequency along the trackbar. The trackbar value may also be adjusted using the arrow keys and/or the PAGE UP/PAGE DOWN keys when the trackbar has the keyboard focus, and the amount by which these keys adjust the value can be set. See tick-frequency, tick-position, and tick-side. (If the value of tick-side is :none, then no tick marks are displayed.

Other Windows-specific properties include increment, page-increment, orientation, visible-range, and no-pointer. In CG/JS mode, the simple control that is supplied by the web browser is used, and the Windows-specific properties will have no effect.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


trackbar-pane

class, cg package

The class of widget-windows that are instantiated whenever a trackbar is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a trackbar subclass or otherwise add methods to the widget-window of a trackbar. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


transparent-pane

class, cg package

The class of transparent-panes.

Instances of this class are windows that allow other windows to show through them from behind. A transparent-pane may be useful for intercepting mouse clicks from, or arbitrarily drawing over, a set of sibling windows that lie behind it.

A transparent-pane differs from a regular window in two ways:

(1) Its :transparent-p initarg (to make-window) when created defaults to non-nil, which tells windows that are behind it that they still need to draw themselves since the window covering them is transparent.

(2) Its redisplay-window method overrides the default method that normally "clears" a window's background by filling the background area with the window's background-color. (Either or both of these effects could be achieved with a window of any class by passing :transparent-p t to make-window and/or overriding the default redisplay-window method; the transparent-pane class merely encapsulates these two options into a subclass.)

Note that a transparent-pane does not behave totally as a truly transparent object would intuitively behave, and therefore has limited application. In particular, if a transparent-pane is moved or another window is brought in front of it, windows that overlap the transparent-pane will not know that they may need to redisplay themselves, and so unexpected leftover images may remain in the area of the transparent-pane. Therefore a transparent-pane is probably useful only as a child of a parent window that knows when it needs to redisplay itself or its other children after manipulating the transparent-pane child.

The frame-child of a form window in the IDE is a transparent-pane that is kept in front of all of the controls on the form. This illustrates the two likely uses of a transparent-pane. First, whenever the user clicks in the interior of a form, regardless of whether the click is over the border or interior of a control or in the empty area of the form, the click goes to the transparent-pane because it is in front; this allows any click in the form's interior to be handled in a standard way by a single method on the transparent-pane, overriding the usual click behavior of the individual controls. Second, drawing can be performed on the transparent-pane that may arbitrarily overlap the controls; this makes it easy for the IDE to draw resizing handles that overlap both the borders and the interiors of controls (when multiple controls are selected). Applications may find similar uses for transparent-panes if they are used with care.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


tray-item

Class, cg package

The class of tray-item objects. A tray-item instance is used for each item that a standalone Common Graphics application places into the system "tray", also known as the Taskbar Notification Area. This is the area at the rightmost end of the system taskbar that contains small icons with custom mouse behavior for various applications.

A Common Graphics application can add an item to the tray by calling make-instance to create a tray-item and then calling add-tray-item to add it to the tray. It may be removed later with remove-tray-item and then added again and removed any number of times. in-tray-p returns whether a tray-item is currently in the tray.

A tray-item generally needs an icon to display, which may be specified either by passing an icon handle as the :icon initarg to make-instance, or later by calling (setf tray-item-icon). An optional tooltip may also be specified either with the :tooltip initarg or by calling (setf tray-item-tooltip). A name for identifying the tray-item programmatically may be specified by passing a symbol as the :name initarg or by calling (setf name).

When the user moves the mouse over the tray icon or clicks on it, the generic function tray-item-message is called. An application may supply tray-item-message methods to handle the mouse events in a custom way.

Microsoft Windows Note: to make it easy for the user to select a choice or to cancel a pop-up menu, you may want to ensure that a window from the same process has the keyboard focus, or at least that such a window is present on the screen. In Microsoft Windows, keypresses will apply to a pop-up menu only if the window that currently has the keyboard focus was created in the process that popped up the menu. Otherwise the Escape key will not dismiss the menu, and a choice cannot be made with the keyboard. Clicking the mouse outside a pop-up menu will dismiss the menu only if there is at least one currently visible (not shrunk) top-level window that was created in the process that popped up the menu.

Here is a complete (though trivial) example:

;;; Define a tray-item subclass in order to specialize a
;;; custom tray-item-message method on it.
(defclass my-tray-item (tray-item)())

(defclass my-frame (frame-window)())

(defmethod tray-item-message ((tray-item my-tray-item)
                              (window my-frame)
                              message)
  (case message
    
    ;; On a left click, select the application window.
    (#.mouse-left-down
     (select-window window)
     (set-foreground-window window))
    
    ;; On a right click, pop up a menu of background colors
    ;; for the application window.  Popping up a menu on a
    ;; down click appears not to work when the tray icon's
    ;; associated window is selected, so use an up click.
    (#.mouse-right-up
     (let* ((menu (open-menu
                   (list (make-instance 'menu-item
                           :name :yellow
                           :title "~Yellow"
                           :value yellow)
                         (make-instance 'menu-item
                           :name :green
                           :title "~Green"
                           :value green)
                         (make-instance 'menu-item
                           :name :cyan
                           :title "~Cyan"
                           :value cyan))
                   'pop-up-menu (screen *system*)))
            (color (pop-up-menu menu window)))
       (close menu)
       (when color
         (setf (background-color window) color)
         (invalidate window))))))

;;; Test the above application code.

(setq window (make-window :tray-test
               :class 'my-frame
               :title "Tray Test"))

(setq ti (make-instance 'my-tray-item
           :icon information-icon
           :tooltip "Click left or right"))

(add-tray-item ti :window window)

;; Try out the tray icon here ...

(remove-tray-item ti)

two-stroke-mixin

class, cg package

This mixin class can be used along with a window class (basic-pane or some subclass of it) for creating windows that interpret certain kinds of touchscreen gestures. This class specializes in interpreting "two-stroke" drags such as three fingers dragged to the right and then downward. It also interprets single-direction drags as well as taps and holds plus two-finger pinches and spreads. As with other touchscreen support, it is currently available only on the Windows platform.

To write code directly on top of Microsoft's touchscreen support, use either gesture-event or touch-event instead of this class. gesture-event interprets certain common gestures for you, but handles only a handful of them, while touch-event requires that you interpret your own gestures from many finger coordinate positions. To make it easier to handle a larger number of gestures, we provide this custom facility on top of the touch-event API, though the particular gestures that it interprets may not be what you want to handle. It specializes in dragging gestures where the user drags one or more fingers either leftward, upward, rightward, or downward, and then perhaps in another one of those directions while their finger are still on the screen.

You probably should put this class before the window class in the precedence for the class that you create for windows, for example:

(defclass my-two-stroke-window (two-sroke-mixin frame-window)())

An application would handle the high-level gestures by adding one or more two-stroke-gesture methods. It could also handle dragging gestures during the actual drag by adding one or more two-stroke-dragging methods.

Here is complete simple example that simply prints the arguments that are passed to the two generic functions.

(in-package :cg-user)

(defclass two-stroke-demo (two-stroke-mixin frame-window)
  ((two-stroke-demo-string :accessor two-stroke-demo-string
                           :initform nil)
   (two-stroke-now-dragging :accessor two-stroke-now-dragging
                            :initform nil))
  (:default-initargs
    :double-buffered t
    :scrollbars nil))

(defmethod redisplay-window ((window two-stroke-demo) &optional box)
  (declare (ignore box))
  (with-boxes (interior)
    (nvisible-box window interior)
    (erase-contents-box window interior)
    (let* ((dragging (two-stroke-now-dragging window))
           (string (two-stroke-demo-string window)))
      (with-font (window (make-font-ex nil "Arial"
                                       (if dragging 24 48)))
        (cond (dragging
               (move-to-x-y window 0 0)
               (princ string window))
              (t (draw-string-in-box
                  window string nil nil interior :center :center)))))))

(defmethod two-stroke-dragging ((window two-stroke-demo) count x y
                                dx-down dy-down dx-prev dy-prev
                                spread-diff spread-factor first last)
  (setf (two-stroke-now-dragging window) t)
  (setf (two-stroke-demo-string window)
    (format nil "~(~r~) finger~:p at ~a ~a~%~
                 distance from start ~a ~a~%~
                 distance from previous ~a ~a~%~
                 spread difference ~a~%~
                 spread factor ~a~%~a"
      count x y dx-down dy-down dx-prev dy-prev spread-diff spread-factor
      (if first "FIRST" "")(if last "LAST" "")))
  (invalidate window)
  t)

(defmethod two-stroke-gesture ((window two-stroke-demo) count gesture)
  (setf (two-stroke-now-dragging window) nil)
  (setf (two-stroke-demo-string window)
    (format nil "~(~r~)   ~s" count gesture))
  (invalidate window)
  t)

#+test
(make-window :two-stroke-demo
  :class 'two-stroke-demo
  :title "Try Some One- and Two-Stroke Finger Gestures"
  :interior (make-box-relative 100 100 800 500))

up-down-control

class, cg package

Class

The class of the up-down control. That is a control with two arrow heads pointing in opposite directions used for incrementing a numeric value in either direction by clicking on the arrow heads. A range of valid values can be specified by the range property.

Can be used on its own or paired with a buddy. A possible buddy-widget is the editable-text control. Once paired, the up-down-control will modify the display of its buddy-widget, otherwise it only modifies its own value (which can be programmatically accessed and, if desired, displayed elsewhere).

For example, place an editable-text control on a form and place an up-down control next it. Make the value of the editable-text 1 and the range of the up-down control (0, 100). Ensure that the editable-text is correctly identified as the buddy-widget of the up-down control (as indicated by the buddy-widget property). When you run the form, the value in the editable text widget will increase (up to 100) and decrease (down to 0) as the up-down control is clicked.

There is special increment behavior for an up-down-control. You can have the increment be a single value or a list of paired values. In the latter case, the first member of each pair indicates a number of seconds and the second indicates the value of the increment during those seconds. For example, a value of ((1 1)(1 3)(2 10)(4 100)) indicates that the up-down-control should increment (or decrement) by 1 for the first second, by 3 for the next second, by 10 for the next 2 seconds, and then by 100 thereafter until either the mouse button is released or the maximum or minimum value of the control's range is reached.

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


up-down-control-pane

class, cg package

The class of widget-windows that are instantiated whenever an up-down-control is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of an up-down-control subclass or otherwise add methods to the widget-window of an up-down-control. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


value-axis

Class, cg package

The class of the value-axis, which, along with item-axis, is a subclass of chart-axis. See chart-axis for a list of properties these classes have in common. The properties unique to value-axis are:

value-axis is a superclass of plot-value-axis. Instantiate this value-axis class for the value-axis or value-axis-2 property of a chart-widget, but instantiate plot-value-axis instead for the x-axis, y-axis, x-axis-2, or y-axis-2 property of a plot-widget.

See chart-widget and also cg-chart-widget.html.


vertical-scroll-bar

class, cg package

The class of a standard scroll-bar control running vertically alongside of its associated control. This control is paired programmatically with other controls (static pictures, for instance) to permit vertical scrolling when too much information prevents the viewer from seeing everything on their display simultaneously.

Scrollbars can also be used as sliders to affect another control by raising or lowering a number, intensifying or fading a color, or otherwise gradually increasing/decreasing some characteristic of the attached control. A good model of this appears in the Widgets and Menubars: general use example. Examples are accessed by clicking Help menu | CG Examples (which brings up the Navigator open to the Examples tab).

The range property of the scrollbar is a list of two integers: for example, (0 100). The value of the scrollbar determines the position of the scrollbox along the length of the scrollbar. The value of the scrollbar is an integer within the range.

The delayed property controls whether the scrollbar's value is updated as the user scrolls or only at the end of the scrolling operation.

See the Navigator dialog example (on the Examples tab) entitled "Car Payments" for an example of basic usage of scroll-bar widgets.

Scrolling by logical objects rather than by pixels

In a typical custom scrolling scheme, an application does not need to worry about how much data is above the current scroll position, and so the redisplay-window method can simply start drawing whatever is known to be currently scrolled to the top of the window. This means that the application does not have to compute and/or cache the pixel sizes of everything above the scroll-position, which simplifies the coding and can also speed scrolling up quite a bit when there is a huge amount of data to be scrolled. The drawbacks are that (1) this approach may be applicable only if data is entirely arranged into "rows" or "columns", (2) scrolling is not as visually smooth since an individual data object is always aligned with the top and/or left side of the window, and (3) custom methods need to be written to override several CG generic functions that are exported for this purpose.

See the Navigator dialog example (on the Examples tab) entitled "Scrolling by arbitrary objects rather than pixels" for a complete example of this special alternative for custom scrolling by logical objects.

It is now possible to customize scrolling in this way by overriding the default methods of several generic functions. Typically this is useful for scrolling by some sort of logical objects such as lines of text or grid cells rather than by pixels, as the default methods do. The generic functions that may need to be modified are:

redisplay-window to decide what should be drawn based on a custom scroll-position and then draw it

nscroll-position to return a position object where a coordinate might be an index into a set of arbitrary objects rather than a pixel distance

scroll-range which may return a value indicating the number of objects to be scrolled into the window rather than a pixel size

update-scroll-bars-for-new-window-size to adjust the scroll-range after a window has been resized

scroll-to to interpret a new programmatic scroll position

user-scroll to interpret an interactive scrolling gesture

See About how to get sample code for creating controls in cgide.html, which explains how to use the IDE to create such code.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


vertical-scroll-bar-pane

class, cg package

The class of widget-windows that are instantiated whenever a vertical-scroll-bar is added to a window. Probably not of concern to applications unless it needs to intercept low-level window events of a vertical-scroll-bar subclass or otherwise add methods to the widget-window of a vertical-scroll-bar. See os-widget-window.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


video-player

Class, cg package

A widget that plays video files, typically mp4 files. It is currently implemented only for CG/JS mode, though it could also be implemented for Windows desktop mode as a widget on top of the mci-animation API. It shares the media-player API with the audio-player widget. The value property of the widget is the file path namestring of the video file that the widget is currently playing or ready to play.


video-player-pane

Class, cg package

The class of the pane of a video-player widget.


widget-column-mixin

class, cg package

The superclass of all of the grid-column mixin classes that implement the several types of built-in cell widgets. The particular subclasses that may be mixed with a grid-column class are:

If a cell lies at the intersection of a widget-column-mixin grid-column and a widget-row-mixin grid-row, then one of the built-in cell widgets will appear in that cell. Refer to the particular widget-column-mixin subclasses for more information.

A quicker but less object-oriented way to use the built-in cell widgets is to write cell-widget methods. That technique allows adding the built-in widgets to arbitrary cells rather than only to special columns for each type of widget.


widget-row

class, cg package

A grid-row subclass whose superclasses are widget-row-mixin and grid-row. This class may be instantiated directly when no further subclassing is needed, and therefore is convenient when creating a grid-widget interactively on a form window and then editing its properties in the inspector (see cg-grid-widget-simplified-tutorial.html). In the inspector, you could move to an existing grid-row and then set its class property to widget-row to turn it into this type of column (where the class choices are available in the drop-down list for the class property). See widget-row-mixin for the widget behavior.


widget-row-mixin

class, cg package

grid-widget rows with this mixin will implement a pseudo-widget wherever they intersect with one of the following built-in widget column classes (and see widget-row for an instantiable subclass that you can use directly when no further subclassing is needed, even specifying it interactively):

See the section Built-In Grid Cell Widgets on the page for the grid-widget class for an overview of the grid column mixins.


widget-window

class, cg package

The class of all windows that implement dialog-items (also known as widgets or controls). The subclasses of this class are os-widget-window (for widgets that are provided by the underlying window system or operating system) and lisp-widget-window (for widgets that are implemented from scratch within Lisp). This class is not instantiable.

To create a widget, an application calls make-instance on a dialog-item class. When the dialog-item is added to a parent window (with add-component or with the :dialog-items argument to make-window), then an instance of the associated widget-window class is automatically created to implement the visible window of the widget. Calling the function window on the dialog-item will then return its associated widget-window. A widget-device method tells the dialog-item class which widget-window class to instantiate.

A diagram of window and widget classes is shown in Widget and window classes in cgide.html.


window

class, cg package

The class formerly named window has been removed. It was never an instantiable class, but was rather a mixin class to group basic-pane and menu together, though those classes are not significantly related. This change will only affect user code if tests of the form (typep win (find-class 'window)) are used.

A diagram of window and widget classes is shown in Widget and window classes in cgide.htmlcgide.html.



Copyright (c) 2023, Franz Inc. Lafayette, CA., USA. All rights reserved.

ToC DocOverview CGDoc RelNotes FAQ Index PermutedIndex
Allegro CL version 11.0