Callback methods
20.12. List Gadgets
A list gadget allows the user to make single or multiple selections from many alternatives. The list of choices is scrollable if the list is too long to be displayed all at once. A LIST gadget is thus appropriate if you have a long list of choices, or if you are constructing the list dynamically (at run time), especially if you cannot predict how many choices there will be. You must specify whether the gadget is a single or multiple-choice list, and give the width and height of the displayed portion. The length defines the number of choices that will be visible within the gadget. You may optionally specify a text tag to be displayed at the top-left above the gadget, the position on the form and a callback command. Typically you enter text values into the list using an array of strings and assigning to its Dtext member.
list .List 'Select some of these' MULTIPLE width 15 height 8 !Elements[1]= 'Element 1' !Elements[2]= 'Element 2' !Elements[3]= 'Element 3' !Elements[4]= 'Element 4' !Elements[5]= 'Element 5' !Elements[6]= 'Element 6' !This.List.Dtext= !Elements More examples:
list .Components SINGLE width 10 height 15
list .Components 'Colour:' AT . . . MULTIPLE width 10 height 15
list .Elements 'Elements to be deleted' callback '!this.Delete' MULTIPLE width 10 length 15 As with the option gadget, the list gadget actually contains two parallel lists, of the same length, one containing display values (Dtext) and the other containing replacement values (Rtext). The Dtext values must be supplied, but the replacement values are optional. If you don’t supply the Rtext values they will default to the Dtext values. The Rtext values are often used to assign callback strings to each field of the list. Resetting a list gadget's display- texts automatically deletes the existing display and replacement-texts and clears any current selections. For example, the contents of gadget
!Choices[ 1 ] = 'Tea' !Choices[ 2 ] = 'Coffee' !Choices[ 3 ] = 'Chocolate' !This.List.Dtext = !Choices
You can replace the list’s Rtext with a new array of the same length without disturbing the current Dtexts:
!newRtext[1] = ‘drink6’ !newRtext[2] = ‘drink4’ !newRtext[3] = ‘drink12’ !This.List.Rtext = !newRtext
You can use the new Add methods to add a single new entry to be appended to LIST and SELECTOR gadgets:
Add( !Dtext is STRING )
Add( !Dtext is STRING, !Rtext is STRING )
Where Dtext is the text to be displayed in the option list, and Rtext is the replacement text for the new field. If Rtext is not specified, it will be set to the Dtext string by default.
20.12.1. Single Choice List Gadgets
You can set and get the current selection in a single-choice list using the display-text, replacement text, or .val member. For example:
!This.List.val =2 - selects second list field !This.List.Select( 'Dtext', 'Coffee' )
!This.List.Select( 'Rtext', 'drink4' ) !fieldNumber = !This.List.val !Rtext = !This.List.selection() !Dtext = !This.List.selection(‘Dtext’)
Zero-Selections and Single Choice List Gadgets
You can also define a single-choice list-gadget to allow zero-selections.. The list syntax allows you to define the gadget with the SINGLE ZEROSELECTIONS keyword to indicate that the list is single choice with no mandatory selected field, e.g.
list .List |Cars| Anchor all single zerosel width 25 length 10
The val member now allows programmatic de-selection of the current field. For Single choice lists the keyword NORESELECT disables UnSelect and Select events when the currently selected field is clicked with the mouse, for example:
list .l1 |List gadget| zeroSel noReselect width 15 length 5 tooltip 'single choice list'
For ZeroSelection lists it is now possible to interactively deselect the selected field by clicking in unused rows or after the last column. Single choice List gadgets support UNSELECT events. Typically when a field is selected, an UNSELECT event is raised for the previously selected field (if any) and then a SELECT interactively deselected.
Notes:
1. UNSELECT events are not notified to PML unless an open callback has been specified (so that SELECT and UNSELECT events can be differentiated).
2. Typically the UNSELECT action allows Appware to manage consequences of deselection for any dependent gadgets or forms.
3. It is recommend that you do not change the List's selection programmatically in an UNSELECT event.
20.12.2. Multiple Choice List Gadgets
You can read the current selections in a multiple-choice list using the selection() methods. This will return the replacement-texts:
!Xarray = !This.List.selection() - returns selected replacement texts by default !Xarray = !This.List.selection(‘Dtext’) - returns selected display texts
To read the index numbers of the currently selected fields of a multi-choice list gadget: !ChosenNumbersArray = !!Form.List.Val
You can read back the current Dtexts or Rtexts as an array or simply as strings: !array = !This.List.Dtext - get all the Dtexts
!string = !This.List.Rtext[3] - get Rtext of the third list field
You can select fields of this list either singly (additive) or by array of Dtext or Rtext, using its select() methods:
!This.List.select(‘Rtext’, ‘Tea’) !This.List.select(‘Dtext’, !array)
Callbacks on Multi-Choice List Gadgets
At PDMS11.6 we introduced support for Extended Selection Mode for multi-selection lists, whereby CTRL and SHFT keys can qualify the list selection. As a result a whole set of UNSELECT events followed by a whole set of SELECT events can result from a single (atomic) user action. These events are presented in sequence, but AppWare cannot tell where the sequence starts or ends. At PDMS11.6, problems may arise if a multi-selection list is programmatically changed during the list callback. Modifying the list content or its selection during the sequence can cause unexpected results or even software crashes. At PDMS11.6Sp1 we nave introduced new START and STOP batch actions to bracket the sequence of UNSELECT and SELECT event actions. For maximum upwards compatibility, the START and STOP batch actions are only notified to PML if the user has assigned an open callback, since this is the only way that different event types (actions) can be differentiated because START and STOP events will not be notified to it. AppWare which used open callbacks and worked at PDMS11.6 will continue to work if the SELECT and UNSELECT meta-events were explicitly differentiated in the callback, as shown below, because the new START and STOP events will be ignored
Define method .listSelectionChanged( !list is GADGET, !action is STRING ) . . .
if( !action eq ‘SELECT’ ) then . . .
elseif( !action eq ‘UNSELECT’ then . . .
endif . . .
If you experience a change in behaviour, then you may need to rewrite your callback to explicitly handle the new START and STOP events and modify the list content or its selection only on receiving the STOP event action. For newly written AppWare we strongly advise you use open callbacks to service multiselection list gadgets.
20.12.3. Multi-Column List Gadgets
You can simulate a multi-column list using spaces and tabs if you are using a fixed-width font. But if you are using a proportionally spaced font, then you cannot do this and guarantee the columns will always line up. The list gadget may have multiple columns as shown in the following example, which is also a single-choice, zero-selection list. The column widths can be interactively modified using the mouse cursor in the headings row.
Picture Nr.27. - Multi-Column List Gadget
The number of columns is deduced from the List's data. If the user specifies a set of (1 or more) column headings before the list is populated, then this will determine the number of columns. If no headings are pre-specified then the number of columns is deduced from the display text of the List's first row. This provides upwards compatibility for existing Appware using single column lists. A List gadget's headings can be replaced after the list has been populated. If the new headings specify the same number of columns then the headings are replaced but the List's data fields and selection remain unchanged. If the number of columns is different, then the list is replaced by an empty list with the new headings. Invoking the Clear() method will clear the list's data fields and rebuild the current headings. The column headings, and hence the number of columns, for the list are assigned as an array of STRING:
!This.List.SetHeadings( !headings )
The Dtexts for each column of each row of the list can be provided as a PML array, where each element is an array of STRING. This can be row oriented or column oriented.
!This.List.SetRows( !rows )
!rows is an array of ‘row arrays’, and its size determines the number of rows in the list. !This.List.SetColumns( !columns )
!columns is an array of ‘column arrays’, and its size must match the number of columns of the list. The size of all the column arrays must be the same and determines the no of rows in the list. The default width of each column is determined by the longest header or Dtext value supplied. Rtext values for each row are supplied as for single column lists. Selection within the list applies to the entire row not individual cells, but rows of the list can be selected on the basis of a column’s Dtext:
This selects the first list row whose column has the given Dtext. If the list is a multi-choice list then repeated use of this method will add selected rows to the list.
Note: For a multi-column list gadget each row’s Dtext string is held as a ‘horizontal tab’ character separated string of column data, matching the column headings (as opposed to a simple string for single column list). The standard list members val, Dtext, Dtext[n] and methods Select( ‘Dtext’, …), Selection( ‘Dtext’ ) work on multicolumn lists with the following limitations:
• Querying Dtexts will return the tab separated strings.
• Supplying Dtext to populate the list or invoke selections will require tab separated strings as input.
Popup-Menus on Multi-Column List Gadgets
List gadgets with a popup menu assigned to them will pop up the menu when the rightmouse button is released when the cursor is over the list title or any list selection field. For multi- column lists right-mouse in a list field will first select that field, and unselect any other selected fields, before the popup appears. This selection behaviour does not occur for single column lists. The use of popup menus on list gadgets can be confusing so use them with care.