Summary:
See also: Classes and Objects, Interaction Model, Multiple Dialogs, Windows and Forms
The Dialog class is a built-in class that provides an interface to an interactive instruction such as INPUT.
ui.Dialog
Class Methods | |
Name | Description |
getCurrent( ) |
Returns the current dialog object. NULL if no current active dialog. |
setDefaultUnbuffered( v INTEGER ) |
Sets the default of the UNBUFFERED attribute for the next dialogs. |
Object Methods | |
Name | Description |
accept( ) |
Validates all dialog fields. |
appendRow( arrname
STRING ) |
Append a row at the end of the list. |
appendNode( arrname
STRING, pos INTEGER
) |
Append a new tree node at the end of the list. |
deleteRow( arrname
STRING, pos INTEGER
) |
Deletes row at position pos. |
deleteNode( arrname
STRING, pos INTEGER
) |
Deletes a tree node at position pos. |
deleteAllRows( arrname
STRING ) |
Delete all rows of the list. |
getArrayLength( arrname STRING
) |
Returns the total number of rows in a list. |
getCurrentItem(
) RETURNING STRING |
Returns the current item having the focus. This can be a field, list or action. |
getCurrentRow( arrname STRING
) |
Returns the current row of a list. |
getFieldBuffer( fieldname STRING
) |
Returns the current input buffer of the field identified by fieldname. |
getFieldTouched(
fieldlist STRING
) |
Returns TRUE if the TOUCHED flag of one of the the specified fields is set. |
getForm() |
Returns the current form used by this dialog. |
insertRow( arrname
STRING, pos INTEGER
) |
Inserts a row before position pos. |
insertNode( arrname
STRING, pos INTEGER
) |
Inserts a new tree node before position pos. |
isRowSelected( arrname
STRING, pos INTEGER
) |
Returns TRUE if the row at pos is selected. |
nextField(
fieldname STRING ) |
Registers the name of the next field that must get the focus when control returns to the dialog. |
selectionToString( arrname
STRING ) |
Builds a tab-separated value list from the selected rows. |
setArrayLength( arrname STRING,
v INTEGER
) |
Sets the total number of rows in a list for paged mode. |
setActionActive( actname STRING,
v INTEGER ) |
Enables or disables the action identified by actname. |
setActionHidden( actname STRING,
v INTEGER
) |
Hides or shows the default action view identified by actname. |
setCurrentRow( arrname STRING,
row INTEGER) |
Change the current row in a list. |
setFieldActive(
fieldlist STRING,
v INTEGER ) |
Enables or disables one or several fields identified by fieldlist. |
setFieldTouched(
fieldlist STRING,
v INTEGER ) |
Sets the TOUCHED flag of one or several fields identified by fieldlist. |
setCellAttributes( attarr ARRAY OF RECORD
) |
Defines decoration attributes for each cell (singular dialogs only). |
setArrayAttributes( arrname
STRING, attarr
ARRAY OF RECORD
) |
Defines decoration attributes for each cell (multiple dialogs). |
setSelectionMode( arrname
STRING, mode INTEGER ) |
Defines the row selection mode. Possible values
are: 0 = single row selection, 1 = multi-row selection. |
setSelectionRange( arrname
STRING, start INTEGER, end INTEGER,
value INTEGER ) |
Sets the selection flags for a range of rows. |
validate(
fieldlist STRING ) |
Check form-level validation rules for the list
of fields. Returns error number if problem. |
This class provides an interface to the interactive instructions INPUT, INPUT ARRAY, DISPLAY ARRAY, CONSTRUCT, and MENU.
The DIALOG keyword is a pre-defined object variable. To get an instance of this class, use DIALOG inside the interactive instruction block:
01
INPUT BY NAME custid, custname02
ON ACTION disable03
CALL DIALOG.setFieldActive("custid",0)04
END INPUT
The dialog object is only valid during the execution of the interactive instruction. Using the DIALOG keyword outside a dialog instruction block results in a compilation error. However, you can pass the object to a function, in order to write common dialog configuration code:
01
INPUT BY NAME custid, custname02
BEFORE INPUT03
CALL setupDialog(DIALOG)04
END INPUT05
06
FUNCTION setupDialog(d)07
DEFINE d ui.Dialog08
IF user_group = "admin" THEN09
CALL d.setActionActive("delete",1)10
CALL d.setActionActive("convert",1)11
ELSE12
CALL d.setActionActive("delete",0)13
CALL d.setActionActive("convert",0)14
END IF15
END FUNCTION
If needed, you can get the current active dialog object with the ui.Dialog.getCurrent()
class method:
01
FUNCTION field_disable(name)02
DEFINE name STRING03
DEFINE d ui.Dialog04
LET d = ui.Dialog.getCurrent()05
IF d IS NOT NULL THEN06
CALL d.setFieldActive(name, FALSE)07
END IF08
END FUNCTION
The method returns NULL if there is no current active dialog.
You can use the accept()
method to validate field input and
terminate the dialog. This method is equivalent to the ACCEPT INPUT / ACCEPT
DISPLAY / ACCEPT DIALOG instructions. The method is provided as a
3GL alternative to the ACCEPT control instructions, if you need for
example to terminate the dialog in a function, outside the context of a dialog
block, where control instructions cannot be used.
See ACCEPT DIALOG for more details.
The getArrayLength("screen-array")
method can be used to retrieve the total
number of rows of an INPUT ARRAY or DISPLAY ARRAY list. You must pass the
name of the screen array to identify the list:
01
DIALOG02
DISPLAY ARRAY custlist TO sa_custlist.*03
BEFORE ROW04
MESSAGE "Row count: " || DIALOG.getArrayLength("sa_custlist")05
...06
END DISPLAY07
INPUT ARRAY ordlist TO sa_ordlist.*08
BEFORE ROW09
MESSAGE "Row count: " || DIALOG.getArrayLength("sa_ordlist")10
...11
END INPUT12
...
The setArrayLength("screen-array", length)
method is used to specify the total number
of
rows when using the DISPLAY ARRAY
paged
mode. You must pass the
name of the screen array to identify the list, followed by an integer expression
defining the number of rows. When using a dynamic array
without paged mode (i.e. without the ON FILL BUFFER clause), you don't need to
specify the total number of rows to the DIALOG instruction: It is
defined by the number of elements in the array. However, when using the paged
mode in a DISPLAY ARRAY, the total number of rows does not
correspond to the elements in the program array, because the program array holds
only a page of the whole list. In any other cases, a call to this method is just
ignored.
Understand that a call to setArrayLength()
will not trigger the
execution of the ON FILL BUFFER clause immediately: The trigger to fill
a page of rows will be executed when all the user code has been execute and the
control goes back to the dialog instruction.
Note also that setArrayLength()
will also be called to fix the
final number of rows when using COUNT=-1 attribute, to implement a
paged list without knowing the total number of rows when the dialog starts.
The nextField(field-specification)
method can be used register the name of the next
field that must get the focus when control goes back to the dialog. This method
is similar to the NEXT FIELD
instruction, except that it does not implicitly break the program flow. If
you want to get the same behavior as NEXT FIELD, the method call must
be followed by a CONTINUE DIALOG / INPUT / CONSTRUCT instruction.
Since this method takes an expression as parameter, you can write generic
code, when the name of the target field is not known at compile time. In the
next example, the check_value()
function returns a field name where
the value does not satisfy the validation rules:
01
DEFINE fn STRING02
...03
ON ACTION save04
IF ( fn := check_values() ) IS NOT NULL THEN05
CALL DIALOG.nextField(fn)06
CONTINUE DIALOG07
END IF08
CALL save_data()09
...
The first parameter identifies the form field, see Identifying fields in dialog methods for more details.
The getCurrentRow("screen-array")
method can be used to retrieve the current
row of an INPUT ARRAY or DISPLAY ARRAY list. You must pass the
name of the screen array to identify the list:
01
DIALOG02
DISPLAY ARRAY custlist TO sa_custlist.*03
BEFORE ROW04
MESSAGE "Current row: " || DIALOG.getCurrentRow("sa_custlist")05
...06
END DISPLAY07
INPUT ARRAY ordlist TO sa_ordlist.*08
BEFORE ROW09
MESSAGE "Current row: " || DIALOG.getCurrentRow("sa_ordlist")10
...11
END INPUT12
...
If you want to change the current row in an INPUT ARRAY or DISPLAY
ARRAY list, you can use the setCurrentRow("screen-array",
index)
method. You must
pass the name of the screen array to identify the list, and the new row number:
01
DEFINE x INTEGER02
DIALOG03
DISPLAY ARRAY custlist TO sa_custlist.*04
...05
END DISPLAY06
ON ACTION goto_x07
CALL DIALOG.setCurrentRow("sa_custlist", x)08
...
Moving to a different row with setCurrentRow()
will
not trigger control blocks
such as BEFORE ROW / AFTER ROW, as the FGL_SET_ARR_CURR()
built-in function does.
Note also that this method will not set the focus; You need to use NEXT FIELD to set the focus to a list (this works with DISPLAY ARRAY as well as with INPUT ARRAY).
If the passed row index is lower than 1, the first row will be selected. If the row index is greater than the total number of rows, the last row will be selected.
If the new current row is out of the current page of rows, the dialog will adapt the list offset to make the new current row visible.
If multi-row selection is enabled, all selection flags of rows are cleared, and the new current row gets automatically selected.
The getCurrentItem()
method returns the name of the current form
item having the focus:
getCurrentItem()
returns the name of the
corresponding action. Note that if several action views a bound to the same
action handler with a unique name, there is no way to distinguish which
action view has the focus.getCurrentItem()
returns the [tab-name.]field-name of that
current field. The tab-name. prefix is added if a FROM
clause is used with an explicit list of fields. No prefix is added if FROM
screen-record.* is used or if BY NAME clause is used.getCurrentItem()
returns the screen-array
name identifying the list.getCurrentItem()
returns screen-array.field-name,
identifying both the list and the current field. Note however that in some
context, the current field is undefined. For example when entering the INPUT
ARRAY sub-dialog, getCurrentItem()
will return the screen-array
only when in the BEFORE INPUT control block.The getFieldBuffer("field-specification")
method returns the current input buffer of
the specified field. The input buffer is used by the dialog to synchronize form
fields and program variables. In some situations, especially when using the BUFFERED
mode or in a CONSTRUCT, you may want to access
that input buffer.
The field-specification is a string containing the field qualifier, with an
optional prefix ("[table.]column
").
01
LET buff = DIALOG.getFieldBuffer("customer.cust_name")
The input buffer can be set with:
See Identifying fields in dialog methods for more details about field name specification.
The getFieldTouched("field-list")
method returns TRUE if the TOUCHED
flag of the specified field is set.
The field-list is a string containing the field qualifier, with an
optional prefix ("[table.]column
"), a table
prefix followed by a dot and an asterisk ("table.*
"), or a
simple asterisk ("*
").
See Identifying fields in dialog methods for
more details about the field -list specification.
The next code example checks if a specific field has been touched:
01
AFTER FIELD cust_name02
IF DIALOG.getFieldTouched("customer.cust_address") THEN03
...
If the parameter is a screen record following by dot-asterisk, the method checks the touched flags of all the fields that belong to the screen record:
01
ON ACTION quit02
IF DIALOG.getFieldTouched("customer.*") THEN03
...
When passing a simple asterisk (*) to the method, the runtime system will check all fields used by the dialog:
01
ON ACTION quit02
IF DIALOG.getFieldTouched("*") THEN03
...
See Identifying fields in dialog methods for more details about field name specification.
The setFieldTouched("field-list")
method can be used to change the TOUCHED
flag of the specified field(s).
The field-list is a string containing the field qualifier, with an
optional prefix ("[table.]column
"), or a table
prefix followed by a dot and an asterisk ("table.*
"). See Identifying fields in dialog methods for
more details about the field -list specification.
You typically use this method to set the touched flag when assigning a
variable, to emulate a user input. Remember when using the UNBUFFERED
mode, you don't need to DISPLAY
the value to the fields. The setFieldTouched()
method is provided
as a 3GL replacement for the DISPLAY
instructions to set the touched flags.
01
ON ACTION zoom_city02
LET p_cust.cust_city = zoom_city()03
CALL DIALOG.setFieldTouched("customer.cust_city", TRUE)04
...
If the parameter is a screen record following by dot-asterisk, the method checks the touched flags of all the fields that belong to the screen record. You typically use this to reset the touched flags of a group of fields, after modifications have been saved to the database, to get back to the initial state of the dialog:
01
ON ACTION save02
CALL save_cust_record()03
CALL DIALOG.setFieldTouched("customer.*", FALSE)04
...
Note that the touched flags are reset to false when using an INPUT ARRAY list, every time you leave the modified row.
The getForm()
method returns a ui.Form
object as a handle to the current form used by the dialog. Use this form object to
modify elements of the current form. For example, you can hide some parts of the
form with the ui.Form.setElementHidden() method.
The runtime system is able to detect hidden fields and exclude them from the
input list. See Example 2.
In methods like setActionActive(), the first parameter identifies the action object to be modified. This parameter can be full-qualified or partly-qualified. If you don't specify a full-qualified name, the action object will be identified according to the focus context.
The action name specification can be any of the following:
Here action-name identifies the name of the action specified in ON ACTION action-name or COMMAND "action-name" handlers, while dialog-name identifies the singular dialog or sub-dialog and field-name defines the field bound to the action INFIELD clause of ON ACTION.
Note that the action name must be passed in lowercase letters.
The runtime system will raise the error -8089 if the action specified by [dialog-name.][field-name.]action-name can not be found within the current dialog.
In the DIALOG instruction,
actions can be prefixed with the sub-dialog
identifier. However, if methods like setActionActive()
are called in the
context of the sub-dialog, the prefix can be omitted. When using a
field-specific action defined with the INFIELD
clause of ON ACTION, you can identify the action with the
full-qualified name dialog-name.field-name.action-name. Like sub-dialog
actions, if you specify only action-name, the runtime system will search
for the action object according to the focus context.
When using a singular dialog like INPUT, you can identify field-specific actions by field-name.action-name if the dialog was defined without a NAME attribute.
For more details, see Binding action views to action handlers.
Dialog actions can be enabled and disabled with the setActionActive("action-specification",
boolean)
dialog method:
01
BEFORE DIALOG02
CALL DIALOG.setActionActive("zoom", FALSE)
The first parameter identifies the action object of the dialog, see Identifying actions in dialog methods for more details.
In GUI applications,
push-buttons triggering actions should normally be disabled if the current
context / situation makes the corresponding action invalid or unusable. For
example, a "print" button should be disabled if there is nothing to
print. The setActionActive()
method is typically used to
enable/disable actions according to the context.
The second parameter of the method must be a boolean expression that evaluates to 0 (FALSE) or 1 (TRUE).
To simplify action activation, you can write a common "setup" function which centralizes all rules to enable/disable actions. This function can then be called from any place in the DIALOG instruction, passing the DIALOG object as parameter. See Example 3.
You can also use the INFIELD clause of ON ACTION to automatically disable an action if the focus leaves the specified field.
The Default View
(and Context Menu option) of an
action can made visible or invisible with the setActionHidden("action",
value)
dialog method:
01
ON ACTION hide02
CALL DIALOG.setActionHidden( "confirm", 1 )
The first parameter identifies the action object of the dialog, see Identifying actions in dialog methods for more details.
Values of the second parameter can be 1 or 0.
In methods like setFieldActive(), the first parameter identifies the form field (or, for some methods, a list of fields) to be modified. The form field names can be full-qualified or partly-qualified.
Note that in methods like setFieldActive(), fields are identified by the form field name specification, not the program variable name used by the dialog. Remember form fields are bound to program variables with the binding clause of dialog instruction (INPUT variable-list FROM field-list, INPUT BY NAME variable-list, CONSTRUCT BY NAME sql ON column-list, CONSTRUCT sql ON column-list FROM field-list, INPUT ARRAY array-name FROM screen-array.*).
The field name specification can be any of the following:
Here are some examples:
"cust_name"
,"customer.cust_name"
,"cust_screen_record.cust_name"
,"item_screen_array.item_label"
,"formonly.total"
,"customer.*"
(only some methods accept the
"dot asterisk" notation)When no field name prefix is used, the first form field matching that field name will be used. If the field specification is invalid (i.e. no field in the current dialog matches the field specification), the method will throw the error -1373.
Note that when using a prefix in the field name specification, it must match the field prefix assigned by the dialog according to the field binding method used at the beginning of the interactive statement: When no screen-record has been explicitly specified in the field binding clause (for example, when using INPUT BY NAME variable-list), the field prefix must be the database table name (or FORMONLY) used in the form file, or any valid screen-record using that field. But when the FROM clause of the dialog specifies an explicit screen-record (for example, in INPUT variable-list FROM screen-record.* / field-list-with-screen-record-prefix or INPUT ARRAY array-name FROM screen-array.*) the field prefix must be the screen-record name used in the FROM clause.
Some methods like validate(), setFieldActive(), setFieldTouched(), getFieldTouched() can take a list of fields as parameter, by using the "dot-asterisk " notation (screen-record.*). This way you can check, query or change a complete list of fields in one method call:
01
ON ACTION save02
CALL save_cust_record()03
CALL DIALOG.setFieldTouched("customer.*", FALSE)04
...
Form fields used by the dialog can be enabled/disabled with the setFieldActive("field-list",
boolean)
method. When a
field is disabled, it is still visible, but the user cannot edit the value.
01
ON CHANGE cust_name02
CALL DIALOG.setFieldActive( "customer.cust_addr", (rec.cust_name IS NOT NULL) )
The field-list is a string containing the field qualifier, with an
optional prefix ("[table.]column
"), or a table
prefix followed by a dot and an asterisk ("table.*
"). See Identifying
fields in dialog methods for more details about the field -list
specification.
Note that you should not disable all fields of a dialog, otherwise the dialog execution stops (at least one field must get the focus during a dialog execution).
See also Example 1.
The insertRow("screen-array", index)
method is
just a basic row creation function, to insert a row in the list at a given
position. It does not set the current row or raise any
BEFORE ROW / BEFORE INSERT / AFTER INSERT / AFTER
ROW control blocks. It is quite similar to inserting a new element in the
program array, except the internal registers are automatically updated (like the
total number of rows returned by getArrayLength()).
If the list was decorated with cell attributes, the program array defining the
attributes will also be synchronized. If multi-row selection is enabled, selection flags of existing rows are kept.
Selection information is synchronized (i.e. flags are shifted down) for all rows
after the new inserted row.
This method should not be called in control blocks such as BEFORE ROW, AFTER ROW, BEFORE INSERT, AFTER INSERT, BEFORE DELETE, AFTER DELETE, but it can safely be used in an ON ACTION block.
After the method is called, a new row is created in the program array, so you
can assign values to the variables before the control goes back to the user. The
getArrayLength()
method will return the new row count.
Note that the method does not set the current row and does not give the focus to the
list; you need
to call setCurrentRow()
and execute NEXT FIELD
if you want to give the focus.
The insertRow() method must not be used when controlling a treeview. You must usethe insertNode() method instead.
The method takes two parameters:
If the index is greater than the number of
rows, a new row will be appended at the end or the list. This will be equivalent
to call the appendRow()
method.
If the list is empty, getCurrentRow() will return zero. So you must test this and use 1 instead to reference the first row otherwise you can get -1326 errors when using the program array.
Following code example shows a user-define action to insert ten rows in the list at the current position:
01
ON ACTION insert_some_rows02
LET r = DIALOG.getCurrentRow("sa")03
IF r == 0 THEN LET r = 1 END IF04
FOR i = 10 TO 1 STEP -105
CALL DIALOG.insertRow("sa", r)06
LET p_items[r].item_quantity = 1.0007
END FOR
The insertNode("screen-array", index)
method
is similar to insertRow(), except that it has to be
used when the dialog controls a treeview.
This method must be used when modifying the array of a treeview during the execution of the dialog, for example when implementing a dynamic tree with ON EXPAND / ON COLLAPSE triggers. Before the execution of the dialog, you can fill the program array directly. This includes the context of BEFORE DISPLAY or BEFORE DIALOG control blocks.
The method takes two parameters:
When adding rows for a treeview, the id of the parent node and new
node matters because that information is used to build the internal tree
structure. When calling insertNode()
, you pass the index of the
next sibling node. In the program array, the parent-id member of the new node
will automatically be initialized with the value of the parent-id of the next sibling
node, then the internal tree structure is re-built.
The appendRow("screen-array")
method is
just a basic row creation function to append a row to the end of the list. It does not set the current row or raise any
BEFORE ROW / BEFORE INSERT / AFTER INSERT / AFTER
ROW control blocks. It is quite similar to appending a new element to the
program array, except the internal registers are automatically updated (like the
total number of rows returned by getArrayLength()).
If the list was decorated with cell attributes, the program array defining the
attributes will also be synchronized. If multi-row selection is enabled, selection flags of existing rows are kept.
New row is inserted at the end of the list with selection flag set to
zero.
This method should not be called in control blocks such as BEFORE ROW, AFTER ROW, BEFORE INSERT, AFTER INSERT, BEFORE DELETE, AFTER DELETE, but it can safely be used in an ON ACTION block.
After the method is called, a new row is created in the program array, so you
can assign values to the variables before the control goes back to the user. The
getArrayLength()
method will return the new row count.
Note that the method does not set the current row and does not give the focus to the
list; you need
to call setCurrentRow()
and execute NEXT FIELD
if you want to give the focus.
The appendRow()
method does not create a temporary
row as the implicit append action of INPUT ARRAY; The row is
considered as permanent once it is added.
The method takes only one parameter:
Following code example implements a user-defined to append ten rows at the end of the list:
01
ON ACTION append_some_rows02
FOR i = 1 TO 1003
CALL DIALOG.appendRow("sa")04
LET r = DIALOG.getArrayLength("sa")05
LET p_items[r].item_quantity = 1.0006
END FOR
The appendNode("screen-array", index)
method has to be
used to add a new node under a given parent, when the dialog controls a treeview.
This method must be used when modifying the array of a treeview during the execution of the dialog, for example when implementing a dynamic tree with ON EXPAND / ON COLLAPSE triggers. Before the execution of the dialog, you can fill the program array directly. This includes the context of BEFORE DISPLAY or BEFORE DIALOG control blocks.
The method takes two parameters:
When adding rows for a treeview, the id of the parent node and new node
matters because that information is used to build the internal tree structure.
When calling appendNode()
, you pass the index of the parent node
under which the new node will be appended. In the program array, the parent-id
member of the new node will automatically be initialized with the value of the
id of the parent node identifier by the index passed as parameter, then
the internal tree structure is re-built.
If the parent index is zero, a new root node will be appended.
The methods returns the index of the new inserted node.
In the program array, the parent-id member of the new node will automatically be initialized with the value of the id member of the parent node identified by the index.
The deleteRow("screen-array", index)
method is
just a basic row deletion function. It does not reset the current row or raise
any BEFORE DELETE / AFTER DELETE / AFTER ROW / BEFORE
ROW control blocks (except in some particular situation as described
below). It is quite similar to deleting an element to the
program array, except that internal registers are automatically updated (like
the total number of rows returned by getArrayLength()).
If the list was decorated with cell attributes, the program array defining the
attributes will also be synchronized. If multi-row selection is enabled, selection information is synchronized (i.e.
selection flags are shifted up) for all rows
after the deleted row.
This method should not be called in control blocks such as BEFORE ROW, AFTER ROW, BEFORE INSERT, AFTER INSERT, BEFORE DELETE, AFTER DELETE, but it can safely be used in an ON ACTION block.
After the method is called, the row does no more exist in the program array,
and the getArrayLength()
method will return the new row count.
If the deleteRow()
method is called during an INPUT
ARRAY, and after the call no more rows are in the list, the dialog will
automatically append a new temporary
row if the focus is in the list, to let the user enter new data. When using AUTO APPEND = FALSE attribute, no temporary row will be created
and the current
row register will be automatically changed to make sure that it will not be greater
than the total number of rows.
If deleteRow()
method is called during an INPUT
ARRAY or DISPLAY ARRAY that has the focus, control blocks
such as BEFORE ROW / BEFORE FIELD will be executed if you delete
the current row. This is required
to reset the internal state of the dialog.
The method takes two parameters:
If you pass zero as row index, the method does nothing (if no rows are in the
list, getCurrentRow()
returns zero).
Following code example implements a user-defined action to remove the rows that have a specific property:
01
ON ACTION delete_invalid_rows02
FOR r = 1 TO DIALOG.getArrayLength("sa")03
IF NOT s_orders[t].is_valid THEN04
CALL DIALOG.deleteRow("sa",r)05
LET r = r - 106
END IF07
END FOR
The deleteNode("screen-array", index)
method
is similar to deleteRow(), except that it has to be
used when the dialog controls a treeview.
This method must be used when modifying the array of a treeview during the execution of the dialog, for example when implementing a dynamic tree with ON EXPAND / ON COLLAPSE triggers. Before the execution of the dialog, you can fill the program array directly. This includes the context of BEFORE DISPLAY or BEFORE DIALOG control blocks.
The method takes two parameters:
The main difference with deleteRow() is that deleteNode()
will remove recursively all child nodes before removing the node identified by
index.
If the index is zero, all root nodes will be deleted from the tree.
The deleteAllRows("screen-array")
method removes all the rows of a list driven by a DISPLAY ARRAY or INPUT
ARRAY. This is equivalent to a deleteRow()
call, but instead
of deleting one particular row, it removes all rows of the specified list.
This method should not be called in control blocks such as BEFORE ROW, AFTER ROW, BEFORE INSERT, AFTER INSERT, BEFORE DELETE, AFTER DELETE, but it can safely be used in an ON ACTION block.
After the method is called, all rows are deleted from the program array,
and the getArrayLength()
method will return zero.
The method takes the name of the screen-array as parameter.
If the deleteAllRows()
method is called during an INPUT
ARRAY, the dialog will automatically append a new temporary
row if the focus is in the list, to let the user enter new data. When using AUTO APPEND = FALSE attribute, no temporary row will be created
and the current
row register will be automatically changed to make sure that it will not be greater
than the total number of rows.
If deleteAllRows()
method is called during an INPUT
ARRAY or DISPLAY ARRAY that has the focus, the BEFORE ROW
control block will be executed if you delete the current row. This is required
to reset the internal state of the dialog.
If the list was decorated with cell attributes, the program array defining the attributes will be cleared. If multi-row selection is enabled, selection flags are cleared.
In order to execute NOT NULL, REQUIRED
and INCLUDE validation rules defined
in the form specification files, you can call
the validate("field-list")
method by passing a list of fields or screen records
as parameter. The method returns zero if success and the input error code of the
first field which does not satisfy the validation rules.
Note that the current field is always checked, even if it is not part of the validation field list. This is mandatory, otherwise the current field may be left with invalid data.
If an error occurs, the validate()
method automatically displays
the corresponding error message, and registers the next
field to jump to when the interactive instruction gets the control back.
The validate() method does not stop code execution if an error is detected. You must execute a CONTINUE DIALOG or CONTINUE INPUT instruction to cancel the code execution.
A typical usage is for a "save" action:
01
ON ACTION save02
IF DIALOG.validate("cust.*") < 0 THEN03
CONTINUE DIALOG04
END IF05
CALL customer_save()
See Identifying fields in dialog methods for more details about the field -list specification.
By default dialogs are not sensitive to variable changes. To make a dialog
sensitive, use the UNBUFFERED attribute in the dialog
instruction definition. However, you can define the default for all subsequent dialogs
by using the setDefaultUnbuffered()
class method:
01
CALL ui.Dialog.setDefaultUnbuffered(TRUE)
In an INPUT ARRAY or DISPLAY
ARRAY instruction, the setArrayAttributes("screen-array",
program-array)
method can be used to specify display attributes for each cell. You must define
an array with the same number of record elements as the data array used by the INPUT
ARRAY or DISPLAY ARRAY. Each element must have the same name as in
the data array, and must be defined with a character data type (you typically
use STRING).
Fill the display attributes array with color and video attributes. These must be specified in lowercase characters and separated by a blank (ex: "red reverse").
Possible values for cell attributes are a combination of the following:
reverse
blink
underline
white, yellow, magenta, red, cyan, green,
blue, black
Then, pass the
array to the dialog with the setArrayAttributes()
method, in a BEFORE INPUT or BEFORE DISPLAY block. Display
attributes can be changed dynamically during the dialog:
01
ON ACTION set_attributes02
CALL DIALOG.setArrayAttributes( "sr", attarr )
Note that like data values, if you change the cell attributes during the dialog, these are not displayed automatically unless the UNBUFFERED mode is used.
01
ON ACTION modify_cell_attribute02
LET attarr[index].col8 = "red reverse"
If you set NULL to a , the default TTY attributes will be reset:
01
ON ACTION clean_cell_attribute02
LET attarr[index].col8 = NULL
The cell attributes array can be detached from the dialog by passing NULL
as second parameter to the setArrayAttributes()
method. When doing this, the default TTY attributes will be reset (those
defined by the window or dialog ATTRIBUTE clause):
01
ON ACTION remove_attributes02
CALL DIALOG.setArrayAttributes( "sr", NULL )
For a complete example, see Example 4.
An equivalent method called setCellAttributes(program-array)
,
takes only the program array as argument. The setCellAttributes()
method is designed for singular dialogs, where only one screen array is
used.
The DISPLAY ARRAY dialogs supports
multi-row selection. This option is disabled by default and can be enabled with
the setSelectionMode("screen-array", mode)
method:
01
ON ACTION mrs_on02
CALL DIALOG.setSelectionMode( "sr", 1 )
Possible values of the second parameter are 0 (single row selection) or 1 (multi-range selection); other values are reserved for future use.
Multi-row selection can be enabled and disabled during the dialog execution. If multi-row selection is switched off, selected rows get de-selected.
For more details about multi-row selection, see Multiple Dialogs page.
If multi-row selection is enabled with setSelectionMode(),
you can check whether a row is selected with the isRowSelected("screen-array",
index)
method:
01
ON ACTION check_current_row_selected02
IF DIALOG.isRowSelected( "sr", DIALOG.getCurrentRow("sr") ) THEN03
MESSAGE "Current row is selected."04
END IF
If multi-row selection is off, the method returns TRUE for the current row and FALSE for other rows.
If multi-row selection is enabled with setSelectionMode(),
you can set the selection flags for a range of rows with the setSelectionRange("screen-array",
start-index, end-index, value)
method.
01
ON ACTION select_all02
CALL DIALOG.setSelectionRange( "sr", 1, -1, 1)
The start and end index must be in the range of possible row indexes (from 1
to DIALOG.getArrayLength("screen-array")
).
If you specify an end index of -1, it will set the flags from start index to the end of the list.
The selectionToString("screen-array")
method
can be used to get a tab-separated value list of the selected
rows. When multi-row selection is
disabled, the method
serializes the current row. You typically use this method in conjunction with
Drag & Drop to fill the buffer, by using a text/plain MIME type, to export
data to external applications.
01
ON ACTION serialize02
LET buff = DIALOG.selectionToString( "sr" )
Numeric and date data will be formatted according to current locale settings (DBMONEY, DBDATE).
The visual presentation of data is respected: The dialog will copy the rows in the sort order specified by the user, moved columns will appear in the same positions as in the table and hidden columns will be ignored. Note that phantom columns are not copied.
Items in the tab-separated record will be surrounded by double-quotes if the value contains special characters such as a new-line, a double-quote, or controls characters with ASCII code < 0x20. Double-quotes in the value will be doubled.
01
FUNCTION input_customer()02
DEFINE custid INTEGER03
DEFINE custname CHAR(10)04
INPUT BY NAME custid, custname05
ON ACTION enable06
CALL DIALOG.setFieldActive("custid",1)07
ON ACTION disable08
CALL DIALOG.setFieldActive("custid",0)09
END INPUT10
END FUNCTION
01
FUNCTION input_customer()02
DEFINE f ui.Form03
DEFINE custid INTEGER04
DEFINE custname CHAR(10)05
INPUT BY NAME custid, custname06
BEFORE INPUT08
LET f = DIALOG.getForm()09
CALL f.setElementHidden("customer.custid",1)10
END INPUT11
END FUNCTION
01
FUNCTION input_customer()02
DEFINE custid INTEGER03
DEFINE custname CHAR(10)04
INPUT BY NAME custid, custname05
BEFORE INPUT06
CALL setup_dialog(DIALOG)07
END INPUT08
END FUNCTION09
10
FUNCTION setup_dialog(d)11
DEFINE d ui.Dialog12
CALL d.setActionActive("print",user.can_print)13
CALL d.setActionActive("query",user.can_query)14
END FUNCTION
01
FUNCTION display_customer()02
DEFINE i INTEGER03
DEFINE arr DYNAMIC ARRAY OF RECORD04
key INTEGER,05
name CHAR(10)06
END RECORD07
DEFINE att DYNAMIC ARRAY OF RECORD08
key STRING,09
name STRING10
END RECORD11
12
FOR i=1 TO 1013
CALL arr.appendElement()14
LET arr[i].key = i15
LET arr[i].name = "name " || i16
CALL att.appendElement()17
IF i MOD 2 = 0 THEN18
LET att[i].key = "red"19
LET att[i].name = "blue reverse"20
ELSE21
LET att[i].key = "green"22
LET att[i].name = "magenta reverse"23
END IF24
END FOR25
26
DIALOG ATTRIBUTES(UNBUFFERED)27
DISPLAY ARRAY arr TO sr.*28
ON ACTION att_attach29
CALL DIALOG.setArrayAttributes("sr", att)30
ON ACTION att_detach31
CALL DIALOG.setArrayAttributes("sr", NULL)32
ON ACTION att_modify_cell33
LET att[2].key = "red reverse"34
ON ACTION att_clear_cell35
LET att[2].key = NULL36
END DIALOG37
38
END FUNCTION