GEOS SDK TechDocs
|
|
5.2 Manipulating Children Directly
|
6 Vardata
MSG_GEN_COPY_TREE, MSG_GEN_DESTROY, MSG_GEN_DESTROY_AND_FREE_BLOCK, MSG_GEN_BRANCH_REPLACE_PARAMS, MSG_GEN_BRANCH_REPLACE_OUTPUT_OPTR_CONSTANT
In addition to instantiating and manipulating generic objects one at a time, you can create, move, and destroy entire branches. One way of doing this is copying a resource using
ObjDuplicateResource()
and sending
MSG_GEN_ADD_CHILD
to the parent object, passing it the optr of the top object in the tree. This method has the advantage of retaining the same chunk offsets to objects within the duplicated block as in the source block.
Code Display 2-22 Using ObjDuplicateResource()
@start ResourceToCopy;
/* For simplicity, the GenItems in this listing contain no monikers or * identifiers. */
@object GenItemGroupClass MyList = {
GI_comp = @AirplaneEntry, @TrainEntry, @CarEntry, @BicycleEntry;
}
@object GenItemClass AirplaneEntry = {}
@object GenItemClass TrainEntry = {}
@object GenItemClass CarEntry = {}
@object GenItemClass BicycleEntry = {}
@end ResourceToCopy;
@method MyProcessClass, MSG_COPY_MY_RESOURCE {
MemHandle newBlock;
newBlock = ObjDuplicateResource(OptrToHandle(@MyList), /* Block will be owned by the same geode. */ -1, /* Block will be run by the same thread. */ -1);
@call MyPrimary::MSG_GEN_ADD_CHILD(ConstructOptr(newBlock, OptrToChunk(@MyList)); }
Another way to duplicate groups of objects is with
MSG_GEN_COPY_TREE
. This message greatly simplifies generic tree construction. Those branches of the tree which are roughly similar can be duplicated with one message instead of several.
In many cases, it might be useful to create a UI resource template. This template should contain objects but should not contain object-specific information such as visual monikers, optrs, etc., as this information may be different for different instances of the branch. You can then duplicate these templates with
MSG_GEN_COPY_TREE
. The trees can then be updated to reflect their unique data either object by object or by using
MSG_GEN_BRANCH_REPLACE_PARAMS
, which will replace instance data within an entire branch.
To set up a template, create the generic tree you wish to function as a template, making sure that the top-level object of that tree is not usable (~GS_USABLE). Then use
MSG_GEN_COPY_TREE
to copy the tree to the proper location. You can then set the other instance data within the method. Finally, to make that tree appear on screen, set the top-level object GS_USABLE. You can remove any tree created with
MSG_GEN_COPY_TREE
with
MSG_GEN_DESTROY
. If you use
ObjDuplicateResource()
to copy a resource block, you can use
ObjFreeDuplicate()
to remove it. If the generic branch to be destroyed resides completely within a single block, you may send MSG_GEN_DESTROY_AND_FREE_BLOCK to the top object in that generic branch.
optr MSG_GEN_COPY_TREE(
MemHandle destBlock,
ChunkHandle parentChunk,
word flags);
This message copies an entire branch of a generic object tree, starting at the object first called. Pass this message the handle of the destination object block. The object sent the message must not be GS_USABLE.
You may pass
parentChunk
null if you wish the block to remain unattached to the generic tree. Note that if a generic tree is copied using
MSG_GEN_COPY_TREE
, the objects contained therein not only will have a new resource handle but will also have new chunk handles. Note that this is different from using
ObjDuplicateResource()
, which will keep the same chunk offsets into the object block.
Unlike
ObjDuplicateResource()
, this message will copy the entire branch desired, even if those objects reside in separate resources. This message is therefore more flexible than
ObjDuplicateResource()
, which only copies a given object block.
GenClass
provides the default behavior of broadcasting this message down a generic tree, where each object will make a copy of itself in the destination block. It creates an object chunk the same size as the object chunk being copied, copies over the entire contents of any instance fields and creates an outside chunk for a visual moniker, if any.
If you have a subclass of a generic object which references (and therefore might need to create) a chunk outside the object, you must be sure to intercept this message and allocate, copy over, and update any references to this chunk.
Source: Unrestricted.
Destination: Any generic object.
Parameters: destBlock The block to copy the tree into. This block cannot be the same as the source object block.
parentChunk
. If zero, copy tree into block without linking it to a particular chunk.
CompChildFlags
to use when adding the tree.
Interception: This message is handled by all generic objects. If you wish to intercept this message, you should first call the superclass to copy over the
GenClass
instance data and then copy over any lmem chunks that are referenced by instance data of the intercepting class.
Code Display 2-23 MSG_GEN_COPY_TREE
/* Create a template resource block. For demonstration purposes, this block will * only contain one object, a GenItem. All declared resources must also be * declared in an application's corresponding .gp file. */
@start MyTemplate;
@object GenItemClass TemplateItem = {
GI_states = @default & ~GS_USABLE; /* Make sure it is NOT usable. */
}
@end MyTemplate;
/* Start the Interface resource block */
@start Interface;
@object GenItemGroupClass MyList = { }
/* Object the template above will be added to. */
@end Interface;
@method MyProcessClass, MSG_COPY_A_LIST_ITEM {
optr newListEntry;
/* This call copies TemplateItem to the location at MyList. The macros
* OptrToHandle and OptrToChunk are used to cast the optr of MyList into
* the proper type for MSG_GEN_COPY_TREE. This new linkage will be marked
* dirty, and the child will become the first child of MyList. */
newListEntry = @call TemplateItem::MSG_GEN_COPY_TREE(
OptrToHandle(@MyList),
OptrToChunk(@MyList),
(CCF_MARK_DIRTY | CCO_FIRST));
/* The newListEntry is set usable to bring it up on screen. */
@call newListEntry::MSG_GEN_SET_USABLE(VUM_NOW);
}
void MSG_GEN_DESTROY(
VisUpdateMode updateMode,
word flags);
This message destroys a generic branch starting at the object called. The message sets all required generic objects not usable, removes them from the generic tree, and destroys them, including any chunks associated with the specific object destroyed. This message is the safest way to destroy a generic branch.
The message will leave the block that the objects previously resided in intact (except for objects removed, of course), but any chunks coming from those resources will be marked dirty and will be resized to zero.
It is usually a good idea to destroy generic branches that are not needed to be saved to state when an application detaches or exits. This ensures that when an application is reattached, it will not contain the previous links. This keeps the state file more compact and avoids the possibility of a child not being saved to state while retaining the parent's child pointer.
The only valid flag in
CompChildFlags
is CCF_MARK_DIRTY, which will mark the links as dirty and save them to state.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
updateMode
VisUpdateMode
to determine when the generic tree is to be visually updated. May not be VUM_MANUAL.
CompChildFlags
to use when destroying the branch (either CCF_MARK_DIRTY or zero).
Interception: This message is handled by all generic objects. If you wish to intercept this message, you should first destroy any chunks that are referenced by instance data of the intercepting class and then call the superclass to destroy the object's
GenClass
instance data.
Boolean MSG_GEN_DESTROY_AND_FREE_BLOCK();
This is a utility message used to destroy a generic branch which resides completely within one block. The block will be freed. The object called with this message must be the only top object in the block. This message is called by
UserDestroyDialog()
.
If any object within the block resides on the application active list, or if the object is not a window, a slow, non-optimized approach is taken: the branch is set not usable, removed from the generic tree, and sent
MSG_META_BLOCK_FREE
. If no object of the block can be found on this list, an optimized approach is taken: the window is taken off the screen; FTVMC, mouse, etc. exclusives released; the linkage changed to be one-way upward; and the block sent
MSG_META_BLOCK_FREE
. In other words, the whole unbuild process is carefully avoided.
Source: Unrestricted
Destination: Top object within a block to be freed.
Return: true if the message was handled, false otherwise.
Interception: Generally not intercepted.
void MSG_GEN_BRANCH_REPLACE_PARAMS(@stack
BranchReplaceParamType type,
dword replaceParam,
dword searchParam);
This message travels down a generic branch to all of an object's children; the message replaces all instance data specified in
type
with replacement instance data. A typical way to implement this is to set up a template UI branch with
MSG_GEN_COPY_TREE
. Most often, you will use this message to search and replace optrs set within your template. This is easily done by setting these optrs to certain constant values and then searching for those values in
type
.
If you only wish to replace your destination optrs, use
MSG_GEN_BRANCH_REPLACE_OUTPUT_OPTR_CONSTANT
, which is just a specialized case of this message.
When replacing optrs, the constant BRPT_DUMMY_OPTR_START should be used as the
searchParam
value. If multiple optrs are to be replaced, enumerated values based on that value should be used for other optrs. These values will be constants, and since the
TravelOption
types are also constants, care must be taken to replace these dummy values before anything else is done on the generic branch; otherwise, their output may be interpreted as a
TravelOption
.
This message may not be supported by several subclasses of
GenClass
.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
searchParam
Specifies the search parameter. Typically this search parameter is a pre-set constant used to identify the instance data to replace. The search parameter must be a dword.
replaceParam
searchParam
will be replaced with the data specified in
replaceParam
. The data must be a dword.
type
BranchReplaceParamType
. The only value supported is BRPT_OUTPUT_OPTR, which specifies that all optrs with values matching
searchParam
should be replaced by the value in
replaceParam
.
Interception: This message is handled by most generic objects (although not all). If you wish to intercept this message, you should first call the superclass to search and replace any
GenClass
instance data, if applicable, and then search and replace any instance data in the intercepting class.
void MSG_GEN_BRANCH_OUTPUT_OPTR_CONSTANT(
optr replacementOptr,
word searchConstant);
This message is a special case of
MSG_GEN_BRANCH_REPLACE_PARAMS
where the
BranchReplaceParamType
is BRPT_OUTPUT_OPTR with a search parameter of a constant value set up beforehand. You must pass this message the optr to replace the search constant found.
Source: Unrestricted.
Destination: Any generic object.
Parameters: replacementOptr The optr to replace all instance fields with destinations matching the searchConstant .
Interception: Generally not intercepted. This message invokes
MSG_GEN_BRANCH_REPLACE_PARAMS
so intercept that instead.
GEOS SDK TechDocs
|
|
5.2 Manipulating Children Directly
|
6 Vardata