Lists of selectable items can be created with the list-panel class. Here is a simple example of a list panel:
(setq list
(make-instance 'list-panel
:items '(one two three four)
:visible-min-height '(character 2)
:print-function 'string-capitalize))
(contain list)
Notice how the items in the list panel are passed as symbols, and a print-function is specified which controls how those items are displayed on the screen.
Any item on the list can be selected by clicking on it with the mouse.
By default, list panels are single selection — that is, only one item in the list may be selected at once. You can use the :interaction
keyword to change this:
(setq list-panel
(make-instance 'list-panel
:items (list "One" "Two" "Three" "Four")
:interaction :multiple-selection))
(contain list-panel)
You can add callbacks to any items in the list using the :selection-callback
keyword.
(setq list-panel
(make-instance 'list-panel
:items (list "One" "Two" "Three" "Four")
:selection-callback 'test-callback))
(contain list-panel)
If you select different items in the list, only the last item you select remains highlighted. The way in which the items in a list panel interact upon selection can be controlled with the :interaction
keyword.
The list produced in the example above is known as a single-selection list because only one item at a time may be selected. List panels are :single-selection
by default.
There are also multiple-selection and extended-selection lists available. The possible interactions for list panels are:
:single-selection
— only one item may be selected.:multiple-selection
— more than one item may be selected.:extended-selection
— see Extended selection.
To get a particular interaction, supply one of the values above to the :interaction
keyword, like this:
(contain
(make-instance
'list-panel
:items '("Red" "Green" "Blue")
:interaction :multiple-selection))
Note that :no-selection
is not a supported choice for list panels. To display a list of items with no selection possible you should use a display-pane.
Application users often want to make single
and
multiple selections from a list. Some of the time they want a new selection to deselect the previous one, so that only one selection remains — just like a :single-selection
panel. On other occasions, they want new selections to be added to the previous ones — just like a :multiple-selection
panel.
The :extended-selection
interaction combines these two interactions. Here is an extended-selection list panel:
(contain
(make-instance
'list-panel
:items '("Item" "Thing" "Object")
:interaction :extended-selection))
Before continuing, here are the definitions of a few terms. The action you perform to select a single item is called the
selection gesture
. The action performed to select additional items is called the
extension gesture
. There are two extension gestures. To add a single item to the selection, the extension gesture is a click of the left button while holding down the Control
key. For selecting a range of items, it is a click of the left button while holding down the Shift
key.
As well as selecting items, users often want to deselect them. Items in multiple-selection and extended-selection lists may be deselected.
In a multiple-selection list, deselection is done by clicking on the selected item again with either of the selection or extension gestures.
In an extended-selection list, deselection is done by performing the extension gesture upon the selected item. (If this was done using the selection gesture, the list would behave as a single-selection list and all other selections would be lost.)
Just like a selection, a deselection — or retraction — can have a callback associated with it.
For a multiple-selection list panel, there may be the following callbacks:
:selection-callback
— called when a selection is made.:retract-callback
— called when a selection is retracted.
Consider the following example. The function set-title
changes the title of the interface to the value of the argument passed to it. By using this as the callback to the check-button-panel, the title of the interface is set to the current selection. The
retract-callback
function displays a message dialog with the name of the button retracted.
(defun set-title (data interface)
(setf (interface-title interface)
(format nil "~A" (string-capitalize data))))
(setq check-button-panel
(make-instance 'check-button-panel
:items '(one two three four five)
:print-function 'string-capitalize
:selection-callback 'set-title
:retract-callback 'test-callback))
(contain check-button-panel)
Figure 5.5 The example check button panel before the callback.
Figure 5.6 The example check button panel after the callback.
For an extended-selection list panel, there may be the following callbacks:
:selection-callback
— called when a selection is made.:retract-callback
— called when a selection is retracted.:extend-callback
— called when a selection is extended.Also available in extended-selection and single-selection lists is the action callback. This is called when you double-click on an item.
List panels — all choices, in fact — can have selections, and you can set them from within Lisp. You can specify default settings and arrange for side-effects when a user selection is made. For the details see Selections..
A list panel can include images displayed on the left of each item. To include images supply the initarg :image-function
. You can use images from an image-list via the initarg :image-lists
.
Additionally, state images are supported on Microsoft Windows, GTK+ and Motif, via the initarg :state-image-function
and, if required, :image-lists
.
A list panel can have an alternating background color on Cocoa and GTK+, when specified by the initarg :alternating-background
.
You can add a filter to a list-panel by passing the :filter
initarg.
List panel filters are used in the LispWorks IDE, for example in the Inspector tool.
When a list-panel has a filter, you can the state of the filter by using list-panel-filter-state. The accessor collection-items
on a list-panel with a filter returns the items after filtering. The function list-panel-unfiltered-items can be used to retrieve all the items. (setf collection-items)
resets the filter, and (setf list-panel-unfiltered-items)
can be used to set the items without affecting the filter. The function list-panel-items-and-filter can be used to get or set the unfiltered items and filter state together. (setf list-panel-items-and-filter)
is especially useful, because setting the items and the filters separately causes the list-panel to redisplay twice.
multi-column-list-panel is a subclass of list-panel which has several columns. Each line in a multi-column-list-panel displays several strings corresponding to a single item. multi-column-list-panel takes an initarg :item-print-functions
which specifies how to generate the strings. The initarg :columns
specifies column properties including width, alignment, and title.
The columns can have headers, which can be active (that is, they have callbacks). In particular, the headers can be made to sort the items based on some key and comparison function, by supplying the header's
selection-callback
as :sort
and defining
sort-descriptions
(inherited from sorted-object via list-panel) with types that match the titles of the columns.
(example-edit-file "capi/choice/multi-column-list-panels")
double-list-panel is a choice that displays the items in two list-panels side-by-side, and allows the user to move items between them. It is not a subclass of list-panel.
The selection interface functions (choice-selected-items, the choice accessor choice-selection
, and so on) treat the items in one sub-panel as the selected items and the items in the other sub-panel as the non-selected items. double-list-panel takes more space, but is very convenient for the user when she needs to add or remove items from the selection, especially when there are many items.
list-panel has an initarg :keyboard-search-callback
which allows you to define searches in the list-panel in response to user input. The function list-panel-search-with-function is intended to simplify writing the callback.
The default search uses a timeout to decide whether to:
This timeout can be set by set-list-panel-keyboard-search-reset-time.
The keyboard-search-callback can actually be used to perform other tasks in response to user keyboard input.
CAPI User Guide and Reference Manual (Windows version) - 3 Aug 2017