Writing C++ Applications Using Prototypes
As a general rule, you create your prototypes in Views Studio and then use them in your application. The following section explains the C++ API that you use to add prototypes to your application and how to manipulate these prototypes.
The following items are described in this section:
Header Files
To make sure that your application is linked with the necessary library packages, you must first include the header files corresponding to the graphic objects, the accessors (subclasses of
IlvUserAccessor), and the interactors used in the prototypes that you will load.
To include all the predefined accessor classes, use the header file <ILVHOME>/include/ilviews/protos/allaccs.h.
Here is a typical set of header files to include in order to build an application that can load prototypes containing any type of graphic object:
#include <ilviews/protos/protogr.h> // for IlvProtoGraphic.
#include <ilviews/protos/allaccs.h> // for all accessors.
#include <ilviews/graphics/all.h> // for all graphic objects.
#include <ilviews/gadgets/gadgets.h> // if you use gadgets in your prototypes.
#include <ilviews/graphics/inter.h> // for all object interactors.
You may also want to add the following header files:
#include <ilviews/protos/groupholder.h> // to get the groups attached
// to a given container or manager.
#include <ilviews/protos/proto.h> // to manipulate prototypes and
// their libraries.
#include <ilviews/protos/grouplin.h> // to attach prototypes to
// application objects.
If you know in advance the Prototypes that you will use, you can reduce the size of your application by including only the necessary header files instead of allaccs.h, graphics.h, and gadgets.h.
To compile applications that use the prototypes package, you must compile them with the library ilvproto. This library also requires the following libraries: ilvgrapher, ilvmgr, and the usual Views libraries for your platform. The ilvgdpro library may be needed for applications that use old features of prototypes.
Loading a Panel Containing Prototype Instances
To load a
.ilv file containing prototype instances, you simply use the
read or
readFile methods of
IlvManager or
IlvContainer:
Container->readFile("protoSample.ilv");
All the prototypes used in the file will be loaded automatically from their prototype libraries. Prototype libraries are searched for in the file system using the display path. For example, if the panel contains prototypes from a prototype library called mylib located in /usr/home/yourdir/protolibs/mylib.ipl, you should include /usr/home/yourdir/protolibs/ in your ILVPATH environment variable.
To allow handling of groups in a container or manager, the
IlvGroupHolder class provides all the necessary interface. Instances of the
IlvGroupHolder class are automatically attached to containers or managers containing prototype instances. This class provides the methods for adding, removing, and retrieving groups (and thus prototype instances). You can retrieve the group holder attached to a container, manager, or graphic holder with the global methods:
IlvGroupHolder* groupHolder = IlvGroupHolder::Get(manager); IlvGroupHolder* groupHolder2 = IlvGroupHolder::Get(manager ->getHolder());
IlvGroupHolder* groupHolder3 = IlvGroupHolder::Get(container); Loading Prototypes
You may need to create instances of your prototypes by coding. To create instances of your prototypes, you must first load them. You can load a whole prototype library and then load one or more of the prototypes it contains. To do this, create an instance of the
IlvProtoLibrary class and call its
load method:
IlvProtoLibrary* lib = new IlvProtoLibrary(display, "mylib");
if(!lib->load())
IlvFatalError("Could not load prototype library");
If you want to load a prototype library that is not located in the display path, you can specify the directory where the library is located in the call to the constructor:
IlvProtoLibrary* lib = new IlvProtoLibrary(display, "mylib",
"/usr/somewhere/protos");
if(!lib->load())
IlvFatalError("Could not load prototype library");
Once you have loaded a prototype library, you can retrieve all its prototypes or a particular prototype with the following methods:
IlUInt count;
IlvPrototype** protos = lib->getPrototypes(count);
or:
IlvPrototype* proto = lib->getPrototype("myproto");
The array returned by the getPrototypes method is allocated with the new[] operator and must be released with the delete[] operator when it is no longer needed.
Alternatively, you can load each prototype individually with the global function IlvLoadPrototype:
IlvPrototype* proto = IlvLoadPrototype("mylib.myproto", display);
The first argument specifies the name of the prototype library and the name of the prototype (separated by a period). The second argument is the instance of
IlvDisplay that your application has created. The prototype library file and the prototype files are searched for in the file system using the display path.
Creating Prototype Instances
To create an instance of a prototype, use the clone method:
IlvPrototypeInstance* instance = proto->clone("myinstance");
The argument of the clone method is the name of the new instance. You can pass 0, which means that a name is generated automatically.
Instances of the
IlvGroupHolder class are automatically attached to containers or managers containing prototype instances. This class provides the methods for adding, removing, and retrieving groups (and thus prototype instances).
To add the new prototype instance to a manager or a container, you can use the
addGroup methods of the
IlvGroupHolder attached to manager/container classes:
IlvGroupHolder* groupHolder = IlvGroupHolder::Get(manager);
groupHolder->addGroup(instance);
Alternatively, you can create an
IlvProtoGraphic object and directly place it in the manager.
IlvPrototype* proto;
// Create an instance of the prototype proto and places it
IlvProtoGraphic* protoGraphic1 = new IlvProtoGraphic(proto);
// Create an instance of a prototype
IlvProtoInstance* protoInstance = proto->clone(“instance2”);
IlvProtoGraphic* protoGraphic2 = new IlvProtoGraphic(protoInstance);
manager->addObject(protoGraphic1);
manager->addObject(protoGraphic2);
Often, you will set the position of the prototype instance when you add it to a manager or container. You can do this by either:
manager->moveObject(protoGraphic1, 100, 100).
Deleting Prototype Instances
To remove a prototype instance from its container or its manager, you can use the
removeGroup methods of the
IlvGroupHolder class:
groupHolder->removeGroup(instance);
You can also remove its embedding
IlvProtoGraphic from its container or manager:
manager->removeObject(protoGraphic);
To completely delete a prototype instance, simply call the delete operator. You can also delete its encapsulating protoGraphic.
Retrieving Groups and Prototype Instances
To get all the groups contained in a manager or container, use the getGroups method of its attached group holder:
IlUInt count;
IlvGroup** instances = groupHolder->getGroups(count);
Note: The array of pointers returned by the getGroups method is allocated using the new[] operator and must be deleted with the delete[] operator when it is no longer needed. |
To retrieve a group by its name, use the getGroup method:
IlvProtoInstance* pump = (IlvProtoInstance*)groupHolder->getGroup("pump");
This method returns 0 if the specified group does not exist.
Getting and Setting Attributes
Prototype instances are manipulated through a uniform API based on named attributes (also called properties or accessors). This API is the same as the one provided by the class
IlvGraphic and basically consists of the
IlvGraphic::changeValue and
IlvGraphic::queryValue methods.
A named attribute is represented by an instance of the
IlvValue class and is defined by the following:
The attribute name, “label” for example, to access the label of a button.
A value, which can be of different types (for example, a character string, an integer, or a pointer).
A type that corresponds to the type of the data.
The type of the value is set automatically by the
IlvValue class. You use constructors to initialize values of predefined types (such as
IlInt,
const char*,
IlvColor*, and so on). You can also change a value using the assignment operator
= or by casting an
IlvValue to a predefined type. The
IlvValue class handles all conversions automatically. For more details, see the
IlvValue class in the
Views Reference Manual.
To set a value for a prototype instance, you must create an
IlvValue and call the
IlvGraphic::changeValue method:
IlvValue xval("x", (IlInt)100);
instance->changeValue(xval);
Note: The explicit cast of the value 100 to the type IlInt is necessary because an ambiguity exists between the integer and Boolean types. Without the cast, the compiler might (on some platforms) call the constructor that creates an IlvValue of type IlBoolean. It is recommended that you always use explicit casts when using constants to initialize an IlvValue. |
You do not need to create a new
IlvValue every time you want to change a value. You can use an existing
IlvValue and change its data with the assignment operator:
xval = (IlInt)200;
instance->changeValue(xval);
You can set several values in a single call. To do this, you must create and initialize an array of
IlvValue objects and call the
changeValues method. The following example shows how to set the position of an object in a single call:
IlvValue vals[] = {
IlvValue("x", (IlInt)100),
IlvValue("y", (IlInt)200)
};
instance->changeValues(vals, 2);
To retrieve a value, use the queryValue method:
IlvValue xval("x");
IlInt x = instance->queryValue(xval);
The
queryValue method takes an
IlvValue reference as parameter. The
IlvValue must be initialized with the name of the value to retrieve. The
queryValue method stores the retrieved value in its argument and returns a reference to it. In the example, assigning the result of
queryValue to the integer variable
x calls the
IlvValue to the
IlInt cast operator.
To retrieve several values in a single call, create an array of
IlvValue objects and call the
queryValues method:
IlvValue vals[] = { "x", "y", "width", "height" };
instance->queryValues(vals, 4);
IlInt x = vals[0];
IlInt y = vals[1];
IlUInt width = vals[2];
IlUInt height = vals[3];
The
IlvValue class converts values automatically as required. This means that you do not need to know the exact type of a value that you set or retrieve. For example, you could set the position of an object using a string value as follows:
IlvValue xval("x", "100");
instance->changeValue(xval);
Conversely, when you retrieve a value, you can convert it to the type you need as follows:
IlvValue xval("x");
instance->queryValue(xval);
float x = xval;
User-Defined and Predefined Attributes
A prototype and its instances have three kinds or attributes: user-defined attributes, predefined attributes, and sub-attributes.
User-Defined Attributes
The user-defined attributes are the attributes defined by the accessors that you attached to the prototype when you designed it in Views Studio. They vary from one prototype to another. The effect of setting or retrieving a user-defined attribute is determined by the accessor objects that compose it.
For example, suppose that you have created a prototype representing a thermometer. You defined a temperature attribute by adding a reference accessor that maps the temperature to the value attribute of a gauge. To change the temperature displayed by an instance of your prototype, use the changeValue method as follows:
IlvValue tempVal("temperature");
tempVal = 22.5;
instance->changeValue(tempVal);
Predefined Attributes
The predefined attributes of a group let you modify or retrieve common properties that all prototypes have, such as the position, the size, the visibility, and so on.
Most predefined attributes take effect only when a group is added to a manager or a container, but they can be set before that. They are stored in the graphic node but only take effect when the group is added.
Predefined Attributes of Prototypes and Prototype Instances
Attribute | Type | Description |
---|
layer | IlInt | Set this attribute to move all the nodes of the group to a given layer. Retrieving this attribute returns the layer where the nodes of the group are contained. If all nodes are not in the same layer, the result is undefined. |
visible | IlBoolean | Set this attribute to hide or show a group. Retrieving this attribute returns IlTrue if all the graphic nodes of the group are visible and IlFalse if they are all invisible. The result is undefined if some nodes are visible and other nodes are invisible. |
x | IlInt | This attribute is the horizontal coordinate of the upper-left corner (in manager coordinates) of the group bounding box, without applying any view transformers. |
y | IlInt | This attribute is the vertical coordinate of the upper-left corner (in manager coordinates) of the group bounding box, without applying any view transformers. |
width | IlUInt | This attribute is the width of the group bounding box (in manager coordinates), without applying any view transformers. |
height | IlUInt | This attribute is the height of the group bounding box (in manager coordinates), without applying any view transformers. |
centerX | IlInt | This attribute is the horizontal coordinate of the center of the group bounding box (in manager coordinates), without applying any view transformers. |
centerY | IlInt | This attribute is the vertical coordinate of the center of the group bounding box (in manager coordinates), without applying any view transformers. |
interactor | const char* | Set this attribute to associate an interactor with all the graphic nodes of the group. The value of the attribute is the interactor name (for example, “Button”). Retrieving this attribute returns the name of the interactor associated with the graphic nodes of the group. If all nodes do not have the same interactor, the result is undefined. |
Sub-attributes
The sub-attributes of prototypes let you directly access the attributes of the objects contained in your prototypes. The names of sub-attributes are built by concatenating the path of the object and the attribute name. The components of a sub-attribute name are separated by a period. For example, if your prototype contains an
IlvLabel named
title, you can set or retrieve its label using the attribute name
title.label.
All the predefined properties listed in
Predefined Attributes of Prototypes and Prototype Instances can also be accessed for a particular graphic node.