ClassPackage: cgToCDocOverviewCGDocRelNotesFAQIndexPermutedIndex
Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version


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 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
                                   (#.yellow #.light-blue
                                   (#.yellow #.light-blue
                     :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.htm.

Copyright (c) 1998-2022, Franz Inc. Lafayette, CA., USA. All rights reserved.
This page was not revised from the 10.0 page.
Created 2019.8.20.

Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version