IlvGraphic: The Graphic Objects Class

Views graphic objects inherit attributes from the abstract base class IlvGraphic. This class allows a Views graphic object to draw itself at a given destination port, and, if desired, with a transformation of its coordinates determined by an associated object of the IlvTransformer class.

IlvGraphic has member functions that allow you to set and change geometric dimensions. A handful of member functions are given to set and get user properties that can be associated with an object for application-specific purposes. The IlvGraphic class does not actually implement these member functions. They are declared as virtual member functions, and are defined to do various operations in the classes that inherit IlvGraphic attributes. Though the member functions to manipulate geometric shapes and graphic attributes are present, they do nothing.

Member Functions

IlvGraphic member functions can be presented in several groups:

  • Geometric properties  These member functions handle location, size, and drawing properties, which include the draw method used to draw the graphic object. The virtual draw method should be defined conjointly with the method boundingBox, which defines the smallest rectangle that entirely contains all the area covered by the graphic object.

  • Graphic properties  Use these member functions to change the visible aspect of the objects, that is, their color or pattern. You do so by means of member functions that indicate graphic properties of graphic objects and modify the palette bound to these graphic objects. The following example shows how to set the background of any graphic object:

IlvButton* mybutton = new IlvButton(display,

IlvPoint(20,20),

"Quit");

IlvColor* color = display->getColor("gold");

if (color) mybutton->setBackground(color);

  • User properties  IlvGraphic objects can be associated with a set of source code user properties. User properties are a set of key-value pairs, where the key is an IlSymbol object and the value may be any kind of information value. User properties are not persistent.

These member functions provide you with a simple way to connect your graphic objects with information that comes from your application. You can keep track of the graphic part of your application by storing the pointers to objects you create, and connect the graphic side to the application by means of user properties, for example:

IlInt index = 10;

IlSymbol* key = IlGetSymbol("objectIndex");

mybutton->addProperty(key, (IlAny)index);

Some member functions provide tag management. Tags are markers that you can apply to graphic objects to identify them. You can then use various Views functions to manipulate only the tagged objects.

  • Gadget properties  Gadget properties handle the sensitivity of objects to events, the callbacks to be called when the object is activated, the client data stored with objects, and the object interactor associated with the object class. For details on using callbacks, see the section Callbacks.

  • Focus chain properties  The focus indicates the object on the screen that is receiving any keyboard events. The focus chain is the order of the objects on the screen that receive the focus. The focus moves to the next object in the focus chain when, typically, the Tab key is pressed, or to the previous object when shift-Tab is pressed.

  • Class information   Subtypes of the class IlvGraphic can handle information at the class level. This means that all instances of a given class can share the same information. For example, IlvGraphic::className allows you to get the class name and IlvGraphic::isSubtypeOf returns IlTrue if the target IlvGraphic object is a subclass of the given class argument. This example shows how to use class information member functions:

IlvButton* button = new IlvButton(display,

IlvPoint(10,10),

"sample");

// Get the IlvClassInfo object associated with the button class.

IlvClassInfo* classInfo = button->getClassInfo();

 

// Get the name of the IlvGraphic class and print it: "IlvButton"

const char* name = classInfo->getClassName();

IlvPrint(name);

 

// Get the name of the super class and print it: "IlvMessageLabel"

name = classInfo->getSuperClass()->getClassName();

IlvPrint(name);

 

IlBoolean isSubtype =

classInfo->isSubtypeOf(IlvSimpleGraphic::ClassInfo());

name = isSubtype ? "It's a subtype" : "error";

IlvPrint(name);

  • Class properties  Static member functions and their non-static equivalents let you handle properties at the class level, that is, these properties are defined for every instance of the class. In some methods, the IlBoolean parameter allows you to operate iteratively on each superclass of the object until a match is found. Here are the member functions that deal with class properties:

void AddProperty(const IlSymbol* key, IlAny value);

void RemoveProperty(const IlSymbol* key);

void ReplaceProperty(const IlSymbol* key, IlAny value);

void GetProperty(const IlSymbol* key,

IlBoolean checkSuperClass = IlFalse);

const IlvClassInfo* HasProperty(const IlSymbol* key,

IlBoolean checkSuperClass = IlFalse);

void addClassProperty(const IlSymbol* key, IlAny value);

IlBoolean removeClassProperty(const IlSymbol* key);

IlBoolean replaceClassProperty(const IlSymbol* key,

IlAny value);

IlAny getClassProperty(const IlSymbol* key,

IlBoolean checkSupCl = IlFalse) const;

const IlvClassInfo* hasClassProperty(const IlSymbol* key,

IlBoolean checkSupCl = IlFalse) const;

Here is an example that shows how to use class properties:

Let us imagine a map where graphic instances are shown with toggle-like sensitive behavior (Views provides specific objects called interactors that allow you to associate a behavior with graphic objects). Sometimes we may want these elements to be insensitive. Instead of scanning the object list to set the sensitivity to IlFalse, we use a class-level property in this way:

Let myClass be a subclass of IlvGraphic; and let myInteractor, a subclass of IlvToggleInteractor, be an interactor attached to myClass.

// Add the class-level property

myClass* obj = new myClass(display);

obj->addClassProperty(IlGetSymbol("sensitive"),

(IlAny)IlTrue);

In the applicative code, the application tests whether sensitivity must be inverted. There is another way to add a property to a class object, using a static member function, since both statements are equivalent:

if (anyValue == IlTrue)

{

myClass::AddProperty(IlGetSymbol("sensitive"),

(IlAny)IlFalse);

}

In the implementation file of the myInteractor class, we redefine the parent class method handleEvent to add our specific behavior, that is freezing the sensitivity when a certain condition is present:

IlBoolean

myInteractor::handleEvent(IlvGraphic* object,

IlvEvent& event,

IlvContainer* cont,

IlvTransformer* transf)

{

// gets the sensitivity state

IlSymbol* symbol = IlGetSymbol("sensitive");

if (object->hasClassProperty(symbol))

{

if (!object->getClassProperty(symbol))

return IlFalse;

}

return IlvViewToggleInteractor::handleEvent(object,

event,

cont,

transf);

}

  • Input/Output properties  These member functions let you read and write your object descriptions from and to special kinds of streams, known as IlvInputFile and IlvOutputFile, which handle the reading and writing of objects from C++ streams.

Views offers a basic implementation of these classes, which were designed so that you can easily add your specific information. Therefore, when you need to save and load application-dependent data, you should create your own subtypes of these two classes.

Writing Graphic Objects

The IlvOutputFile class writes the complete description of a series of objects in an output stream. You can use this class in the following way:

// Open a file output stream

fstream outstream("image.ilv", ios::out | ios::trunc);

 

// Initialize the number of objects and their array of pointers

const IlvUInt n = 10;

IlvGraphic* outObjects[n];

for (IlvUInt i=0; i<n; i++)

outObjects[i] = new IlvRectangle(display,

IlvRect(0, 0, 200, 100));

 

// Create the IlvOutputFile

IlvOutputFile outfile(outstream);

 

// Write the objects and get in outTotalCount the number

// of objects actually stored

IlvUInt outTotalCount = 0;

outfile.saveObjects(n, outObjects, outTotalCount);

Reading Graphic Objects

The IlvInputFile class is the main class for reading objects from a stream. The following code shows how to read IlvGraphic objects from an input stream:

// Open a file input stream

fstream instream("image.ilv", ios::in);

 

// Create the IlvInputFile

IlvInputFile infile(instream);

 

// Get the number of created objects and their array of pointers

IlUInt InTotalCount = 0;

IlvGraphic* const* inObjects = infile.readObjects(display,

InTotalCount);