PCL and Customization > User Interface and List Processor Functions > Introduction
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX''">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX''">   
Introduction
Nearly all of the forms and widgets that are contained in Patran were created using PCL. Users can customize the Patran interface by adding a menu to the main form and by adding items to that menu. Adding a PCL function called a “callback” which is referenced by the user defined menu can then bring up forms and widgets in any way the user desires.
Customization of the interface occurs through PCL programs. The PCL Class was specifically designed to manage Forms and widgets. Each Class contains a reserved set of PCL Functions called init, display and refresh which are used to define, display and update the form and all the widgets contained in the form, respectively. The Class structure is as follows.
CLASS classname	
 
	CLASSWIDE declarations...
 
	hheader init
		widget definitions
	END FUNCTION
 
	hheader display
		ui_form_display(classname)
	END FUNCTION
 
	hheader refresh
		db_get_item(...)
		ui_wid_get(...)
	ui_wid_set(...)
	END FUNCTION
	functions (see Structure of a PCL Function, 26
END CLASS
The Init Function
The init function contains PCL functions which define the form and the individual widgets. An example of a built-in to create a button widget looks like this:
 /*
 	* Create the “Apply” button
 	*/
 
 apply_button = ui_button_create( 				@
 		/* parent 			*/ 	form_id, 		@
 		/* callback 			*/ 	“apply_cb”, 		@
 		/* x 			*/ 	0.136, 		@
 		/* y 			*/ 	y_loc, 		@
 		/* width 			*/ 	1.0, 		@
 		/* height 			*/ 	0.0, 		@
 		/* label 			*/ 	“Apply”, 		@
 		/* labelinside 			*/ 	TRUE, 		@
 		/* highlight 			*/ 	TRUE 		)
widget Hierarchy
Widgets are created in a hierarchical manner. Every widget has a parent except for a form. In the previous example which is the built-in to create an “Apply” button, the parent widget was a form and its id was “form_id”. “form_id” is a PCL variable that is declared as widget and returned as a value from a widget creation call similar to the way the PCL variable “apply_button” is assigned a value from the call to “ui_button_create” in the previous button example. When creating widgets, the parent widget must be identified, usually as the first argument in the call to the create function. A parents widgets are referred to as its children.
Events
If the user “clicks” on a widget with the mouse button, an event is generated. Events are handled by the event manager which, in general performs the appropriate operation to respond to the user. If the user provides customized forms and widgets, it is necessary to inform the event manager that he is “listening” for events that occur regarding any of the user supplied widgets. The resulting response to a user supplied widget is a PCL function called a Callback which the user must write and identify when he creates a widget.
Callbacks
A Callback is a PCL function. If an event occurs for a user supplied widget which requires an action, a Callback must be specified at the time the widget is created to handle the event. The second argument in the widget creation call is normally a string which contains the function name as the Callback. In the “Button” example, apply_cb is the Callback function for the “Apply” button. The Callback function must exist in the Class in which the widget is created. In our example, the Callback looks like this:
apply_cb()
	/*
	* Add all the elements with shape element_shape into the group	
	* specified in the group_name_box list box
	*/
 
 	STRING group_name[32]
 	STRING element_shape[5]
 
 	ui_wid_get(group_name_box, “VALUE”, group_name)
 	ui_wid_get(el_shape_switch, “VALUE”, element_shape)
 	put_element_in_group(element_shape, group_name)
	ui_wid_refresh()
 
 END FUNCTION /* apply_cb end function */
The “Apply” button for our example takes all the elements of a certain shape as specified in a switch and adds them to a group which was typed into a databox. The widget id for the switch is “el_shape_switch” and the widget id for the databox is “group_name_box”. The function “ui_wid_get” gets information or parameters as specified in the second argument from the identified widget. The form might look something like this:
Locating and Sizing Widgets
When creating a widget, the widget location is always specified relative to its parent. The position is given in inches. The only exception is a form which is positioned relative to the graphics display and can be positioned relative to the upper-left, lower-left, upper-right or lower-corner of the display.
Each widget is sized in inches, usually as a x and y dimension. In some cases, a value of zero can be input so that the size is based on the font size contained in the widget.
Tailoring Widgets
Each widget has a number of resources or parameters which can be set or changed to modify the look and response of the widget. The functions ui_wid_set and ui_wid_get allow changing the widget resources. A typical call looks like:
ui_wid_set(apply_button, “ENABLE”, FALSE)
This results in the button whose id is apply_button to be ghosted as in the following example.
The Display Function
Once the widget are defined in the init function in the Class, the display function is used to make them visible. An example of a display function is:
FUNCTION DISPLAY()
 
	ui_form_display(“group_elements”)
 
END FUNCTION
The function ui_form_display has one argument which is a Class name. Any form defined in the init function for the given class is displayed along with all of its children widgets. Individual widgets on the form may be set to invisible by calling ui_wid_set(widget_id, “DISPLAY”, FALSE).
Displaying a Form, “ui_exec_function (class_name, “display”)”
To actually make the form appear it is necessary to invoke a special function called ui_exec_function. This function is specifically designed to execute a PCL function defined in the named Class so that, if the init function hasn’t been previously called, it will be prior to executing the named function in the Class, otherwise, it just executes the named function. It is important that the init function is called only once during a Patran session since this is the function which defines all of the widget attributes and saves it in memory. If the init function were to be called more than once during a session, the data would be duplicated in memory and the program would produce unexpected results.
During the development of a PCL program where forms and widgets are being created, it might be convenient to remove the definition of the widgets from memory. This can be accomplished by a call to ui_form_delete(class_name). Any form defined in the given Class is deleted from memory as well as all of its children widgets. After modifying the PCL Class and re-compiling use ui_exec_function to re-display the form with the revised widgets (which in turn invokes the init function).
When putting the code into “production”, ui_form_delete should be replaced with ui_form_hide(class_name) to un-display the form but not delete its resources and widget definitions.
Refreshing a form
Once a form is defined and displayed, it may display information which can change while it is being displayed. An example might be the contents of a group on the group modify form. If the user were to delete one of the entities contained in the group while the form was displayed, the form would become out-of-date if some mechanism wasn’t provided to “refresh” the form. In Patran, the function ui_wid_refresh() performs that function. When ui_wid_refresh() is called (no arguments), the User Interface Management system is invoked to determine the Class name of all forms currently displayed. For every Class whose form is displayed, the refresh function is called in that Class to update the form. An example of a refresh function is:
 /*$$ callback FUNCTION refresh( )
 *
 * Purpose:
 * Get the current analysis code
 *
 * Input:
 * <none>
 *
 * Output:
 * <none>
 *
 */
 FUNCTION refresh( )
 
 INTEGER db_status
 STRING current_analysis_code[32]
 
 	db_status = db_get_default_anal_code( current_analysis_code )
 
	IF( db_status != 0 ) RETURN
 
 	ui_wid_set( analysis_code, “LABEL”, current_analysis_code )
 
 END FUNCTION /* refresh */
In the above example, a label is displayed which shows the current analysis code, the call db_get_default_anal_code(current_analysis_code) returns the current analysis code in a string. the call to ui_wid_set for the label whose id is analysis_code changes the label to indicate the new analysis code.