The SUBDIALOG clause
Purpose of SUBDIALOG
The SUBDIALOG clause defines a declarative dialog to be attached to the
current procedural DIALOG
block.
By using form inclusion (with the FORM clause in LAYOUT
sections) and declarative dialogs + SUBDIALOG, you enforce code reusability in your
application sources.
Defining the declarative dialog
The declarative dialog is implemented outside the scope of the using DIALOG
block, at the same level as a function.
The declarative dialog can be defined in a different module, to be reused in other
DIALOG instructions. The sub-dialog module must be imported with the IMPORT FGL instruction.
Like other module elements such as functions and reports, the name specification is mandatory
when defining a declarative dialog. The name of the declarative dialog will be referenced in a
SUBDIALOG clause of a procedural dialog instruction.
In the "comment.4gl" module:
DIALOG comment_input()
...
END DIALOG
IMPORT FGL comment
...
FUNCTION mydialog()
DIALOG ...
...
SUBDIALOG comment.comment_input
...
END DIALOG
END FUNCTIONSee also Identifying sub-dialogs in DIALOG.
Sub-dialogs in form definitions
Implementing a sub-dialog as a declarative dialog in a separate module is typically used in
conjunction with the FORM clause, in the
LAYOUT section of form specification files:
LAYOUT
...
FORM "comment"
...
END
Semantics with SUBDIALOG
In terms of semantics, behavior and control block execution, a declarative dialog attached to a
procedural dialog with SUBDIALOG, behaves like a sub-dialog that is defined inside
the procedural DIALOG block.
For example, BEFORE INPUT
inside an INPUT block of a declarative dialog will be executed when the focus goes
to one of the fields of that sub-dialog.
Scope of dialog instructions
Other sub-dialogs can reference the attached declarative dialog in the current scope.
NEXT
FIELD instruction referencing a field in another
sub-dialog:DIALOG ... -- Parent dialog block
...
NEXT FIELD the_comment -- Field of the declarative dialog.
...
END DIALOGScope of DIALOG keyword
DIALOG keyword inside a declarative dialog block to use
ui.Dialog class methods, it references the current procedural dialog
object:DIALOG comment_input()
...
CALL DIALOG.setFieldActive("the_comment",TRUE)
...
END DIALOGWriting generic code
To be reused by different procedural DIALOG instructions, the code of
sub-dialog modules must be generic. However, if the sub-dialog code needs to interact with
the parent DIALOG, it must be possible to call a function from the parent
DIALOG.
You achieve this by using function references. Parent modules can then configure the sub-dialog module at runtime, with callback functions:
- Create a user-defined
TYPEwith theFUNCTIONtype matching the callback function of the using module. - Define a module variable, with the declared function type. If you want to keep it private to the module, define a setter function to assign the variable with the callback function reference.
- When the parent
DIALOGneeds to be notified by some change in the sub-dialog, check that the callback variable is notNULL, and call the function with appropriate values.
DIALOG, that something happened in the
sub-dialog. The parent DIALOG can then query the sub-dialog module
for more information, as long as the sub-dialog module provides functions to query
its status. PUBLIC TYPE cb_comment_event FUNCTION (event STRING)
PRIVATE DEFINE cb_ce cb_comment_event
...
PUBLIC FUNCTION set_event_callback(f cb_comment_event)
LET cb_ce = f
END FUNCTION
DIALOG comment_input()
...
IF cb_ce IS NOT NULL THEN
CALL cb_ce("comment_changed")
END IF
...
END DIALOG
For a complete example, see Example 3: DIALOG with SUBDIALOG.