Previous Next Contents Index Doc Set Home


Structured Code Generation and Reusable Definitions

8



8.1 Introduction

This chapter describes how WorkShop Visual helps you to control the structure of the generated code. Being able to do this is essential for creating reusable widget hierarchies. These reusable hierarchies, known as definitions, appear on the widget palette and can be added to the hierarchy like any other widget. A detailed description of definitions also appears in this chapter.


8.2 Structured Code Generation

WorkShop Visual provides controls for structuring your generated code so that it is more flexible and can be reused more easily. Before reading this section, you should review the structure of the default generated code in the Analysis of the Primary Module section on page 244. In particular, note that the default code has a single creation procedure for each Shell in the design. Widgets are declared as local if they have not been named and global if they are named or are Application Shells.

The structured code controls let you:

WorkShop Visual's controls for structuring code are located on the "Code generation" page of the Core resource panel.


8.3 Function Structures

The simplest case of structured code generation is to designate a widget as a function structure. This makes WorkShop Visual generate a separate function that creates that widget and its descendants. This function is called by the creation procedure for the enclosing widget.

To do this, select the "Code generation" page of the Core resource panel and select "Function" from the "Structure" option menu.

Figure  8-1 Example: Structure
The hierarchy shown in Figure 8-1 produces the following generated code, slightly simplified for clarity:1

Widget shell = (Widget) NULL;
Widget form = (Widget) NULL;
Widget button_box = (Widget) NULL;
Widget b1 = (Widget) NULL;
/* This is the creation function for the button_box. */

Widget create_button_box (Widget parent)
{
	Widget children[1];      /* Children to manage */
	Arg al[64];                    /* Arg List */
	register int ac = 0;           /* Arg Count */
	Widget button_box = (Widget)NULL;

	button_box = XmCreateRowColumn ( parent, "button_box", al, ac 
);
	b1 = XmCreatePushButton ( button_box, "b1", al, ac );
	children[ac++] = b1;
	XtManageChildren(children, ac);
/* The button box is created, but not managed, and returned. */

	return button_box;
}
/* The creation function for the Shell calls the button box creation function. */

void create_shell (Widget parent)
{
	Widget children[1];      /* Children to manage */
	Arg al[64];                    /* Arg List */
	register int ac = 0;           /* Arg Count */

	XtSetArg(al[ac], XmNallowShellResize, TRUE); ac++;
	shell = XmCreateDialogShell ( parent, "shell", al, ac );
	ac = 0;
	XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
	form = XmCreateForm ( shell, "form", al, ac );
	ac = 0;
	button_box = create_button_box ( form );
/* The constraint resources for the button box are set in the parent's creation function. */

	XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
	XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
	XtSetValues ( button_box,al, ac );
/* The button box is managed at this point. */

	children[ac++] = button_box;
	XtManageChildren(children, ac);
}
This module now has two functions: one (create_shell()) for creating the whole hierarchy and one (create_button_box()) for creating the button box.


8.4 Data Structures

The next type of code structuring is the data structure. This is similar to a function structure, in that WorkShop Visual generates a separate creation procedure for the widget and its descendants. When a widget is designated as a data structure, WorkShop Visual also generates a typedef for a structure including that widget and its children. The creation procedure for the widget creates and sets up that type of structure and returns a pointer to it. A deletion function (delete_<widget_name>) is also generated so that the allocated memory can be freed.

To designate a widget as a data structure, select the "Code generation" page from the Core resource panel and select "Data structure" from the "Structure" option menu.

Using the same hierarchy as shown above, but with button_box designated as a data structure, the following code is produced, slightly simplified for clarity:2

/* First the type declarations are generated for the data structure. */

typedef struct button_box_s {
	Widget button_box;
	Widget b1;
} button_box_t, *button_box_p;
Widget shell = (Widget) NULL;
Widget form = (Widget) NULL;
button_box_p button_box = (button_box_p) NULL;
/* The creation procedure returns a pointer to a button_box structure. */

button_box_p create_button_box (Widget parent)
{
	Widget children[1];      /* Children to manage */
	button_box_p button_box = (button_box_p)NULL;
/* Space is allocated for the structure and the fields are filled in. */

	button_box = (button_box_p) XtMalloc ( sizeof ( button_box_t ) 
);
	button_box->button_box = XmCreateRowColumn ( parent, 
"button_box", al, ac );
	button_box->b1 = XmCreatePushButton
( button_box->button_box, "b1", al, ac );
	children[ac++] = button_box->b1;
	XtManageChildren(children, ac);
	return button_box;
}
/* A deletion function is supplied to free the allocated memory. */

void delete_button_box ( button_box_p button_box )
{
	if ( ! button_box )
		return;
	XtFree ( ( char * )button_box );
}
/* Again, the Shell creation function calls the button box creation function. */

void create_shell (Widget parent)
{
	Widget children[1]; /* Children to manage */
	Arg al[64]; /* Arg List */
	register int ac = 0; /* Arg Count */
	shell = XmCreateDialogShell ( parent, "shell", al, ac );
	form = XmCreateForm ( shell, "form", al, ac );
	button_box = create_button_box ( form );
	XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
	XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
/* The button_box widget has to be referenced inside the structure. */

	XtSetValues ( button_box->button_box,al, ac );
	ac = 0;
	children[ac++] = button_box->button_box;
	XtManageChildren(children, ac);
	ac = 0;
}


8.5 C++ Classes

The use of C++ classes is very similar to data structures. WorkShop Visual does not wrap each widget in the hierarchy with a C++ class, but instead designates sections of the hierarchy as classes in their own right. Each widget designated as a C++ class has a class defined for it. Its named descendant widgets become members of that class and widget creation and widget destruction methods are supplied. In addition, if the class contains members that are themselves (pointers to) classes, a constructor and destructor method is generated to create and destroy these members. Note that the widgets are not created at the time of the class instance but by an explicit call to the widget creation function. Similarly, destroying the class instance does not destroy the widgets.

To designate a widget as a C++ class, select the "Code generation" page of the Core resource panel and select "C++ class" from the "Structure" option menu. Note that if you designate a widget as a C++ class, then generate C, the widget is treated as a data structure.

Figure  8-2 Example: C++ Class Structures
The C++ code generated from this example is shown below, simplified for clarity:3

// Classes are declared for button_box and shell.

class button_box_c: public xd_XmRowColumn_c {
public:
	virtual void create (Widget parent, char *widget_name = NULL);
protected:
	Widget button_box;
	Widget b1;
	Widget b2;
};

typedef button_box_c *button_box_p;
// The shell class has constructor and destructor functions because it
// contains a pointer to class (or data structure) member.

class shell_c: public xd_XmDialog_c {
public:
	virtual void create (Widget parent, char *widget_name = NULL);
	shell_c();
	virtual ~shell_c();
protected:
	Widget shell;
	Widget form;
	Widget text;
	button_box_p button_box;
};

typedef shell_c *shell_p;

shell_p shell = (shell_p) NULL;
// The creation function now becomes a method of the class. This method
// is declared public in the WorkShop Visual base class, which is supplied
// with the release.

void button_box_c::create (Widget parent, char *widget_name)
{
	Widget children[2];      /* Children to manage */
	Arg al[64];                    /* Arg List */
	register int ac = 0;           /* Arg Count */

	if ( !widget_name )
		widget_name = "button_box";

	button_box = XmCreateRowColumn ( parent, widget_name, al, ac );
// _xd_rootwidget is a protected member of the class that stores the widget
// that is at the root of the sub-hierarchy. This lets the base class
// operate on the widget.

	_xd_rootwidget = button_box;
	b1 = XmCreatePushButton ( button_box, "b1", al, ac );
	b2 = XmCreatePushButton ( button_box, "b2", al, ac );
	children[ac++] = b1;
	children[ac++] = b2;
	XtManageChildren(children, ac);
	ac = 0;
}
// The Shell's creation method calls that for the button box.

void shell_c::create (Widget parent, char *widget_name)
{
	Widget children[2];      /* Children to manage */
	Arg al[64];                    /* Arg List */
	register int ac = 0;           /* Arg Count */

	if ( !widget_name )
		widget_name = "shell";

	XtSetArg(al[ac], XmNallowShellResize, TRUE); ac++;
	shell = XmCreateDialogShell ( parent, widget_name, al, ac );
	ac = 0;
	_xd_rootwidget = shell;
	XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
	form = XmCreateForm ( shell, "form", al, ac );
	ac = 0;
	text = XmCreateText ( form, "text", al, ac );
// The button box class is instantiated in the constructor method and so at // this point only the widgets need to be created.

	button_box->create ( form, "button_box" );

	XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
	XtSetArg(al[ac], XmNtopWidget, button_box->xd_rootwidget()); 
ac++;
	XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
	XtSetValues ( text,al, ac );
	ac = 0;

	XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
	XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
	XtSetValues ( button_box->xd_rootwidget(),al, ac );
	ac = 0;
	children[ac++] = text;
	children[ac++] = button_box->xd_rootwidget();
	XtManageChildren(children, ac);
	ac = 0;
}

shell_c::shell_c()
{
// Instantiate the child classes.

	button_box = new button_box_c;
}
shell_c::~shell_c()
{
// Free the child classes.

	delete button_box;
}
If a widget is designated a C++ class and C code is generated, the widget is treated as if it were a data structure.

By default, the generated class is derived from one of the supplied WorkShop Visual base classes. You can override this by specifying the base class in the field below the C++ Access option menu. The WorkShop Visual base classes supplied with the release provide minimal support, sufficient for the generated code to execute correctly. You can modify and extend those classes to provide reusable methods that suit your approach to GUI development.

Descendant widgets appear as protected members of the class if they are named, or if they are themselves data structures or C++ classes. It is therefore important to name the C++ class widget itself and any of its descendants that you want to access as class members. You can alter the default access control by selecting the required level (Public, Protected, or Private) from the C++ Access option menu.

Using an unnamed widget for the C++ class widget itself does not cause an immediate error. However, this is not recommended as numbers assigned by WorkShop Visual can change when you edit your hierarchy.

8.5.1 Callback Methods

The X toolkit functions which invoke callback functions expect a callback function in the following form:

void my_callback (Widget, XtPointer, XtPointer)
An ordinary member function is not suitable as a callback function because the C++ compiler passes it an extra first parameter - the this pointer - that lets it find the instance data for the object. If you use an ordinary member function as a callback function, the member function interprets the widget pointer as the instance data pointer and does not work as expected.

WorkShop Visual uses a common technique to work around this. A static member function (which does not expect a this pointer) is declared and used as the callback function:

static void my_callback (Widget, XtPointer client_data, 
XtPointer call_data)
The client data parameter is used to pass in a pointer to the instance. The static member function merely calls an ordinary non-static member function using that instance pointer and passes on the widget and call data parameters. The non-static member function has the following form:

virtual void my_callback (Widget, XtPointer call_data)
WorkShop Visual generates both function declarations, all the code for the static callback function and a stub for the regular member function which is written by you. Note, because this function is declared as virtual, you can override it in a derived class to modify the behavior. For a discussion of this technique, see "Object-Oriented Programming with C++ and OSF/Motif" by Douglas Young.

8.5.2 Editing Callback Methods

When you add a callback method, WorkShop Visual also adds a declaration for the method (if it has not already been declared). Pressing the "Methods" button in the Callbacks dialog shows you a list of the methods declared in the enclosing class of the currently selected widget.

By default, WorkShop Visual declares methods as not pure virtual and with public access. If these attributes are not as you intended, use the Method Declarations dialog to change them. See the Method Declarations section on page 274 for details.


8.6 Method Declarations

If you add a callback to a method, for convenience WorkShop Visual adds the declaration of the method in the enclosing class for that widget. You can view, add and remove method declarations by selecting the widget which is the enclosing class and selecting "Method declarations" from the "Widget" menu. The Method Declarations dialog is shown in Figure 8-3.

Figure  8-3 Method Declarations Dialog
To find which widget is the enclosing class, use "Structure colors" from the "View" menu, as described in the Structure Colors section on page 47, and select the nearest ancestor of the widget for which you have added a method. Of course, this would be the same widget if it is defined as a C++ class.

8.6.1 Method Access Control

By default, methods added by WorkShop Visual have public access. You can control the access for individual callback methods using the "Access" option menu in the Method Declarations dialog.

8.6.2 Pure Virtual Methods

You can set the "Pure virtual" toggle to declare the non-static member function as pure virtual. For example, if you set this toggle for a callback method OnNew() in a menubar class, WorkShop Visual would declare the method as:

class menubar_c: public xd_XmMenuBar_c {
...
public:
...
	virtual void OnNew( Widget, XtPointer ) = 0;
};
Because the function is pure virtual, you do not have to provide an implementation of menubar_c::OnNew() and menubar_c becomes an abstract class. That is, you cannot create an instance of menubar_c but only use it as a base class for others.

By default, methods added by WorkShop Visual are not pure virtual.

8.6.3 Deleting Callback Methods

When you remove a callback method from a widget you are only removing the use of the method (the call to it). When you add a method callback in WorkShop Visual, a declaration of the method is automatically added for you. If you want to remove this declaration as well you must remove it from the method declarations list of the widget which is the enclosing class. See the Method Declarations section on page 274 for more information on how to do this and for information on the declaration added by WorkShop Visual.

8.6.4 Method Preludes

You can add additional data or function members to a C++ class using the "Code preludes" dialog. Select "Public methods", "Protected methods", or "Private methods" and type your declarations into the text area (or into the code if you are editing in place). C++ code preludes are generated into the class declaration, both in the primary module and in the Externs file.

8.6.5 Creating a Derived Class

To add a function to a class it is often better to write a new class derived from the generated class. The logical gap between the subclass and generated base class can be used to add members and provide implementations for virtual functions.

By default, WorkShop Visual derives the name of a C++ class from the variable name of the root widget and so the class for the widget menubar is menubar_c:

class menubar_c: public xd_XmMenuBar_c {
...
};
When WorkShop Visual generates code to create an instance of the class, it uses the same name:

menubar = new menubar_c;
You can change the default behavior so that WorkShop Visual declares the generated class under one name and creates the instance under another. For example:

menubar = new mymenubar_c;
To make this change, use the "Instantiate as" field on the Code Generation page of the Core resource panel.

8.6.6 Modifying the Base Classes

By default, WorkShop Visual derives a generated class from a base class appropriate to the type of the root widget. For example, a class with a MenuBar at the root of its widget hierarchy is derived from xd_XmMenuBar_c. The name of the base class can be changed in the Core resource panel.

The WorkShop Visual distribution contains a sample implementation of a set of base classes. These can be used as they stand or modified to add extra functionality appropriate to a particular application area.

A Makefile is included to build the sample base classes. WorkShop Visual makes two assumptions about the base classes:

There is a data member _xd_rootwidget of type Widget.

There is an accessor function xd_rootwidget() that returns the value of _xd_rootwidget to be retrieved.

These assumptions, together with a few items of basic class restrictions, are encapsulated in the class xd_base_c:

class xd_base_c
{
public:
	xd_base_c() {_xd_rootwidget=NULL;}
	Widget xd_rootwidget() const {return _xd_rootwidget;}

protected:
	Widget _xd_rootwidget;
private:
	void operator=(xd_base_c&); // No assignment
	xd_base_c(xd_base_c&);      // No default copy
};
WorkShop Visual places no other constraints on the base classes used. In other words, any set of base classes can be used provided that they are derived from xd_base_c (or another base class that satisfies WorkShop Visual's assumptions).

Note that actual parameters for the base class constructor can be supplied with the class name. If parameters are supplied (if the base class string contains a '()', the class is forced to have a constructor and the parameter string is passed to the base class. For example, setting the "Base class" string to mymenubar_c ("Hello World") for the widget menubar will cause WorkShop Visual to generate:

    class menubar_c : public mymenubar_c { 
	public: 	
		menubar_c(); 	
		...     
	};
    ...
    menubar_c::menubar_c () 	
		:mymenubar ( "Hello World" )     
	{     
	}
    ...
	menubar = new menubar_c;


8.7 Children Only Place Holders

The Children Only structure option lets you designate one widget (the Children Only widget) as a container structure for another structure. Children Only widgets provide context for their descendants in the hierarchy, but no code is generated for them. Consider the following example:

Figure  8-4 Use of Children Only Structure
When you generate code from the design shown in Figure 8-4, WorkShop Visual produces code for the pulldown menu structure only. This feature lets you generate fragments of the design that can be controlled by your application program.


Note - If you specify a widget as "children only", code is only generated for children which are structured or named. Therefore, if all you have underneath a "children only" widget is unstructured and unnamed widgets, then all you will see in the code is Widget declarations.


8.8 Structured Code Generation and UIL

When generating UIL for a design that contains structures of some kind, the approach is basically similar for that of C and C++. Independent hierarchies are generated into the UIL file and separate creation functions are generated into the code file. The creation function fetches the appropriate widgets from the UIL hierarchy and fills in the data structure fields as appropriate.


8.9 Changing Declaration Scope

Widgets are normally declared locally in the enclosing creation function unless they are structured in some way, or named. In this case they are declared in the enclosing structure if there is one, or as global variables. This default behavior can be modified by setting the storage class of a widget in the Core resource panel. Setting the storage class to Local forces a widget that would otherwise be declared globally or within a structure to be local to the creation function. Setting the storage class to Global forces an unnamed widget or a named element of a structure to be global. Global status is especially useful for widget-type resources and links as discussed in the Unreachable Widgets subsection below. The Static option is similar to Global but the declaration is static to the module.

There is no way to force an unnamed widget into a data structure. Unnamed children of a data structure widget are created and managed locally to the data structure's creation procedure.

8.9.1 Unreachable Widgets

When you use the structured code generation in conjunction with widget-type resources such as XmNdefaultButton for a BulletinBoard, you could specify designs that reference widgets that are not in scope. These are considered unreachable widgets. WorkShop Visual attempts to detect these cases and warns you at code generation time. Also, if you use unreachable widgets in conjunction with Children Only structures or dynamic run time creation of hierarchies, unexpected failures may result.

Figure  8-5 Hierarchy with Unreachable Widgets
An unreachable widget is illustrated in Figure 8-5. b1 must be available to the Form's creation function so that it can be used as the default button argument. However, since b1 is local to the button_box function, it is not in scope in the Form's creation function. WorkShop Visual detects this situation and displays the following warning at code generation time.

Figure  8-6 Unreachable Widget Error
Code is still generated but it may not compile or run as expected. The simplest solution to this is to force the appropriate widget to be global by using the Storage Class option.


8.10 Definitions

Once a hierarchy of widgets has been encapsulated as a structure (either a C++ class or a C structure), you can re-use it in other designs by turning it into a definition. A definition is a reusable hierarchy of widgets which is added to the WorkShop Visual widget palette. Selecting a definition from the palette creates an instance of the definition in the design. This instance can be further modified and in turn be made into a definition.

8.10.1 Prerequisites

A widget hierarchy can become a definition provided that:

1. The root widget has a non-default variable name.

2. The root widget has been designated as a C++ class or a structure.

3. The root widget is not part of another definition.

4. The widget hierarchy does not contain a definition.

5. The widget hierarchy does not contain any global or static widgets.

8.10.2 Designating a Definition

Designating a definition requires that the design file containing the widget is saved and the widget marked in it as being a definition. To mark the widget as a definition use the Definition toggle in the Widget menu. Creating a definition freezes the widgets within it. Their resource panels are disabled and you cannot add widgets or change widget names. You can edit the widgets that make up a definition only by temporarily removing the definition status. This should be done with caution to avoid conflicts with designs that use the definition. For details, see the Modifying a Definition section on page 286.

To make the definition available for use in other designs WorkShop Visual needs an external reference to it. This is provided by means of a definitions file which is edited using the Edit Definitions dialog.

8.10.3 Definition Shortcut

The "Define" button in the Palette Menu is a quick way of adding a new definition. It designates the currently selected widget as a definition, saves the design and adds the definition to the palette. The header filename for the definition is taken from the type declarations filename in the code generation dialog. No icon is used.


8.11 The Definitions file

The definitions file is read by WorkShop Visual to establish the set of definitions which are to appear on the palette. The definitions filename is specified by setting the definitionsFileName resource. The default value is $HOME/.xddefinitionsrc.

If you need to work on multiple projects, each of which uses a different set of definitions, you can change the definitions file by setting the resource. For example:

visu.definitionsFileName:/home/project6/xddefs
The value of this resource can include environment variables:

visu.definitionsFileName:$PROJECT_ROOT/xddefs
To change to the new setting, exit and restart WorkShop Visual.

8.11.1 Editing the Definitions File

To modify the definitions file use the Edit Definitions button in the Palette menu.

This displays the dialog shown in Figure 8-7.

Figure  8-7 Adding a Definition to the Palette.
You can use this dialog to add a new definition, delete a definition, or edit an existing definition. To add a definition, you must supply:

You can also specify:

Attributes not set at creation time can be set later. For example, you can test and debug a definition before designing its icon.

You can use the "Prime" button to fill in several of the fields for the currently selected widget.

8.11.2 Base Directory

If a definition is specified with a relative file name (a name that does not start with /), WorkShop Visual adds the base directory to the front of the file name. If a base directory is not specified, the directory that contains the definitions design file is used.

To specify a base directory, display the Edit Definitions dialog, click on "Base Directory", select a new directory and click on "Apply". The new base directory is saved in your definitions file and is immediately used in the current session of WorkShop Visual. The base directory cannot be changed if the current design contains instances of existing definitions.


8.12 Modifying a Definition

Widgets in the definition are frozen. You cannot add or delete widgets, rename them, set constraints on them in the layout editor, or reset resources. To modify a definition, you must temporarily undefine it. When you need to modify a definition, use the following steps:

1. Open the save file that contains the definition.

2. Select the root widget of the definition.

3. Pull down the Widget Menu and turn off the "Definition" toggle.

Turning off the toggle unfreezes the widgets in the definition so you can make any necessary changes. After making your edits:

4. Select the root widget and set the "Definition" toggle on again.

5. Regenerate the code file and externs file.

6. Save the design.

8.12.1 Impact of Modifying a Definition

Changing a definition affects every design file that uses it. Each time you open a design that uses a definition, WorkShop Visual also opens the file that contains the definition and merges information from the two files. If the definition has been modified, WorkShop Visual tries to reconcile the new definition with the design that uses the old version of it.

If any changes cannot be reconciled, WorkShop Visual displays an error message and saves any irreconcilable parts of the design in temporary WorkShop Visual clipboard files. At this stage there are several ways to proceed:

To minimize the risk of incompatibilities:


8.13 Instances

To create an instance of a definition simply click on the appropriate button in the palette. The instance is shown with a colored background.


Note - Definitions and instances must be in separate designs. Although you can see them in the same design within WorkShop Visual, the generated code needs to be kept separate so that the code generated for the instance can include the header file generated for the definition.

8.13.1 Definition Families

Definitions are grouped together on the widget palette according to their family. An option menu above the definitions on the widget palette allows you to change which family is currently displayed. See the Editing the Definitions File section on page 283 for details on specifying a definition's family.

8.13.2 Modifying and Extending an Instance

Creating an instance of a definition corresponds to creating an instance of the structure (either a C structure or a C++ class). You can modify an instance after you have created it provided that the modifications can be reflected in the generated code. For example, you can set resources on widgets or add children to widgets only if they are accessible (i.e. if they are named and, for C++, they have an appropriate access mode). You cannot remove widgets or change their names. The root widget is an exception. Because the root widget of the instance is always accessible (through the member function xd_rootwidget()), it can always be modified.


Note - You cannot move a widget in the layout editor, or specify constraints for it, unless it is accessible.

8.13.3 Creating a Derived Structure

It is frequently useful to create a new structure that is derived from the definition. To do this simply set the Structure option on the Code generation page of the Core resources dialog. The derived structure can only be set to the same value as the definition, e.g. it is not possible to derive a C++ class from a C structure.

8.13.4 Overriding a Definition Callback Method

Inherited methods from definitions can be overridden in the instance so that the instance has different behavior from that specified in the definition.


8.14 Definitions and Resource Files

Resource values for widgets that are components of definitions can be either hard-coded or specified in resource files.

8.14.1 Instances and Definition Resource Files

When you specify a resource file for a definition, WorkShop Visual #includes that file in the resource file for any design that contains an instance of the definition. The Xlib mechanisms that read the resource file interpret this directive and use it to find the resource file for the definition.


8.15 Online Help for Definitions

To record information about a definition and communicate with other developers who are using it, you can provide online help for definitions. The online help is accessed in the WorkShop Visual interface by using the <Tab> and arrow keys to get to the icon or button for the definition, then pressing the <osfHelp> key (usually <F1>).

Help files are stored in subdirectories of the WorkShop Visual help directory. The help directory is determined by the helpDir resource. By default, it is

$VISUROOT/lib/locale/{$LANG}/help
where VISUROOT is the path to the WorkShop Visual installation root directory and LANG is the name of your locale (default C).

8.15.1 Text Help Documents

Text help documents are in HTML format. The name of the file is formed by concatenating the document name and marker name. These are joined using the value of the visu.userHelpCatString resource. By default this resource is set to ".". WorkShop Visual looks for this file in the UserDocs subdirectory of the WorkShop Visual help directory.


Previous Next Contents Index Doc Set Home


1 The comments describing the functions and procedures are not generated.

2 The comments describing the functions and procedures are not generated.

3 The comments describing the functions and procedures are not generated.