Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Version 14 (modified by landauf, 8 years ago) (diff)

fixed links

ClassTreeMask

Description

The ClassTreeMask defines a mask that includes or excludes branches and single classes in the class-tree. You can think of the ClassTreeMask like a mask in computer graphics: A mask is a black/white picture where black means invisible and white means fully visible. That way you can show some parts of an image and hide others. The ClassTreeMask does the same with the class-tree, but show means include and hide means exclude. An unmodified mask shows everything / is white / includes the BaseObject (those statements are equivalent).

Creating the mask

Include and exclude

You can include and exclude classes in the mask by calling the corresponding functions. Including/Excluding a class usually applies not only to the specified class but to all subclasses too.

Notation: Including or excluding a class is denoted as "adding a new rule".

The class-tree starts with the BaseObject but has some additional Interfaces that are parents of some subclasses (or "nodes" in the speak of tree-structure). Because we can't include or exclude classes directly, we use the corresponding Identifiers instead. In the following we'll speak about "classes" but implicitly mean "the Identifiers of those classes".

The overwrite flag

Including a class means: "The whole branch starting with this class gets included", unless you didn't set the overwrite flag to false. Including a class without overwriting means: "Include the whole branch starting with this class but don't include previously excluded classes". The same aplies for excluding.

The clean flag

After including/excluding a class, the ClassTreeMask is scanned for useless rules. If you include the BaseObject and include a subclass of BaseObject too, this brings no new information, so the inclusion-rule of the subclass can be discarded. Only rules that change the state are saved. You can turn this cleanup off by setting the clean flag to false. Warning: This could change the meaning of your mask when you add further rules with overwrite set to false. If, in our example, the subclass of BaseObject was included without clean and afterward you exclude the BaseObject without overwrite, the subclass stays included. You'll find some examples for this in the corresponding section of this page.

Rules for single classes

It's also possible to include/exclude only a single class wihtout changing the rule for following classes. This is achieved with the includeSingle/excludeSingle functions.

Interfaces

Including/excluding interfaces is a bit different, because interfaces aren't directly in the class-tree. Instead the ClassTreeMask will apply the rule for all direct parents of the interfaces. If you set overwrite to false, only direct parents without an explicit rule apply the new rule. This may sound difficult, but it's really intutive. Just look at the examples.

Functions

Branches

  • include(class [, overwrite, clean]): Includes class and all following classes. If overwrite is false, only classes that weren't explicitly excluded previously are included (default is true). If clean is true, only relevant rules stay in the branch (default is true).
  • exclude(class [, overwrite, clean]): Excludes class and all following classes. If overwrite is false, only classes that weren't explicitly included previously are excluded (default is true). If clean is true, only relevant rules stay in the branch (default is true).

Single classes

  • includeSingle(class [, clean]): Includes class without changing the rule for following classes. If clean is true, only relevant rules stay in the branch (default is true).
  • excludeSingle(class [, clean]): Excludes class without changing the rule for following classes. If clean is true, only relevant rules stay in the branch (default is true).

Tree

  • clean(): Cleans the ClassTreeMask by droping all useless rules, where "useless" means: They add no new information to the mask (because a rule applied to a parent already sais the same).
  • reset(): Deletes all rules and includes everything.

Operators

It's possible to calculate with masks in the meaning of set-theory, so you can create unions (+), intersections (*), differences (-) and complements (!) by using the corresponding operators.

  • Union: Every class that is included in at least one of the two masks will be included in the resulting mask, all others are excluded (or).
    • operator+, operator|, operator+=, operator|=
  • Intersection: Every class that is included in both masks will be included in the resulting mask, all others are excluded (and).
    • operator*, operator&, operator*=, operator&=
  • Difference: Every class that is included in the left mask but not in the second mask will be included in the resulting mask, all others are excluded.
    • operator-, operator-=
  • Complement: Every class that is excluded in the mask will be included in the resulting mask and vice versa (not).
    • operator!, operator~
  • Exclusivity: Every class that is included in exactly one of the two masks will be included in the resulting mask, all others are excluded (xor).
    • operator^, operator^=

Iterator

Sometimes you want to iterate through all existing objects which are instances of classes included in a ClassTreeMask. This can be achieved by using an ClassTreeMaskObjectIterator.

This is done the following way:

for (ClassTreeMaskObjectIterator it = mask.begin(); it != mask.end(); ++it)
    it->doSomething();

Note: The ClassTreeMaskObjectIterator handles all objects as BaseObjects. If you want to use another class, you should use a dynamic_cast:

for (ClassTreeMaskObjectIterator it = mask.begin(); it != mask.end(); ++it)
    (dynamic_cast<SomeClass*>(*it))->doSomethingAdvanced();

Performance of ClassTreeMaskObjectIterator is good as long as you don't exclude subclasses of included classes. Of course you can still exlucde subclasses, but if this is done more often, we need a new implementation using a second ObjectList in the Identifier, containing all objects of exactly one class. Including subclasses of excluded classes however is really fast.

Examples

Include and Exclude

// Create a new mask - at the beginning everything is included

ClassTreeMask mymask;





// Now exclude A2

mymask.exclude(Class(A2));





// Include A2B1C1, A2B2C1 and A3B2

mymask.include(Class(A2B1C1));
mymask.include(Class(A2B2C1));
mymask.include(Class(A3B2));



Include single and exclude single

// Create a new mask and exclude only A2 but noth the following classes

ClassTreeMask mymask;
mymask.excludeSingle(Class(A2));




Overwrite true and false

// Create a new mask, exclude A1 but include A1B1

ClassTreeMask mymask;
mymask.exclude(Class(A1));
mymask.include(Class(A1B1));



// Now exclude the BaseObject with overwrite = true (this is default)
//  -> everything is now excluded

mymask.exclude(Class(BaseObject), true);




// If we instead exclude the BaseObject with overwrite = false
//  -> A1B1 stays included

ClassTreeMask mymask;
mymask.exclude(Class(A1));
mymask.include(Class(A1B1));
mymask.exclude(Class(BaseObject), false);

Clean true and false

// Create a new mask and explicitly include BaseObject
// Then include A2 too with clean = true (this is default)
// The resulting mask includes everything - the include rule of A2 had no effect

ClassTreeMask mymask;
mymask.include(Class(BaseObject))
mymask.include(Class(A2), true, true)

// Now exclude the BaseObject without overwrite
// This excludes everything, because only the include rule of of BaseObject was
// saved, and now this rule was changed to exclude.

mymask.exclude(Class(BaseObject), false)



// Instead of this we create a new mask again and explicitly include BaseObject
// This time include A2 with clean = false
// The resulting mask includes still everything, but the include rule of
// A2 is saved

ClassTreeMask mymask;
mymask.include(Class(BaseObject))
mymask.include(Class(A2), true, false)

// Now exclude the BaseObject without overwrite
// This excludes everything except A2, because the include rule of A2 was saved
// and not overwritten

mymask.exclude(Class(BaseObject), false)



Inclusion and exclusion of interfaces

// Create a new mask and exclude Interface1
// This excludes all classes that inherit from Interface1, namely A2B2 and A3

ClassTreeMask mymask;
mymask.exclude(Class(Interface1));



// Create another mask: Exclude BaseObject but include A2 and A3

ClassTreeMask mymask;
mymask.exclude(Class(BaseObject));
mymask.include(Class(A2));
mymask.include(Class(A3));


// Now exclude Interface1 without overwrite
// This excludes A2B2 and all following classes, but it doesn't exclude
// A3 because A3 explicitly has it's own rule. If overwrite would have been
// set to true (which is default), A3 would be excluded too.

mymask.exclude(Class(Interface1), false);



Operators

In the following examples we use two masks: mask1 and mask2. They are defined in the following pieces of code:

// Create mask1:

ClassTreeMask mask1;
mask1.exclude(Class(A1B1));
mask1.exclude(Class(A2));
mask1.include(Class(A2B2));
mask1.exclude(Class(A2B2C1));
mask1.exclude(Class(A3B1));
mask1.include(Class(A3B1C2));
mask1.exclude(Class(A3B2C1));
mask1.exclude(Class(A3B2C2));

// Create mask2:

ClassTreeMask mask2;
mask2.exclude(Class(BaseObject));
mask2.include(Class(A1));
mask2.exclude(Class(A1B2));
mask2.exclude(Class(A1B1C2));
mask2.include(Class(A2));
mask2.exclude(Class(A2B2));
mask2.include(Class(A3B1));
mask2.include(Class(A3B2));
mask2.exclude(Class(A3B2C2));

// or-operator:

ClassTreeMask result = mask1 + mask2;





// and-operator:

ClassTreeMask result = mask1 * mask2;





// minus-operator:

ClassTreeMask result = mask1 - mask2;





// xor-operator:

ClassTreeMask result = mask1 ^ mask2;





// not-operator:

ClassTreeMask result = !mask1;





Attachments (19)

Download all attachments as: .zip