Share

AcDbAssocAction Class

Class Hierarchy

AcRxObject
    AcGiDrawable
        AcDbObject
            AcDbAssocAction
                AcDbAssoc2dConstraintGroup
                AcDbAssocNetwork
                AcDbAssocVariable

C++

class AcDbAssocAction : public AcDbObject;

File

AcDbAssocAction.h

Description

Any object that wants to exhibit associative behavior, i.e. be automatically evaluated by the associative mechanism when objects it depends on change, needs to be derived from an AcDbAssocActionBody class (see comments at the AcDbAssocActionBody class) and owned by a parent AcDbAssocAction object. The action body is fully owned by its parent action, such as when the parent action is erased, it also erases the owned action body.

The AcDbAssocAction class itself does not have virtual methods that could be overridden, therefore it is not possible for external developers to derive directly from the AcDbAssocAction class and override its methods. Internal AutoCAD developers can derive from the AcDbImpAssocAction class and override its virtual methods, but it should only be done when there is no possibility that objects of the derived action classes could become proxies.

Each action is owned by an AcDbAssocNetwork that itself is an action, therefore hirearchical associative structures can be represented.

The main protocol of the AcDbAssocAction class is the evaluate() method that calls the evaluateOverride() method of the owned AcDbAssocActionBody object. Actions own AcDbAssocDependency objects that allow the actions to depend on arbitrary AcDbObjects. This is how the connectivity in the network is represented. When objects the dependencies depend on change, the dependencies are notified, actions owning the dependencies are notified and also the hierarchy of the networks owning the actions is notified. This notification just changes AcDbAssocStatus of the dependencies and of the actions/networks to "dirty", it does not trigger any action evaluation.

The actual action evaluation happens when the client code calls the evalaute() method on the top-level network. This automatically evaluates all the actions the network owns that need to be evaluated because they depend, either directly or transitively, on objects that changed. If an action modifies an object (has a write-dependency on it) and there is another action that uses the modified object (has read-dependency on it), then, if the first action is evaluated, the second action also needs to be transitively evaluated.

The flow of information is as follows:

Object1 --ReadDep--> Action1 --WriteDep1--> Object2 --ReadDep--> Action2 ...

Notice that an action may depend on multiple objects and may modify multiple other objects. The network forms a directed acyclic graph. The evalution algoritm makes sure that all actions that need to be evaluated are evaluated and that the evaluation happens in the correct order so that every action is evaluated only after all other actions that modify objects this action depends on have already been evaluated (the situation is actually little bit more complex, there are other aspects controlling the evaluation order).

The AcDbAssocManager::evaluateTopLevelNetwork() static method should be used to evaluate the top-level network of the database. It will collect and evaluate all the actions that need to be evaluated. Explicit evaluation of the individual sub-networks is not recommended.

Actions may own action parameters that allow custom action body classes keep and access their data in a uniform an high-level manner. Instead of each concrete custom action body devising its own way how to keep its data, they the data is uniformly stored in the form of AcDbAssocActionParam(eters), and for simple numerical values, in the form of value action parameters. The action parameters take care of keeping the data in various ways and provide the current values to the action body anytime the action body requests them. The custom action body does not even need to implement code to serialize and clone its data, because the data is owned and managed by the parent AcDbAssocAction. See the AcDbAssocActionParam class and derived classes for more details.

Another advantage of keeping the action body data in action parameters is that it is possible to write code that traverses and inspects the action body data in a generic way, without knowing anything about the action body itself. AcDbAssocAction owns an array of AcDbAssocActionParams and an array of value action parameters. The AcDbAssocActionParams and the value action parameters are completely independent of each other. The value action parameter represents a named array of numerical values, such as a doubles, ints, strings or vectors. Usually the array will contain only a single element, but generally it con contain any number of elements. The value parameter name is a case-sensitive string. Each individual value may either be a constant, or defined by an expression. When it is defined by an expression, the value parameter keeps AcDbObjectId of a read-only AcDbAssocValueDependency (the dependency is owned by the parent AcDbAssocAction) on an anonymous AcDbAssocVariable that keeps the expression and provides the input value for the value parameter. This anonymous variable is exclusively managed by the value parameter who is responsible for its creation, deletion, copy, etc. If the user enters the expression in the form of "name=expression", the automatically created AcDbAssocVariable is assigned the given "name" instead of being anonymous, i.e. with empty name. If the variable has explicit name, it appears in the parameters manager and can be referenced by other expressions as any other variable. However, it is still completely managed by the value parameter who takes care of the variable deletion, copy, etc.

Links

AcDbAssocAction Methods

Was this information helpful?