Typedefs | |
typedef struct mdlDesc | MdlDesc |
typedef StatusInt(* | DependencyProcessingCallback )(DgnPlatform::ElementId dependentID, DgnModelRefP modelRef, DgnPlatform::DependencyLinkage *pLinkage, UChar *pRootStatus, UChar selfStatus) |
UserFunction called by mdlDependency_processAffected when a dependent element is affected by changes to root elements. More... | |
typedef void(* | DependencyProcessingCallbackForUndoRedo )(DgnPlatform::ElementId dependentID, DgnModelRefP modelRef, DgnPlatform::DependencyLinkage *pLinkage, UChar *pRootStatus, UChar selfStatus) |
Callback to be invoked whenever changes affecting a dependent element are undone or redone. More... | |
typedef void(* | DependencyProcessingCallbackForLoad )(DgnPlatform::ElementId dependentID, DgnModelRefP modelRef, DgnPlatform::DependencyLinkage *pLinkage, bool futureUse) |
Callback to be invoked whenever an element carrying the specifying dependency linkage is loaded. More... | |
Functions | |
StatusInt | mdlDependency_registerCallback (UShort appID, MdlDesc *pMdlDescr, DependencyProcessingCallback func) |
Register a callback to be invoked whenever MDL detects changes that affect elements with a DgnPlatform::DependencyLinkage having the specified appID. More... | |
StatusInt | mdlDependency_getCallback (MdlDesc **ppMdlDescr, DependencyProcessingCallback *pFunc, UShort appID) |
Get the current callback that is registered to handle dependencies with the specified appID. More... | |
void | mdlDependency_removeCallback (UShort appID) |
Un-register the current callback for dependencies having the specified appID. More... | |
StatusInt | mdlDependency_registerCallbackForUndoRedo (UShort appID, MdlDesc *pDesc, DependencyProcessingCallbackForUndoRedo func) |
Register a callback to be invoked whenever changes affecting a dependent element are undone or redone. More... | |
StatusInt | mdlDependency_getCallbackForUndoRedo (MdlDesc **ppMdlDescr, DependencyProcessingCallbackForUndoRedo *pFunc, UShort appID) |
Get the current callback that is registered to handle dependencies with the specified appID for undo/redo purposes. More... | |
void | mdlDependency_removeCallbackForUndoRedo (UShort appID) |
Un-register the current callback for dependencies having the specified appID for undo/redo purposes. More... | |
StatusInt | mdlDependency_registerCallbackForLoad (UShort appID, MdlDesc *pDesc, DependencyProcessingCallbackForLoad func) |
Register a callback to be invoked whenever an element carrying the specifying dependency linkage is loaded or unloaded. More... | |
StatusInt | mdlDependency_getCallbackForLoad (MdlDesc **ppMdlDescr, DependencyProcessingCallbackForLoad *pFunc, UShort appID) |
Get the current load/unload callback for this appID. More... | |
void | mdlDependency_removeCallbackForLoad (UShort appID) |
Un-register the current load/unload callback for this appID. More... | |
DgnPlatform::DependencyStatus | mdlDependency_processAffected () |
This function invokes callbacks on all dependent elements affected by changes to root elements since the last call to this function. More... | |
void | mdlDependency_rootChanged (ElementRefP root) |
Declare that the specified root is changed and its dependents should be notified. More... | |
bool | mdlDependency_wasAdded (ElementRefP ref) |
Query if the specified element is new. More... | |
void | mdlDependency_setProcessingDisabled (bool bSuppress) |
Disable or enable post-processing of affected dependent elements. More... | |
int | mdlDependency_getProcessingDisabled (void) |
Query if processing of affected elements has been disabled. More... | |
void | mdlDependency_setIgnoreMissingCallbacks (bool b) |
Set the policy for what post-processing should do when a dependent element requires an application to process root changes, but the callback is not currently registered. More... | |
bool | mdlDependency_getIgnoreMissingCallbacks (void) |
Query the policy for what to do when a dependent element requires an application to process root changes, but the callback is not not currently registered. More... | |
StatusInt | mdlDependency_initLinkage (DgnPlatform::DependencyLinkage *pLinkage, UShort appID, int dataType, int copyOptions) |
This is a convenience function to initialize a DgnPlatform::DependencyLinkage. More... | |
StatusInt | mdlDependency_appendLinkage (MSElementP pEl, DgnPlatform::DependencyLinkage *pLinkage) |
This function adds the specified DgnPlatform::DependencyLinkage to an element. More... | |
StatusInt | mdlDependency_appendLinkageEx (MSElementP pEl, DgnPlatform::DependencyLinkage *pLinkage, int xtrabytes) |
This function adds the specified DgnPlatform::DependencyLinkage to an element. More... | |
StatusInt | mdlDependency_appendLinkageUsingDescr (MSElementDescrH ppEd, DgnPlatform::DependencyLinkage *pLinkage, int xtrabytes) |
Add DgnPlatform::DependencyLinkage to an element descriptor. More... | |
int | mdlDependency_deleteLinkage (MSElementP pEl, UShort appID, UShort appValue) |
Remove DependencyLinkages from an element. More... | |
StatusInt | mdlDependency_updateLinkage (MSElementP pEl, DgnPlatform::DependencyLinkage *pDep, int xtrabytes) |
Update a DependencyLinkages on an element. More... | |
StatusInt | mdlDependency_getLinkage (DgnPlatform::DependencyLinkage *pLinkage, size_t maxSize, MSElementCP pEl, UShort appID, UShort appValue) |
Retrieve the DgnPlatform::DependencyLinkage on the specified element with matching appID and type. More... | |
StatusInt | mdlDependency_getLinkageEx (DgnPlatform::DependencyLinkage *pDependencyLinkage, DgnPlatform::DependencyLinkage **ppDependencyLinkageInplace, size_t *pDependencyLinkageSize, size_t maxSize, MSElementCP pEl, UShort appID, UShort appValue) |
Retrieve the DgnPlatform::DependencyLinkage on the specified element with matching appID and type. More... | |
DgnPlatform::DependencyLinkage * | mdlDependency_bufferFromFileFormat (LinkageHeaderP pHeader) |
Memory format DgnPlatform::DependencyLinkage from the specified user data linkage. More... | |
DgnPlatform::DependencyLinkage * | mdlDependency_bufferToFileFormat (LinkageHeaderP pHeader) |
File format DgnPlatform::DependencyLinkage from the specified user data linkage. More... | |
size_t | mdlDependency_sizeof (DgnPlatform::DependencyLinkage *pDep, int xtrabytes) |
Get the stored size of the specified dependency linkage. More... | |
int | mdlDependency_getDependentElementRefs (ElementRefP *pDependents, DgnPlatform::ElementId rootElemId, DgnModelRefP rootModelRef, int maxDependents) |
This function returns a list of ElementRefs that depend on the specified element. More... | |
int | mdlDependency_getNumOfDependents (DgnPlatform::ElementId rootElemId, DgnModelRefP modelRef) |
This function returns a number of the elements that depend on the specified element. More... | |
void | mdlDependency_setTraceLevel (int traceLevel) |
For debugging purposes only: More... | |
void | mdlDependency_fmtRoot (WStringR buf, DgnModelRefP modelRef, DgnPlatform::DependencyLinkage *pLinkage, int iRoot) |
Formats the specified root in the specified linkage for display in a debugging message. More... | |
unsigned | mdlDependency_getRoots (DgnPlatform::DependencyRoot *pRoots, DgnModelRefP modelRef, DgnPlatform::DependencyLinkage *pDep, int iRoot) |
This function returns a list of root elements on which the specified item in a dependency linkage depends. More... | |
StatusInt | mdlDependency_setRoots (DgnPlatform::DependencyLinkage *pDep, DgnModelRefP modelRef, const DgnPlatform::DependencyRoot *pRoots, int iRoot) |
This function updates the roots identified by the specified item in the dependency linkage. More... | |
int | mdlDependency_addSimpleDependencyLinkageToDescr (MSElementDescrH nodeEdPP, UShort appId, UShort appValue, int copyOption, DgnPlatform::ElementId uniqueId) |
This function creates a simple dependency linkage on an element descr. More... | |
StatusInt | mdlDependencyAssoc1_fromAssocAndSubtype (DgnPlatform::DependencyLinkage *dl, int iRoot, DgnPlatform::AssocPoint const *assocPoint, int assoc1Subtype) |
Define an DEPENDENCY_DATA_TYPE_ASSOC1_I dependency linkage root to capture the state of the specified DgnPlatform::AssocPoint. More... | |
StatusInt | mdlDependencyAssoc1_fromAssoc (DgnPlatform::DependencyLinkage *dl, int iRoot, DgnPlatform::AssocPoint const *assocPoint) |
Define an DEPENDENCY_DATA_TYPE_ASSOC1_I dependency linkage root to capture the state of the specified DgnPlatform::AssocPoint. More... | |
StatusInt | mdlDependencyAssoc1_toAssoc (DgnPlatform::AssocPoint *assocPoint, DgnPlatform::DependencyLinkage const *dl, int iRoot) |
Recreate an DgnPlatform::AssocPoint from an DEPENDENCY_DATA_TYPE_ASSOC1_I root. More... | |
size_t | mdlDependency_sizeofRootDataType (int rootDataType) |
Calculates the size of a single dependency root of the specified type. More... | |
DgnModelRefP | mdlDependency_resolveReferenceAttachment (DgnModelRefP homeModelRef, DgnPlatform::ElementId refAttId) |
Evaluate a root model ref for the target file. More... | |
DgnModelRefP | mdlDependency_resolveReferenceAttachmentRelative (DgnModelRefP homeModelRef, DgnPlatform::ElementId refAttId) |
Evaluate a reference model ref for the target file. More... | |
bool | mdlDependency_isUnsupportedDependency (ElementRefP targetElement, DgnModelP dependentCache) |
Query if MicroStation cannot support a dependency of an element in the dependentCache on the specified target element. More... | |
bool | mdlDependency_isRefMergeInProgress () |
Query if reference file merging was done since the last time mdlDependency_processAffected was called. More... | |
typedef StatusInt(* DependencyProcessingCallback)(DgnPlatform::ElementId dependentID, DgnModelRefP modelRef,DgnPlatform::DependencyLinkage *pLinkage,UChar *pRootStatus, UChar selfStatus) |
UserFunction called by mdlDependency_processAffected when a dependent element is affected by changes to root elements.
The dependentID and modelRef parameters identify the affected dependent element.
The pLinkage parameter points to a copy of the linkage that caused the callback.
Note: If a dependent element has multiple DependencyLinkages, the appropriate callback is invoked for each one that identifies changed roots. An element can even have multiple DependencyLinkages, each with the same appID. In this case, the callback for that appID is invoked once for each linkage.
Note: Since multiple callbacks may be made on the same element and each callback may modify and rewrite the element, possibly moving it, each callback must use mdlAssoc_getElement to read the element from its element ID to get the current version.
The pRootStatus parameter points to an array of status values, one for each root item in the dependency linkage root array. Each entry can have one of the following values:
The DEPENDENCY_STATUS_RESOLVED status is passed when the corresponding root comes from a different model than the dependent. The root might have been changed without notifying the dependent, so the callback should check this.
The DEPENDENCY_STATUS_UNRESOLVED status is passed when the corresponding root cannot be found. This normally happens only when the root is in a different model (or file) and that model is not loaded. The situtation may be temporary. If the root is resolved later on, the callback will be invoked and the root status will move to DEPENDENCY_STATUS_RESOLVED.
(Note: If an entry in the pLinkage->root array refers to more than one root element, then the corresponding entry in pRootStatus is the greatest of the individual root change status values.)
The selfStatus parameter is the change status of the dependent element itself. This can have one of the following values:
All callbacks on a given dependent element will see the same selfStatus value.
If the dependent was changed directly and none of its roots was changed, then the values in the pRootStatus array will all be zero, while the value of selfStatus will be non-zero. The selfStatus parameter is meant to be a convenience to the callback, so that it can know if the dependent had been changed at the same time that it is notified about root changes.
A callback may modify the dependent element and even add or delete DependencyLinkages on it. Changes to dependency linkages will not affect the remaining callbacks on this element during the current wave but will affect the next wave (if any). Note that the linkage passed in is a copy and should not be modified. The callback must call the necessary MDL functions to write any changes to file.
If multiple applications want to handle the same dependency, then they must cooperate among themselves. See mdlDependency_getCallback for notes on how to chain callbacks together.
If "far" or DgnPlatform::AssocPoint root references are used, then the root elements may not be in this model.
This modelRef cannot be used to display the element. This modelRef is a "working model ref." This model ref is not attached to any view. To display the dependent element (or a root), you must call mdlElmdscr_displayAllReferences.
If a dependent or a root element is complex, your dependency callback can detect if it is dropped (i.e., converted from complex to non-complex). This is done as follows:
Then you know that the complex element was dropped.
As a concrete example, suppose that you have added a dependency linkage to a cell. The basic logic outlined here works equally well for other complex types and for cases where the complex element is a root. Suppose that a user has just applied the DROP command to that cell. Your dependency callback will be invoked as soon as the user accepts the drop.
When your dependency callback is invoked, the "selfChanged" status of the cell header will be DEPENDENCY_STATUS_CHANGED. This is misleading, because in fact the cell header element was effectively deleted by the drop command. You can detect this in one of two ways: if you call mdlAssoc_getElement and pass in the cell header element's DgnPlatform::ElementId, you will get an error status. That tells you that the cell header has been deleted. Or, you can call dgnCache_findElemById. That should return the cell header's ElementRefP. You can then call elementRef_isDeleted to verify that the cell header element itself has been deleted.
When elements are grouped, the elements become complex components of a new orphan cell. The elements retain their unique ElementIDs.
If an element has a dependency linkage, then when it is moved into a group, the DependencyProcessingCallback function will be called twice on it: once with selfStatus == DEPENDENCY_STATUS_DELETED and once with selfStatus == DEPENDENCY_STATUS_CHANGED (not necessarily in that order).
The DEPENDENCY_STATUS_CHANGED status indicates that the element has been re-added as a complex component. Calling mdlDependency_wasAdded will return true.
The DEPENDENCY_STATUS_DELETED status indicates that the original, stand-alone version of the element was deleted. To distinguish this from a real deletion, call
When this function returns SUCCESS, than means that the element with this unique ID is not deleted. Therefore, the element was only moved.
[in] | dependentID | element ID of dependent element |
[in] | modelRef | model containing dependent element (see remarks) |
[in] | pLinkage | copy of dependent element's linkage |
[in] | pRootStatus | change status of each root in linkage: DEPENDENCY_STATUS_XXX |
[in] | selfStatus | change status of dependent itself : DEPENDENCY_STATUS_XXX |
typedef void(* DependencyProcessingCallbackForLoad)(DgnPlatform::ElementId dependentID, DgnModelRefP modelRef,DgnPlatform::DependencyLinkage *pLinkage,bool futureUse) |
Callback to be invoked whenever an element carrying the specifying dependency linkage is loaded.
[in] | dependentID | element ID of dependent element |
[in] | modelRef | modelRef of dependent element |
[in] | pLinkage | copy of dependent element's linkage |
[in] | futureUse | for future use (always true) |
typedef void(* DependencyProcessingCallbackForUndoRedo)(DgnPlatform::ElementId dependentID, DgnModelRefP modelRef,DgnPlatform::DependencyLinkage *pLinkage,UChar *pRootStatus, UChar selfStatus) |
Callback to be invoked whenever changes affecting a dependent element are undone or redone.
When elements are grouped, the elements become complex components of a new orphan cell. The elements retain their unique ElementIDs.
When the Group operation is undone, each component element is moved out of the orphan cell. If an element has a dependency linkage, then the DependencyProcessingCallbackForUndoRedo function will be called twice on it when the Group operation is undone: once with selfStatus == DEPENDENCY_STATUS_CHANGED and once with selfStatus == DEPENDENCY_STATUS_DELETED (not necessarily in that order).
The DEPENDENCY_STATUS_CHANGED status indicates that the original, non-complex element has been re-added. Calling mdlDependency_wasAdded will return true.
The DEPENDENCY_STATUS_DELETED status indicates that the grouped version of the element as a complex component has been deleted. To distinguish this from a real deletion, call
When this function returns SUCCESS, than means that the element with this unique ID is not deleted. Therefore, the element was only moved.
[in] | dependentID | element ID of dependent element |
[in] | modelRef | modelRef of dependent element |
[in] | pLinkage | copy of dependent element's linkage |
[in] | pRootStatus | change status of each root in linkage: DEPENDENCY_STATUS_XXX |
[in] | selfStatus | change status of dependent itself : DEPENDENCY_STATUS_XXX |
typedef struct mdlDesc MdlDesc |
The Dependency API provides functions that allow an application to create and manage dependencies between elements and to do selective change tracking of marked elements. See the overview for the terms and concepts behind the dependency manager.
int mdlDependency_addSimpleDependencyLinkageToDescr | ( | MSElementDescrH | nodeEdPP, |
UShort | appId, | ||
UShort | appValue, | ||
int | copyOption, | ||
DgnPlatform::ElementId | uniqueId | ||
) |
This function creates a simple dependency linkage on an element descr.
[in,out] | nodeEdPP | element desciptor to add linkage to |
[in] | appId | application ID of dependency to watch. |
[in] | appValue | appValue of linkage to delete |
[in] | copyOption | DEPENDENCY_ON_COPY_... |
[in] | uniqueId | elementid of root element |
StatusInt mdlDependency_appendLinkage | ( | MSElementP | pEl, |
DgnPlatform::DependencyLinkage * | pLinkage | ||
) |
This function adds the specified DgnPlatform::DependencyLinkage to an element.
The pLinkage parameter should point to a fully specified DgnPlatform::DependencyLinkage structure containing a valid appID, type, and refs list.
The dependencies are not actually registered until you write the element to the cache.
A given dependent element can have multiple DependencyLinkages, specifying dependencies with the same appID and type on various root elements or dependencies with various appIDs and types on the same root elements. A given element can be both a dependent and a root. Circular dependencies are allowed. An element may depend on itself.
To test for existing linkages, call mdlDependency_getLinkage.
To set up a linkage, call mdlDependency_appendLinkage.
To remove a DgnPlatform::DependencyLinkage from an element, call mdlDependency_deleteLinkage.
To update a DgnPlatform::DependencyLinkage in place on an element, call mdlDependency_updateLinkage.
A note on dependency linkage size:
The dependency linkage is a variable-length linkage. When a DgnPlatform::DependencyLinkage is appended to an element, mdlDependency_appendLinkage looks at the nRoots field to determine how much root data is actually used, and it allocates only that amount of space on the element.
Binary portability:
This function converts the stored linkage data to disk format if necessary.
[in,out] | pEl | element to receive the linkage |
[in] | pLinkage | linkage data to append |
StatusInt mdlDependency_appendLinkageEx | ( | MSElementP | pEl, |
DgnPlatform::DependencyLinkage * | pLinkage, | ||
int | xtrabytes | ||
) |
This function adds the specified DgnPlatform::DependencyLinkage to an element.
The pLinkage parameter should point to a fully specified DgnPlatform::DependencyLinkage structure containing a valid appID, type, and refs list. See mdlDependency_appendLinkage for more details.
The format (and binary-portability) of the additional data is up to the caller.
For example:
A note on dependency linkage size:
In the previous example, we used a short-cut: we know that the in-memory DgnPlatform::DependencyLinkage structure pre-allocates about 1000 bytes of space for root data, of which we would use only 8 bytes. (When dependency linkage data is appended to an element, we allocate space for only the exact amount of root data used.) So, we know that the DgnPlatform::DependencyLinkage struct would have ample space following the first root to hold our extra data. But, what if we needed to specify a great deal of root data and/or extra data and could not use this trick? In that case, we would have to allocate contiguous space on the stack or heap sufficient to hold both. For example:
Binary portability:
This function converts the stored DgnPlatform::DependencyLinkage data to disk format if necessary. Extra data is not converted.
[in,out] | pEl | element to receive the linkage |
[in] | pLinkage | linkage data to append |
[in] | xtrabytes | number of bytes of "extra" stuff tacked onto the end by the caller |
StatusInt mdlDependency_appendLinkageUsingDescr | ( | MSElementDescrH | ppEd, |
DgnPlatform::DependencyLinkage * | pLinkage, | ||
int | xtrabytes | ||
) |
Add DgnPlatform::DependencyLinkage to an element descriptor.
[in,out] | ppEd | descriptor to receive the linkage |
[in] | pLinkage | linkage data to append |
[in] | xtrabytes | number of bytes of "extra" stuff tacked onto the end by the caller |
DgnPlatform::DependencyLinkage* mdlDependency_bufferFromFileFormat | ( | LinkageHeaderP | pHeader | ) |
Memory format DgnPlatform::DependencyLinkage from the specified user data linkage.
"Extra" data will immediately follow the linkage.
Binary portability:
This function converts the linkage data from native format in place if necessary. Extra data is not converted.
[in] | pHeader | linkage data in raw file format |
DgnPlatform::DependencyLinkage* mdlDependency_bufferToFileFormat | ( | LinkageHeaderP | pHeader | ) |
File format DgnPlatform::DependencyLinkage from the specified user data linkage.
"Extra" data will immediately follow the linkage.
Binary portability:
This function converts the linkage data to native format in place if necessary. Extra data is not converted.
[in] | pHeader | linkage data in raw file format |
Remove DependencyLinkages from an element.
Only DependencyLinkages having the specified appID and type are removed. If the element has multiple matching DependencyLinkages, all are removed. See mdlDependency_appendLinkage for adding a linkage.
[in,out] | pEl | element to strip |
[in] | appID | appID of linkage to delete |
[in] | appValue | appValue of linkage to delete |
void mdlDependency_fmtRoot | ( | WStringR | buf, |
DgnModelRefP | modelRef, | ||
DgnPlatform::DependencyLinkage * | pLinkage, | ||
int | iRoot | ||
) |
Formats the specified root in the specified linkage for display in a debugging message.
[out] | buf | formatted root |
[in] | modelRef | modelRef that contains the dependent element |
[in] | pLinkage | linkage to query |
[in] | iRoot | root within linkage to query |
StatusInt mdlDependency_getCallback | ( | MdlDesc ** | ppMdlDescr, |
DependencyProcessingCallback * | pFunc, | ||
UShort | appID | ||
) |
Get the current callback that is registered to handle dependencies with the specified appID.
[out] | ppMdlDescr | current callback: MDL descriptor |
[out] | pFunc | current callback: function (MDL or native) |
[in] | appID | appID of dependency |
StatusInt mdlDependency_getCallbackForLoad | ( | MdlDesc ** | ppMdlDescr, |
DependencyProcessingCallbackForLoad * | pFunc, | ||
UShort | appID | ||
) |
Get the current load/unload callback for this appID.
[out] | ppMdlDescr | current callback: MDL descriptor |
[out] | pFunc | current callback: function (MDL or native) |
[in] | appID | appID of dependency |
StatusInt mdlDependency_getCallbackForUndoRedo | ( | MdlDesc ** | ppMdlDescr, |
DependencyProcessingCallbackForUndoRedo * | pFunc, | ||
UShort | appID | ||
) |
Get the current callback that is registered to handle dependencies with the specified appID for undo/redo purposes.
[out] | ppMdlDescr | current callback: MDL descriptor |
[out] | pFunc | current callback: function (MDL or native) |
[in] | appID | appID of dependency |
int mdlDependency_getDependentElementRefs | ( | ElementRefP * | pDependents, |
DgnPlatform::ElementId | rootElemId, | ||
DgnModelRefP | rootModelRef, | ||
int | maxDependents | ||
) |
This function returns a list of ElementRefs that depend on the specified element.
The specified element is a "root" element. The elements identified in the return array are its "dependents".
See mdlDependency_appendLinkage for adding dependencies to an element.
See mdlDependency_getNumOfDependents to query the total number of dependents.
See mdlDependency_getLinkage for inspecting linkages.
See mdlDependency_getRoots and for the inverse lookup from dependent to roots.
See mdlElmdscr_getByElemRef to get an element descriptor from an ElementRefP.
See elementRef_getElemID to get the DgnPlatform::ElementId for an ElementRefP.
[out] | pDependents | elementRefs of dependent elements |
[in] | rootElemId | element ID of root element |
[in] | rootModelRef | modelRef that contains root element |
[in] | maxDependents | max # dependent elementRefs to return in pDependents |
bool mdlDependency_getIgnoreMissingCallbacks | ( | void | ) |
Query the policy for what to do when a dependent element requires an application to process root changes, but the callback is not not currently registered.
StatusInt mdlDependency_getLinkage | ( | DgnPlatform::DependencyLinkage * | pLinkage, |
size_t | maxSize, | ||
MSElementCP | pEl, | ||
UShort | appID, | ||
UShort | appValue | ||
) |
Retrieve the DgnPlatform::DependencyLinkage on the specified element with matching appID and type.
If multiple DependencyLinkages with the same appID and type are present, the first is returned. This function returns SUCCESS if a matching DgnPlatform::DependencyLinkage is found; ERROR otherwise. The pLinkage parameter may be NULL, if the caller just wants to test for the presence of a matching linkage.
Binary portability:
This function converts the linkage data to native format if necessary. Extra data is not converted.
[out] | pLinkage | existing linkage if any (optional) |
[in] | maxSize | max amount of data to return in output buffer |
[in] | pEl | element to scan |
[in] | appID | appID to match |
[in] | appValue | appValue of linkage to delete |
StatusInt mdlDependency_getLinkageEx | ( | DgnPlatform::DependencyLinkage * | pDependencyLinkage, |
DgnPlatform::DependencyLinkage ** | ppDependencyLinkageInplace, | ||
size_t * | pDependencyLinkageSize, | ||
size_t | maxSize, | ||
MSElementCP | pEl, | ||
UShort | appID, | ||
UShort | appValue | ||
) |
Retrieve the DgnPlatform::DependencyLinkage on the specified element with matching appID and type.
If multiple DependencyLinkages with the same appID and type are present, the first is returned. This function returns SUCCESS if a matching DgnPlatform::DependencyLinkage is found; ERROR otherwise. The pLinkage parameter may be NULL, if the caller just wants to test for the presence of a matching linkage.
Binary portability:
This function converts the linkage data to native format if necessary. Extra data is not converted.
[out] | pDependencyLinkage | optional: where to copy DgnPlatform::DependencyLinkage if found |
[out] | ppDependencyLinkageInplace | optional: where to return pointer to start of DgnPlatform::DependencyLinkage in pEl if found |
[out] | pDependencyLinkageSize | optional: size in bytes of DgnPlatform::DependencyLinkage found |
[in] | maxSize | max amount of data to return in output buffer |
[in] | pEl | element to scan |
[in] | appID | appID to match |
[in] | appValue | appValue of linkage to delete |
int mdlDependency_getNumOfDependents | ( | DgnPlatform::ElementId | rootElemId, |
DgnModelRefP | modelRef | ||
) |
This function returns a number of the elements that depend on the specified element.
The specified element is a "root" element.
[in] | rootElemId | element ID of root element |
[in] | modelRef | modelRef that contains the root element |
int mdlDependency_getProcessingDisabled | ( | void | ) |
Query if processing of affected elements has been disabled.
unsigned mdlDependency_getRoots | ( | DgnPlatform::DependencyRoot * | pRoots, |
DgnModelRefP | modelRef, | ||
DgnPlatform::DependencyLinkage * | pDep, | ||
int | iRoot | ||
) |
This function returns a list of root elements on which the specified item in a dependency linkage depends.
The input dependency linkage comes from from the "dependent" element. The elements identified in the returned array are its "roots".
Note: A NULL value in the 'ref' field of a DgnPlatform::DependencyRoot indicates that the dependency is unresolved because the root element cannot be found. This may be because the target is in another file or model that is not open.
See mdlDependency_getDependents for the inverse lookup from a root to its dependents.
[out] | pRoots | elements referenced by the i'th root (max: DEPENDENCY_MAX_TARGETS_PER_ROOT) |
[in] | modelRef | modelRef of dependent element |
[in] | pDep | dependency linkage to query |
[in] | iRoot | root in the linkage to query |
StatusInt mdlDependency_initLinkage | ( | DgnPlatform::DependencyLinkage * | pLinkage, |
UShort | appID, | ||
int | dataType, | ||
int | copyOptions | ||
) |
This is a convenience function to initialize a DgnPlatform::DependencyLinkage.
The arguments are the required values to define a linkage. The rest of the linkage fields are initialized to zero.
To add a linkage to an element, call mdlDependency_appendLinkage.
[in,out] | pLinkage | linkage data to initialize |
[in] | appID | appID |
[in] | dataType | DEPENDENCY_DATA_TYPE_... |
[in] | copyOptions | DEPENDENCY_ON_COPY_... |
bool mdlDependency_isRefMergeInProgress | ( | ) |
Query if reference file merging was done since the last time mdlDependency_processAffected was called.
bool mdlDependency_isUnsupportedDependency | ( | ElementRefP | targetElement, |
DgnModelP | dependentCache | ||
) |
Query if MicroStation cannot support a dependency of an element in the dependentCache on the specified target element.
[in] | targetElement | the target (root) of the dependency |
[in] | dependentCache | the cache containing the dependent element |
DgnPlatform::DependencyStatus mdlDependency_processAffected | ( | ) |
This function invokes callbacks on all dependent elements affected by changes to root elements since the last call to this function.
See DependencyProcessingCallback for how a dependency callback is defined.
Processing of affected dependent elements occurs at frequent intervals, but not necessarily on every file update. Applications may call this function directly to force processing. (See mdlDependency_setEager for the post-processing schedule. See mdlDependency_setProcessingDisabled for how to suspend or disable post-processing.)
All changes must be written to file before calling this function.
If callbacks cause further changes to root elements, then processing will iterate until no more changes are detected or until the maximum number of iterations is reached.
Changes caused by processing may become part of the undo group of the immediately preceeding command. So, undo will encompass both the results of the preceeding command and the effects of post-processing the dependent elements affected by it. (See mdlDependency_setAppendChanges for how to control this policy.)
If a callback returns a non-zero status or if the maximum number of iterations is reached, processing will normally halt, and MicroStation will undo all changes to the previous mark. (See mdlDependency_setErrorLevel for how to control failure policies.)
See DgnPlatform::DependencyLinkage .u.f.requireApp and u.f.dontRequireAppForDelete and mdlDependency_setIgnoreMissingCallback for what MDL does when a dependent element is affected and no callback is registered.
Self-dependencies
Normally an element depends on other (root) elements and callbacks are invoked when the roots are changed.
An element is also considered to depend on itself it if contains a DgnPlatform::DependencyLinkage (of any kind). The DgnPlatform::DependencyLinkage does not have to refer to the element as a root, but it may. The registered callback for the element's DgnPlatform::DependencyLinkage(s) will be fired by mdlDependency_processAffected as a result of a change to the element itself.
Background:
An element with a DgnPlatform::DependencyLinkage is called a "dependent element". A dependent element depends on other elements, called "root elements". A callback is triggered by a change to a root element (or to the dependent element itself).
An application registers an interest in DependencyLinkages that have a particular appID. When a dependency is triggered, MDL examines each DgnPlatform::DependencyLinkage found on the affected dependent element and invokes the callback that is registered for the appID of the linkage.
If an element contains a single DgnPlatform::DependencyLinkage that references multiple root elements, the registered callback for that linkage will be invoked only once, even if multiple root elements have changed.
A given dependent element can have multiple DependencyLinkages, specifying dependencies with the same appID on various root elements or dependencies with various appIDs and types on the same root elements. A callback will be made on each linkage whose roots have changed. (If there is more than one linkage with the same appID on the same element, the registered callback will be invoked on each one.)
A given element can be both a dependent and a root. Circular dependencies are allowed. An element may depend on itself.
Example:
In the following example, suppose that:
App
is loaded and registers an interest in dependencies with an appID of 1001. That is, App
calls mdlDependency_registerCallback, specifying the appID of 1001 as the key and its own MDL descriptor and the function func
as the callback. Behind the scenes:
When MDL first noticed the DgnPlatform::DependencyLinkage on ELEMENT1, it updated the system's dependency graph to indicate that ELEMENT2 has ELEMENT1 as a dependent. Dependency registration happens when ELEMENT1 is appended or rewritten to the file after mdlDependency_appendLinkage was called initially and every time the design file containing ELEMENT1 is loaded thereafter. See the note on "Dependency Maintenance" below for more details on when dependencies are registered and when changes to dependencies become effective.
When App
called mdlDependency_registerCallback, dependency added an entry to its run-time callback registry associating App:func
with appID 1001. Note that the app must call registerCallback every time it loads, since the callback registry is not persistent. (See DgnPlatform::DependencyLinkage u.f.requireApp and u.f.dontRequireAppForDelete and mdlDependency_setIgnoreMissingCallback for what MDL does when a dependent elementis affected and no callback is registered.)
Triggering a dependency:
Now suppose that ELEMENT2 is changed. ELEMENT2 has dependents (ELEMENT1). Dependency notes the change but does not fire callbacks at this point.
When mdlDependency_processAffected is called, dependency looks at the change list, determines that ELEMENT1 affects ELEMENT2, examines ELEMENT2's DependencyLinkages, and finds one with appID:1001. Dependency then looks up 1001 in its callback registry, finds App:func
and fires it.
Cycles
Post-processing iterates as long as new changes are produced. To prevent infinite cycles, post-processing is terminated at a pre-set maximum of 200 iterations. To help prevent infinite cycles, MDL ignores calls to rewrite an element when the before and after versions of the element are identical. This test is sometimes insufficient to detect nearly equal floating point numbers. To prevent infinite cycles, a post-processing callback should check its results and should not call element rewrite if all relevant data is unchanged. Comparisons involving floating point values (and DPoint3ds) should be done to a tolerance. See mdlVec_pointEqualUOR for example.
Dependency Maintenance
When the cache containing a dependent element is loaded, MicroStation notices the element's DependencyLinkages and creates live dependencies on the root elements that it references. Therefore, the result of calling mdlDependency_getDependents on a root element will include the dependent element immediately after the dependent's cache is loaded.
When the cache containing a dependent element is unloaded (e.g., when the file is closed), MicroStation "unplugs" the dependent element from its roots. Therefore, the result of calling mdlDependency_getDependents on a root element will omit the unloaded dependent element after the dependent's cache is unlaoded. The dependent element still has its DependencyLinkages, of course, so that MicroStation will reconnect it to its roots the next time it is loaded.
When a dependent element is created or rewritten, MicroStation detects new DependencyLinkages on it and connects it to its roots immediately. Therefore, the result of calling mdlDependency_getDependents on a root element will include the dependent element right after the dependent is appended or rewritten to the file with a new reference to that root in its DgnPlatform::DependencyLinkage.
Note that calling mdlDependency_appendLinkage or mdlDependency_updateLinkage does not connect the dependent to new roots. This happens only when the element is subsequently appended or rewritten to the file.
When a dependent is rewritten to the file, MicroStation detects changed and removed DependencyLinkages on it, but does not remove dependencies immediately. Instead, MicroStation waits until the next call to mdlDependency_processAffected to remove dropped dependencies. Therefore, after removing a root from a dependent's DgnPlatform::DependencyLinkage and until mdlDependency_processAffected is called, the result of calling mdlDependency_getDependents on the root will continue include the dependent element, even though the result of calling mdlDependency_getRoots will not include the root element. The result of mdlDependency_getDependents will omit the dependent after mdlDependency_processAffected is called.
When a dependent changes in size and is rewritten to the file, causing it to move within the file, MicroStation will maintain the dependency of the dependent on its roots. Until mdlDependency_processAffected is called, however, the result of calling mdlDependency_getDependents on one of its roots will include the dependent twice. That is, the results will include both the element reference that identified the dependent before the move and the element reference the identifies the element after the move. The pre-move element reference is removed from the root's dependency list by mdlDependency_processAffected.
Debugging
mdlDependency_setTraceLevel and mdlDependency_fmtRoot can be used to debug change processing.
StatusInt mdlDependency_registerCallback | ( | UShort | appID, |
MdlDesc * | pMdlDescr, | ||
DependencyProcessingCallback | func | ||
) |
Register a callback to be invoked whenever MDL detects changes that affect elements with a DgnPlatform::DependencyLinkage having the specified appID.
Note: ONLY ONE APPLICATION MAY REGISTER FOR A GIVEN appID.
If multiple applications want to handle the same dependency, then they must cooperate among themselves. See mdlDependency_getCallback for notes on how to chain callbacks together.
The same application can register an interest in multiple dependencies.
A registered callback can be an MDL function or a native function. See the DependencyProcessingCallback typedef for the arguments of the callback.
[in] | appID | application ID of dependency to watch. |
[in] | pMdlDescr | MDL descriptor for callback |
[in] | func | callback function, can be either MDL or native code. |
StatusInt mdlDependency_registerCallbackForLoad | ( | UShort | appID, |
MdlDesc * | pDesc, | ||
DependencyProcessingCallbackForLoad | func | ||
) |
Register a callback to be invoked whenever an element carrying the specifying dependency linkage is loaded or unloaded.
The load/unload callback allows an initapp to monitor the loading and unloading of specific elements. A load/unload callback is registered for a specific appID and is invoked whenever an element carrying a dependency linkage with that appID is loaded or unloaded.
The load/unload callback is distinct from the changed and undo/redo callbacks. Load callbacks are invoked after the cache is completely loaded. Unload callbacks are invoked just before the cache is unloaded.
The status of reference attachments is undefined at the time of load and unload callbacks.
[in] | appID | appID of dependency to watch |
[in] | pDesc | MDL descriptor for callback |
[in] | func | callback function (MDL or native) |
StatusInt mdlDependency_registerCallbackForUndoRedo | ( | UShort | appID, |
MdlDesc * | pDesc, | ||
DependencyProcessingCallbackForUndoRedo | func | ||
) |
Register a callback to be invoked whenever changes affecting a dependent element are undone or redone.
[in] | appID | appID of dependency to watch |
[in] | pDesc | MDL descriptor for callback |
[in] | func | callback function (MDL or native) |
void mdlDependency_removeCallback | ( | UShort | appID | ) |
Un-register the current callback for dependencies having the specified appID.
[in] | appID | appID of dependency |
void mdlDependency_removeCallbackForLoad | ( | UShort | appID | ) |
Un-register the current load/unload callback for this appID.
[in] | appID | appID of dependency |
void mdlDependency_removeCallbackForUndoRedo | ( | UShort | appID | ) |
Un-register the current callback for dependencies having the specified appID for undo/redo purposes.
[in] | appID | appID of dependency |
DgnModelRefP mdlDependency_resolveReferenceAttachment | ( | DgnModelRefP | homeModelRef, |
DgnPlatform::ElementId | refAttId | ||
) |
Evaluate a root model ref for the target file.
[in] | homeModelRef | modelref containing reference attachment |
[in] | refAttId | reference attachment element id |
DgnModelRefP mdlDependency_resolveReferenceAttachmentRelative | ( | DgnModelRefP | homeModelRef, |
DgnPlatform::ElementId | refAttId | ||
) |
Evaluate a reference model ref for the target file.
[in] | homeModelRef | modelref containing reference attachment |
[in] | refAttId | reference attachment element id |
void mdlDependency_rootChanged | ( | ElementRefP | root | ) |
Declare that the specified root is changed and its dependents should be notified.
The root need not really be changed. This function is useful for propagating changes across indirect references, e.g., an element reference path.
[in] | root | the root element |
void mdlDependency_setIgnoreMissingCallbacks | ( | bool | b | ) |
Set the policy for what post-processing should do when a dependent element requires an application to process root changes, but the callback is not currently registered.
This function can be used to override the DgnPlatform::DependencyLinkage.u.f.requireApp field (on all linkages), so that root changes are allowed, even if some callbacks are not available to post-process affected dependency elements.
See mdlDependency_processAffected for more details on post-processing.
[in] | b | true: ignore; false: don't ignore |
void mdlDependency_setProcessingDisabled | ( | bool | bSuppress | ) |
Disable or enable post-processing of affected dependent elements.
Call mdlDependency_setErrorLevel to control post-processing failure handling without disabling post-processing.
See mdlDependency_processAffected for more details on post-processing.
[in] | bSuppress | if true, disable; else enable |
StatusInt mdlDependency_setRoots | ( | DgnPlatform::DependencyLinkage * | pDep, |
DgnModelRefP | modelRef, | ||
const DgnPlatform::DependencyRoot * | pRoots, | ||
int | iRoot | ||
) |
This function updates the roots identified by the specified item in the dependency linkage.
[in,out] | pDep | dependency linkage to query |
[in] | modelRef | modelRef of dependent element |
[in] | pRoots | elements referenced by the i'th root |
[in] | iRoot | root in the linkage to query |
void mdlDependency_setTraceLevel | ( | int | traceLevel | ) |
For debugging purposes only:
Enable or disable tracing messages to help debug dependencies and callbacks.
[in] | traceLevel | 1 to enable tracing messages; 0 to to disable |
size_t mdlDependency_sizeof | ( | DgnPlatform::DependencyLinkage * | pDep, |
int | xtrabytes | ||
) |
Get the stored size of the specified dependency linkage.
This can be useful in order to predict whether adding a linkage to an element will exceed the maximum element size.
The returned size includes the standard DgnPlatform::LinkageHeader size. The returned size is padded and rounded as required for stored linkage sizes.
The returned size is in in bytes.
[in] | pDep | linkage to test |
[in] | xtrabytes | # bytes of "extra" stuff tacked onto the end by the caller |
size_t mdlDependency_sizeofRootDataType | ( | int | rootDataType | ) |
Calculates the size of a single dependency root of the specified type.
[in] | rootDataType | a dependency root data type.
|
StatusInt mdlDependency_updateLinkage | ( | MSElementP | pEl, |
DgnPlatform::DependencyLinkage * | pDep, | ||
int | xtrabytes | ||
) |
Update a DependencyLinkages on an element.
This function will update the linkage in place, as long as it hasn't changed size. Otherwise, it will delete the current version of linkage from the element and append the new version.
NOTE: Changes to dependencies are not actually recognized until you rewrite the element to the cache.
[in,out] | pEl | element to receive the linkage |
[in] | pDep | new version of linkage |
[in] | xtrabytes | number of bytes of "extra" stuff tacked onto the end by the caller |
bool mdlDependency_wasAdded | ( | ElementRefP | ref | ) |
Query if the specified element is new.
[in] | ref | the element to query |
StatusInt mdlDependencyAssoc1_fromAssoc | ( | DgnPlatform::DependencyLinkage * | dl, |
int | iRoot, | ||
DgnPlatform::AssocPoint const * | assocPoint | ||
) |
Define an DEPENDENCY_DATA_TYPE_ASSOC1_I dependency linkage root to capture the state of the specified DgnPlatform::AssocPoint.
[out] | dl | the dependency linkage to write to |
[in] | iRoot | index into the dl roots array to write to |
[in] | assocPoint | the input DgnPlatform::AssocPoint |
StatusInt mdlDependencyAssoc1_fromAssocAndSubtype | ( | DgnPlatform::DependencyLinkage * | dl, |
int | iRoot, | ||
DgnPlatform::AssocPoint const * | assocPoint, | ||
int | assoc1Subtype | ||
) |
Define an DEPENDENCY_DATA_TYPE_ASSOC1_I dependency linkage root to capture the state of the specified DgnPlatform::AssocPoint.
[out] | dl | the dependency linkage to write to |
[in] | iRoot | index into the dl roots array to write to |
[in] | assocPoint | the input DgnPlatform::AssocPoint |
[in] | assoc1Subtype | the assocPoint subtype to define. Should be a DEPENDENCY_ASSOC1_SUBTYPE_... value |
StatusInt mdlDependencyAssoc1_toAssoc | ( | DgnPlatform::AssocPoint * | assocPoint, |
DgnPlatform::DependencyLinkage const * | dl, | ||
int | iRoot | ||
) |
Recreate an DgnPlatform::AssocPoint from an DEPENDENCY_DATA_TYPE_ASSOC1_I root.
[out] | assocPoint | the DgnPlatform::AssocPoint to write to |
[in] | dl | the input dependency linkage |
[in] | iRoot | index into the dl roots array |