User-Defined Widgets |
14 |
![]() |
WorkShop Visual comes with a utility, visu_config, which helps you provide the information WorkShop Visual needs to support user-defined widgets. You specify which widgets you want to use and provide information about any nonstandard resource types defined by the widgets. visu_config generates two C files that serve as a bridge between WorkShop Visual and the user-defined widgets.
After generating the visu_config files, you build a new version of WorkShop Visual from the following components:
To help you get started, WorkShop Visual is distributed with an example configuration file for the Athena widgets, Athena.xdc. There are also pre-built configuration files for various commercial widgets. Look in the WorkShop Visual release directory for the latest set of supported widget integrations.
14.2 Requirements
User-defined widgets must build and run against the X11 Release 5 X Toolkit Intrinsics. For each widget class you need the public header file and the object file that implements the widget class. Both of these are provided by your widget supplier. The object file may be in an archive library. You may also need the private header file for the widget class.
14.2.1 UIL Restriction
UIL code compiles correctly only for designs restricted to the default set of Motif widgets. C or C++ generated code must be used for designs containing user-defined widgets. 14.2.2 Caveats
Since WorkShop Visual's dynamic display works by creating actual instances of the widget, any widget you build into WorkShop Visual becomes part of the tool. If the widget doesn't function as expected, WorkShop Visual may fail when the user adds the widget to a design. Any memory leaks in the widget can affect WorkShop Visual and may cause a gradual degradation of performance or a core dump. Even widely-used widgets from standard vendors can have problems. You should therefore test widgets thoroughly before adding them to WorkShop Visual.
14.3 Prerequisites
To configure WorkShop Visual, you need some knowledge of C and an understanding of common UNIX development tools such as make. You don't have to be an expert on X but you need some knowledge of X and the X Toolkit Intrinsics. visu_config requires you to supply information about the widget, such as the widget class pointer and symbolic constants representing resource types. For suggestions on how to get the required information from the widget documentation or source code, see the Getting Widget Information section on page 476.
14.4 How WorkShop Visual Works
Before you start configuring a widget, it is helpful to understand how WorkShop Visual uses widgets in the dynamic display. This section describes some aspects of how WorkShop Visual works internally. 14.4.1 Creating Widgets
WorkShop Visual builds its dynamic display with real widgets, not simulations. It creates widgets by passing the widget class pointer to XtCreateWidget(). The widget class pointer also gives access to information about the widget's resources and their types so that WorkShop Visual can build a resource panel for the widget.
Note - Neither of these problems occur in the generated code. WorkShop Visual generates code that creates the hierarchy from the bottom up and sets all resources at creation time.
14.4.2 Highlighting Selected Widget
When the user selects a widget in the tree, WorkShop Visual highlights that widget's icon in the tree. It also highlights the widget itself in the dynamic display by swapping the widget's foreground and background colors. Highlighting the widget may cause problems if the widget has a create-only foreground resource. In this case, you can disable foreground swapping on the Widget Edit Dialog, as described in the Widget Attributes section on page 483.
14.4.3 Preventing Invalid Hierarchies
WorkShop Visual prevents invalid hierarchies by disabling all palette icons for widgets that are not valid children for the selected widget. Also, when a new widget is added to the hierarchy, WorkShop Visual doesn't automatically select it if it can't have children.
14.4.4 Building the Resource Panel
WorkShop Visual builds a resource panel for the widget based on resource names and resource types in the widget class record. Resources inherited from a known superclass, such as the Core widget or a Motif parent class, are left off the resource panel and can be set on the resource panel for the superclass.
When the resource panel is displayed, WorkShop Visual uses XtGetValues() to get the current values of all resources for the widget. All resources except enumerations are converted to text strings and displayed in text fields on the resource panel. The user can set the resource by editing a text string. In some cases, such as fonts, colors and callbacks, the user can supply text indirectly through a popup dialog. For resources that don't already have a popup dialog in WorkShop Visual, you can supply a popup; see the Popups section on page 500.
14.4.5 Setting Resources
When the user applies a new resource value, WorkShop Visual converts the text string to a value and applies it to the widget with XtSetValues(). It then immediately calls XtGetValues() to retrieve all resource values for the widget, converts the values back to text and displays them in the resource panel. This procedure shows immediately whether the toolkit accepted the new value and whether the new value caused other resources to change.
For enumeration resources, WorkShop Visual builds an option menu which, by default, is placed on the "Settings" page of the resource panel. WorkShop Visual can handle Boolean enumeration resources for user-defined widgets. For other enumerations, you must provide a list of valid values in visu_config so that WorkShop Visual can build an option menu. For details, see the Enumerations section on page 492.
14.4.6 Saving Designs and Code Generation
Saving designs and parsing save files is straightforward. For resource settings, WorkShop Visual writes the resource name and the text representation of its value to the .xd file. The resource name and value are saved as they appear on the resource panel.
For enumerations, WorkShop Visual also uses two versions of each possible value: a resource file symbol such as center and a code symbol such as XtJustifyCenter. When you configure an enumeration, you must provide both versions of each value.
14.5 Getting Widget Information
To configure your widget, you may have to supply one or more variable names and symbolic constants from the widget code. This section summarizes the information you may have to provide. Most of the information you need should be available in the documentation for the widget. If not, you can get it from the widget's public and private header file, from the widget source code (if available), or from your widget supplier's technical support service. 14.5.1 The Widget Class Pointer
When you add a widget class in visu_config, you need to supply the widget class pointer. The widget class pointer is the name of a pointer variable of type WidgetClass. This pointer gives access to a structure containing information about the widget class, including a list of resources and their types. WorkShop Visual uses this information to build a resource panel for the widget class. By convention, widget class pointers have names of the form <classname>WidgetClass.externalref WidgetClass fredWidgetClass
or
extern WidgetClass fredWidgetClass
In either case, the widget class pointer is fredWidgetClass. 14.5.2 Resource Information
The resource name is a character string used to identify the resource in generated X resource files and on the resource panel. WorkShop Visual gets this name directly from the widget class record and so you don't need to supply it. This string is usually a straightforward name without a prefix, such as label.#define XtNtop "top"
#define XtNbottom "bottom"
14.5.3 Non-Standard Resource Types
To configure resources of non-standard types, you need to know the resource type. This is not a type such as unsigned char but a symbolic constant defined as a string by which the widget class knows the resource type. By convention, resource types have the form <Prefix>R<Type>. For non-standard resource types, especially enumerations, <Type> may be the same as the resource name.#define XtRFoo "foo"
In this example, you would enter XtRFoo whenever visu_config asks for a resource type. The resource type can also be found in the source code for the widget. The following structure defines a resource whose resource type is XtRFoo. Note that you can also get the resource's defined name, XtNfoo, from this structure.{
XtNfoo, XtCFoo, XtRFoo,
sizeof(foo), XtOffset( FooWidget, foo),
XtRImmediate, (XtPointer) NULL,
}
14.5.4 Non-Standard Enumerations
If your widget has non-standard enumeration resources, you need to specify a list of possible values. In some cases you may have to read the source code to get the names you need. For instructions, see the Enumerations section on page 492.
14.6 visu_config - the Main Dialog
Run visu_config:visu_config
The main dialog shown in Figure 14-1 is displayed.
Figure 14-1 The Main visu_config Dialog
14.6.1 Menu Commands
The visu_config File Menu has options to save and read files containing your configuration data. By convention, these files have the suffix .xdc. Use "Open" to open an existing widget specification file; "Read" to merge another file with the one you are currently editing; "Save" and "Save As..." to save your file and "New" to clear the editing area.
The Generate Menu contains options to generate the two code files needed to build WorkShop Visual with the added widgets. For information on generating code from visu_config and building WorkShop Visual, see the Generating and Compiling Code section on page 513.
14.6.2 Families
The main dialog displays a list of families. Families are groups of widgets that are displayed together in the widget palette. The list is empty when you start the program. Figure 14-1 shows the dialog after loading the Athena.xdc file supplied with WorkShop Visual. We recommend that you open this file and inspect it as you read.
You can organize user-defined widgets into families in any way. Grouping widgets into families has two purposes. First, it keeps the WorkShop Visual widget palette to a reasonable size. At any given time, WorkShop Visual displays the icons for the default Motif widgets plus one user-defined widget family. An option menu lets the user switch from one family to another as with the pages of a resource panel. Second, grouping widgets into families also makes it easy to generate versions of WorkShop Visual with different sets of families. At code generation time, you can select any group of families from your list. This lets you customize WorkShop Visual to support users with different needs and skill levels.
14.6.3 Editing the Family List
To add a new family to the list, type a name for the family in the "Selection" field, then click on "Add". The family can have any name you choose. It is used to identify the family in visu_config and in the option menu in the WorkShop Visual widget palette. 14.6.4 Suggestions for Organizing Families
You can include the same widget class in more than one family. For example, in Athena.xdc, the family named "Athena" contains all the Athena widgets and each of the two smaller families, "Composites" and "Primitives", contains a subset of the Athena group. When you generate code from visu_config, you can decide how you want the widget palette to appear. You can either use the large family to display all the Athena widgets on the palette at the same time, or use either of the two smaller families to display a subset of the Athena widgets. 14.6.5 Adding and Editing Widgets In a Family
To add or configure widgets in any family, select the family and then click on "Edit" to display the Family Edit dialog. The Family Edit Dialog lets you:
For details about the Family Edit dialog, see the following sections.
Figure 14-2 The "Widgets" Page of the Family Edit Dialog
14.7.1 Adding a Widget Class
To add a new widget class to the family, enter the widget class pointer in the "Selection" field and click on "Add". To complete the process, specify attributes for the class as described in the Widget Attributes section below. 14.7.2 Editing the Widget Class List
To delete a widget class from the family, select it in the list and click on "Delete". To reorder the list, select an item and use the arrow buttons to move it up or down. The order of the widget class list determines the order of widgets in the palette.
14.8 Widget Attributes
To specify attributes of a widget class, select the widget class in the Family Edit Dialog and click on "Edit". This displays the Widget Edit Dialog, shown in Figure 14-3. The title bar displays the name of the widget class you are editing.
This section discusses the attributes set on the left side of the Widget Edit dialog. The right side is used to assign resources to existing or new pages, to specify custom popup dialogs for widget resources, and to override the default resource memory management. For details, see the Resources section on page 488.
14.8.1 Applying Changes
When you finish entering widget attributes, click on "Apply" to set the new values. "Undo" reverts to the last applied changes.
Figure 14-3 The Widget Edit Dialog with Attributes for Athena Form
14.8.2 Include File
In the "Include file" field specify the name of the public header file for the widget class. Enter the file name (usually relative to /usr/include) without quotes or angle brackets. This file is included in two places: in the code file generated by visu_config and in application code generated by WorkShop Visual. 14.8.3 Icons
An icon is an X pixmap or bitmap that represents a user-defined widget in the WorkShop Visual widget palette and design hierarchy. For each widget, you can specify both a pixmap and a bitmap. Icon pixmaps are stored in separate files and specified via an entry in the WorkShop Visual resource file. $VISUROOT/lib/palettes/icons.xpm
where VISUROOT is the install directory of your WorkShop Visual. See the Pixmap Editor Palette Menu section on page 167 for more information on reading palettes into the Pixmap editor.
14.8.4 Pixmap Resource
Use the "Pixmap resource" field to specify a name for the pixmap resource. After building WorkShop Visual, you can set this resource to specify the pixmap file.visu.myWidgetPixmap: /usr/local/newwidget.xpm
This specifies /usr/local/newwidget.xpm as the location of the XPM file. You can use either an absolute or a relative pathname. For details on how to use the pixmap resource, see the Palette Icons section on page 617.
14.8.5 Bitmap
To specify a built-in icon bitmap, you must provide two items of information: the name of the bitmap and the name of the corresponding bitmap file. To specify an icon for the large-screen (workstation) version of WorkShop Visual, use the "Large icon" and "Large icon file" fields. For the small-screen (VGA) version, use the "Small icon" and "Small icon file" fields. You can provide an icon for either version of WorkShop Visual, both, or neither.#define <bitmap_name>_width 32
Enter the icon file name in the "Large icon file" or "Small icon file" field without quotes or angle brackets. Because this file is included when you build WorkShop Visual, your WorkShop Visual makefile must reference (-I) the directory where it is stored. This file does not have to be available to end users. 14.8.6 Help
These attributes let you specify on-line help that is displayed when the user invokes help for the widget on the palette or from the widget's resource panel. For each help item, you specify a document (without any suffix) and a tag if the help for this widget is contained within a larger document. The WorkShop Visual help system searches the path list specifed by the visu.helpDir resource to locate the appropriate file. The file name must have a ".html" suffix. The tag refers to an HTML hypertext anchor within the document. 14.8.7 Configuration Functions
There are four fields for specifying configuration functions: a Defined Name function, a Can Add Child function, an Appropriate Parent function and a Realize function. These functions can be used to fine-tune the way WorkShop Visual handles the widget in the dynamic display. If your widget uses a configuration function, type the name of the function in the corresponding text field.
For full definitions, synopses and examples of configuration functions, see the Configuration Functions section on page 518. Note that many widgets do not require configuration functions.
14.8.8 Disable Foreground Swapping
Normally, WorkShop Visual highlights the currently selected widget in the dynamic display. To disable highlighting for this widget class, turn on the "Disable Foreground Swapping" toggle. Do this only if the widget class has a foreground resource that cannot be set after widget creation time. This is required because WorkShop Visual's highlighting procedure can cause problems with such widgets. In all other cases, leave the toggle off. 14.8.9 Can Create Widgets
When the "Can Create Widgets" toggle is on, users can build the widget directly into hierarchies. Leave this toggle on if you want the widget's icon to appear in the palette.
14.9 Resources
By default, when WorkShop Visual creates the resource dialog for a widget, it gets the name and type of the resource directly from the widget code and builds a resource panel. It assigns each resource to a page of the resource panel (based on the resource type) and assigns a popup dialog for certain types. For example, resources of type XtRPixel are put on the Display page of the resource panel, with a button to pop up the WorkShop Visual color editor. 14.9.1 Default Handling of Standard Resource Types
Resources of standard types are assigned to pages of the resource panel as shown in the following table:
14.9.2 Changing Widget Attributes
The right side of the Widget Edit dialog lets you do the following things for individual widget resources:
To remove the resource from the resource panel, turn off the "Visible" toggle.
To specify a different page of the resource panel, click on the "Page" button to display the current list of pages. The list is preset with the default WorkShop Visual pages. To add a page, type the name of the new page in the "Page name" field and then click on "Update". To assign the current resource to a page, select the page in the list and then click on "Apply".
visu_config automatically invokes the WorkShop Visual predefined popups for some types of resources, as shown in the following table. You don't have to specify a popup explicitly to use these popups for resources of these types:
You can specify a popup dialog for any resource. You can select one of the predefined popups or create your own. For more information, see the Popups section on page 500.
14.9.3 Nonstandard Resource Types
By default, resources of types not in the table of WorkShop Visual standard resource types are placed on the "Miscellaneous" page of the resource panel. The user can set them by typing strings into text fields. The strings are generated into the code exactly as the user types them and resource settings take effect when the generated code is compiled.
Figure 14-4 The "Aliases" Page of the Family Edit Dialog
14.11 Enumerations
Enumeration resources are resources with a fixed set of possible values. You can determine if a widget has enumeration resources by inspecting the documentation. If the documentation lists all possible values for a resource, it is an enumeration. Note that enumerations of type XtRBoolean are handled automatically and don't require the configuration procedure described in this section. 14.11.1 Configuring an Enumeration
Select "Enumerations" from the View Menu in the Family Edit Dialog to display the "Enumerations" page. Figure 14-5 shows the list of enumerations for the Athena Primitives family.
Figure 14-5 The "Enumerations" Page of the Family Edit Dialog
14.11.2 Configuring Enumeration Values
To complete the process, you need to provide the following information about the enumeration resource:
Figure 14-6 The Enumerations Entry Dialog
14.11.3 Specifying the Type
Enter the resource type in the "Type" field. 14.11.4 Specifying Values
To get a list of values for an enumeration, look in the widget documentation or the public header file. Make an entry in the "Entries" list for each possible value vis the "Enumerations" page. Entries in the list are only used in the option menu on the resource panel and can be any names you want. WorkShop Visual uses names that are meaningful to the user, such as Horizontal rather than XmHORIZONTAL. 14.11.5 Configuring Values
For each value, you must specify the code symbol and the resource file symbol in the Enumerations Entry dialog. The code symbol is a symbolic constant that denotes the value in generated code. The resource file symbol is a string that denotes the value in resource files.
14.11.6 Specifying the Default Value
The first entry in the list of values on the "Enumerations" page is reserved for the default value. This entry is used to indicate a resource that is not set explicitly. The option menu should also contain an entry for the same value set explicitly. By convention, the default value is distinguished by putting its name in parentheses, as shown in the following list:(Center)
Center
Left
Right
Specify the same code and resource symbols as for the corresponding explicit value. 14.11.7 Specifying Order of Entries
The order of entries in the list on the "Enumerations" page controls the order in which they appear in the option menu on the resource panel. Entries can be listed in any order as long as the default value is listed first. To move an entry to a different position, select it in the list and use the arrow buttons to move it up or down. 14.11.8 Getting the Resource File Symbol
This section explains how to get the resource file symbol you need to enter on the Enumerations Entry Dialog from the resource converter code for the widget. The resource converter is a function used to convert a string read from the resource file to the corresponding value. A simple converter may contain fragments like this:if (StringsAreEqual (in_str, "vertical"))
i = XmVERTICAL;
else if (StringsAreEqual (in_str, "horizontal"))
i = XmHORIZONTAL;
In this example, the string "horizontal" is converted to the value XmHORIZONTAL and "vertical" is converted to XmVERTICAL. horizontal and vertical are the resource file symbols; XmHORIZONTAL and XmVERTICAL are the code symbols.if (!haveQuarks) {
XtQEhorizontal = XrmStringToQuark(XtEhorizontal);
XtQEvertical = XrmStringToQuark(XtEvertical);
haveQuarks = 1;
}
XmuCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr);
q = XrmStringToQuark(lowerName);
if (q == XtQEhorizontal) {
orient = XtorientHorizontal;
done(&orient, XtOrientation);
return;
}
if (q == XtQEvertical) {
orient = XtorientVertical;
done(&orient, XtOrientation);
return;
}
In this code, the resource file symbols are represented by the symbolic constants XtEhorizontal and XtEvertical. To get the resource file symbols, horizontal and vertical, examine the related header files for lines such as:#define XtEhorizontal "horizontal"
#define XtEvertical "vertical"
The code file symbols, XtorientHorizontal and XtorientVertical, are the end result of the conversion. Note that in this example there is an intermediate step: the strings are converted to quarks and the quarks are used for the comparison. The mechanics of the conversion procedure do not affect visu_config.
14.12 Converters
If your user-defined widget has resources of non-standard types other than enumerations, WorkShop Visual places them on the "Miscellaneous" page of the resource panel by default. The resources can be allocated to other pages from the Widget Edit Dialog. The user can set these resources by typing a string into a text field. By default, the string is generated into the code or resource file but WorkShop Visual doesn't set it in the dynamic display. To make the resource work in the dynamic display, you can configure WorkShop Visual with a converter function for this resource. The converter function is a function that converts a text string to a resource value.
Figure 14-7 The "Converters" Page of the Family Edit Dialog
14.12.1 Resource Type
Enter the resource type in the "Selection" field and click on "Add". 14.12.2 Converters Added Internally
Many widgets add their own converters internally when the class is initialized. If this is the case, all you have to do is add the resource type to the list on the "Converters" page. Adding the resource type to the list informs WorkShop Visual that the converter is available; otherwise WorkShop Visual doesn't attempt to set the resource in the dynamic display. 14.12.3 Converters Added Explicitly
If the widget doesn't add converters internally, you can instruct WorkShop Visual to add them explicitly. To do this, specify the name of the converter function in the "Converter" box. The converter must be a function of type XtTypeConverter. Toggles are provided to add the converter explicitly either in WorkShop Visual (for use in the dynamic display), in the generated code, or in both. In general, if you have to add the converter explicitly, both toggles should be on. 14.12.4 Popup Dialog
The "Popup" button lets you specify a popup dialog to be used for setting all resources of this type. For details, see the Popups section below.
14.13 Popups
Resource popups are dialogs used to set a resource, such as WorkShop Visual's color and font selectors. For resources that have popups, WorkShop Visual creates a button on the resource panel to invoke the popup, in addition to the usual text field. Figure 14-8 shows popup buttons on the WorkShop Visual Core resource panel.
Figure 14-8 Popup Buttons on Core Resource Panel
14.13.1 Popups for Individual Resources
You can specify a popup dialog for any individual resource. To do this, use the right side of the Widget Edit Dialog, shown in Figure 14-9. Select the name of the resource in the list. If you haven't yet added the resource to the list, enter the defined name of the resource, such as XtNresourceName, in the "Resource" field and click on "Update".
Figure 14-9 Popup Portion of Widget Edit Dialog
14.13.2 Popups for Resource Types
If you specify a converter for a resource type, you can specify a popup dialog for that type. To do this, click on "Popups" on the "Converters" page of the Family Edit dialog. This displays the Popups Dialog. Select a popup using the instructions in the following section. 14.13.3 The Popups Dialog
The Popups Dialog is shown in Figure 14-10.
Figure 14-10 The Popups Dialog
To apply an existing popup to the currently selected individual resource or converter type, select the popup creations function in the list and click on "Apply". Note that all popup dialogs return the resource value in the form of a string such as "red" or "<big_font>". Therefore they work for resources that are declared as strings but are used to specify fonts, colors, or filenames.
14.13.4 Custom Popup Dialogs
You can create your own popup dialog, add it to the list and apply it to any resource or converter type. Three functions are required for each popup dialog: a create function, an initialize function and an update function. Enter the name of each function in the appropriate text field and then click on "Update" to add the popup to the list. 14.13.5 Code Requirements
The popup functions are invoked at different points in WorkShop Visual, as shown below:
Function |
Called |
create function |
When the dialog is first popped up. |
initialize function |
Each time the user clicks on the resource button. |
update function |
Each time a new widget is selected. |
Callback |
Functionality |
Apply callback |
Sets new resource value in source text widget. |
Close callback |
Pops down the dialog by unmanaging it. |
The Text or TextField widget on the resource panel (called the source text widget) is used to pass information from the dialog to the resource panel. When the user sets a value on the popup dialog, the value should be converted to text and set into the source text widget. The user can then click on "Apply" on the resource panel to set the value in the dynamic display, just as if the text had been typed by hand.
14.13.6 Create Function
The create function is called the first time the user clicks on the resource button to pop up the dialog. This function should create the widget hierarchy for the dialog.void popup_create ( Widget parent )
The parent parameter is the Application Shell widget for WorkShop Visual, to be used as the parent widget for the dialog. This parameter is required to call functions such as XmCreateDialogShell(). You can build popup dialogs in WorkShop Visual and use WorkShop Visual's generated creation procedure as the create function, or write a create function that calls it. In this case, pass parent on to the function generated by WorkShop Visual. 14.13.7 Initialize Function
The initialize function is called every time the user clicks on the resource button to pop up the dialog. The first time the dialog is invoked, the initialize function is called after the create function. The function should make the dialog visible by managing it and initialize any fields in it. The initialize function is passed the source text widget, the currently selected widget and the resource name.void popup_initialize( Widget source_text, Widget current, char
*resource_name)
The source_text parameter is the source text widget on the resource panel. This widget can be used to obtain the resource value currently displayed on the resource panel. Since the source text widget is used to pass back the new value from the dialog, the initialize function should also save the source text widget in a static variable so that it is available later. 14.13.8 Update Function
The update function is called for every popup dialog each time the selection changes in the widget hierarchy.void popup_update( Widget current )
current represents the newly selected widget. The update function should make the "Apply" button insensitive if the newly selected widget is of a different class, or if current is NULL. If you use the same dialog to set multiple resources, the safest approach is to make the "Apply" button insensitive in all cases. The user then has to click on the resource button again in order to use the popup. This extra step invokes the initialize function and ensures that the intended resource is set. 14.13.9 Popup Example
This example shows a simple resource popup consisting of a slider that is used to select an integer value. When the user clicks on "Apply" in the popup, the slider's value is converted to a text string and placed into the text widget in the resource panel.typedef struct foo_dialog_s {
Widget foo_dialog;
Widget form;
Widget scale;
Widget apply;
Widget close;
} foo_dialog_t, *foo_dialog_p;
static foo_dialog_p foo_dialog = (foo_dialog_p) NULL;
The following function is generated to create the Shell and all its children. The body of the generated function is omitted.foo_dialog_p create_foo_dialog (Widget parent)
{
/* WorkShop Visual generated code to create the dialog omitted here.*/}
In the module prelude a static variable is created to hold the source text widget. The initialize function provides the source text widget.static Widget source_text;
The dialog has an "Apply" button and a "Close" button, each with an Activate callback. The "Apply" button invokes the callback function shown below. This callback function gets the current value of the Scale, converts it to a text string and sets it into the source text widget. Note that this doesn't set the resource; the user must still click on "Apply" on the resource panel.static void
foo_do_apply (Widget w, XtPointer client_data, XtPointer
call_data )
{
int i;
char buf[52];
XmScaleGetValue ( foo_dialog->scale, &i );
sprintf ( buf, "%d", i );
XmTextSetString ( source_text, buf );
}
The dialog also has a "Close" button. The Activate callback function on this button simply unmanages the child of the dialog's Shell widget.static void
foo_do_close (Widget w, XtPointer client_data, XtPointer
call_data )
{
XtUnmanageChild ( foo_dialog->form );
}
The create function calls the WorkShop Visual generated creation function and saves the widget structure.foo_create( Widget parent )
{
foo_dialog = create_foo_dialog( parent );
}
The initialize function extracts the text from the source text field, converts it to an integer and sets the Scale to reflect the current value. It saves the source text field and so the new value set using the Scale can be applied to the source text field. It enables or disables the "Apply" button depending on the class of the current widget and makes the dialog visible.foo_initialize( Widget text, Widget current)
{
char *source_value;
int i;
source_text = text;
source_value = XmTextGetString( source_text );
i = atoi( source_value );
XtFree( source_value );
XmScaleSetValue( foo_dialog->scale, i );
XtSetSensitive( foo_dialog->apply,
current && XtIsSubclass (current, fooWidgetClass ) );
XtManageChild( foo_dialog->form );
}
The update function enables or disables the "Apply" button, depending on the class of the current widget. foo_update( Widget current )
{
XtSetSensitive( foo_dialog->apply,
current && XtIsSubclass( current, fooWidgetClass ) );
}
14.14 Resource Memory Management
WorkShop Visual assumes a default memory management model for XmString and String (char *) type resources. For XmString type resources this model assumes that the widget will copy the XmString both on SetValues and on GetValues (i.e. the application can free the XmString after a GetValues or SetValues).
14.15 XmStringTable Resources
For WorkShop Visual to handle XmStringTable resources correctly, you must also specify the integer type resource which is used as a count for the number of entries in the table. Add a resource specification for the XmStringTable.
14.16 Headers
visu_config generates two code modules, the Config file and the Code file. visu_config lets you specify a list of headers for each of these files. To specify headers, use the Family Edit Dialog. Select "Headers" from the View Menu to display the "Headers" page, shown in Figure 14-11.
Figure 14-11 The "Headers" Page of the Family Edit Dialog
14.17 Motif Widgets Stop List
You can use visu_config to stop selected Motif widgets from appearing in WorkShop Visual. Stopped widgets do not appear in the widget palette. They work correctly if read in from an existing design file but cannot be selected in the hierarchy or created interactively. For example, you can use this feature to prevent users from using the PanedWindow widget if it isn't in your company's style guide.
Figure 14-12 The Stopped Motif Widgets Dialogs
User-defined widgets cannot be stopped using this dialog. You can select which user-defined families to make available in WorkShop Visual via the visu_config Generate dialog, as discussed in the following section.
14.18 Generating and Compiling Code
The Generate Menu has two options, Config and Code which are used to generate the two configuration files. The pages displayed for each option are similar, as shown in Figure 14-13. Use the toggle buttons to select the families you want to include. Generate both files, using the same set of families for each.
Figure 14-13 The Config and Code Generate Dialogs
14.18.1 Compiling
The example makefile in $VISUROOT/user_widgets/Athena1 compiles a Config file named config.c, a Code file named Athena.c and a file containing configuration functions, Athenaextras.c. These files and all the Athena icon bitmaps, are located in $VISUROOT/user_widgets/Athena. You can use this makefile to compile the Athena example. The result is an executable file called visu.bin. 14.18.2 Invoking WorkShop Visual
The executable file is invoked with the correct environment by setting the environment variable USER_WIDGETS to the name of the user widgets directory (in this example "Athena") and invoking the standard visu command in $VISUROOT/bin. This causes the local bitmaps or color_icons directories to be added to $XBMLANGPATH and the local app-defaults directory to replace $VISUROOT/lib/locale/<LANG>/app-defaults in $XFILESEARCHPATH.
14.19 Testing the Configuration
This section describes a recommended testing procedure for the WorkShop Visual interface for a user-defined widget. Use visu_config as suggested to fix any problems. Note that these tests are designed to detect problems with the way in which the widget was configured into WorkShop Visual; they do not test the widget itself. 14.19.1 Creating a Widget
Run WorkShop Visual and verify that the icon for the user-defined widget is correct. If you use the small screen WorkShop Visual, invoke WorkShop Visual with the name small_visu and verify that the icon is correct in this case, too.
Note - This test is not appropriate if you turned off the "Can create widgets" toggle in the widget attributes panel.
If this does not work, try setting the "Disable foreground swapping" toggle in visu_config.
14.19.2 Foreground Swapping
If you have not disabled foreground swapping, create a hierarchy containing the user-defined widget. Select the Shell in the hierarchy and then select the user-defined widget. Verify that the widget in the dynamic display highlights correctly when selected. If this causes a problem, set the "Disable foreground swapping" toggle in visu_config. 14.19.3 Defined Name
Create a dialog containing an instance of the user-defined widget with every resource set. Generate C from WorkShop Visual and compile it. If it fails to compile, you may get a message like this:XtNfoo undefined
If you get such a message, first verify that the generated code includes the right public header for the widget class. If it doesn't, correct the header in the "Include file" field of visu_config's Widget Edit dialog.#define <something> "foo"
If <something> is not XtNfoo, you need a Defined Name function. For details, see the Configuration Functions section on page 518.
14.19.4 Pages
If you have specified that resources for the user-defined widget should appear on specific pages, verify that they do and that all the required pages are present. 14.19.5 Converters
Display the "Miscellaneous" page of the resource panel for the user-defined widget. Verify that you can type valid resource values into the text widgets and that they are correctly applied to the widget. If you get a message indicating that there is no resource converter, you need to use the "Add in WorkShop Visual" setting in visu_config. 14.19.6 Enumerations
Display the "Settings" page of the resource panel for the user-defined widget. Make sure the option menus all have the default value in parentheses at the top of their menus. 14.19.7 Popup Dialogs
If you specified custom popup dialogs for any resources, display the page of the resource panel on which each resource appears. Verify that the resource panel displays a button for each resource with a popup dialog. Click on the button. Verify that the dialog appears and is correctly initialized with the current value for that resource. 14.19.8 Code Inspection
Finally, verify that the generated code is correct. To check the generated code, set each resource in turn, generate a C code file and an X resource file and inspect them to see that you get what you expect.
14.20 Configuration Functions
visu_config lets you provide configuration functions to customize WorkShop Visual's handling of user-defined widgets. This section provides definitions and examples of the configuration functions.$VISUROOT/user_widgets/Athenaextras.c2.
14.20.1 Realize Function
By default, WorkShop Visual creates widgets in the dynamic display by calling XtCreateWidget(). You can supply a Realize function to substitute for this. A Realize function is only needed for widgets that cause problems when created in WorkShop Visual. 14.20.2 Realize Function Prototype
The Realize function has the following form. Note that it takes the same parameters and returns the same result as XtCreateWidget().Widget realize( char *name, WidgetClass class, Widget parent,
ArgList args, Cardinal arg_count )
The ArgList passed to a Realize function is always empty. 14.20.3 Realize Function Example
Some composite widgets, such as the Athena Form widget, cannot be realized without children unless their dimensions are explicitly set at creation time. Otherwise the widget is created at zero size, causing an X error. To solve this problem in the dynamic display, you can supply a Realize function like the one shown below, found in Athenaextras.c. This function initializes the widget's width and height resources to non-zero values, then calls XtCreateWidget() and returns the result.WidgetsizedCreate( char *name, WidgetClass class, Widget parent,
ArgList args, Cardinal arg_count )
{
Arg al[2];
int ac=0;
XtSetArg(al[ac], XtNheight, 20); ac++;
XtSetArg(al[ac], XtNwidth, 20); ac++;
return XtCreateWidget ( name, class, parent, al, ac);
}
The Realize function is only used when WorkShop Visual creates the widget in the dynamic display. It has no effect in the generated code. 14.20.4 Defined Name Function
In order to generate both code files and X resource files, WorkShop Visual uses both the resource name, such as label, and the corresponding defined name, such as XtNlabel. WorkShop Visual gets the name directly from the widget class record. By default, WorkShop Visual derives the symbolic constant from the name by adding an XtN prefix.#define XtNlabel "label"
#define XtNfont "font"
#define XtNinternalWidth "internalWidth"
You need a Defined Name function if any of the defined names don't follow the naming convention. For example, many widget toolkits, including Motif, use a different prefix:#define XmNbuttons "buttons"
#define XmNbuttonSet "buttonSet"
#define XmNbuttonType "buttonType"
14.20.5 Defined Name Function Prototype
The Defined Name function has the following form:char *defined_name ( char *name )
The Defined Name function is passed a character string containing a resource name and should return a character string containing the corresponding defined name. Your Defined Name function can refer to WorkShop Visual's internal Defined Name function, def_defined_name(). This function simply adds the default XtN prefix to the resource name.
Note - The function names defined_name and def_defined_name are already used by WorkShop Visual so you should make sure that you do not use these names.
14.20.6 Defined Name Function Example
The defined name for the Athena Clock widget resource hands is not XtNhands but XtNhand. Therefore, the Clock widget needs the following Defined Name function:char *clock_defined_name( char *name )
{
/*
* XtNhand is defined as hands, so can't just put
* XtN on the front
*/
if ( strcmp ( name, "hands" ) == 0 )
return "XtNhand";
return def_defined_name ( name );
}
All Clock resources except hands follow the naming convention and so def_defined_name() is used to convert them. 14.20.7 Can Add Child and Appropriate Parent Functions
You can supply Appropriate Parent and Can Add Child functions to define the rules for valid parent-child relationships involving user-defined widgets. These rules control WorkShop Visual features such as graying-out of palette icons, automatic selection of newly created widgets and dragging icons in the construction area. 14.20.8 Appropriate Parent Function Prototype
The Appropriate Parent function is called when the user tries to add a widget of the user-defined class to the hierarchy, or tries to drag or copy the user-defined widget to another parent. This function determines whether the user-defined widget can be added as a child of the selected widget.Boolean is_appropriate_parent ( Widget parent, WidgetClass
childclass )
The first parameter is an instance of a widget in the hierarchy that is a proposed parent widget; the second is a pointer to your new widget class. The function should return TRUE if it is valid to add a child of your new class to the proposed parent widget and FALSE otherwise. 14.20.9 Appropriate Parent Function Example
By default, WorkShop Visual lets Motif Manager widgets, such as the Form and Row Column, have children of any type. Appropriate Parent functions let you restrict the widget to being a child of only certain classes. For example, if your widget can only be a child of a DrawingArea, supply an Appropriate Parent function that returns TRUE if the proposed parent widget is a DrawingArea and FALSE if not. The code for this case is very simple:Boolean drawing_area_parent ( Widget w, WidgetClass class )
{
if ( XtClass ( w ) == xmDrawingAreaWidgetClass )
return True;
return False;
}
14.20.10 Can Add Child Function Prototype
The Can Add Child function has the following form:Boolean can_add_child (XWidget_p parent, WidgetClass childclass)
{
...
}
This function is used for two purposes. WorkShop Visual calls the Can Add Child function to determine whether a widget of a specific class is a valid child of the user-defined widget and calls the Can Add Child function to determine whether it should automatically select a newly created instance of the user-defined widget. 14.20.11 Can Add Child Example
The following example shows a Can Add Child function.Boolean paned_can_add_child ( XWidget_p xw, WidgetClass class ) {
/* For newly created instance of this widget class, make the newly created widget the currently selected widget in the hierarchy. */if (class == NULL)
return TRUE;
/* Allow all children except Drawing Area and ScrollBar. */if ( class == xmDrawingAreaWidgetClass ||
class == xmScrollBarWidgetClass )
return False;
else
return True;
}
2 $ is the path to the installation root directory.