Flow of Control for Frame SCL Entries

Introduction

There is a specific flow of control for frame SCL. In general, the INIT section runs before the window opens, the MAIN section executes after a field is modified or a component is selected, and the TERM section runs when the window closes. Because the FRAME entry allows additional statements to run for components as well as for multiple extended tables via SCL methods, there are additional points of interest in the flow of control in FRAME entry programs.
After each SCL section runs, if the FRAME entry's status has been set to H (for Halt), execution halts. You can set the status to H either by assigning the _STATUS_ variable in the SCL or by calling the FRAME entry's _setStatus method. Likewise, a STOP statement in the frame SCL program can halt the frame application, interrupting the normal flow of control. However, in both of these cases, all _term methods execute.

FRAME Entries and Automatic Methods at Build Time

When you build a frame, an instance of a frame is created. When a frame or frame SCL is used at build time, specific methods are automatically called. You can override these automatic methods at build time, if necessary.
Although frames and frame SCL entries are typically executed at run time, there are some cases where you might actually use an existing frame and its frame SCL entry at build time. For example, you might have created a custom editor for use during the development of other frames.
The following table provides information about automatic build time methods. For more information about these methods, refer to the SAS/AF online Help.
Automatic Build-time Methods
Method
Class
Description
_bInit
Frame
a _bInit method that runs at build time when you open the FRAME entry, first for the frame, and then for each component. The Frame object and each component must successfully execute this method (and its parent's definition) to be usable.
_bInit
Object
initializes each object in the FRAME entry.
_bPostInit
Frame
performs postprocessing after the _bInit method for the Frame object. Also runs the _bPostInit for all the components; _bPostInit for non-visual components runs first, followed by _bPostInit for visual components.
_bPostInit
Object
performs postprocessing on objects after the _bInit method. You should override this method rather than _bInit if your initialization code refers to any objects besides _SELF_.
_bUpdate
Frame, Widget
updates the Frame object or widget with any values that you might have changed in the Attributes window. For your own GUI subclasses, you might need to override this method to execute code after the user closes the Attributes window.
This method is used only by legacy classes. Any object that uses the Properties window or a custom Properties window does not invoke this method.
_bTerm
Object
terminates the components in the FRAME entry at build time. You only need to override this method for cleanup purposes. For example, you might need to delete SCL lists or non-visual components that you create during _bInit or _bPostInit.
_bTerm
Frame
terminates the Frame object at build time. You only need to override this Frame class method for cleanup purposes. For example, you might need to delete SCL lists or non-visual components that you create during _bInit or _bPostInit.

Build-Time Order of Program Execution

The following figure illustrates the order in which the automatic methods are invoked at build time and the circumstances under which they are invoked.
Automatic Methods and Build-Time Order of Program Execution
Flow of control for automatic methods and the build-time order of program execution
Note: Events are not sent during _bInit and _init, including attributeName changed events sent by _setAttrValue as well as events sent by _sendEvent. The reasoning behind this behavior is that it is impossible to know which objects exist when your _init is running. Therefore, not all objects that are listening for your event will be notified. You can not be sure that all objects exist until your _postInit runs.

FRAME Entries and Automatic Methods at Run Time

When a frame or frame SCL executes at run time, specific methods are automatically called. The following table provides information about automatic run-time methods. For more information about these methods, refer to the SAS/AF online Help.
Automatic Run-time Methods
Method
Class
Description
_init
Frame
initializes all components for the frame.
_init
Object
initializes the Frame object and all components.
_initLabel
Frame
runs the INIT section of the FRAME entry's SCL program.
_postInit
Frame
performs additional processing for the Frame object after _initLabel has run. Also runs the _postInit for all components; non-visual components are run first, followed by visual components.
_postInit
Object
performs additional processing on all widgets after the INIT section has run.
_objectLabel
Widget
runs the object label section in the FRAME entry's SCL program.
_select
Widget
responds to a user selection or modification.
_mainLabel
Frame
runs the MAIN section of the FRAME entry's SCL program.
_refresh
Widget
redraws a widget without updating its data.
_preTerm
Frame
performs additional processing before _termLabel is run.
_preTerm
Widget
performs additional processing before the TERM section runs.
_termLabel
Frame
runs the TERM section of the FRAME entry's SCL program.
_term
Frame
deletes the Frame object. Also runs the _term for non-visual components. The _term for visual components should have already run by this point. If this method runs the _term for visual components, then a problem exists with the visual components and a warning message appears.
_term
Object
deletes an object and the SCL list that is used to represent the object.

Run-Time Order of Program Execution

The following figure illustrates the order in which the automatic methods are invoked at run time and the circumstances under which they are invoked.
Automatic Methods and Run-Time Order of Program Execution
Flow of control for automatic methods and run-time order of program execution
1 The _init methods for the FRAME entry and its components execute. The _init for non-visual objects is run first, followed by the _init for visual objects. The _init for visual objects follows a specific window order. See Example: Order of Processing for Multiple Window Components for more information.
Event handlers are installed and drag and drop sites are also set up at this point.
2The statements in the INIT section of the SCL program execute via the _initLabel method.
3The _postInit methods for the FRAME entry and its components execute. Any attribute links are also synchronized at this point. That is, _getAttribute is invoked on the source attribute (to access the attribute value), and then _setAttrValue is called on the target attribute.
  • For extended tables that are being used as selection lists, the _setSelection method executes for all components in the row.
  • The _getRowLabel method and the _getRow method run for each row of each extended table until the table fills (or until the _endTable method is called, for dynamic tables).
Note: Because an object cannot be initialized twice, the _init and _postInit methods are not permitted after the object is initialized. After the first _init method is sent to an object, any subsequent _init methods result in an SCL program halt. After the first _postInit method is sent to an object, the FRAME entry will not send additional _postInit methods, but instead sends _refresh methods.
4When one of these conditions is met:
  • a field is modified
  • a component is selected
  • a command is issued and CONTROL ALWAYS, CONTROL ALLCMDS, or CONTROL ENTER is in effect.
The following steps occur (these steps are not illustrated in the figure):
  • If the modified component is in an extended table that is being used as a selection list, the _selectRow method executes.
  • If a field is modified, the field's informat is applied. If the value does not match the informat, the field is flagged as being in error. If a field within an extended table is modified, the corresponding row of the extended table is also marked as modified.
  • If the modified field matches the informat, the field's _validate method is queued to run. If the validation fails, the field is flagged as being in error.
  • The _objectLabel method for the object that is modified or selected is queued to run, unless CONTROL NOLABEL is in effect. CONTROL LABEL is the default for FRAME entries.
  • If the component that is modified or selected is in an extended table, the _putRowLabel method is queued to run immediately after the _objectLabel methods for all modified components in that row. The _putRow method for the row that is modified or selected is queued to run after the _putRowLabel method. The _objectLabel method of the extended table is queued to run immediately after all _putRowLabel and _putRow methods.
5All methods that were queued in step 4 execute. (Only 5A and 5B are illustrated in the figure.)
  • 5A) The _objectLabel method for each modified component executes. For example, if you modify the PRICE field in one or more rows of an extended table, the PRICE label executes once for each modified field, and the _CURROW_ system variable is updated with the number of the updated row each time.
  • 5B) If a modified field is not in error or if CONTROL ERROR is in effect, the _select method is invoked for the selected or modified component. The default _select method submits the SAS command that is assigned to that component.
  • 5C) Any _putRowLabel methods that are queued execute in order after all labels for components within the row execute. If the component is in an extended table, the _CURROW_ system variable is updated to reflect the row number.
  • 5D) The _putRow method for the extended table containing modified components executes after all other labels and methods for that row execute.
  • 5E) The _objectLabel method for the extended table executes, and then the extended table receives a _select method after all _putRowLabel and _putRow methods run.
6If any component is marked as being in error (after the labels or the _select, _putRowLabel, or _putRow methods execute) and CONTROL ALWAYS, CONTROL ALLCMDS, or CONTROL ENTER is not in effect, the FRAME entry returns control to the user and awaits the next modification or command.
7Unless one of the following conditions is met, the statements in the _mainLabel method execute:
  • one or more fields are in error
  • a CANCEL, ENDSAS, BYE, or RETURN command is issued
  • neither CONTROL ALLCMDS, CONTROL ALWAYS, CONTROL ENTER, or CONTROL ERROR is in effect
8 If the FRAME entry is not ending, each FRAME entry component that has been modified or marked as needing refreshment is refreshed by invoking its _refresh method. An object cannot receive a _refresh method unless it is completely initialized (that is, the object's _init and _postInit methods must have run). If a _refresh method is sent to an object before its _postInit method runs, the _refresh method is converted to a _postInit method. When you use a REFRESH statement or send a _refresh method to a FRAME entry before the FRAME entry receives a _postInit method, a _postInit method is sent to the FRAME entry, and then the refreshment proceeds.
Extended tables receive the _refresh method first, and then the other objects receive a _refresh method. Extended tables are refreshed by executing their _getRowLabel and _getRow methods and refreshing all components within the rows. This action is performed either for all rows or only for rows that have been modified, depending on the settings of the table's Putrow Options attribute. The extended table updates the _CURROW_ system variable to reflect the logical row number for each row that it processes. _CURROW_ is added as an automatic instance variable of both the extended table and the objects within the table.
  • For extended tables with the selectionList attribute, the _setSelection method executes for all components on the row.
  • When an extended table is refreshed, it executes the _getRowLabel method.
  • The _getRow method for the extended table executes.
  • The table executes the _update method for the objects in the current row.
  • If the end of a table is reached, the _hide method is called for the remaining objects in the rows that are still visible.
9If you issue the END, CANCEL, ENDSAS, BYE, or RETURN command, program termination begins.
  • 9A) The _preTerm methods for the Frame object and all components are executed unless the command is BYE or ENDSAS. This enables objects to set the entry's _STATUS_ system variable to R (to resume rather than terminate) under certain circumstances. For example, empty required fields are not allowed, and they prevent normal program termination except after a CANCEL, ENDSAS, BYE, or RETURN command.
  • 9B) If no _preTerm method sets the _STATUS_ variable to R or H via the _setStatus method of the Frame class, the _termLabel method is executed. If a statement in the TERM section sets _STATUS_ to R, the program resumes instead of terminating, unless the command issued is ENDSAS, BYE, CANCEL, or RETURN. The TERM label does not execute if an ENDSAS, BYE, or ENDAWS command is issued.
  • 9C) If the program termination is not stopped by an R status, the FRAME entry window closes and the _term method executes for each object in the entry and for the FRAME entry itself.
    Note: Once the _term methods begin, the components are deleted. _term methods should not attempt to apply methods to other components in the FRAME entry. Also, any value assigned to _STATUS_ is ignored once _term methods begin since the FRAME window is closed.

Changing Frame Components and Frame SCL Programs

You can change the attributes, location, and appearance of components in a FRAME entry without recompiling the SCL source program. Only the following changes require you to recompile:
  • changing the name of a component
  • changing the type of a component from character to numeric and vice versa
  • changing the length of a component
  • changing the SUBMIT replacement string from the Attributes window
  • adding a new component
  • deleting an existing component
  • changing the SCL source entry
  • modifying the SCL source
When you are in the build environment, this message appears when you need to recompile:
NOTE: Intermediate code has been removed.