IlvPalette: Drawing Using a Group of Resources

In Views, the drawing resources are assembled into an object of the IlvPalette class. The only way to draw anything is to use an IlvPalette object. Most predefined graphic objects handle one IlvPalette (but sometimes more) to draw themselves.

Unlike other IlvResource subclasses, IlvPalette has public constructors. However, the standard way of creating a palette is still to get it from the getPalette methods. The public constructors must only be used to create palettes that cannot be shared.

An IlvPalette can be shared or not. Named palettes are a subset of shared palettes.

For additional details, see the sections:

Locking and Unlocking Resources

An IlvPalette locks all the resources it contains and unlocks them when they are no longer used (palette destruction or replacement of a resource).

Clipping Area

The following methods are used to change the clipping area used to draw with the palette.

void setClip(const IlvRect* = 0) const;

void setClip(const IlvRegion*) const;

If you use a drawing method, the drawing will appear only in the clipping area; other areas will not be modified.

That is why you must clip the drawing when you write the draw method of an IlvGraphic subclass. The draw method gives you a clipping region as a parameter. You must set this clip on all the palettes that you are using to do the drawing. Once you have finished drawing, you must reset the clip of each palette to its previous clip, since the palettes are shared. This can be done using the IlvPushClip class.

Here is an example:

void MyGraphic::draw(IlvPort* dst,

const IlvTransformer* t,

const IlvRegion* clip) const

{

IlvPalette* myPalette = getPalette();

IlvPushClip (*myPalette, clip);

IlvPoint p1(10, 10), p2(50, 50);

// Do my drawings

dst->drawLine(myPalette, p1, p2);

}

Creating a Non-shared Palette

You can create a palette that cannot be shared by using the public constructors of IlvPalette:

IlvPalette(IlvDisplay* display);

IlvPalette(IlvPalette* palette);

IlvPalette(IlvDisplay* display,

IlvColor* background,

IlvColor* foreground,

IlvFont* font,

IlvPattern* pattern);

The first constructor creates a default palette, the second creates a copy of the palette given as its argument, and the third creates the palette with its characteristics passed as arguments. Once you have a new palette, you can use its member functions to set its internal resources (doing so with shared palettes is not recommended).

You can use this technique on the rare occasions when you do not want the palette to be shared at all or when you want to have total control on the way the palette is shared. You then have the responsibility of deleting it explicitly when it is no longer needed. Note that a palette built this way still uses shared resources (colors, fonts, and so on).

Creating a Shared Palette

Each IlvDisplay instance maintains a list of shared palettes. When you need a new palette, you must ask the display to supply it. This class provides a method getPalette that lets you specify the internal resources of the palette. The other member function getPalette(const char* name) is discussed in the next section on named palettes.

If a palette matching your requirements already exists in the list, this palette is returned. If no such palette is found in the list of shared palettes, a new palette is created, added to the list and returned. The member function getPalette does not lock the returned palette. You can set some resource parameters of this function to NULL. The display then uses the corresponding default resources.

The use of shared palettes is very common and sufficient for most applications. However, you must keep in mind that these palettes are indeed shared and that modifying one of them is very likely to have undesirable side effects. Most of the time, palettes are used to control the way graphic objects (that is, subclasses of IlvGraphic) are drawn.

You should not try to modify a palette itself, but instead use the graphic object member functions to modify its graphic properties. The graphic object then gets another palette for the display and keeps the old palette unchanged, in case it is used somewhere else in the application.

The following code shows the right and wrong ways of using palettes:

// To set the foreground color of IlvGraphic* graphic

IlvColor* color = graphic->getDisplay()->getColor("blue");

 

// The following line will affect all objects sharing the palette

graphic->getPalette()->setForeground(color); // Wrong way

 

// The following line will give another palette to the graphic object

// and will not affect objects pointing to the previous palette

graphic->setForeground(color); // Right way

Naming Palettes

As with most other resources, palettes can be named using their IlvResource::setName member function. This function overwrites any existing name, so before naming a palette, you should check if the palette already has a name.

You can use the member function getPalette(const char* name) to retrieve a shared palette by its name.

The name of a palette is saved when graphic objects are written to an output stream. When this data is read as an input stream, the display first tries to find an existing palette with the same name. If none is found, the display tries to load the palette the usual way (that is, it looks for an existing palette matching the description, and if none exists, it creates a new palette and names it).