GEOS SDK TechDocs
|
|
4.2 Drawing to the Screen
|
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.
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 .
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
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
.
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.
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.
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.
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
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
.
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.
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
MSG_VIS_NOTIFY_GEOMETRY_VALID
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
MSG_VIS_RECALC_SIZE_AND_INVAL_IF_NEEDED
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
MSG_VIS_RESET_TO_INITIAL_SIZE
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
VisCompClass
and perhaps
VisContentClass
will change this method.
MSG_VIS_POSITION_AND_INVAL_IF_NEEDED
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_GEOMETRYvoid 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.
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.
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
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.
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
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.
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;
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.
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
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.
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
Return: If the object was repositioned, the message will return
true
. Otherwise, it will return
false
.
Interception: Unlikely.
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.
GEOS SDK TechDocs
|
|
4.2 Drawing to the Screen
|
4.4 Handling Input