Controlling User Input
The Grid object is designed to allow you to implement simple applications with very little programming effort. You merely present the data to be edited by setting the Values property and then get it back again once the user has signalled completion. The validation imposed by the associated Edit object(s) will prevent the user from entering invalid data and your program can leave the user interaction to be managed entirely by APL. However, for more sophisticated applications, the Grid triggers events which allow your program to respond dynamically to user actions.
Moving from Cell to Cell
When the user moves from one cell to another, the Grid generates a CellMove event. This reports the co-ordinates (row and column) of the newly selected cell. The CellMove event serves two purposes. Firstly, it allows you to take some special action when the user selects a particular cell. For example, you could display a Combo or List object to let the user choose a new value from a pre-defined set, then copy the selected value into the cell. Secondly, the CellMove event provides the means for you to position the user in a particular cell under program control, using ⎕NQ
.
Changing Standard Validation Behaviour
Input validation is provided by the Edit object associated with a cell. By default, the built-in validation will prevent the user from leaving the cell should the data in that cell be invalid. For example, if the FieldType is 'Date'
and the user enters 29th February and a non-leap year, APL will beep and not allow the user to leave the cell until a valid date has been entered If you wish instead to take some other action, for example display a message box, you should use the CellError event. This event is generated immediately the user attempts to move to another cell when the data in the current cell is invalid. The event is also generated if the user selects a MenuItem, presses a Button or otherwise changes the focus away from the current cell.
The CellError event reports the row and column number of the current cell, the (invalid) text string in that cell, the name of the object to which the user has transferred attention or the co-ordinates of the new cell selected. The default action of the event is to beep, so to disable the beep your callback function should return a 0. If you wish to allow the user to move to a different cell, you must do so explicitly by generating a CellMove event using ⎕NQ
or by returning a CellMove event as the result of the callback.
Reacting to Changes
If enabled, the Grid object generates a CellChange event whenever the user alters data in a cell and then attempts to move to another cell or otherwise shifts the focus away from the current cell. This allows you to perform additional validation or to trigger calculations when the user changes a value. The CellChange event reports the co-ordinates of the current cell and the new value, together with information about the newly selected cell or the external object to which the focus has changed.
The default action of the CellChange event is to replace the current value of the cell with the new one. If you wish to prevent this happening, your callback function must return a 0. If in addition you wish the focus to remain on the current cell, you must do this explicitly by using the CellMove event to reposition the current cell back to the one the user has attempted to leave.
Restoring User Changes
The Grid object supports an Undo method which causes the last change made by the user to be reversed. This method can only be invoked under program control using ⎕NQ
and cannot be directly generated by the user. If you want to provide an undo facility, it is recommended that you attach a suitable callback function to a MenuItem or a Button. To perform an undo operation, the callback function should then generate an Undo event for the Grid object.
Updating Cell Data
You can change the entire contents of the Grid by resetting its Values property with ⎕WS
. However, this will causes the entire Grid to be redrawn and is not to be recommended if you only want to change one cell or just a few cells.
You can change the value in a particular cell by using ⎕NQ
to send a CellChange event to the Grid. For example, if you want to alter the value in row 2 column 3 of the Grid object called Test.G
to 42, you simply execute the following statement :
⎕NQ 'Test.G' 'CellChange' 2 3 42
To update an entire row or column of data you can use the RowChange and ColChange events. For example, to change all 12 columns of row 500 to the 12-element vector TOTAL
, you could execute :
⎕NQ 'Test.G' 'RowChange' 500 TOTAL
Deleting Rows and Columns
You can delete a row or column by using ⎕NQ
to send a DelRow or DelCol message to the Grid object. For example, the following statement deletes the 123rd row from the Grid object Test.G
. Note that if you have specified it, the corresponding element of RowTitles is removed too.
⎕NQ 'Test.G' 'DelRow' 123
Inserting Rows and Columns
You can insert or add a row or column using the AddRow or AddCol method. You must specify the following information.
row or column number |
title (optional) |
height or width (optional) |
undo flag (optional) |
resize flag (optional) |
title colour (optional) |
gridline type (optional) |
The event message must specify the number of the row or column you wish to insert. This is index-origin dependent and indicates the number that the row or column will have after it has been inserted. For example, if ⎕IO
is 1 and you wish to insert a row between the 10th and 11th rows, you specify the number of the row to be inserted as 11. If you wish to insert a new column before the first one, you specify a column number of 1. To append a row or column to the end of the Grid, you should specify 1 + the current number of rows or columns.
If you have specified RowTitles or ColTitles, the message may include a title for the new row or column and this will be inserted in RowTitles or ColTitles as appropriate. If you fail to supply a new title, an empty vector will be inserted in RowTitles or ColTitles for you. If you are using default row and column headers and you have not specified RowTitles or ColTitles, any title you supply will be ignored. In this case the rows and columns will be re-labelled automatically.
If you have set CellHeights or CellWidths to a vector, the AddRow or AddCol event message may include the height or width of the new row or column being inserted. If you fail to supply one or you specify a value of ¯1
the default value will apply. Note that setting the height or width to 0 is allowed and will cause the new row or column to be invisible. If CellHeights or CellWidths has not been specified or is a scalar, the new row or column will be given the same height or width as the others and any value that you specify is ignored.
The undo flag indicates whether or not the insertion will be added to the undo stack and may therefore be subsequently undone. Its default value is 1.
If the data in the Grid is entirely numeric, the new row or column will be filled with zeros. If not, it will be filled with empty character vectors. If you want to set the row or column data explicitly, you should invoke the ChangeRow or ChangeCol immediately after the AddRow or AddCol event. The ChangeRow and ChangeCol event require just the row or column number followed by the new data.
The following example adds a new row entitled "Chateau Latour" to a Grid object called Test.G
. The first statement adds a new row between rows 122 and 123 (it becomes row 123) of the Grid. It will be of default height (or the same as all the other rows) and the change may not be undone (the undo flag is 0). The second statement sets the data in the new row to the values defined by the vector LATOUR_SALES
.
⎕NQ 'Test.G' 'AddRow' 123 'Chateau Latour' ¯1 0
⎕NQ 'Test.G' 'ChangeRow' 123 LATOUR_SALES