Write a PCL function to create a group of elements based on element shape.
-
The function should have 2 arguments; the name of the group to be created and the element shape code, i.e.,
FUNCTION GroupElmsByShape(GroupName, ElmShapeId)
-
Use the following built-in functions:
ga_group_create(GroupName)
db_count_elems(NumElms)
db_get_elem_ids(NumElms, ElmIds)
db_get_elem_etop(NumElms, ElmIds, ElmTops)
db_get_elem_topology_data(NumElms, ElmTops, ElmShapes, NodesPerElm)
ga_group_entity_add(GroupName, ElmString)
-
Sample code outline:
-
Declare variables
-
Count the elements in the database
-
Get the element Ids
-
Get the element topology codes
-
Use the element topology codes to get the element shape codes
-
Create the group
-
LOOP: If an element’s shape code matches the selected shape code then add it to the group
Extra Credit: For each element of the correct shape, automatically include its associated nodes in the group as well.
Extra Credit: Modify the function to create a group for each of several selected element shapes.
Extra Credit: Write a PCL function to create groups based on element topology (i.e., quad4, tria3, hex8, hex20, etc.) instead of element shape.
Graphical User Interface -
Nearly all forms and widgets that are contained in MSC.Patran were created in PCL
-
PCL can be used to customize the MSC.Patran interface by adding menus to the top menu bar.
-
Each menu item will reference a PCL function that is referred to as a “callback” function. Typically, this “callback” function will perform an operation (such as, delete groups, etc.) or open a form.
Graphical User Interface
The PCL Class Statement -
The Class is a way of grouping functions for a common task. Classes in PCL are similar (but not equivalent) to Classes in C.
-
Classes allow variables to be visible or “Global” among a limited set of functions.
CLASSWIDE REAL global_tol
-
At least one class is required for each form.
-
Only one class should be defined per file and the file name should match the class name.
-
Generally, only functions related to managing forms and form data are defined within a class.
-
A class structure consists of a CLASS class_name statement near the beginning of the file and a END CLASS statement at the end of the file.
CLASS I_have_class
CLASSWIDE WIDGET main_form
FUNCTION init()
END FUNCTION /* init /
.
.
FUNCTION display()
END FUNCTION /* display */
.
.
END CLASS /* end of I_have_class */
Graphical User Interface
PCL Widgets
Graphical User Interface
Required Functions for Building/Displaying a Form
Every form is defined within a class and has at least two, but usually more specific functions; init(), display(). Sometimes the refresh() function is also required.
The init() Function -
The init() function is user defined, but must be called init().
-
It is the first function defined in the class and is the function that defines the form and all of its widgets.
-
It is also used to initialize any classwide variables that need initializing the first time the form is opened.
-
The built-in functions for defining widgets will only be called in this function. Below are examples to build a form and place a button:
main_form = ui_form_create(“”, @
/* x position */ FORM_X_LOC, @
/* y position */ FORM_Y_LOC, @
/* relative to */ “UL”, @
/* width */ FORM_WID_SML, @
/* height */ FORM_HGT_QTR, @
/* label */ “My_Form_Label”, @
/* unused */ “”)
my_button = ui_button_create( @
/* parent */ main_form, @
/* callback */ “my_button_cb”, @
/* x position */ FORM_L_MARGIN, @
/* y position */ y_loc, @
/* width */ BUTTON_WID_FULL, @
/* height */ BUTTON_HGT, @
/* label */ “My Button…”, @
/* unused */ “”, @
/* highlight */ FALSE)
Graphical User Interface
The display() Function -
The display() function is simple, but required. A complete function may only contain the following:
FUNCTION display()
ui_form_display(“my_class”)
END FUNCTION
-
The only required element is the built-in function ui_form_display(classname). Classname is the name of the class that these functions are members of.
-
Once the display() function is called it will display the form and all widgets that are currently visible.
-
The display() function may also contain function calls to get data from the database or from external files to initialize the form with proper data.
sys_get_user(user_name)
ui_wid_set(databox_user_name, ”VALUE”, user_name)
-
It is also used to hide and display widgets that are not always visible:
IF (flag_advanced == TRUE) THEN
ui_wid_set(frame_advanced, ”DISPLAY”, TRUE)
END IF
Graphical User Interface
The refresh() Function
-
This optional function is used to keep forms up-to-date. Any time a function changes the contents of the database, it should make a call to ui_wid_refresh(). This causes the refresh() function, if it exists, to be called in every displayed form/class. An example function is given below:
FUNCTION refresh()
INTEGER db_status
STRING current_analysis_code[32]
db_status_ = db_get_default_anal_code(current_analysis_code)
IF (db_status != 0) THEN RETURN
ui_wid_set(analysis_code,”LABEL”,current_analysis_code)
END FUNCTION
-
It is the responsibility of the author of each form to write a refresh() function to update the form if the contents of the form are based on information in the database.
-
The refresh() function is also typically called by the display() function to initialize the form properly.
Graphical User Interface
Widget Heirarchy
-
Widgets are created in a hierarchical manner. Every widget has a parent except the form.
main_form = ui_form_create( @
/* callback */ "", @
/* x position */ FORM_X_LOC, @
/* y position */ FORM_Y_LOC, @
/* relative to */ "UL", @
/* width */ FORM_WID_SML, @
/* height */ FORM_HGT_QTR, @
/* label */ "Form Label", @
/* unused */ "")
my_button = ui_button_create( @
/* parent */ main_form, @
/* callback */ "my_button_cb", @
/* x position */ FORM_L_MARGIN, @
/* y position */ y_location,…… )
-
All widgets could be children of the form, but widgets can also be children of other widgets.
my_frame = ui_frame_create( @
/* parent */ main_form, @
/* callback */ “”, @
/* x position */ x_loc, @
/* y position */ y_loc, @
/* width */ FORM_WID_SML,… )
inner_button = ui_button_create( @
/* parent */ my_frame, @
/* callback */ "inner_button_cb", @
/* x position */ FRAME_L_MARGIN, @
/* y position */ y_loc, @
/* width */ BUTTON_WID_FULL, @
/* height */ BUTTON_HGT,… )
-
If a widget is hidden or disabled, all of its child widgets do the same.
-
All widgets are placed relative to their parents.
Graphical User Interface
Widget Callbacks What Are They? -
A callback is a PCL function that is called when an "event" happens in a particular widget.
-
An “event” is an action performed on a widget. The action is typically via user interaction such as a mouse click. However, it could also be from another PCL function.
-
Every widget has a unique set of event possibilities, or none at all. For example, a button can just be pushed, but databoxes can gain focus, lose focus, or its contents can be changed. Labels and frames are examples of widgets that have no events that will register a callback.
-
The callback function is named when the widget is defined in the init() function.
my_button = ui_button_create( @
/* parent */ my_frame, @
/* callback */ "my_button_cb", @
/* x position */ FRAME_L_MARGIN, @
/* y position */ y_loc, @
/* width */ BUTTON_WID_FULL, @
/* height */ BUTTON_HGT,… )
-
The callback function must be defined within the same class as the init() function.
Graphical User Interface
What Are They Used For? -
Callbacks can be used to do anything including dance a jig, sing a tune, or perhaps display another form as the function below does.
FUNCTION my_button_cb()
ui_exec_function("another_form", “display”)
END FUNCTION
-
Callbacks are NOT required and most of the time they are not used. When no immediate action is required, put an empty string (“”) for the callback name.
-
Callbacks are usually used to make changes to the form or bring up another form based on user interaction.
Callback Arguments (Widget Function Data) -
When a callback is made, information may be passed to the callback function. Each widget type has a unique set of callback information that is passed.
Graphical User Interface
| |
Description of Callback data
| | | | | | | | | | | |
Widget Id of the colorbar
User data
Selected color Id
| | |
Widget Id of the colorbar
User data
Selected color Id
| | |
“GAIN”, “LOSE”, “CR”, or “WIDSET” (if appropriate ui_wid_set() call has been made) depending on which event initiated the callback
| | |
Complete pathname of the selected file
“OPEN” or “CANCEL”
| | | | | | | | | | | | | | | | | | | | | | | |
Number of selected items
Label of the selected items in the listbox
| | | | | | | | | | | |
Name of the currently selected item
| | | | | |
“GAIN”, “LOSE”, “CR”, or “WIDSET” (if appropriate ui_wid_set() call has been made) depending on which event initiated the callback
| | | | | | | | | | |
String[]
Integer
Integer
Integer
Integer
|
“SELECTED”
starting selected column
starting selected row
ending selected column
ending selected row
selected layer
| | |
Name of the switch item changed
“ON” or “OFF”
| | | | | |
Value of the toggle, TRUE or FALSE
| | |
Value of the toggleicon, TRUE or FALSE
|
Graphical User Interface
Widget Placement -
Widgets are placed on the form using predefined constants defined in the appforms.p file (see Appendix D). This file is found in the …patranXX/customization directory.
-
T
FORM LABEL
Frame Label
FORM_R_MARGIN
FORM_L_MARGIN
FRAME_LABEL_HGT
FORM_T_MARGIN
FRAME_1EDGE
FRAME_B_MARGIN
FORM_B_MARGIN
FRAME_T_MARGIN
OPT_MENU_HGT…
INTER_WIDGET_SPACE
OPT_MENU_HGT…
FRAME_1EDGE
INTER_WIDGET_SPACE
DBOX_HGT_LABOVE
INTER_WIDGET_SPACE
BUTTON_HGT
he predefined constants are used to maintain a consistent spacing between different hardware platforms and between different MSC.Patran applications.
Graphical User Interface
-
These constants should be used in conjunction with a position or placement variable to keep track of your location on the form. For example a portion of the code to create the form on the preceding would look like:
dbox_id = ui_databox_create( @
/* parent */ my_frame, @
/* callback */ "", @
/* x position */ FORM_L_MARGIN, @
/* y position */ y_loc,…)
y_loc += DBOX_HGT_LABOVE + INTER_WIDGET_SPACE
apply_btn = ui_button_create( @
/* parent */ my_frame, @
/* callback */ "apply_btn_cb", @
/* x position */ FRAME_L_MARGIN, @
/* y position */ y_loc, @
/* width */ BUTTON_WID_HALF, @
/* height */ 0,… )
-
This strategy allows widgets to be added and removed in the middle of the form without causing any placement problems. Each widget is simply placed relative to the widget above it by always referencing the y_loc variable.
Graphical User Interface
Widget Variables -
Widget variables are typically defined as either classwide or in the init() function and are used to store the widget Id, i.e., an internal pointer to the widget.
CLASS my_class
CLASSWIDE WIDGET my_frame
FUNCTION init()
.
.
my_frame = ui_frame_create( @
/* parent */ main_form, @
/* callback */ “”, @
/* x position */ x_loc, @
/* y position */ y_loc, @
/* width */ "FORM_WID_SML,… )
END FUNCTION /* init */
-
Widget variables are only needed if the widget will be referenced. There are 3 situations when a widget might be referenced, i.e.,
-
if it will be modified
-
if data will be retrieved from it
-
if it will be a parent to another widget.
-
Buttons, labels, and item widgets are examples of widgets that often do not need to be referenced for any reason and hence do not require a widget variable
ui_button_create( @
/* parent */ my_frame, @
/* callback */ "apply_cb", @
/* x position */ FRAME_L_MARGIN, @
/* y position */ y_loc, @
/* width */ BUTTON_WID_FULL, @
/* height */ BUTTON_HGT,… )
Note: It is a good practice to always use widget variables even if the widget is not referenced. It is also good practice to always declare widget variables as classwide.
Graphical User Interface
Modifying Widgets -
Most of the attributes describing a widget can be modified after it has been created in the init() function, including whether they are visible or not.
-
Modifications are made with the ui_wid_set() function. Common modifications are described below:
-
DISPLAY – displays or hides a widget.
ui_wid_set(group_lst_frame, ”DISPLAY”, FALSE)
-
ENABLE – enables or disables the widgets use (“ghosting”).
ui_wid_set(button_post_curve, ”ENABLE”, FALSE)
-
LABEL – modifies a particular attribute of a widget such as a label above a databox.
ui_wid_set(button_post_curve, ”LABEL”, ”Unpost Current Curve”)
-
VALUE – modifies the current value of a widget such as the contents of a databox, current menu item, or slidebar value.
ui_wid_set(slider_line_thk, ”VALUE”, new_thickness)
-
X or Y – modifies the position of a widget on the form.
ui_wid_set(button_apply, ”Y”, new_bottom_location)
Graphical User Interface
Getting Data from Widgets -
Most data is retrieved from widgets using the ui_wid_get() function. The example below gets the current setting or value from a slidebar widget.
FUNCTION apply_btn_cb()
REAL shrink_value
ui_wid_get(slidbar_element_shrink, ”VALUE”, shrink_value)
ga_display_shrfem_set(“general”, shrink_value)
END FUNCTION
In this example the value represents an element shrink factor. As soon as the data is gathered, the graphical display is updated using the ga_display_shrfem_set(…) function.
-
Usually widget data is retrieved after the user hits the Apply button on the form. The Apply button references a callback function, typically called apply_cb(), that contains the ui_wid_get() function calls. Once the data is gathered, action can be taken to reflect the user input, such as, updating the element display to reflect the new shrink factor.
-
If it is desired to update the element shrink factor immediately as the slidebar is being moved, then the data would need to be retrieved from the widget’s callback function. This is only required if an immediate action needs to be performed based on an event. For this case, the slidebar callback function would look like this:
FUNCTION slider_cb(slider_value, change_type)
REAL slider_value
STRING change_type[]
ga_display_shrfem_set(“general”, shrink_value)
END FUNCTION
Graphical User Interface
Putting it all Together (Example)
#include “appforms.p”
CLASS first_class
C
LASSWIDE WIDGET main_form
CLASSWIDE WIDGET my_dbox
CLASSWIDE WIDGET apply_btn, cancel_btn
FUNCTION init()
REAL y_loc
main_form = ui_form_create( @
/* callback */ "", @
/* x position */ FORM_X_LOC, @
/* y position */ FORM_Y_LOC, @
/* relative to */ "UL", @
/* width */ FORM_WID_SML, @
/* height */ 0, @
/* label */ "Form Label", @
/* unused */ "")
y_loc = FORM_T_MARGIN
my_dbox = ui_databox_create( @
/* parent */ main_form, @
/* callback */ "", @
/* x position */ FORM_L_MARGIN, @
/* y position */ y_loc, @
/* label length */ 0, @
/* box length */ DBOX_WID_SINGLE, @
/* label */ "Enter a Value", @
/* value */ "", @
/* label above */ TRUE, @
/* datatype */ "REAL", @
/* number of values */ 1)
y_loc += DBOX_HGT_LABOVE + INTER_WIDGET_SPACE
apply_btn = ui_button_create( @
/* parent */ main_form, @
/* callback */ "apply_btn_cb", @
/* x position */ BUTTON_THIRD_X_LOC1, @
/* y position */ y_loc, @
/* width */ BUTTON_WID_THIRD, @
/* height */ 0, @
/* label */ "Apply", @
/* unused */ TRUE, @
/* highlight */ TRUE)
Graphical User Interface
cancel_btn = ui_button_create( @
/* parent */ main_form, @
/* callback */ "cancel_btn_cb", @
/* x position */ BUTTON_THIRD_X_LOC3, @
/* y position */ y_loc, @
/* width */ BUTTON_WID_THIRD, @
/* height */ 0, @
/* label */ "Cancel", @
/* unused */ TRUE, @
/* highlight */ FALSE)
y_loc += BUTTON_DEF_HGT + FORM_B_MARGIN
ui_wid_set(main_form,"HEIGHT",y_loc)
END FUNCTION /* init */
FUNCTION display()
ui_form_display("first_class")
END FUNCTION /* display */
FUNCTION refresh()
/* For this example this function is not necessary
but is included for completeness */
END FUNCTION /* refresh */
FUNCTION apply_btn_cb()
REAL dbox_value, answer
ui_wid_get(my_dbox, "VALUE", dbox_value)
> crunch_numbers(dbox_value, answer)
ui_write("The answer is: "//str_from_real(answer))
END FUNCTION /* apply_btn_cb */
FUNCTION cancel_btn_cb()
ui_form_hide("first_class")
END FUNCTION /* cancel_btn_cb */
END CLASS /* first_class */
Share with your friends: |