VisClass: 4.3 Using VisClass: Positioning Visible Objects

Up: GEOS SDK TechDocs | Up | Prev: 4.2 Drawing to the Screen | Next: 4.4 Handling Input

Every visible object has an instance data field called VI_bounds that records the object's visible bounds. Visible bounds are the left, top, right, and bottom bounds of a rectangle that define the maximum area covered by the visible object. The bounds are used primarily for determining the object's size and location.

The VI_bounds field is a Rectangle structure, provided by the graphics system. This structure has four components, as shown below:

  typedef struct {
    sword   R_left;    /* x of upper-left corner */
    sword   R_top;     /* y of upper-left corner */
    sword   R_right;   /* x of lower-right corner */
    sword   R_bottom;  /* y of lower-right corner */
} Rectangle;

The bounds of non-window objects are stored in document coordinates relative to the document displayed by the window in which they appear. The left and top bounds constitute the position of the object. The difference between the right and left bounds is the object's width; the difference between bottom and top is its height. Together, the width and height constitute the object's size.

The bounds of a window or portal object (VTF_IS_WINDOW or VTF_IS_PORTAL) represent the location of the window, in document coordinates, within its parent window. The coordinate system within the window object is independent from that of its parent.

Unless an object's bounds are set in the Goc code, they will be set at zero and must be initialized to some values before the object can be drawn. This initialization can be done with the messages that set position and size, or it can be done automatically by the geometry manager (if a composite is managing its children).

The VI_bounds instance field exists in VisClass and therefore occurs also in VisCompClass and VisContentClass and all their subclasses. Any object can directly set any or all of its bounds; other objects (such as a parent VisComp) can direct the object to set its bounds to certain coordinates as a result of either geometry management or some user action. For example, a VisComp that has ten children may recalculate their positions if one of those children gets resized; the composite must then notify all the children of their new positions. To learn how a composite object can manage its children in different ways, see the VisComp chapter.

Object Position and Bounds

MSG_VIS_GET_POSITION, MSG_VIS_SET_POSITION, MSG_VIS_GET_BOUNDS

An object's bounds determine both the location and the size of the object in the document space. The object may reposition itself or resize itself at will; for example, it may allow the user to move or resize it with the mouse. The object can also receive direction from other objects that it should change its bounds. Note that none of these messages by themselves will cause the object to redraw; you must also send a MSG_VIS_MARK_INVALID to the object to get either its geometry or its image to be marked invalid.

An object's position is represented by the upper-left corner of its bounds, defined by VI_bounds . R_top and VI_bounds . R_left . You can retrieve an object's position by sending it MSG_VIS_GET_POSITION , or you can set it with MSG_VIS_SET_POSITION . You can also use MSG_VIS_GET_BOUNDS to get all four components of the object's bounds.

An object can access its own bounds field with a simple pointer. Since every message has pself as an implicit parameter (a pointer to the object's instance data structure), any object can look at or change its bounds directly. (See the example in Grabbing and Releasing the Mouse .)

Using Swat, you can see a visible object's bounds with the command pobj .

If you have a composite object managing several children, you can arrange to have their positions determined automatically. This is discussed in Geometry Management .

MSG_VIS_SET_POSITION

void	MSG_VIS_SET_POSITION(
        int	xOrigin,
        int	yOrigin);

This message causes the object to set its VI_bounds to the new location specified, retaining its current size. The left bound ( VI_bounds . R_left ) is set to the value of xOrigin , and the top bound ( VI_bounds . R_top ) is set to that of yOrigin . The right and bottom bounds are set to match the new origin and the width and height of the object.

Source: Unrestricted--usually the visible parent or geometry manager.

Destination: Any visible object.

Parameters: xOrigin New horizontal coordinate of the object's position.

yOrigin
New vertical coordinate of the object's position.

Return: Nothing.

Interception: Unlikely. It's much more likely that the object will subclass MSG_VIS_POSITION_BRANCH .

Warnings: This message will not cause an image invalidation. You must mark the object invalid with MSG_VIS_MARK_INVALID .

See Also: MSG_VIS_POSITION_BRANCH , MSG_VIS_MARK_INVALID .

MSG_VIS_GET_POSITION

XYValueAsDWord MSG_VIS_GET_POSITION();

This message returns the current origin of the object. The origin returned consists of the left and top object bounds ( VI_bounds . R_left and VI_bounds . R_top , respectively).

Source: Unrestricted.

Destination: Any visible object.

Parameters: None.

Return: A dword value representing the left bound in the low word and the top bound in the high word. Use the macros DWORD_X and DWORD_Y to extract the bounds from the return value (see the file graphics.h ).

Interception: Unlikely.

MSG_VIS_GET_BOUNDS

void	MSG_VIS_GET_BOUNDS(
        Rectangle *retValue);

This message returns the current rectangle structure stored in the object's VI_bounds field. This rectangle represents both the position and the size of the object by giving its left, top, right, and bottom bounds.

Source: Unrestricted.

Destination: Any visible object.

Parameters: retValue A pointer to an empty Rectangle structure. The values in the object's VI_bounds field will be returned in the structure pointed to.

Return: The retValue pointer will be returned with the bounds filled into the Rectangle structure.

Interception: Unlikely.

Object Size

MSG_VIS_GET_SIZE, MSG_VIS_SET_SIZE

A visible object's size is defined as its width and height. The width is the difference between the object's left and right bounds; the height is the difference between the object's top and bottom bounds.

You can retrieve a visible object's size with the message MSG_VIS_GET_SIZE , and you can set it with MSG_VIS_SET_SIZE . MSG_VIS_SET_SIZE will set the object's right and bottom bounds without recalculating the object's position. If geometry is being managed automatically, you may want to subclass other messages; these are described in Geometry Management .

In Swat, you can see the object's size indirectly with the command pobj . This command will show, among other things, the VI_bounds field of the object. You can manually calculate the size from that information.

MSG_VIS_SET_SIZE

void	MSG_VIS_SET_SIZE(
        int	width,
        int	height);

This message sets the object's height and width to the passed values, retaining the object's current position. The object's position will not be recalculated as a result of the size change.

Source: Unrestricted--usually the geometry manager or the object's visible parent calculating geometry.

Destination: Any visible object.

Parameters: width The new width of the object. width will be added to the object's left bound to get the object's new right bound.

height
The new height of the object. height will be added to the object's top bound to get the object's new bottom bound.

Return: Nothing.

Interception: Unlikely.

Warnings: This message will not cause an image invalidation. You must mark the object invalid with MSG_VIS_MARK_INVALID .

MSG_VIS_GET_SIZE

SizeAsDWord MSG_VIS_GET_SIZE();

This message returns the current size (width and height) of the object. Both values are word-sized integers and are returned in a single dword value. The high word of this value is the object's width, and the low word is the object's height.

Source: Unrestricted.

Destination: Any visible object.

Parameters: None.

Return: A dword value representing the object's width in the low word and height in the high word. Use the macros DWORD_WIDTH and DWORD_HEIGHT to extract the width and height; see DWORD_HEIGHT .

Interception: Unlikely.

Geometry Management

MSG_VIS_UPDATE_GEOMETRY, MSG_VIS_NOTIFY_GEOMETRY_VALID, MSG_VIS_RECALC_SIZE, MSG_VIS_GET_CENTER, MSG_VIS_RECALC_SIZE_AND_INVAL_IF_NEEDED, MSG_VIS_RESET_TO_INITIAL_SIZE, MSG_VIS_POSITION_BRANCH, MSG_VIS_POSITION_AND_INVAL_IF_NEEDED, MSG_VIS_INVAL_ALL_GEOMETRY

Geometry management consists of positioning and sizing visible objects properly. This can be done manually by the programmer or automatically by GEOS. If you wish to manually control your visible tree's geometry, set the flag VCGA_CUSTOM_MANAGE_CHILDREN in the top composite's VCI_geoAttrs field (see the VisComp chapter). You can then use any messages, either native to VisClass or defined by your subclasses, for object positioning and sizing.

Automatic geometry management occurs when the geometry of the visible tree is marked invalid somewhere and a visual update is initiated. The tree's geometry can be marked invalid in several ways--an object can be added to or removed from the tree, an object can be manually marked invalid (with MSG_VIS_MARK_INVALID ), or an object can be opened or closed ( MSG_VIS_OPEN or MSG_VIS_CLOSE ).

When automatic geometry management is invoked, the geometry manager will recalculate the entire affected branch's geometry. It will calculate geometry for each affected window group, from the topmost affected window object down to the bottommost affected object. If the geometry manager encounters window groups below the topmost window, it will check first to see if the lower window's size is controlled by its children (e.g., a GenView that follows the geometry of its content). If the lower window is scrollable or otherwise not subject to its children's geometry, the geometry manager will finish calculating the geometry above the lower window before proceeding.

Calculating geometry is an involved, complex task. The process involves composites and their children negotiating on desired sizes. How the geometry is calculated depends primarily on the relationships between the objects and how their flags are set.

For example, if a GenView is set up to be exactly the same size as its VisContent object, the calculations will be different than if the GenView were scrollable. The same is true for visible composites that manage their children: If the composite resizes itself large enough to hold all its children, the children must be resized first.

The negotiation between parent and child in the visible tree takes the form of a single message: MSG_VIS_RECALC_SIZE . This is the single most important message in calculating the tree's geometry, though others are also significant. This message is sent by a composite to each of its children in turn; it passes a suggested size, and the child returns its desired size.

The composite collects all the desired sizes of its children and compares that to the size it thinks it should be. If necessary, it makes another pass through the children, or it passes on its desired size to its parent composite. Depending on the situation and the disparity between parent and children sizes, the geometry calculation may take a single pass or several. If the sizes can not be resolved through this negotiation, the geometry manager will make a decision after several passes, typically expanding the parent as much as possible to fit all the children.

After a visible object has calculated its size, its size will be set either by itself or by its parent. Often this is done with MSG_VIS_SET_SIZE . Once all sizes have been determined and set, the objects set their positions with MSG_VIS_POSITION_BRANCH , which propagates down the tree. It sets the position of the topmost composite and then sets each of its children's positions appropriately.

When geometry calculations are complete, the geometry manager will send a MSG_VIS_NOTIFY_GEOMETRY_VALID to all visible objects with the flag VGA_NOTIFY_GEOMETRY_VALID set in its VI_geoAttrs field.

Several other messages may be used during geometry updates. Some of them may be intercepted to alter the behavior of the default method. These messages are listed below. Others can be used to invalidate a visible object's geometry or to cause a geometry update on the tree.

MSG_VIS_UPDATE_GEOMETRY
This message is typically called by the UI during a window group update. It calculates the geometry of the entire branch receiving it. It's not likely you'll subclass this method--altering its behavior can be used for certain optimizations, however.
MSG_VIS_NOTIFY_GEOMETRY_VALID
This message will be sent to an object when all its geometry messages have been handled and its geometry has been fully resolved (at least for the moment). This message will be sent only if VGA_NOTIFY_GEOMETRY_VALID is set in the object's VI_geoAttrs field. There is no default behavior for this message; it should be intercepted only if the object needs to do calculations after the geometry has settled down.
MSG_VIS_RECALC_SIZE
This message is normally sent by the geometry manager to a composite object. The composite is expected to send it to all its children; the children will then determine their sizes, and the composite will figure the total size and return. A composite that manages its own children can also use this message to query its children for their desired sizes.
MSG_VIS_RECALC_SIZE_AND_INVAL_IF_NEEDED
This message is an optimized MSG_VIS_RECALC_SIZE . Composites should use this version when sending a recalculation message to their children. This message only causes recalculation if needed and will invalidate the object if the size gets recalculated. It invalidates the object's image at its old bounds and only invalidates its geometry if the bounds change. It is highly unlikely that you'll subclass this method.
MSG_VIS_GET_CENTER
This message returns the amount of space on each side the object wants reserved for itself. It does not, as the name suggests, return the coordinates of the object's center. Instead, it returns the distance in each direction the object requires (you may think of it as external margins).
MSG_VIS_RESET_TO_INITIAL_SIZE
This message propagates down the visible tree and causes every object that receives it to reset itself to its original size. It does this by clearing VGA_GEOMETRY_CALCULATED in the object's VI_geoAttrs field, causing the object to believe it is being put on-screen for the first time. This message will also set the object's flags to indicate that its geometry has become invalid. It's highly unlikely your application will subclass this method.
MSG_VIS_POSITION_BRANCH
This message is sent by the geometry manager when an entire visible branch should be repositioned. If an application wants to do something special, it should subclass the handler for this message. Typically, though, only subclasses of VisCompClass and perhaps VisContentClass will change this method.
MSG_VIS_POSITION_AND_INVAL_IF_NEEDED
This message is an optimized MSG_VIS_POSITION_BRANCH that causes a branch reposition only if it's necessary. It will also invalidate both the object's and the parent's original images and, if the position changes, the geometry as well. It is highly unlikely that you'll subclass this method.
MSG_VIS_INVAL_ALL_GEOMETRY
This message invalidates all geometry under the recipient object, forcing invalidation of all children. This is a brute-force message used only when absolutely necessary.

MSG_VIS_UPDATE_GEOMETRY

void	MSG_VIS_UPDATE_GEOMETRY();

This message is sent during a visual update to cause objects to recalculate their geometry. Applications can use this message to ensure that geometry gets updated for a visual branch even if the branch is not currently drawn on the screen.

Source: Visual update mechanism.

Destination: Any visible object.

Interception: May be intercepted for optimizations. A thorough knowledge of the geometry update mechanism and the specifics of the visible tree's geometry is strongly recommended, however.

MSG_VIS_NOTIFY_GEOMETRY_VALID

void	MSG_VIS_NOTIFY_GEOMETRY_VALID();

This message is sent by the geometry manager to objects that have VGA_NOTIFY_GEOMETRY_VALID set. The message is sent only after all geometry messages have been handled for the object. It has no default behavior.

Source: Visible update mechanism.

Destination: Any visible object--typically a child of the object sending the message.

Interception: This message has no default behavior. It should be intercepted by any object that needs to do something after its geometry has been made valid.

MSG_VIS_RECALC_SIZE

SizeAsDWord MSG_VIS_RECALC_SIZE(
        int	width,
        int	height);

This message takes the suggested height and width of the object and recalculates the object's desired size based on them. Composite objects are expected to pass this message to their children and then calculate their sizes based on those of their children. The default behavior of the handler for this is to return the current size no matter what the suggested size is.

Source: Visible update mechanism.

Destination: Any visible object.

Parameters: width Suggested new width of the object as determined by the object's parent.

height
Suggested new height of the object as determined by the object's parent.

Return: A dword value representing the object's desired size as calculated by the object. The high word of the return value represents the width and the low word the height. Use the macros DWORD_WIDTH and DWORD_HEIGHT to extract the width and height; see DWORD_HEIGHT .

Interception: Default behavior is to return the object's current size no matter what the passed width and height are. Any object that wants special sizing behavior based either on the object's children or on the suggested size should subclass the method.

MSG_VIS_RECALC_SIZE_AND_INVAL_IF_NEEDED

SizeAsDWord MSG_VIS_RECALC_SIZE_AND_INVAL_IF_NEEDED(
        int	width,
        int	height);

This message is the same as MSG_VIS_CALC_RESIZE except that it is somewhat optimized. It will recalculate only if certain flags are set for the object, and it will mark the geometry invalid only if recalculation is done.

Source: Visible update mechanism.

Destination: Any visible object.

Parameters: width Suggested new width of the object as determined by the object's parent.

height
Suggested new height of the object as determined by the object's parent.

Return: A dword value representing the object's desired size as calculated by the object. The low word of the return value represents the width and the high word the height.

Interception: Unlikely--Default behavior is to return the object's current size no matter what the passed width and height are. Any object that wants special sizing behavior based either on the object's children or on the suggested size should subclass the method.

MSG_VIS_GET_CENTER

void	MSG_VIS_GET_CENTER(
        GetCenterParams *retValue);

This message returns the amount of space needed by the object in each direction from its center. It does not, as the name suggests, return the coordinates of the center of the object. Instead, the object must determine the amount of space it requires from its center to each edge for geometry management and return them in the structure passed.

Source: Visible update mechanism.

Destination: Any visible object

Parameters: retValue A pointer to an empty GetCenterParams structure, defined below.

Return: The method must fill the GetCenterParams structure pointed to by the retValue parameter.

Interception: Any object that wants to effect a different centering than the default should subclass this method. For example, if a set of objects can be overlapped, or if they should have extra space between them, they should subclass this message and alter the returned values appropriately.

Structures: The GetCenterParams structure is defined as follows:

typedef struct {
    word   GCP_aboveCenter;    /* space above */
    word   GCP_belowCenter;    /* space below */
    word   GCP_leftOfCenter;   /* space left */
    word   GCP_rightOfCenter;  /* space right */
}  GetCenterParams;

MSG_VIS_RESET_TO_INITIAL_SIZE

void	MSG_VIS_RESET_TO_INITIAL_SIZE(
        VisUpdateMode updateMode);

This message propagates down an entire visual branch, causing the objects in it to reset their sizes to their original width and height. First it invalidates the object's geometry, then it recalculates the geometry starting at the top.

Source: Visible update mechanism.

Destination: Any visible object.

Parameters: updateMode A VisUpdateMode indicating when the visual update of the tree should occur.

Return: Nothing.

Interception: Unlikely.

MSG_VIS_POSITION_BRANCH

void	MSG_VIS_POSITION_BRANCH(
        word	xOrigin,
        word	yOrigin);

This message repositions an entire visible branch. It propagates down the branch, causing each visible object to reposition itself based on the new origins passed. Composites must pass the appropriate altered positions to their children.

Source: Visible update mechanism.

Destination: Any visible object.

Parameters: xOrigin The new horizontal position of the object relative to the document or window it's in. This value is set into the object's VI_bounds . R_left bound, and the right bound is set according to the object's size.

yOrigin
The new vertical position of the object relative to the document or window it's in. This value is set into the object's VI_bounds . R_top bound, and the bottom bound is set according to the object's size.

Return: Nothing.

Interception: The default behavior is to set the object to the passed position. Composite objects that want to position their children a special way should subclass this (and not call the superclass) method. Non-composites will rarely, if ever, subclass this message.

MSG_VIS_POSITION_AND_INVAL_IF_NEEDED

Boolean	MSG_VIS_POSITION_AND_INVAL_IF_NEEDED(
        word	xPosition,
        word	yPosition);

This message is an optimized version of MSG_VIS_POSITION_BRANCH . It repositions the branch only if necessary and will mark the image invalid only if the position was changed. It returns a flag indicating whether or not the object was repositioned.

Source: Visible update mechanism.

Destination: Any visible object--typically sent by a composite to its children.

Parameters: xPosition The new horizontal position of the object relative to the document or window it's in. A negative value means that the object should choose its own position as best it can.

yPosition
The new vertical position of the object relative to the document or window it's in. A negative value means that the object should choose its own position as best it can.

Return: If the object was repositioned, the message will return true . Otherwise, it will return false .

Interception: Unlikely.

MSG_VIS_INVAL_ALL_GEOMETRY

void	 MSG_VIS_INVAL_ALL_GEOMETRY(
        VisUpdateMode		updateMode);

This is a brute-force, desperation message used to invalidate all geometry in the recipient's tree; that is, all geometry of the recipient and all objects under it in the tree will be invalidated. You should only use this message when the whole tree should be recalculated.

Source: Unrestricted.

Destination: The object requiring geometry recalculation.

Parameters: updateMode A visual update mode indicating when the visual update of the recalculation should occur.

Return: Nothing.

Interception: Generally not intercepted.


Up: GEOS SDK TechDocs | Up | Prev: 4.2 Drawing to the Screen | Next: 4.4 Handling Input