PCL and Customization > User Interface and List Processor Functions > Creating Forms and Widgets Using PCL
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX''">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX''">   
Creating Forms and Widgets Using PCL
As an example of using PCL to create a form and some widgets, the PCL Class uil_list_boolean is shown. The purpose of this Class is to display the form and all the widgets which appear when the “Boolean...”pick is selected under List in the Main Menu. Actually, three forms come up, the “List A” form, the “List B” form and the “Boolean List” form. The uil_list_boolean Class controls the “List Boolean” form. The form contains an icon switch with four icons, a list box, five buttons and a separator. The form looks like this:
The Class uil_list_boolean contains nine functions which are:
1. init - Creates all the widgets displayed on the form and the form itself.
2. display - Displays the form and all its widgets.
3. bool_cb - Callback for boolean switch, calls uil_list_boolean.create.
4. create - performs boolean operation on the list.
5. save_cb - Callback from “Add to Group...” button.
6. repa_cb - Callback for “Replace A” button.
7. repb_cb - Callback for “Replace B” button.
8. hilight_cb - Callback for “Highlight” button.
9. cancel_cb - Callback for “Cancel” button.
To display the form type ui_exec_function(“uil_list_boolean”,“display”) in the command line.
Style and Externalization
Add the start of the uil_list_boolean Class are three lines as follows:
#include “appforms.p”
#include “appstrings.p”
#include “msg_list.i”
These are references to files which are used in conjunction with the C pre-processor or cpp.
See The C Preprocessor, 31for more about use of the C preprocessor in PCL and other language source files.
The first file “appforms.p” can be found in the delivery directory along with p3. It contains define strings which look like:
#define TBOX_WID_SINGLE uil_form_sizes.tbox_wid( 1 )
#define TBOX_WID_DOUBLE uil_form_sizes.tbox_wid( 2 )
#define TBOX_WID_TRIPLE uil_form_sizes.tbox_wid( 3 )
#define TBOX_WID_SPECIAL uil_form_sizes.tbox_wid( 4 )
(Excerpt from appforms.p)
and are used to position and size widgets on the form which is described in the section General Form Style, 225. The second file, “appstrings.p”, also contains define strings but are used to externalize the displayed text for internationalization. The last file, “msg_list.i” contains the define strings for defining the unique error codes used by the message facility, i.e., msg_to_form() for displaying error messages.
uil_list_boolean.init
The init function contains all of the PCL calls to create the forms and widgets. The call to create the form itself is:
bool_form = ui_form_create( 								@
 	/* callback */ 			““, 				@
 	/* x */			 FORM_X_LOC_SML, 				@
 	/* y */ 			FORM_Y_LOC, 				@
 	/* position */ 			“UL”, 				@
 	/* width */ 			FORM_WID_SML, 				@
 	/* height */ 			FORM_HGT_HALF, 				@
 	/* label */ 			“Boolean List”, 				@
 	/* iconname */ 			““)
The define strings FORM_X_LOC_SML, FORM_Y_LOC, FORM_WID_SML and FORM_HGT_HALF can all be found in “appforms.p”. The List Boolean form is a small form located in the standard position to the far right of the display directly beneath the Main Menu. The call to ui_form_create returns the widget id which was declared as classwide:
 CLASSWIDE widget bool_form,boolean_switch,text_box,save_btn,sdbox,sframe
Note that there is no callback for a form and that the label on the title bar at the top of the form says “Boolean List”.
Next, we create a selectframe and selectdatabox which will be used to highlight all the resulting entities in the list after the boolean operation (‘listc‘). These widgets will never be made visible. This is necessary since the call gm_hilight_widget takes a widget id of a selectdatabox to highlight the entities contained within. To hide the widgets we make a call to ui_wid_set as and set the “DISPLAY” parameter as follows:
ui_wid_set(sdbox,“DISPLAY”,False)
ui_wid_set(sframe,“DISPLAY”,False)
Now, we create the icon switch. We begin be creating the switch itself:
boolean_switch = ui_switch_create 								@
	/* parent */ 				(bool_form, 			@
 	/* callback */ 				“bool_cb”, 			@
 	/* x */ 				.01, 			@
 	/* y */ 				y_pos,			@
 	/* cols */ 				4, 			@
 	/* label */ 				“Operation:”, 			@
 	/* alwayson */ 				TRUE)
Its parent is the form and the callback is “bool_cb”. The switch has four columns, one for each of the boolean icons (only one row). The title of the switch is “Operation” and one of the items must always be selected.
Once the switch is created, we can add item icons as follows:
 ui_itemicon_create 										@
 	( boolean_switch, 			“and”, 		“and_bool.icon”, 				TRUE )
 ui_itemicon_create 										@
 	( boolean_switch, 			“or”, 		“or_bool.icon”, 				FALSE )
 ui_itemicon_create 										@
 	( boolean_switch, 			“a-b”, 		“minus_bool.icon”,				FALSE )
 ui_itemicon_create 										@
 	( boolean_switch, 			“b-a”, 		“b_minus_a_bool.icon”,				FALSE )
Each icon is given a name which is returned in the callback argument bool_cb(name) to indicate which switch was selected. The third argument to ui_itemicon_create is the file name which contains the bitmap for the icon. The file must exist in the PCL path, otherwise the “bart” icon will appear in its place. In our example, the “and” boolean is selected by default. To create icon files, use the UNIX or Windows NT utility bitmap.
Once all the widgets are created and placed on the form, the form is re-sized to just fit the last widget. The pcl variable, y_pos, contains the current location just beneath the last widget created (The apply button). By setting the “HEIGHT” parameter for the form with a call to ui_wid_set and passing y_pos, the form will be properly resized.
/*
* Set the form height
*/
 
ui_wid_set(bool_form, “HEIGHT”, y_pos)
ui_set_focus(text_box)
select_focus.exit()
The display function
The display function displays both the List Boolean form and the List A and List B forms. Try to always use ui_exec_function to display forms so that the init function only gets called once. The function ui_register_help is used to provide context sensitive help to the form so that when the cursor is on the form and the F1 key is pressed, the help for the boolean form appears.
FUNCTION display
 
ui_exec_function( “uil_list_a”, “display” )
ui_exec_function( “uil_list_b”, “display” )
ui_form_display( “uil_list_boolean” )
 
ui_register_help(bool_form,“uil_list_boolean”)
 
END FUNCTION /* display */
The icon switch callback: bool_cb
If the user selects any of the boolean icons on the switch, the callback function bool_cb is called. It has two arguments (see Callbacks, 221 the first is the name of the icon item selected or unselected and the second is a string indicating if it was selected or unselected, “ON” or “OFF” respectively. bool_cb is only concerned if an icon was selected, so the test for “ON” is only checked. The function uil_list_boolean.create actually performs the boolean operation which is shown later. Note that the reason a separate routine was needed to perform the operation was because it stand alone to be valid in the session file. The “>” at the beginning of the line indicates that the PCL command appears in the session file when executed.
 FUNCTION bool_cb( boolean, onoff )
 
 GLOBAL STRING listc[VIRTUAL]
 STRING boolean[],onoff[]
 
 IF (onoff == “ON”) THEN
 
> uil_list_boolean.create(boolean)
 
 ui_wid_set( text_box, “VALUE”, listc )
 
END IF
 
 END FUNCTION /* bool_cb */
After the boolean operation is performed, the contents of the databox is updated with the global PCL variable listc. uil_list_boolean.create modifies the contents of listc based on the selected boolean operation.
/****************************************************************/
 FUNCTION create(boolean)
 
 GLOBAL String listc[VIRTUAL],lista[VIRTUAL],listb[VIRTUAL]
 STRING boolean[]
 INTEGER status
 
 status = list_create_boolean_list(lista,listb,boolean,listc)
 
 END FUNCTION /* create */
/****************************************************************/
uil_list_boolean listing
A listing of the contents of the Class follows:
/*$$ UIL List Boolean Form (uil_list_boolean)
 *
 * Purpose:
 * Create the List boolean form
*
 * Side effects:
 * A small form is created (List Boolean) in the third column(panel)
 * which contains a icon switch, a list contents textbox, an
 * “Add to Group...” button, a “Enumerate...” button, a “Done” button and
 * a “Cancel” button.
 *
 * The icon switch determines which operation applies to the
 * contents of two related forms, “List A’ and List B”. See
 * PCL Classes uil_list_a and uil_list_b for further details.
 * In each of the other forms is a text box with a list defined
 * in them. The switch determines which boolean operation is to
 * apply to both and applies it and places the result in the textbox
 * “List Contents”.
 *
 * Note:
 * To properly display this form call uil_list_save.load. Do
 * not call uil_list_save.display
 *
 */
 
#include “appforms.p”
#include “appstrings.p”
#include “msg_list.i”
 
CLASS uil_list_boolean
 
 CLASSWIDE WIDGET bool_form,boolean_switch,text_box,save_btn,sdbox,sframe
 CLASSWIDE WIDGET hilight_btn,repa_btn,repb_btn,cancel_btn
 
 /*$$ FUNCTION init
 *
 * Purpose:
 * Initialize the LIST CREATE GRID ATTRIBUTE form panel
 *
 * Input:
 * <none>
 *
 * Output:
 * <none>
 */
 
 FUNCTION init
 
 /*
 * Local Declarations:
 */
 
 REAL x_pos, y_pos 
 
 /*
 * Create the “List A” form
 */
 
 bool_form = ui_form_create( 								@
 	/* callback */ 			““, 				@
 	/* x */			 FORM_X_LOC_SML, 				@
 	/* y */ 			FORM_Y_LOC, 				@
 	/* position */ 			“UL”, 				@
 	/* width */ 			FORM_WID_SML, 				@
 	/* height */ 			FORM_HGT_HALF, 				@
 	/* label */ 			“Boolean List”, 				@
 	/* iconname */ 			““)
 
 /*
 * Create the operation option menu.
 */
 
 y_pos = FORM_T_MARGIN
 
 sframe = ui_selectframe_create 										@
 	/* parent */				( bool_form, 					@
 	/* callback */ 				““, 					@
 	/* x */ 				FORM_L_MARGIN, 					@
 	/* y */ 				y_pos, 					@
 	/* width */ 				SFRAME_WID_SINGLE, 					@
 	/* height */ 				SFRAME_1SDB_HGT_LABOVE, @
 	/* label */ 				““, 					@
 	/* recycle */ 				FALSE )
 
 sdbox = ui_selectdatabox_create 									@
 	/* parent */ 				( sframe, 				@
 	/* callback */				 ““, 				@
 	/* x */ 				FORM_L_MARGIN, 				@
 	/* y */ 				y_pos, 				@
	 /* label len*/ 				0.0, 				@
	 /* width */ 				SDBOX_WID_SINGLE, 				@
	 /* label */ 				““, 				@
	 /* value */ 				““, 				@
 	/*label_above*/ 				FALSE, 				@
 	/*datatype */ 				“ANY”, 				@
 	/* prompt */ 				““ )
 
 ui_wid_set(sdbox,“DISPLAY”,False)
 ui_wid_set(sframe,“DISPLAY”,False)
 
 
 boolean_switch = ui_switch_create 								@
	 /* parent */ 				( bool_form, 			@
 	/* callback */ 				“bool_cb”, 			@
 	/* x */ 				.01, 			@
 	/* y */ 				y_pos,			@
 	/* cols */ 				4, 			@
 	/* label */ 				“Operation:”, 			@
 	/* alwayson */ 				TRUE )
 
 ui_itemicon_create 										@
 	( boolean_switch, 			“and”, 		“and_bool.icon”, 				TRUE )
 ui_itemicon_create 										@
 	( boolean_switch, 			“or”, 		“or_bool.icon”, 				FALSE )
 ui_itemicon_create 										@
 	( boolean_switch, 			“a-b”, 		“minus_bool.icon”,				FALSE )
 ui_itemicon_create 										@
 	( boolean_switch, 			“b-a”, 		“b_minus_a_bool.icon”,				FALSE )
 
 y_pos += 40. * PIXEL_WID + 5. * INTER_WIDGET_SPACE
 
 
 /*
 * Create the list contents text box.
 */
 
 text_box = ui_text_create(	 							@
	 /* parent */ 			bool_form, 				@
 	/* callback */			 ““, 				@
 	/* x */ 			UNFRAMED_L_MARGIN, 				@
 	/* y */			 y_pos, 				@
 	/* width */ 			TBOX_WID_SINGLE,	 			@
	 /* Num. Cols*/ 			6, 				@
 	/* Label */ 			“‘listc‘ contents:”, 				@
 	/* contents */ 			““, 				@
 	/* edit? */ 			FALSE )
 
 y_pos += TBOX_5L_HGT_LABOVE + INTER_WIDGET_SPACE + @
 TBOX_1L_HGT_NO_LABOVE
 
 /*
 * Create the Add To Group... button.
 */
 
 save_btn = ui_button_create( 									@
 	/* parent */ 				bool_form, 				@
 	/* callback */ 				“save_cb”, 				@
 	/* x */ 				BUTTON_HALF_X_LOC1, 				@
 	/* y */ 				y_pos, 				@
 	/* width */ 				BUTTON_WID_FULL, 				@
 	/* height */ 				0., 				@
 	/* label */ 				“Add To Group...”, 				@
	 /* labelinside */ 				TRUE, 				@
 	/* highlight */ 				FALSE )
 
 
 x_pos = 0.0
 y_pos += BUTTON_HGT + INTER_WIDGET_SPACE
 
 repa_btn = ui_button_create( 								@
	 /* parent *	/ 		bool_form, 				@
 	/* callback *	/ 		“repa_cb”, 				@
 	/* x */ 			BUTTON_HALF_X_LOC1, 				@
 	/* y */ 			y_pos, 				@
 	/* width */ 			BUTTON_WID_HALF, 				@
 	/* height */ 			0., 				@
	/* label */ 			“Replace A”, 				@
	/* labelinside */ 			TRUE, 				@
	/* highlight */ 			FALSE )
 
 /*
 * Create the Cancel button.
 */
 
 repb_btn = ui_button_create( 									@
 	/* parent */ 				bool_form, 				@
 	/* callback */ 				“repb_cb”, 				@
 	/* x */ 				BUTTON_HALF_X_LOC2, 				@
 	/* y */ 				y_pos, 				@
 	/* width */ 				BUTTON_WID_HALF, 				@
 	/* height */ 				0., 				@
 	/* label */ 				“Replace B”, 				@
 	/* labelinside */ 				TRUE, 				@
 	/* highlight */ 				FALSE )
 
 
 y_pos += BUTTON_HGT + INTER_WIDGET_SPACE
 
 
 /*
 * Add a separator
 */
 
 ui_separator_create( 							@
 	/* parent */ 			bool_form, 			@
 	/* callback */ 			““, 			@
 	/* x */ 			x_pos, 			@
 	/* y */ 			y_pos, 			@
 	/* length */ 			FORM_WID_SML, 			@
 	/* horizontal */ 			TRUE )
 
 y_pos += LINE_THICKNESS + INTER_WIDGET_SPACE
 
 /*
 * Create the Hilight button.
 */
 
 hilight_btn = ui_button_create( 									@
 	/* parent */ 				bool_form, 				@
 	/* callback */ 				“hilight_cb”, 				@
 	/* x */ 				BUTTON_HALF_X_LOC1, 				@
 	/* y */ 				y_pos, 				@
 	/* width */ 				BUTTON_WID_HALF, 				@
 	/* height */ 				0., 				@
 	/* label */ 				“Highlight”, 				@
	 /* labelinside */ 				TRUE, 				@
 	/* highlight */ 				FALSE )
 
/*
 * Create the Cancel button.
 */
 
 cancel_btn = ui_button_create( 									@
 	/* parent */ 				bool_form, 				@
 	/* callback */ 				“cancel_cb”, 				@
 	/* x */ 				BUTTON_HALF_X_LOC2, 				@
 	/* y */ 				y_pos, 				@
	 /* width */ 				BUTTON_WID_HALF, 				@
 	/* height */ 				0., 				@
 	/* label */ 				“Cancel”, 				@
 	/* labelinside */ 				TRUE, 				@
 	/* highlight */ 				FALSE )
 
 y_pos += BUTTON_HGT + FORM_B_MARGIN
 
 /*
 * Set the form height
 */
 
 ui_wid_set( bool_form, “HEIGHT”, y_pos)
 ui_set_focus(text_box)
 select_focus.exit()
 
 END FUNCTION /* init */
 
/*$$ FUNCTION display
 *
 * Purpose:
 * Display the List Boolean form
 *
 * Input:
 * <None>
 *
 * Output:
 * <None>
 *
 * Log:
 *
 * Notes:
 *
 *
 */
 FUNCTION display
 
 ui_exec_function( “uil_list_a”, “display” )
 ui_exec_function( “uil_list_b”, “display” )
 ui_form_display( “uil_list_boolean” )
 
 ui_register_help(bool_form,“uil_list_boolean”)
 
 END FUNCTION /* display */
 
/*$$ callback FUNCTION bool_cb
 *
 * Purpose:
 * Combines the lists contained in list A and List B by the
 * specified boolean operation.
 *
 * Input:
 * boolean string[] Item selected from icon switch
 * onoff string[] not used.
 *
 * Output:
 * <None>
 *
 *
 */
 FUNCTION bool_cb( boolean, onoff )
 
 GLOBAL STRING listc[VIRTUAL]
 STRING boolean[],onoff[]
 
 IF (onoff == “ON”) THEN
 
> uil_list_boolean.create(boolean)
 
 ui_wid_set( text_box, “VALUE”, listc )
 
END IF
 
 END FUNCTION /* bool_cb */
 
/****************************************************************/
 FUNCTION create(boolean)
 
 GLOBAL String listc[VIRTUAL],lista[VIRTUAL],listb[VIRTUAL]
 STRING boolean[]
 INTEGER status
 
 status = list_create_boolean_list(lista,listb,boolean,listc)
 
 END FUNCTION /* create */
/****************************************************************/
/*$$ FUNCTION save_cb
 *
 * Purpose:
 * Displays the form to save the contents of the list.
 *
 * Input:
 * <None>
 *
 * Output:
 * <None>
 *
 *
 */
 FUNCTION save_cb
 
 
 /*
 * Get the list and display the save list form
 */
 
 uil_list_save.load( “listc” )
 
 END FUNCTION /* save_cb */
/****************************************************************/
 FUNCTION repa_cb
 
 
 /*
 * Replace contents of lista with listc
 */
 
> uil_list_a.replace()
uil_list_a.load()
 
 END FUNCTION /* repa_cb */
/****************************************************************/
 FUNCTION repb_cb
 
 /*
 * Replace contents of listb with listc
 */
 
 
> uil_list_b.replace()
 uil_list_b.load()
 
 END FUNCTION /* repb_cb */
/****************************************************************/
 FUNCTION hilight_cb
 
 GLOBAL String listc[VIRTUAL]
 
gm_hilight_widget(sdbox,0)
ui_wid_set(sdbox,“VALUE”,listc)
gm_hilight_widget(sdbox,-1)
 
 END FUNCTION
/****************************************************************/
/*$$ FUNCTION cancel_cb
 *
 * Purpose:
 * Displays the modal form to evaluate the contents of the list
 * and display it.
 *
 * Input:
 * <None>
 *
 * Output:
 * <None>
 *
 *
 */
 FUNCTION cancel_cb
 
 
 /*
 * reset the widget parameters and exit the form
 */
 ui_wid_restore( “uil_list_boolean” )
 ui_form_hide( “uil_list_boolean” )
 
 
 END FUNCTION /* cancel_cb */
 
END CLASS