Programming Guide : Creating a Frame at Runtime : How You Can Build a Frame Dynamically : How You Can Create the Script
 
Share this page          
How You Can Create the Script
A frame's script is contained in the Script attribute of its FrameSource object. The data type of this attribute is StringObject. The first step to building a script for a frame is creating a string object and assigning it to the Script attribute of the frame's FrameSource object.
After you have created the string object, use the ConcatVarchar method to put the text into your script. This method appends text to a StringObject. The syntax of the ConcatVarchar method is:
StringObject = StringObject.ConcatVarchar(text = varchar)
The ConcatVarchar method returns a reference to the original string.
If your script includes statements that access the database, such as select or update, you can use a select statement to retrieve the necessary column names for the target lists of the statements and a select loop to build at least part of the database statements.
Alternatively, you can use a query object to create the target fields and provide the user with the ability to change the data in the database. For an example of using a query object to perform these operations, see Creating a Frame at Runtime.
The DynamicFrame frame uses a select loop to obtain information and build the target fields and a cursor object to allow the user to make changes to data in the database. For details about the implementation in the DynamicFrame frame, see How You Can Construct the Fields and How You Can Complete the SQL Statements.
How You Can Attach the Frame to the Application
After you have completed all of the frame elements and attached them to the frame, you must attach the frame itself to the application by setting the ParentApplication attribute of the new frame's FrameSource object. The value to which you set this attribute must be the same value that is in the ParentApplication attribute of the currently executing frame. (The currently executing frame is a frame of your dynamic application.)
To access the ParentApplication attribute of a currently active frame, use the ObjectSource attribute of the frame's FrameExec object. Whenever you call or open a frame, OpenROAD creates a FrameExec object for that instance of opening or calling. The FrameExec object gives you information about the current state of a running frame. The ObjectSource attribute points to the frame's FrameSource object. The ParentApplication attribute is defined for the FrameSource object.
For example, the DynamicFrame frame attaches the generated test_frame frame to the currently executing frame (the starting frame) by assigning the value of the ParentApplication attribute of the current frame's FrameSource object to the corresponding attribute of the generated frame's FrameSource object:
test_frame.ParentApplication =
CurFrame.ObjectSource.ParentApplication;
For an example of attaching a frame to an application, see How You Can Add the Frame to the Application.
How You Can Compile and Run the New Frame
This section presents a sample dynamic application that contains two frames, the starting frame and the dynamic frame:
The starting frame
The starting frame is created in OpenROAD Workbench. This frame contains one option field (providing a list of tables) and one menu item, File (with Go and Close submenu options). The following figure illustrates the dynamic application's starting frame:
The dynamic frame
The frame called by the starting frame is built dynamically and contains one field for every column in the selected table. This frame contains a File menu option (with two submenu options: Commit and Close, and Rollback and Close) and an Edit menu option (with Delete, Update, and Next submenu options). The generated frame lets the user edit the data in the fields, save or cancel changes, or request the next row of retrieved data.
The following illustrates the dynamic application's generated frame:
All of the application's dynamic work is done in the frame script associated with the starting frame. Each of the following subsections describe a portion of the starting frame's script and the role that it plays in the dynamic application.
Initialize Statement
The example application uses the DynamicFrame frame's initialize statement to perform the following start-up tasks:
Declare necessary variables
Select and list the tables from which the user can choose
Initialize some variables
How You Can Declare Variables
The DynamicFrame frame declares the following local variables in its frame script's initialize block:
initialize ( ) =
declare
    /* Needed for loading the option list */
    i = integer not null;    /* temp index */
    /* Needed in generation of frame */
    numcolumns = integer not null;
    /* number of columns in tab */
    widthchar = integer not null;
    /* width of one character */
    heightchar = integer not null;
    /* height of one character */
    fieldleft = integer not null;
    /* left edge of field*/
    trimleft = integer not null;
    /* left edge of trim */
    fieldtop = integer not null;
    /* top of next field */
    fieldheight = integer not null;
    /* height of a field */
    maxformheight = integer not null;
    /* maximum height of form */
    maxformwidth = integer not null;
    /* fixed width of form*/
    vertspace = integer not null;
    /* space between lines */
    trimspace = integer not null;
    /* space between trim/field */
    dbaname = varchar(32) not null;
    /* name of dba */
    /* variables used for generating the
    ** source code */
    /* select statement string */
    selectstring = varchar(2000) not null;
    /* FETCH statement string */
    fetchstring = varchar(2000) not null;
    /* UPDATE statement string */
    updatestring = varchar(2000) not null;
    /* update clause string */
    selectupdatestring = varchar(2000) not null;
    /* Variables for dictionary information of the
    ** table columns used in select choices */
    tmp_table_name = varchar(32) not null;
    /* used in getting column names */
    columnname = varchar(32) not null;
    /* used in getting columns */
    columndatatype = varchar(32) not null;
    /* used in getting columns */
    columnlength = integer not null;
    /* Variables used as holders of form
    ** objects, etc. */
    test_frame = FrameSource default null;
    /* The frame being generated */
    top_menu = MenuGroup default null;
    /* The menu being generated */
    test_menu = MenuButton default null;
    /* The menu item */
    field_ptr = EntryField default null;
    /* Ptr to entry field */
    trim_ptr = FreeTrim default null;
    /* The trim ptr */
    /* Name of generated frame */
    test_frame_name = varchar(32) not null
enddeclare
How You Can Select Tables for the Option Field
The starting frame lets the user pick a table from a list of tables presented in an option field. The initialize block contains the code that fills in the list of table choices. The DynamicFrame frame lets the user select from any table owned by the user or the database's DBA (which are available to any user with the necessary permissions).
The following statements from the sample application retrieve the name of the database's DBA from the iidbconstants catalog and release the lock taken by the select statement:
/* Get the dba name for finding the tables */
select dba_name as :dbaname
from iidbconstants;
commit;
Note:  The table iidbconstants is a view in the Ingres Standard Catalog Interface that has two columns. One column holds the name of the current user and the other holds the name of the DBA of the current database.
Before loading the table names selected at runtime into the option field, the starting frame clears any previous values from the option field. This step is necessary because you must give a value to the option field when you create it in OpenROAD Workbench. The following statement clears the option field in the example frame:
field(table_choices).ValueList.ChoiceItems.Clear();
ValueList is the attribute of the OptionField class that contains the values that appear in the list. Its data type is ChoiceList. One attribute of ChoiceList is ChoiceItems, which is an array of class ChoiceItem. It is the ChoiceItems array that actually contains the values displayed in the option field. For a more detailed explanation of loading values into the option field, see How You Can Load Values into a ChoiceField Object.
After clearing the option field of values, the starting frame uses a select loop to retrieve the new values to be loaded into the option field. The retrieved values are the names of all the tables that are owned by the DBA. The table names are retrieved from iitables (an Ingres Standard Catalog Interface view). The selected tables are returned one at a time and processed by the select loop. The select loop places each table name into the option field's ValueList.
The following code is an example of the select loop discussed in the previous paragraph:
i = 1;
select distinct table_name as :tmp_table_name
    from iitables
    where table_owner = :dbaname
begin
    field(table_choices).ValueList.ChoiceItems[i]
    EnumText = tmp_table_name;
    field(table_choices).ValueList.ChoiceItems[i]
    EnumValue = i;
    i = i + 1;
end;
The following section, . (see How You Can Load Values into a ChoiceField Object), explains the syntax used to load values into the table_choices option field.
How You Can Load Values into a ChoiceField Object
Because the statement that loads values into the table_choices option field uses the reference variable associated with the option field, the field function is required. For more information about the field function and its use, see Creating a Frame at Runtime and Creating a Frame at Runtime.
As a ChoiceField object, one of the attributes of the table_choices option field is ValueList. ValueList contains the values in an enumerated list. The data type of ValueList is ChoiceList, which means that ValueList contains an object of the class ChoiceList.
A ChoiceList object has an attribute called ChoiceItems. The ChoiceItems attribute contains an array of class ChoiceItem with two attributes, EnumText and EnumValue. The EnumText attribute contains the text associated with the list; in the example frame, the value of EnumText is the table name. The EnumValue attribute contains an enumerated value associated with the text; the example frame uses the row number of the ChoiceItems array.
To access the EnumText and EnumValue attributes, you can move through the ChoiceItems array by incrementing the array index counter.
The following statement assigns the contents of the variable tmp_table_name to the EnumText attribute in the ith row of the array of ChoiceItem objects contained in the ChoiceItems attribute:
field(table_choices).ValueList.ChoiceItems[i].
    EnumText = tmp_table_name;
The ChoiceItems attribute is an attribute of the ChoiceList object that is contained in the ValueList attribute of the OptionField object represented by field(table_choices).
An alternative method for loading the ValueList attribute of a ChoiceField object is using the ChoiceList's AddTextItem or the AddBitmapItem methods. For an example of how to use the AddBitmapItem method, see Working with Images and Text Strings.
How You Can Display the List
When the user opens the starting frame, the frame's initialize statement executes, and the retrieved table names are displayed automatically in the option field. To change the list after the application has started, you must explicitly refresh the option field.
When a fixed-choice list (for example, table_choices) is currently displayed, OpenROAD does not automatically refresh the display after you make changes to the option field's ValueList. You must explicitly refresh the display with ChoiceField's UpdChoiceList method. The following statement from the example application refreshes the display of the table_choices option field:
field(table_choices).UpdChoiceList();
How You Can Initialize Variables
After loading appropriate table names into the option field, the example starting frame initializes all variables whose values remain the same throughout the program. The following code from the starting frame's initialize block initializes variables:
/* Set up initial values. */
widthchar = 100;
heightchar = 200;
trimleft = 100;
trimspace = 100;
maxformheight = 3000;
maxformwidth = 9000;
fieldleft = trimleft + (33*widthchar) + trimspace;
vertspace = 250;
All values refer to one-thousandths of an inch.
The Go Menu Item (Constructing the Frame)
After selecting a table, the user selects the Go menu item. Because the example application lets the user return to the initial frame to select another table, the code for the Go operation checks whether a frame already exists for the chosen table before generating a frame for that table. If such a frame exists, it executes the frame.
The following code from the example starting frame first checks whether the required frame exists. Then it executes the frame, if it does exist, or generates the frame and then executes it if it does not exist:
if Generated_Frame_List.LastRow >0 then
/* There is at least one generated frame. */
    for i = 1 to Generated_Frame_List.LastRow do
    if Generated_Frame_List[i].table_name =
        table_choices then
        /* Frame already there. Execute it. */
        callframe
        :Generated_Frame_List[i].frame_name;
        resume;
        endif;
    i = i + 1;
    endfor;
endif;
Generated_Frame_List is a global array variable used by the example application to keep track of frames that have already been generated, avoiding the need to regenerate them. The LastRow attribute, defined for array objects, returns the sequence number of the last row in the array. If the LastRow attribute returns any positive number in the preceding code, the code checks the Generated_Frame_List array for a table name that matches the user's chosen table. If a match is found, that frame is executed.
If no rows exist in the Generated_Frame_List variable or if no match is found, the starting frame code constructs a frame. The construction proceeds in the following order:
1. Create the FrameSource object and define its attributes.
2. Create the FrameForm object.
3. Construct the fields on the form.
4. Set the height and width of the form.
5. Complete the statement strings.
6. Create the menu items.
7. Generate the frame script for the frame.
8. Add the frame to the application.
After the frame is generated, it can be executed.
The following subsections describe each of these steps in detail.