HELP PWMITEMS                                  Ben Rubinstein, Mar 1987
                                            Revised: Nic Ford, Apr 1987
                                     Extended: Anthony Worrall Nov 1987
                                       Revised: Gareth Palmer, Aug 1989
                                      Extended: Julian Clinton Apr 1991

Input items in PWM windows.

Keywords: PWM, input, items, toggle, cycle, gauge, button, slider

    pwm_itemvalue(<pwmitem>) -> <item>
    <item> -> pwm_itemvalue(<pwmitem>)

    pwm_itemarea(<pwmitem>) -> <vector>

    pwm_kill_item(<pwmitem>)

    pwm_make_toggleitem(<window-id>, <integer:X>, <integer:Y>,
                  <boolean:I>, <string:L>, <procedure:C> ) -> <pwmitem>

    pwm_make_cycleitem(<window-id>, <integer:X>, <integer:Y>,
                     <list:V>, <string:L>, <procedure:C> ) -> <pwmitem>

    pwm_make_radioitem(<window-id>, <integer:X>, <integer:Y>, <item:I>,
                <list:V>, <string|false:L>, <procedure:C>) -> <pwmitem>

    pwm_make_execitem(<window-id>, <integer:X>, <integer:Y>,
                                <string:L>, <procedure:C>) -> <pwmitem>

    pwm_make_labelitem(<window-id>, <integer:X>, <integer:Y>, <integer:W>
                       <string:P>, <string:L>, <procedure:C) -> <pwmitem>

    pwm_make_listitem(<window-id>, <integer:X>, <integer:Y>, <list:V>,
                             <string:L>, <integer:C>, <integer:R>,
                             <procedure|false:P>) -> <pwmitem>

    pwm_make_setitem(<window-id>, <integer:X>, <integer:Y>,
                             <list:S>, <list:V>,
                             <string:L>, <integer:C>, <integer:R>,
                             <procedure|false:P>) -> <pwmitem>

    pwm_make_slideritem(<window-id>, <integer:X>, <integer:Y>, <integer:W>
                  <integer:H>, <integer:Offset>, <integer:Size>,
                  <procedure|false:C>,<Boolean:Interactive>)-> <pwmitem>


== CONTENTS - (Use <ENTER> g to access required sections) ==

 -- Introduction
 -- Utilities for use with pwmitems
 -- Toggle-items
 -- Cycle-items
 -- Radio-items
 -- Exec-items
 -- Label-items
 -- List-items
 -- Set-items
 -- Slider-items
 -- An example

-- Introduction -------------------------------------------------------

An item is a procedure, or series of procedures, in conjunction with
some form of on-screen display, which is used to handle some mouse input
from one part of a screen or window. This file describes procedures
which are available to construct some common kinds of user input items.
Each of the items described here uses -pwm_itemhandler- to take over
"press" and "release" events for the left mouse button within a portion
of a window. You should be familiar with the use of -pwm_itemhandler-,
described in HELP *PWMINPUT.

Each of the items maintains an internal record of its current 'value'.
The item's display on screen usually reflects the current value (a
program can discover the current value by using -pwm_itemvalue-,
described below).  The value of an item can be changed by the user via
the mouse, or from a program (again using -pwm_itemvalue-).  When you
make an item, you can specify a procedure: whenever the value of the
item is changed, whether by the program or the user, this procedure is
called with the new value.

The item-constructing procedures described here can only be used on
graphics windows (although -pwm_itemhandler- can be used on either
graphics or text windows).  As a cosmetic issue, you might like to note
that if you are using a graphics window principally as a 'control panel'
containing these kinds of items, you might prefer the effect of using
the standard cursor in that window (i.e. after making the window, assign
-pwmstdscursor- to -pwm_windowcursor- of the window.)

Each item-constructing procedure takes as its first three arguments a
window identifier, and two integers X and Y which establish the position
of the top-left corner of the item.  The first thing it does is to
calculate the size of the item, and make sure that -pwm_itemhandler- will
allow it reserve the press and release events for that area: i.e. that
there are no overlapping event specifications.  It then draws the item
in the appropriate manner and returns.

The last two arguments to each of the item-constructing procedures are a
string and a procedure.  The string is a label: it will be displayed as
part of the item (the label is optional for "radio-items": the
penultimate argument to -pwm_make_radioitem- can be false instead of a
string).  The procedure will be called whenever the value of an item is
changed: for an "exec-item" it will not be passed an argument; for all
other kinds of item it will be passed one argument, the new value of the
item; so it should be prepared to accept this.  If you don't want
anything to happen when the item's value is changed, you can use -erase-
as the procedure argument (see HELP *ERASE); or in the case of an
"exec-item", -identfn- (see HELP *IDENTFN);

A final warning: do not attempt to kill the window that contains an item
in the procedure which is called when the value of the item is changed:
this will cause an error. The only exception to this is with an
"exec-item" - it is possible to kill the window in the procedure invoked
in an "exec-item", as long as you remove the item itself (using
-pwm_kill_item-) first, that is before killing the window.


-- Utilities for use with pwmitems ------------------------------------

A program can discover or change the current value of an item with the
procedure -pwm_itemvalue-, i.e.

    pwm_itemvalue(<pwmitem>) -> <item>
    <item> -> pwm_itemvalue(<pwmitem>)

Some kinds of items restrict the values they can be given in the updater
version of this function: see the sections below on each item
constructing procedure for details.  If the updater form is used to
assign a new value to an item, and the new value is different from the
old value, the procedure specified when the item was made will be
called.

Note that you should be very careful about having this procedure itself
try to update the value of the item, since this could lead to infinite
recursion.  Normally, the procedure specified when the item is
constructed should only be taking any actions required when the value is
changed, and you should use another procedure, working through
-pwm_itemvalue-, to take those actions and change the item display.  If
you find yourself doing this kind of thing, it may be that you are using
the wrong kind of item (e.g. see -pwm_make_execitem-).

    pwm_itemarea(<pwmitem>) -> <vector>

This function returns the area covered by the item, which is also the
area within which it traps mouse events, as a vector of four integers:
respectively left, top, right and bottom (in pixels, since all these
items can only be installed on graphics windows).  Thus you can use this
to decide where to construct another item, so that they don't overlap.

    pwm_kill_item(<pwmitem>)

This function removes the item from the window (by clearing the area of
the window it covered to the background colour) and removes the event
trap for that item from -pwm_itemhandler-.  After this procedure has
been invoked, the item is unusable, and none of the functions described
in this section can legally be applied to it.

-- Toggle-items -------------------------------------------------------

Toggle-items are useful when some attribute can either be on or off.
They can be constucted using -pwm_make_toggleitem-

    pwm_make_toggleitem(<window-id>, <integer:X>, <integer:Y>,
                  <boolean:I>, <string:L>, <procedure:C> ) -> <pwmitem>

The toggle-item consists of a label (the string L) with a square box
next to it, in which there can be displayed a filled-in square, if the
current value of the attribute is true.  The label and box are enclosed
in another box: pressing the left mouse button anywhere within this box
'toggles' the state of the toggle-item: i.e., if its value was false it
becomes true, and vice-versa.  The argument I determines the initial
value for the toggle-item.  If C is a procedure, it will be called
whenever the toggle-item's value is changed, either by the user clicking
it with the mouse or by a call to -pwm_itemvalue-.  The procedure C is
passed the the new value of the toggle-item as argument.

The initial value, and any new value assigned to the toggle-item by
-pwm_itemvalue-, need not be a boolean.  In line with the usual pop11
interpretation, any item other than -false- will be interpreted as true.
If the value of the toggle-item is updated through -pwm_itemvalue- is
not a boolean, it will be returned by subsequent calls of
-pwm_itemvalue-: however, it the user then clicks twice on the item
(i.e. turning it to false and then back to true) the value then returned
by -pwm_itemvalue- will be -true-, not whatever item had been previously
assigned.

-- Cycle-items --------------------------------------------------------

Cycle-items are useful when some attribute can have several different
values.  They can be constructed using -pwm_make_cycleitem-

    pwm_make_cycleitem(<window-id>, <integer:X>, <integer:Y>,
                     <list:V>, <string:L>, <procedure:C> ) -> <pwmitem>

A cycle-item consists of a label, the string L, separated by one space
from its current value.  The whole is enclosed in a box large enough for
any of the possible values to be displayed.  Each time the left mouse
button is pressed within this box, the cycle-item's value is changed to
the next possible value: thus it cycles through the possible values.
The possible values are contained in the list V: the first thing in the
list will be the initial value for the cycle item.

Any of the values in the list can be a two-element list: in this case,
the first element will be displayed for that value, while the second
element will be the one given as argument to the procedure C, or
returned by -pwm_itemvalue-.

If a new value is assigned to the cycle-item by -pwm_itemvalue-, the new
value must be one of those originally specified in the list V.  If an
attempt is made to assign any other value, a mishap will be generated
(note: in the case of a value for which different items were given to be
displayed and to be returned as the 'current value', it is the latter
that should be used to update the cycle-item).

When -pwm_itemvalue- is used to assign a new value to the cycle-item,
the list of values is invisibly cycled through as if the user had
clicked the mouse on the cycle-item enough times to obtain the required
value: thus the subsequent ordering of values will be unchanged.

-- Radio-items --------------------------------------------------------

Radio-items are useful in similar situations to cycle-items when the
attribute can have several different values.  They have the advantage
over cycle-items that all the possible values can be seen at once, and
that values can be selected in any order (i.e. the user doesn't have to
cycle through the values to get to the one required).   They have the
disadvantage that they take up more space, to display all the values
simultaneously, so cycle-items may be more appropriate if there a lot of
possible values.  A radio-item can be constructed with
-pwm_make_radioitem-

    pwm_make_radioitem(<window-id>, <integer:X>, <integer:Y>, <item:I>,
                <list:V>, <string|false:L>, <procedure:C>) -> <pwmitem>

The name comes from an analogy with push button radios, in which when
one button is pushed to select a channel, any other button that is
currently pushed pops out.  The item displays as a box inside which the
possible values are listed in a column, and beside each a check box like
that used for a toggle-item.  If a label is specified in the argument L
(and note that for this kind of item it is optional) this appears above
all the items, slightly separated.

As with a cycle-item, the possible values are given in the list V; and
any or all of them may be given as a two-element list in which the first
element is used for displaying the value, while the second is the one
that is passed to the procedure C, and returned or accepted by the item
through the procedure -pwm_itemvalue-.  One of the values must be
selected as the initial value of the item: this is given in the
argument I.

Again as with a cycle-item, you should note that when specifying a value
for the item, either in the argument I or with -pwm_itemvalue-, it must
be one of the values originally specified in the list V; and if a value
was specified in V as list of a value-to-be-displayed and a value-to-use
it is the value-to-use that should be used.

-- Exec-items ---------------------------------------------------------

Exec-items are a little different from the other ones described above,
in that they don't really have a value.  Instead, they are like a button
the user can push (with the mouse) to cause your program to do
something.  An exec-item is construced with -pwm_make_execitem-

    pwm_make_execitem(<window-id>, <integer:X>, <integer:Y>,
                                <string:L>, <procedure:C>) -> <pwmitem>

When the user presses the left mouse button on an exec-item, the whole
item is inverted; then the procedure C specified when the item was
constructed is called; finally the item is un-inverted again.  An
exec-item, as noted above, doesn't really have a value: normally calling
-pwm_itemvalue- to get the value of an exec-item will return false.  If
the procedure C is being called at the point at which -pwm_itemvalue-
is called (i.e. it -pwm_itemvalue- is being called by the procedure C,
or by something that C has called) it will return true.

The procedure C may invoke -pwm_kill_item- on the item itself, thereby
causing the item to disappear. It may even kill the window (using
-pwm_kill_window-) containing the item (as a "quit" button might, for
example), but if it does this, it MUST remove itself first, otherwise
the attempt to un-invert the item will cause a mishap.

Finally, if -pwm_itemvalue- is used to assign a value to an exec-item,
if the new value is not false and the item is not currently active (i.e.
C is not being called) then the item will be inverted and C called in
the same way as if the user had pressed the left button on the item.
Thus if there is some function (for example, clearing a display area)
which the user can request your program to execute, and which your
program may itself execute, then you can assign the function as the
argument C to -pwm_make_execitem-, and when your program wishes to call
the function itself it can do

    true -> pwm_itemvalue(clear_item)

That way the user will know what is happening because the button will be
'illuminated' (inverted) while the function is being executed.


-- Label-items --------------------------------------------------------

Label-items are useful when a arbitrary text input or value is required
They can be constructed using -pwm_make_labelitem-

    pwm_make_labelitem(<window-id>, <integer:X>, <integer:Y>,
                       <integer:W> <string:P>, <string:L>,
                       <procedure|false:C) -> <pwmitem>

A Label-item consists of a prompt, the string P, separated by one space
from an label L which is the items current value and an optional
procedure C. The whole is enclosed in a box large enough for up to a W
character label to be displayed. If the string exceeds this size it is
scrolled to the left. The labelitem is selected for input by clicking
the left button on the anywhere in the box. The Input allows only
standard ascii characters and ignores control character except backspace
and delete. When a newline or return character is detected then the
procedure C is executed, if it is not false, with the item as argument.

The label string can be obtained or replaced by using -pwmitem_valof-
The procedure C can be executed by assigning true to the
pwmitem_valof(item). This will not effect the value of the label.

If the left mouse button is cliced on the selected label item then a
menu will popup. The title of the menu is the value of the labelitem and
the two options are CLEAR and STUFF. Clear will set the value of the
labelitem to the null string. Stuff will append the contents of the
selection to the label by calling -pwm_getselection-. It would be nice
if the selection could be set to the value of the labelitem, but this is
not suported by PWM.

There are three procedures that can be used with label items each takes
a label item as argument. They are:-

    pwmselectlabelitem(<labelitem>);
    pwmdeselectlabelitem(<labelitem>);
    pwmlabelcompile(<labelitem>);

pwmlabelcompile will compile the value of the label item in the top
section see HELP * SECTIONS. Another useful procedure is

    pwmselectnextlabelitem(currentitem,nextitem);

This can be used as a closure on nextitem in the creation of a label
item. When return is pressed in this label item then the nextitem will
be selected. If the argument nextitem in pwmselectnextlabelitem is a
word the its value must be a label item.

-- List-items ---------------------------------------------------------

List items are similar to cycle items except you can see more than one
item at a time.

    pwm_make_listitem(<window-id>, <integer:X>, <integer:Y>, <list:V>,
       <string:L>, <integer:C>, <integer:R>,
       <procedure|false:P>) -> pwmitem;

The first four arguments are the same as for cycle item. The integer C
is the width of displayed values in characters. The integer R is the
number of values visible at any one time. The string L is a label at the
top of the item. The procedure P, which maybe false, is called when a
value is selected.

Pwmlistitem will look something like this

                    ---------------------
                   | L A B E L           |
                   |---------------------|
     SCROLL UP --> |/\| VALUE_2          |
                   |--| VALUE_3          |
                   |  | VALUE_4          |
                   |##| VALUE_5          |
       SLIDER ---> |##| VALUE_6          |
                   |##| VALUE_7          |
                   |  |#VALUE#8##########| <-- SELECTED VALUE
                   |  | VALUE_9          |
                   |  | VALUE_10         |
                   |--| VALUE_11         |
   SCROLL DOWN --> |\/| VALUE_12         |
                    ---------------------


Pressing the left mouse button on the scroll up button moves the window
up, i.e. the text scrolls down. Similarly with the scroll down button.
Scrolling can also be done by pressing the left mouse button on the
slider area.

A value can be selected by pressing the left button in the text area.
The value highlighted is the selected value and will be returned by
pwmitem_value. Assigning a value to pwmitem will cause that value to be
highlighted. If the selected value is not visible then the text will be
scrolled so the it is visible.

Initially no value is selected and pwmitem_valof will return undef. A
value can be deselected by assigning undef to pwmitem_valof.

If the selected value is not visible it can be made visible by clicking
the left mouse button on the label area.

A value can be deleted from the list of values using the procedure

        pwmset_delete(item,value);

An attempt to delete a non-existent value is ignored. A value can be
appended to the list of values by using

        pwmset_append(item,value);

In this case value can be a two element vector or list.

All the values of a list item can be obtained by using

    pwmset_contents(item) -> list;

This procedure also has an updater which allows all the values to be
changed. The list|vector should be in the same format as in the
original pwm_make_listitem call.

    <L:list|vector> -> pwmset_contents(item);

-- Set-items ----------------------------------------------------------

Set items are similar to list items except you can select more than one
item at a time.

    pwm_make_setitem(<window-id>, <integer:X>, <integer:Y>,
       <list:S>, <list:V>,
       <string:L>, <integer:C>, <integer:R>,
       <procedure|false:P>) -> pwmitem;

The arguments are the similar as for a list item except that a list S
of initial selections can be passed.

Pwmsetitem will look something like this

                    ---------------------
                   | L A B E L           |
                   |---------------------|
     SCROLL UP --> |/\| VALUE_2          |
                   |--| VALUE_3          |
                   |  | VALUE_4          |
                   |##| VALUE_5          |
       SLIDER ---> |##|#VALUE_6##########| <--|
                   |##|#VALUE_7##########| <--|
                   |  |#VALUE#8##########| <--|-- SELECTED VALUES
                   |  | VALUE_9          |    |
                   |  |#VALUE_10#########| <--|
                   |--| VALUE_11         |
   SCROLL DOWN --> |\/| VALUE_12         |
                    ---------------------


Pressing the left mouse button on the scroll up button moves the window
up, i.e. the text scrolls down. Similarly with the scroll down button.
Scrolling can also be done by pressing the left mouse button on the
slider area.

Values can be selected by pressing the left button in the text area.
The value highlighted is the selected value and will be returned by
pwmitem_value. Assigning a value to pwmitem will cause that value to be
highlighted. If the selected value is not visible then the text will be
scrolled so the it is visible.

Initially no value is selected and pwmitem_valof will return undef. A
value can be deselected by assigning undef to pwmitem_valof.

If the selected value is not visible it can be made visible by clicking
the left mouse button on the label area.

A value can be deleted from the list of values using the procedure

        pwmset_delete(item,value);

An attempt to delete a non-existent value is ignored. A value can be
appended to the list of values by using

        pwmset_append(item,value);

In this case value can be a two element vector or list.

All the values of a list item can be obtained by using

    pwmset_contents(item) -> list;

This procedure also has an updater which allows all the values to be
changed. The list|vector should be in the same format as in the
original pwm_make_setitem call.

    <L:list|vector> -> pwmset_contents(item);


-- Slider-items -------------------------------------------------------

Slider items can be used for controlling integer values in fixed range.
They are constructed using -pwm_make_slideritem-

    pwm_make_slideritem(<window-id>, <integer:X>, <integer:Y>, <integer:W>
                  <integer:H>, <integer:Offset>, <integer:Size>,
                  <procedure|false:C>,<Boolean:Interactive>)-> <pwmitem>


  +------------------------------------------------------------------+
  |                      ##############                              |
  |                      ##############                              |
  +------------------------------------------------------------------+
   <------ Offset ------><--- Size --->

The slider consists of a box containing a black mark. The position of
the mark can be changed by pressing the left mouse button. The mark will
then, within the confines of the box, follow the mouse until the button
is released.

If the width W is greater that the height H then a horizontal slider is
produced other wise a vertical slider is produced. The integer Size is
the size of the mark and can be in the range 1 to max(W,H) - 1. The
integer Offset is the distance from the end of the slider to mark. It
can be in the range 1 to max(W,H) - Size. The Offset can be changed by
user interaction as discused above.
Note: maxium Offset + Size = max(W,H).

If C is not false then it should take two arguments. The first argument
is the offset and the second is the size of the mark. When the procedure
is called depends on the boolean Interactive. If Interactive is true
then the procedure is called every time the mouse moves after the button
has benn pressed, otherwise the procedure is only called when the button
is released. If the procedure takes a long time to execute (for example
more the half a second) then when Interactive is true the mark will lag
behind the mouse. Note all the mouse move events will get processed no
matted how long the procedure call takes. (NB if too many mouse move
events get put on the input queue then PWM has been known to crash).

The value of a slider item is a two element vector, the first entry is
the offset of the mark and the second is the size of the mark. This
allows procedures to control the size of the mark and so the range of
the offset by assigning a vector to pwmitem_valof(slider). Any attempts
to change the value of the slider while it is tracking the mouse are
ignored.

-- An example ---------------------------------------------------------

The quickest way to understand what the items look like and how they
work may be to load the code below, which makes a small window and puts
an example of each kind of item in it.  You can load the example by
marking the whole range (from after this paragraph down to, but not
including, the copyright notice at the end of this file) and typing
<CTRL>D or <ENTER>lmr<RETURN> (see HELP *LMR).

    ;;; make a window
    vars cpanel = pwm_make_gfxwin('control panel', 350, 400);

    ;;; this just makes it look pretty
    pwmstdcursor -> pwm_windowcursor(cpanel);

    ;;; default handler for window, for other mouse buttons and in
    ;;; areas not occupied by an item.

    (erase <> vedputmessage(% 'no items there/not left button' %))
        -> pwm_itemhandler(cpanel, false, false, false);

    ;;; for this item, we can construct a procedure using standard
    ;;; bits of pop11 that will just assign it's argument to the
    ;;; value of a word.  This item changes the value of -vedbreak-
    ;;; so we make its initial value be the current value of -vedbreak-
    ;;; Note that this isn't quite right as a real control panel for VED
    ;;; because it won't change the value of the item when you switch
    ;;; files (the value of -vedbreak- is local to each file).

    vars t1;
    pwm_make_toggleitem(cpanel, 10, 10, vedbreak, 'Break',
                            updater(valof(% "vedbreak" %))) -> t1;

    ;;; for this item, we are specifying four values for -vedautowrite-,
    ;;; in a sensible order: but the list is in a slightly funny order
    ;;; so that it will start off with 1500 as the initial value.
    ;;; Perhaps we ought to be using the current value of -vedautowrite-
    ;;; in the list, since unless you happen to have -vedautowrite-
    ;;; already set to 1500 the item will lie until it has been used at
    ;;; least once.  Note that we specify that when the value of
    ;;; -vedautowrite- is false, it should be displayed as "off".  False
    ;;; work (i.e. it can be displayed quite happily) but this is
    ;;; neater.  As with the item above, it is slightly incomplete,
    ;;; since if you change -vedautowrite- by assigning a number to it,
    ;;; the displayed item will not reflect this.  Maybe -vedautowrite-
    ;;; should be an active variable?

    vars t2;
    pwm_make_cycleitem(cpanel, 10, 35,
                        [1500 3000 [off ^false] 500],
                        'Autowrite:',
                        procedure(v);
                            v -> vedautowrite;
                            vedputmessage('VEDAUTOWRITE now ' >< v);
                        endprocedure) -> t2;

    ;;; this is a silly procedure, used in the item below

    define tuning(frequency);
        vedputmessage('tuning to ' >< frequency >< 'kHz');
    enddefine;

    ;;; here we are having each value displayed with a name which makes
    ;;; sense to the user, but being stored internally as something
    ;;; which makes sense to the program (or would if POPLOG could
    ;;; recieve VHF radio).  The fourth argument (648) is the frequency
    ;;; for the World Service, so it specifies that that should be
    ;;; selected as the initial value of the item.  When this has been
    ;;; made, you can try assigning frequencies to the item (only one
    ;;; of those it knows about) and see how the display is updated and
    ;;; the procedure -tuning- called again (unless you give the
    ;;; frequency it is already tuned to).  E.g. do
    ;;;  95.8 -> pwm_itemvalue(t3);

    vars t3;
    pwm_make_radioitem(cpanel, 140, 10, 648,
                    [['Radio 4' 92.4] [Capital 95.8] [World 648]],
                                       false, tuning) -> t3;

    ;;; again, you can try doing
    ;;;  true -> pwm_itemvalue(t4)
    ;;; and see how the item is 'illuminated' while the refresh is
    ;;; happening.  If you were really keen, you could assign that to
    ;;; <CTRL> L (normally mapped directly to -vedrefresh-), e.g.
    ;;;  vedsetkey('\^L', (updater(pwm_itemvalue))(% true, t4 %));

    vars t4;

    pwm_make_execitem(cpanel, 75, 10, 'Refresh', vedrefresh) -> t4;


    ;;; a simple command line for ved
    ;;; note This will not recover from errors such as unknown command

    vars command_item;
    pwm_make_labelitem(cpanel,10,75,16,
        'Command:','',
        procedure(item);
        lvars item;
            veddo(pwmitem_valof(item));
            unless vedbufferlist=nil then
                if vedcursorset() then
                    vedsetcursor();
                else
                    vedcheck();
                endif;
                ''->pwmitem_valof(item);
            endunless
        endprocedure
    ) -> command_item;


    ;;; an example of pwm_make_listitem.
    vars list_item;

    pwm_make_listitem(cpanel, 10, 140,
        [
         'item1.1' 'item1.2' 'item1.3' 'item1.4' 'item1.5'
         'item2.1' 'item2.2' 'item2.3' 'item2.4' 'item2.5'
         'item3.1' 'item3.2' 'item3.3' 'item3.4' 'item3.5'
         'item4.1' 'item4.2' 'item4.3' 'item4.4' 'item4.5'
         'item5.1' 'item5.2' 'item5.3' 'item5.4' 'item5.5'
        ], 'List of items', 15, 10, false) -> list_item;

    ;;; an example of pwm_make_setitem.
    vars set_item;

    pwm_make_setitem(cpanel, 200, 140, [],
        [
            'red' 'orange' 'yellow' 'green' 'blue'
            'cyan' 'indigo' 'violet' 'magenta'
            'black' 'white' 'grey'
        ], 'Palette', 15, 10, false) -> set_item;

    ;;; an example using a slider item
    vars slider_item;

    pwm_make_slideritem(cpanel, 10, 340, 330, 20, 10, 5,
                        false, false) -> slider_item;

--- C.pwm/help/pwmitems
--- Copyright University of Sussex 1991. All rights reserved. ----------
