VisCompClass
allows visible objects to have children. VisComp objects are the grouping elements within visible object trees.
If you need to have a visible object tree with several levels, or if you need to manage the geometry of visible objects, you will want to read this chapter. You should already be familiar with
VisClass
1 VisCompClass Features
2 VisCompClass Instance Data
2.1 VCI_comp
2.2 VCI_gadgetExcl
2.3 VCI_window
2.4 VCI_geoAttrs
2.5 VCI_geoDimensionAttrs
2.6 Managing Instance Data
3 Using VisCompClass
3.1 Managing Geometry
3.2 Managing Graphic Windows
Composite visible objects provide several features and functions that normal visible objects can not.
VisCompClass
has several instance data fields above and beyond those found in
VisClass
(since
VisCompClass
is a subclass of
VisClass
, it inherits all its instance data and methods). Although it only handles a few messages not defined in
VisClass
, it provides much more functionality. Some of the main features of composite objects are listed below:
VisCompClass
can have children, allowing the tree to be built to any number of levels. See the VisClass chapterfor full information on visible trees.
VisClass
functions.
VisCompClass
inherits all the instance data fields and messages of
VisClass
. As such, it can do everything normal
VisClass
objects can do. See the VisClass chapterfor full information on
VisClass
.
As stated above,
VisCompClass
inherits all the instance data fields from
VisClass
. All of those fields may be set and reset as they could be for an object of that class. Composite objects also have four other instance fields, shown in VisCompClass Instance Fields
.
Code Display 16-1 VisCompClass Instance Fields
/* The VisCompClass instance data fields are shown below and are discussed in * detail throughout the chapter. */
/* VCI_comp * VCI_comp contains the link to the composite object's first child. */
@instance @composite VCI_comp = VI_link;
/* VCI_gadgetExcl * VCI_gadgetExcl is an optr to the object that currently has the gadget * exclusive. This field is rarely used directly by applications. */
@instance optr VCI_gadgetExcl;
/* VCI_window * VCI_window contains the window handle of the graphics window associated * with this object. This field is rarely accessed directly by * applications; it is set by the visual update mechanism. */
@instance WindowHandle VCI_window = NullHandle;
/* VCI_geoAttrs * VCI_geoAttrs is a record that defines some of the geometry management * information for the composite. None of its values are set by default; * the possible flags in this record are shown after the definition. */
@instance VisCompGeoAttrs VCI_geoAttrs = 0; /* Possible flags: * VCGA_ORIENT_CHILDREN_VERTICALLY 0x80 * VCGA_INCLUDE_ENDS_IN_CHILD_SPACING 0x40 * VCGA_ALLOW_CHILDREN_TO_WRAP 0x20 * VCGA_ONE_PASS_OPTIMIZATION 0x10 * VCGA_CUSTOM_MANAGE_CHILDREN 0x08 * VCGA_HAS_MINIMUM_SIZE 0x04 * VCGA_WRAP_AFTER_CHILD_COUNT 0x02 * VCGA_ONLY_DRAWS_IN_MARGINS 0x01 */
/* VCI_geoDimensionAttrs * VCI_geoDimensionAttrs is a record that contains additional information * about the composite's geometry. This field contains two two-bit fields * among its other flags. The default settings are shown in the definition; * all possible flags and settings are shown following. */
@instance VisCompGeoDimensionAttrs VCI_geoDimensionAttrs = 0; /* Possible flags: * Width Justification flags (mutually exclusive): * VCGDA_WIDTH_JUSTIFICATION 0xc0 * WJ_LEFT_JUSTIFY_CHILDREN 0x00 * WJ_RIGHT_JUSTIFY_CHILDREN 0x40 * WJ_CENTER_CHILDREN_HORIZONTALLY 0x80 * WJ_FULL_JUSTIFY_CHILDREN_HORIZONTALLY 0xc0 * * Height Justification flags (mutually exclusive): * VCGDA_HEIGHT_JUSTIFICATION 0x0c * HJ_TOP_JUSTIFY_CHILDREN 0x00 * HJ_BOTTOM_JUSTIFY_CHILDREN, 0x04 * HJ_CENTER_CHILDREN_VERTICALLY 0x08 * HJ_FULL_JUSTIFY_CHILDREN_VERTICALLY 0x0c * * Other flags: * VCGDA_EXPAND_WIDTH_TO_FIT_PARENT 0x20 * VCGDA_DIVIDE_WIDTH_EQUALLY 0x10 * VCGDA_EXPAND_HEIGHT_TO_FIT_PARENT 0x02 * VCGDA_DIVIDE_HEIGHT_EQUALLY 0x01 */
@default VI_typeFlags = VTF_IS_COMPOSITE;
Normal visible objects have just one instance field for tree construction: the
VI_link
field that points to the object's next sibling. For an object to have children, it must also have an instance field declared with the keyword
@composite
; this field, in
VisCompClass
, is
VCI_comp
. The composite field contains the optr of the object's first child; the link field contains a pointer to either the object's next sibling or its parent.
Applications should never access the
VI_link
or
VCI_comp
fields directly at run-time; instead, these fields can be altered or queried with the following messages (all defined in
VisClass
):
MSG_VIS_ADD_CHILD
MSG_VIS_REMOVE_CHILD
MSG_VIS_MOVE_CHILD
MSG_VIS_GET_PARENT
Several other messages may also be used to change or query any visible object's
VI_link
and
VCI_comp
fields. These are discussed in the VisClass chapter.
Since the composite object must manage several other objects, it must also keep track of certain hierarchies used by the UI; the gadget exclusive is one of these. Within each branch of the visible object tree, only one visible object may have the gadget exclusive at a time. The gadget exclusive is kept track of via a path of pointers from the top of the tree down to the object having the exclusive.
The
VCI_gadgetExcl
field determines which child of the composite has the gadget exclusive. The child indicated in this field may or may not actually have the gadget exclusive for the entire visible tree; if the branch does not have the exclusive, neither will the child object. The gadget exclusive is similar to the other hierarchies of the input manager and acts the same way.
Applications never access the
VCI_gadgetExcl
field of a composite directly. Instead, this field may be set with the following three
VisClass
messages:
MSG_VIS_TAKE_GADGET_EXCL
VCI_gadgetExcl
field appropriately.
MSG_VIS_RELEASE_GADGET_EXCL
VCI_gadgetExcl
field appropriately.
MSG_VIS_LOST_GADGET_EXCLThe above messages are detailed in the VisClass chapter.
Every visible object has a window associated with it in which it will be drawn. Normal
VisClass
objects have no control over what window they're associated with; they must be in the same window as their composite parents. Composites may need to appear in different windows from their parents, however.
Thus,
VisCompClass
has the
VCI_window
field, which contains the window handle of the window in which the composite's branch will be drawn.
Applications will not access this field directly. Typically, composites will be drawn in the window associated with their parent composites or contents. Sometimes, however, an application will want a visible branch to appear in a window different from that of the rest of the visible tree. The composite then must use other
VisClass
messages for creating and associating a window. This process is discussed in more detail in Managing Graphic Windows
.
The most-used feature of composite objects is their ability to manage the sizing and placement of their children. This is known as managing the composite's geometry.
The geometry management behavior implemented by a particular composite object is determined by its
VCI_geoAttrs
and
VCI_geoDimensionAttrs
fields. Both of these fields may be set and altered by applications as their geometry needs change. The
VCI_geoAttrs
field, specifically, determines the type of geometry management employed by the composite.
The
VCI_geoAttrs
field may contain any or all of the following eight flags:
VCI_geoDimensionAttrs
), this flag indicates that there should be as much space before the first child and after the last child as there is between the children. If this flag is not set, there will be no space outside the first and last children.
VI_bounds
field, just as other Vis objects. This flag in a composite indicates custom management for the composite's entire branch, not just its children.
MSG_VIS_COMP_GET_MINIMUM_SIZE
handler.
MSG_VIS_COMP_GET_WRAP_COUNT
.
The
VCI_geoDimensionAttrs
field determines how the composite manages its children in each dimension. It provides the geometry information not given in
VCI_geoAttrs
such as child justification and certain sizing behavior.
It contains three fields for each dimension (horizontal and vertical): The first field represents the justification of the children in that dimension. This field is two bits and can be one of four different enumerations. The second and third fields are sizing flags. These fields are listed below:
VCI_geoAttrs
).
VCI_geoAttrs
).MSG_VIS_COMP_GET_GEO_ATTRS, MSG_VIS_COMP_SET_GEO_ATTRS
To retrieve the flags currently set in both
VCI_geoAttrs
and
VCI_geoDimensionAttrs
, use
MSG_VIS_COMP_GET_GEO_ATTRS
. To set the attributes in either or both fields, use
MSG_VIS_COMP_SET_GEO_ATTRS
. both of these messages are detailed below.
void MSG_VIS_COMP_SET_GEO_ATTRS(
word attrsToSet,
word attrsToClear);
This message sets the flags in the composite object's
VCI_geoAttrs
and
VCI_geoDimensionAttrs
fields. The high byte of each parameter represents the dimension attributes, and the low byte represents the geometry attributes. This message does not invalidate or update the object's geometry.
Source: Unrestricted.
Destination: Any visible composite object.
Parameters:
attrsToSet
A word of attributes that should be set for the object. The high byte is a record of
VisCompGeoDimensionAttrs
, and the low byte is a record of
VisCompGeoAttrs
. The attributes set in this parameter will be set for the object.
attrsToClear
attrsToSet
, above. Any attribute set in this parameter will be cleared in the instance fields.Return: Nothing.
Interception: Unlikely.
word MSG_VIS_COMP_GET_GEO_ATTRS();
This message retrieves the flags set in the object's
VCI_geoAttrs
and
VCI_geoDimensionAttrs
fields. The high byte of the return value represents the dimension attributes, and the low byte represents the geometry attributes. This message does not invalidate or update the object's geometry.
Source: Unrestricted.
Destination: Any visible composite object.
Parameters: None.
Return: A word of flags. The high byte is a record of type
VisCompGeoDimensionAttrs
; the low byte is a record of type
VisCompGeoAttrs
. The high byte represents the attributes set in the object's
VCI_geoDimensionAttrs
field, and the low byte represents the attributes set in the object's
VCI_geoAttrs
field.
Interception: Unlikely.
With the exception of the geometry flags mentioned above and the management of children, the use of
VisCompClass
is little different from the use of
VisClass
. In fact, most of the functionality designed for
VisCompClass
is built directly into
VisClass
; for example, nearly all geometry management and object tree management messages are defined in
VisClass
. Some reminders are listed below, however.
Not all composite objects will have something to draw. Some composites will be used simply as grouping objects to manage visible children. In these cases, you will not have to subclass
VisCompClass
but can instead use the class directly.
Many composite objects will have something to draw, though. For example, a composite may want to draw a box around its children or wash a different background color behind them. If this is the case, the object must be a subclass of
VisCompClass
and must handle
MSG_VIS_DRAW
.
One of the primary functions of
VisCompClass
is to pass input events and other messages down and up the tree to the proper objects. This is done automatically. You can, however, change this behavior by subclassing
VisCompClass
and intercepting the messages in which the object will be interested.
MSG_VIS_COMP_GET_CHILD_SPACING, MSG_VIS_COMP_GET_MINIMUM_SIZE, MSG_VIS_COMP_GET_MARGINS, MSG_VIS_COMP_GET_WRAP_COUNT
A special feature of
VisCompClass
, and one that can be used in many ways, is its ability to automatically manage its children. By setting various flags in the composite's instance fields, you can have it control its children's sizing and position without additional code in your application.
Most of the flags you can set in
VCI_geoAttrs
and
VCI_geoDimensionAttrs
are explained fully in VisCompClass Instance Data
. You should especially be aware that if you do not want to use the geometry management capabilities of
VisCompClass
, you should set VCGA_CUSTOM_MANAGE_CHILDREN in
VCI_geoAttrs
.
In addition to the messages provided in
VisClass
for geometry management,
VisCompClass
has four that return information about its current geometry. These are necessary because composites may be children of other composites, and therefore they may be managed. These messages are detailed below.
Most of the issues of geometry management are discussed in the VisClass chapter.
word DWORD_CHILD_SPACING(val);
SpacingAsDWord val;
This macro extracts the child spacing from the given
SpacingAsDWord
value. Use it with
MSG_VIS_COMP_GET_CHILD_SPACING
.
word DWORD_WRAP_SPACING(val);
SpacingAsDWord val;
This macro extracts the wrap spacing from the given
SpacingAsDWord
value. Use it with
MSG_VIS_COMP_GET_CHILD_SPACING
.
SpacingAsDWord MAKE_SPACING_DWORD(child, wrap);
word child;
word wrap;
This macro creates a
SpacingAsDWord
dword from the two given arguments. The
child
argument is the child spacing, and the
wrap
argument is the wrap spacing. Use this macro in your handler (if any) for the message
MSG_VIS_COMP_GET_CHILD_SPACING
.
SpacingAsDWord MSG_VIS_COMP_GET_CHILD_SPACING();
This message returns the child spacing used by the composite. The high word of the return value is the spacing between lines of wrapped children; the low word is the horizontal spacing between children.
Source: Unrestricted.
Destination: Any visible composite object--typically sent by a composite to itself during geometry calculations.
Parameters: None.
Return: A dword containing the child spacing used by the composite. The dword contains two values: The child spacing--the amount of spacing placed between the composite's children--can be extracted from the return value with the macro
DWORD_CHILD_SPACING
. The wrap spacing--the amount of space placed between lines of wrapped children--can be extracted from the return value with the macro
DWORD_WRAP_SPACING
.
Interception: If a composite wants special child or wrap spacing other than the default, it should subclass this message and return the desired values. There is no need to call the superclass in the method.
Tips: In your handler, you can use the macro
MAKE_SPACING_DWORD
to form the return value from the two spacing values.
SizeAsDWord MSG_VIS_COMP_GET_MINIMUM_SIZE();
This message returns the minimum size of the composite. It is used by the geometry manager if the composite has VCGDA_HAS_MINIMUM_SIZE set. This message does not invalidate or update the object's geometry.
Source: Unrestricted.
Destination: Any visible composite object--typically sent by a composite to itself during geometry calculations.
Parameters: None.
Return: A dword containing the minimum size of the composite. The high word is the width, and the low word is the height. Use the macros
DWORD_WIDTH
and
DWORD_HEIGHT
to extract the individual values from the
SizeAsDWord
structure.
Interception: Any composite that wants a minimum size should subclass this message and return its desired size. There is no need to call the superclass in your handler.
Tips: In your handler, use the macro
MAKE_SIZE_DWORD
to create the
SizeAsDWord
return value from the width and height. This macro has the same format as
MAKE_SPACING_DWORD
.
void MSG_VIS_COMP_GET_MARGINS(
Rectangle *retValue);
This message returns the margins the composite should use when recalculating its child spacing. If you want a special left, top, right, or bottom margin around the composite's children, intercept this message and return the margin(s) in the appropriate field(s) of the
Rectangle
structure.
Source: Unrestricted.
Destination: Any visible composite object--typically sent by a composite to itself during geometry calculations.
Parameters:
retValue
A pointer to an empty
Rectangle
structure that will be filled with the composite's desired margins.
Return: The pointer to the filled Rectangle structure is preserved. The structure contains the four margins desired by the object outside of its bounds (e.g. if
retValue->R_top
is 100 upon return, the composite is requesting 100 points of extra "margin" spacing below its top bound before its children are placed).
Interception: Any composite that wants extra margin space added to its bounds when geometry is calculated should subclass this message and return its desired margins. There is no need to call the superclass in your handler.
word MSG_VIS_COMP_GET_WRAP_COUNT();
This message returns the number of children to be counted before wrapping if the composite has VCGA_WRAP_AFTER_CHILD_COUNT set.
Source: Unrestricted.
Destination: Any visible composite object--typically sent by a composite to itself during geometry calculations.
Parameters: None.
Return: The number of children that will be allowed before the composite wraps additional children to a new line.
Interception: Any composite that wants to wrap after a certain number of children should subclass this message and return the proper number of children. There is no need to call the superclass in your handler .
It is very rare that a visible object will want to create its own window without using a generic object. This practice is highly discouraged as well because it will almost certainly violate some principles of most specific UI specifications. You can, however, set up a visible object to have its own window with the following steps:
MSG_VIS_ADD_CHILD
, add any visible object children to the window group as you need. If some of the children had possibly been removed from the visible tree earlier, you may have to mark them invalid.
MSG_VIS_SET_ATTR
to mark the window group visible. The window will be opened, and it will receive a
MSG_META_EXPOSED
indicating that it and all its children should draw themselves.