Classes and Methods

Classes

Overview

When you create an interface with Builder Xcessory, you will often find that you repeatedly create certain combinations of objects, for example, a label, a text area, and a button that acts on the value entered in the text field. Rather than recreate all three objects each time, you can combine them into a class. This class can then be treated as a single object. By planning and creating a library of high-level, reusable classes, you can improve the quality, development time, and maintainability of your applications.


Note: A Builder Xcessory class should not be confused with a C++ or Java class, although the code is generated using language classes.

Designing and Planning Classes

Plan and design your classes to implement them in the most efficient manner. One of the major benefits of working with high-level objects is the ability to reuse them. Before you begin your project, identify the obvious and the non-obvious elements of your application. Think about how the elements will be used in subsequent applications, and use Builder Xcessory to develop the latest additions to your class library or application framework. As you progress through the development of your application, additional classes will undoubtedly become obvious. Builder Xcessory allows you to create new classes at any point in your development cycle.

Creating a Class with Builder Xcessory

When creating a class, you work with all three main Builder Xcessory windows. With the Browser, you switch between Instance and Classes views of your interface, viewing and manipulating the objects within your classes. With the Resource Editor, you customize the look and feel of your classes, setting resources, callbacks and event methods. With the Palette, you create the objects comprising your classes, and use, store, and share the classes themselves.

Creating a class

To create a class, use one of the following methods:

· In Instances view, select the top-level object of the hierarchy that you wish to make a class. Then select Make Class from the Browser:Edit menu (or MB3 Quick Access menu). You are prompted for the name of the new class.

· In Classes view, drag an object from the Palette and place it on the display. You are automatically prompted for the name of the new class. If you drag a widget, your class consists of only that widget. If you drag another class object, the new class is a subclass of the specified object.

Once you supply a class name in the dialog displayed for that purpose, the class is automatically included in the Project Classes group of the Palette.

For example, you might want to create a class that combines a label and text field within a form.

Example:
Creating an object

First, create the objects by following these steps:

1. Create a form.

2. Place a label and a text field within the form as shown in the following figure:

Widget Hierarchy

3. You can use the Form Editor and Ctrl+MB1 on the attachment handles to set any appropriate constraint resources. The collection should now look something like the following figure:

LabelField Widget Collection

Example:
Making a collection of objects into a class

To make this collection of objects into a class, follow these steps:

1. Select the container widget (the form) by clicking on its instance name in the Browser widget hierarchy.

2. Select Make Class from the Browser Edit menu, or from the MB3 Quick Access menu.

3. In the Name field, enter LabelField. The new class is automatically
added to the Palette in the Project Classes group as shown in the following figure:

LabelField Class on Palette

The collection is now collapsed into a class instance on the Browser as shown in the following figure:

Class Instance labelField

Switch the Browser to Classes view. The class is now expanded on the Browser and you can view its entire membership as shown in the following figure:

LabelField Widget Hierarchy

Editing resources and adding callbacks and event methods

When Builder Xcessory is in Classes view, any component of the class can be modified and any component's widget resource can be exposed. Select the component or components in question and edit the resource values, using the Resource Editor, extended editors, or styles. Callbacks and event methods are treated just as any other resource. Changes made to the class propagate to all instances of the class and its subclasses throughout the interface.


Note: One of the most powerful properties of classes is that changes to the class definition propagate to pre-existing class instances.

Callbacks for class members (Motif) are generated in source code as two separate methods, described in detail in Object-Oriented Programming with C++ and OSF/Motif (Prentice Hall, 1995, 2nd Ed. ISBN 0-13-209255-7) by Doug Young. Exposing a callback results in a third, public method.

See Using Callbacks in C++ Classes for detailed information on these methods.

Creating class instances

You create class instances in the same manner in which you would instantiate any other Palette object, that is, select it on the Palette and drag it to the interface window. Refer to Using the Palette .

Reusing classes

Once saved in the Palette Private Classes or Public Classes group, a class is available each time you start Builder Xcessory. You can also read a previously saved class file into an interface.

Additionally, as with widgets, you can add VkComponent and UIComponent subclasses to the Palette, allowing you to completely code a class and its methods and interact with the fully-working object in Play Mode. For more information on Play Mode see Using Play Mode . For information on adding classes to the Palette, see Permanently Placing Classes on the Palette .

Subclassing

Classes can also be subclassed, furthering the re-usability and usefulness of classes. Subclasses can be modified by adding additional widgets, adding methods and data members, and changing resources.

Adding Methods and Data Members

Methods

In addition to their component objects, classes include methods and the data on which they operate. You can add additional class members from the Resource Editor in Classes view (see Resource Editor in Classes View ). Both methods and data are displayed in a list sorted by item type and scope. Parameter argument types are displayed for methods only.

Resource Editor in Classes View

Buttons

You can operate on the items using the following three buttons:

· New

Creates a new class member.

· Edit

Available only for methods. Invokes the code generator and configured editor for this method.

· Delete

Deletes the class member.

Adding members

To add a member to a class, follow these steps:

1. Switch the Browser to Classes view.

2. Select the desired class.

3. Update the Resource Editor.

4. Select the New button.

Builder Xcessory provides an extended editor, the Class Member Editor, to help specify methods and data. (For more details, see Class Member Editor .)

A method or data member specified in the class definition is available to each class instance.


Note: The methods and data you specify on the class itself are in addition to any methods created by Builder Xcessory for callbacks, widget IDs, or event methods that you specify elsewhere.

Class Member Editor

Class Member Editor illustrates the Class Member Editor for a class method:

Class Member Editor

Data/Method

Use the toggles at the top of the window to select Data or Method.

Other fields and toggles allow you to assign the type, name, and other attributes such as the member's scope. The attribute selections represented by the tabbed panels vary depending on the code generation language. Also, some cross checking of selections occurs so that inappropriate selections are disabled. For example, if you are using C++ code generation, an initial static value is unavailable for methods and is disabled.

For methods, the parameter fields allow you to enter argument types, parameter names, and (for C++ code generation) default values.

For data, the parameter entry areas and list are hidden. Static data members can provide initial values.

For more information on the Class Member Editor, see Class Member Editor


Note: The Class Member Editor is a valuable tool for specifying language-specific attributes to each added class member. However, even though some cross-checking is performed to confirm the compatibility of your selections, it is not complete and is not meant to be a robust language checker.

User Code Blocks

Member methods and data can also be inserted directly into the User Code Blocks of the class file. These edits are not visible or editable in the Resource Editor. Because they are inside User Code Blocks, they are retained when the files are regenerated.

Exposing Resources

When designing a class with reuse in mind, you must decide what aspects of the class will be customizable on a per instance basis. Within Builder Xcessory, you can do this by exposing resources .

A resource on a component object is exposed when its default value can be overridden for a particular instance of the class. Ordinarily, you expose resources when you wish to vary a resource value for different instances of a class. For example, you might want to allow users of the LabelField class described at the beginning of this chapter to set the value of the labelString resource for each instance of the class.


Note: For any resource that you want to expose within a class, you must specify a default resource value in the class definition.

Exposing a resource

To expose a resource, follow these steps:

1. Switch the Browser to Classes view.

2. Update the Resource Editor for the desired component object.

3. Scroll the Resource Editor to the desired resource.

4. Set the resource to the value that you wish each instance to take by default.

5. Select Expose from the option menu to the right of the resource text field.


Note: Exposed resources are designated on the Resource Editor with an "open eye" icon to the left of the option menu. The option menu continues to display the resource placement setting (for example, "Code" or "App").

Editing the value of an exposed resource

To edit the value of an exposed resource on a class instance, follow these steps:

1. Select a class instance (Be sure to be in Browser:Instance view).

2. Update the Resource Editor.

The Resource Editor now displays exposed resources with the notation:
<element_name>.<resource>

3. Scroll the Resource Editor to the desired resource.

4. Edit and apply the resource value as you would any other resource value.

Only the currently selected instance takes this resource value. The default resource value in the class definition is unchanged.


Hint: To temporarily turn off display of the element's instance name in an exposed resource name (that is, display background instead of myElementInstance.background ), hold MB1 down while the cursor is over the name. To locate a particular resource quickly, use the Resource Editor Search Area.

Exposing Callbacks and Event Methods

In addition to customizing the appearance of your class, you might also want to customize its behavior. The behavior, or interaction between your UI and the rest of your application is generally controlled with callbacks in Motif, and with event methods in Java. For more information, see Callback Procedures and Event Methods .

As you build your classes, you build a great deal of functionality into your UI classes using the callbacks and event methods for the class elements and the methods, (public, private, and protected) for the class itself.

You can give instances of a class access to the callbacks or event methods of its elements by exposing them just as you would any other resource. The process with which you do this is identical regardless of the language you are using. The results, however, differ slightly.


Note: This is an area where it is very easy to break "good" object-oriented programming practice. Consider very carefully whether you want to use an exposed callback or event method, or whether you should use a subclass instead.

Note: In ViewKit, it is better practice to use ViewKit's callback mechanism, provided by VkCallbackObject, rather than exposed callback resources.

Exposing Callbacks

Exposing a resource

To expose a callback or event method, follow these steps:

1. Switch the Browser to Classes view.

2. Update the Resource Editor for the desired component object.

3. Scroll the Resource Editor to the desired callback or event method.

4. Set the resource to the value that you want each instance to take by default.

5. Select Expose from the option menu to the right of the resource text field.


Note: Exposed resources are designated on the Resource Editor with an "open eye" icon to the left of the option menu.

Callback Source Code

With Motif, you can choose whether the instance callback routine augments or replaces the class's exposed callback. This is controlled by the Remove Overridden Exposed Callbacks toggle on the Code Generation tab of the Code Generation Preferences dialog (Browser:Options). Refer to Toggle options for more information.

Callbacks for class members (Motif) are generated in source code as two separate methods, described in detail in Object-Oriented Programming with C++ and OSF/Motif (Prentice Hall, 1995, 2nd Ed. ISBN 0-13-209255-7) by Doug Young. Exposing a callback results in a third, public method.

See Using Callbacks in C++ Classes for detailed information on these methods.

Subclassing and Receptors

When designing your classes with reuse in mind, you must strike a balance between power and flexibility. If a class has too little functionality, you have little incentive to use and reuse it, and if a class has too much functionality, it often becomes overly specific and difficult to use in other situations. If a class has too much flexibility (through exposed resources and methods), it might be reused, but maintenance benefits to the application are lost.

Subclassing helps to balance functionality, flexibility, and power. Creating a new class by subclassing an existing class allows you to adapt the class to a specific situation, while allowing other developers to leverage their knowledge of the often-reused parent class. Builder Xcessory makes it extremely simple to create subclasses.

Subclassing

All classes created within Builder Xcessory can also be subclassed. A subclass is a class created from another class, which inherits all of the objects, resources, methods, and data members of the superclass while also adding its own.

Making a subclass

To make a subclass, follow these steps:

1. Place Builder Xcessory in Classes view (Browser:Classes view).

2. Select the class you want to subclass.

3. Select Make Subclass from the Browser Edit (or MB3 Quick Access) menu. You are prompted to name the subclass. A new class is created and displayed in the Browser.

Example: 
Make a subclass ToggleField

To continue the example that began on Example: Creating an object , you might want to make a subclass ToggleField from the class LabelField, which consists of a form container with a label and a text field as children.

To make a subclass ToggleField from the class LabelField, follow these steps:

1. Confirm the Browser is in Classes view.

2. Select LabelField on the instance hierarchy.

3. Select Make Subclass from the Browser Edit (MB3) menu.

4. You are prompted to name the subclass. Name it ToggleField. The new class is created and displayed in the Browser ( Superclass LabelField and Subclass ToggleField ):

Superclass LabelField and Subclass ToggleField


Note: Note that LabelField appears in ToggleField's hierarchy with a colon designating it as the superclass of ToggleField.

5. You can now add methods and data members to your new subclass using the Resource Editor and the Member Editor. (See Adding Methods and Data Members for review.)

Editing superclasses

You can edit any of the exposed resources of the parent, or superclass. Edits made to the superclass propagate to all subclasses. Likewise, in each subclass instance, the default value of an exposed resource can be overridden, as can methods and data members.

Overriding exposed resources

To override the exposed resources of a superclass, use the Browser to select the :superclass object, then use the Resource Editor to specify the new resource values. ( :LabelField is an example superclass in Superclass LabelField and Subclass ToggleField .)

Receptors

Frequently, a major element of a new subclass is one or more additional children. Builder Xcessory allows you to add children when subclassing by designating a container in your superclass as the receptor . Specifying a receptor on a class allows you to extend the object hierarchy of an existing class through its subclasses while not affecting the original class and its class instances.

Making receptors

To specify a receptor (only one is allowed per class), follow these steps:

1. Confirm the Browser is in Classes view.

2. Select the component object that you want to designate as the receptor.

3. Select Make Receptor from the Browser Edit (Quick Access MB3) menu. A small icon, consisting of a square within a square, is placed to the left of the object in the Browser class hierarchy, designating the object as the receptor (for example, see Receptor ).

Any objects subsequently added to a subclass automatically become children of the receptor.

Example: Making the Form widget a receptor

Continuing the previous example, you might want to add to the subclass ToggleField a toggle button not part of the superclass LabelField. The toggle button has the LabelField class's form widget as its parent; therefore, you make the form the receptor.

To make the Form widget a receptor, follow these steps:

1. Confirm that the Browser is in Classes view.

2. Select the Form component within the LabelField hierarchy.

3. Select Make Receptor from the Browser Edit (MB3 Quick Access) menu. The result is shown in the following figure:

Receptor

Once you make a component object of a class a receptor, you can add children to any of that class's subclasses.

Adding children to subclasses

To add a child to a subclass, follow these steps:

1. Confirm the Browser is in Classes view.

2. Using MB2, drag the child widget from the Palette and drop it on the object with instance name ":<SuperclassName>" on the desired subclass's instance hierarchy.

The superclass's receptor is the designated parent of any objects added to a subclass.

Adding a toggle button

Continuing the LabelField example, assume you want to include a toggle button to the subclass ToggleField.

Saving and Sharing Classes

An important part of reuse is making the classes easily available to other developers. Builder Xcessory enables you to store and share classes with other Builder Xcessory users.


Note: Individual reuse is useful only when entire groups and organizations reuse the same objects.

Saving Classes

When you make a class, the class is added automatically to the Project Classes group at the bottom of the Palette. Classes in the Project Classes group are saved with your project, allowing other developers to access those classes. To use the class in other projects, or move it to the Private or Public Classes group, you must save it to a separate file.

Saving a class

To save a class, follow these steps:

1. Confirm the Browser is in Classes view.

2. Select the desired class.

3. Select Save Class from the Browser File menu to display a file selection dialog:

File Selection Dialog

4. Enter the file name and directory path, and click OK to save the class.

Sharing Classes

Before you can share a class, you must save the class UIL file separately from the rest of the project. This separates the class definition from any given interface.

Conditions for sharing classes

You can share classes under the following conditions:

· By manually placing classes into locations accessible to all developers, and then importing the classes manually

· By using the Builder Xcessory Palette.

Sharing Class Libraries

You can also share a library of classes among a group of users.

Building a class library

To build a class library:

1. Generate code for your classes and build your library.

2. After generating the class files, deselect the Generate Class toggle (Resource Editor:Component) for each class in your library and save the classes into separate files using Save Class (Browser:File:Class).

3. Move the classes to the Public Classes group.

4. Move the header files and library to the desired location. Save the source files to preserve any user code blocks for future modifications.

Preparing a library for sharing

Now, when you use the class in an application, Generate Code is deselected by default. You still need to do a couple of things:

1. If you are generating C++ and included the BX-generated UIComponent in your library, deselect the Class Tree Root toggle button in the File Names tab (Browser:Options:Code Generation Settings).


Note: If you always want to include the UIComponent in your library, click the Save As Default button on the File Names tab. The UIComponent will not be generated in the future by default.

2. Add the include path for the class header files and library containing the class to the application Makefile and select the Don't Include Ungenerated Class Files toggle button on the Makefile tab (Browser:Options:Code Generation Settings).


Note: If you always want to include the library and its header file path in the Makefile, click the Save As Default button on the Makefile tab.

Moving Classes Between Groups

Dragging classes

Once you save the class, you can drag the class from the Project Classes group to either the Private or Public Class section on the Palette.


Note: You must be in Outline view to drag classes from one group to another.

· If you leave the class in the Project Class group, the class appears on the Palette when the project file is loaded.

· If you move the class into the Private Class group, the class is saved into the .builderXcessory directory in your home directory and appears on the Palette each time you start Builder Xcessory.

· If moved into the Public Class group, the class is saved into the {BX}/xcessory/classes system directory and appears on the Palette of all Builder Xcessory users in your organization.


Note: Classes moved into either the Private or Public groups are locked by default. You cannot edit these classes, regardless of directory permissions. Unlock classes by selecting Unlock Class from the Class menu of the Browser File menu.

Reading Classes

Reading a class

You can read classes that you or other developers saved. To read a class, follow these steps:

1. Select Read Class from the Class menu of the Browser File menu. A file selection dialog is displayed ( File Selection Dialog ).

2. Enter the file and directory of the class, and click OK.

Specifying Include Files

Each class can have its own set of include files, which can be specified from the Resource Editor when Builder Xcessory is in Classes view. When the class is selected, the Resource Editor includes a section labeled Class File Include Information that in turn includes two subsections: Base Class Includes and Derived Class Includes (see Class Includes Sections ).


Note: Derived Classes are available only when you choose C++ as your default language.

Resource Editor:

Class Includes Sections

The two sections are scrollable text regions. The contents of the text regions are included verbatim into the base and derived class .hfiles. This allows you to specify different include file information for each class that you create.


Note: Derived Classes are supported for backward compatibility only. We do not recommend using Derived Classes.

 

To add the toggle button to ToggleField, follow these steps:

1. Confirm the Browser is in Classes view.

2. Drag the toggle button from the Palette.

3. Place the toggle button on the LabelField object on ToggleField's instance hierarchy ( Subclass with Child ):

Code Generation

The following sections describe the files generated by Builder Xcessory for each language.

C Code Generation

Builder Xcessory generates the following files (see files generated for C for more information):

· main-c.c contains function calls necessary for any application.

· creation-c.c contains the code to initialize and create all widgets in the application.

· creation-c.h contains include information, constant definitions, and pixmap specifications.

· callbacks-c.c contains code for all callbacks specified.

· bxutils-c.c contains functions used by Builder Xcessory-generated code.

· makefile-c and Imakefile allow the generated code to be built into the application.

When using classes, Builder Xcessory generates the same files and adds some new ones. The differences are listed as follows:

· creation-c.c is the same for all widgets not part of a class. For each instance of a class, this file has a call to a function to create and initialize the widgets comprising that class. This results in a smaller file.

· creation-c.h also includes the <class>.h files for each class <class> that is generated.

· makefile-c and Imakefile contain the same targets, but include the additional class files to compile and link in to create the targets.

In addition, the following files are created for every class, <class>, created in Builder Xcessory:

· <class>.c contains the code to create and initialize the widgets comprising the class.

· <class>.h contains a data type that is a structure of the widget ID's of all widgets that are part of the class.

C++ Code Generation

If you do not have any classes when you generate the C++ code, the contents of each TopLevelShell are generated as a class and named using the instance name of the shell's immediate child.

In all cases, the following files are generated (see Files generated for C++ for more information):

· main-C.C contains function calls necessary for any application and calls the constructor of each generated top-level class.

· <class_name>.C contains the code for the constructor and destructor for each class generated. In the constructor, all the objects in the application are created (similar in C code to the creation-c.c file).

· <class_name>.h defines the class created by <class_name>.C and any required structures.

· UIComponent.C contains the base class for all objects created.

· UIComponent.h contains the definition of the UIComponent base class and any required structures.

· callbacks-C.C contains code for all callbacks specified on top-level shells and on other elements that are not specific class members.

· bxutils-C.C contains functions called in the other generated files.

· defs-C.h contains definitions of constants, pixmaps, and global instances of widgets or classes used in the application.

· makefile-C and Imakefile allow the generated code to be built into the application.

UIL Code Generation

Builder Xcessory generates the following files (see Files generated for UIL for more information):

· main-uil.c contains function calls necessary for any application.

· uil.uil contains a description of the widgets.

· callbacks-uil.c contains code for all callbacks specified.

· main-uil.h contains declarations of constants, and global instances of widgets or classes used in the interface.

· bxutils-uil.c contains functions used by Builder Xcessory code.

· makefile-uil and Imakefile allow the generated code to be built into the application. Imakefile specifies both UIL and C imake information. Makefile has targets for UIL as well as the associated C files.

· app-defaults includes all resources with app-defaults value set to App.

ViewKit Code Generation

Builder Xcessory divides ViewKit code generation into the following files (see Files generated for ViewKit for more information):

· main-vk.C contains function calls necessary for any application. VkApp is instantiated here along with other application level classes, such as your top-level window classes.

· <class_name>.C contains the code for the constructor and destructor for each class you created. In the constructor, all objects in the application are created (similar in C code to the creation-c.c file). The constructor also binds any callbacks assigned to widgets and contains the methods for those callbacks.

· <class_name>.h defines the class created by <class_name>.C and any structures that it needs.

· defs-vk.h contains the constants registered in your interface.

· callbacks-vk.C contains code for all callbacks specified on elements that are not specific class members.

· bxutils-vk.C contains functions for Builder Xcessory-generated code calls.

· makefile-vk and Imakefile allow the generated code to be built into the application.

Builder Xcessory automatically subclasses from VkWindow, VkSimpleWindow, and VkComponent as appropriate. Additionally, Builder Xcessory subclasses any classes you create from Motif widgets from VkComponent.

Java Code Generation

Builder Xcessory divides Java code generation into the following files (see Files generated for Java for more information):

· MainApp.java creates an instance of each top-level class in your program. If you have only one top-level class, you might not need to use this class. (This is similar to the C language file main.c .)

· MainApp.html is an HTML file in which your applet is embedded, or with which you can launch your application using the Java Virtual Machine in your browser.

· <class_name>.java contains the code for each class you created.

· Defs.java contains the constants registered in your interface.

· makefile-java allows the generated code to be built into the application or applet.


Note: All generated files have comments generated in the JavaDoc format.

Java application attributes

Builder Xcessory allows you to create Java applications or Java applets. Java applications have the following attributes:

· Contain a single main() method

· Execute in a stand-alone fashion

· Do not require a browser

Java applet attributes

A Java applet runs from a browser. Rather than having a single main() method, an applet implements a set of methods that control how it is initialized, drawn, handles events, and so forth. Java applets have the following attributes:

· Require a Java-enabled browser or applet viewer

· Must be embedded in an HTML page

· Typically subject to restrictions, depending upon the browser, due to security issues relating to the transfer of code


Note: Due to security restrictions present in most web browsers, many commonly used system methods, such as System.exit()cannot be used.

 

Documentation: