HierarchyObjectInterface Manual

About

maxon::HierarchyObjectInterface is a base interface used to create elements that can be organized in a tree like structure. A parent element can have one or many child elements. A child element can have only one parent but none, one or many siblings.

A parent object can organize its child elements in multiple sub-branches.

Hierarchy Interface

The hierarchy interface provides functions to insert an element into a given tree structure:

// This example creates several elements and inserts them under the "root" element.
// At the end, the order of elements is checked.
// create "root" element
const TreeElementRef root = TreeElementFactory().Create("root"_s) iferr_return;
// create child elements
const TreeElementRef elementA = TreeElementFactory().Create("Element A"_s) iferr_return;
const TreeElementRef elementB = TreeElementFactory().Create("Element B"_s) iferr_return;
const TreeElementRef elementC = TreeElementFactory().Create("Element C"_s) iferr_return;
// insert first element under the root element
elementC.InsertAsLastChildOf(root) iferr_return;
// insert second element as a sibling under the root element
elementB.InsertBefore(elementC) iferr_return;
// insert third element under the root element
root.InsertChildAsFirst(elementA) iferr_return;
// check element order
const auto children = root.GetChildren() iferr_return;
for (const auto& child : children)
{
const TreeElementRef treeElement = maxon::Cast<TreeElementRef>(child);
const maxon::String name = treeElement.GetName();
DiagnosticOutput("Child Element: @", name);
}
const char const char * name
Definition: abstract.h:195
Definition: string.h:1235
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:176
#define iferr_return
Definition: resultbase.h:1521

Child elements can be replaced or removed:

// This example creates multiple elements, inserts them as
// child elements of the "root" element and removes them again.
// create "root" element
const TreeElementRef root = TreeElementFactory().Create("root"_s) iferr_return;
// create child elements
const TreeElementRef elementA = TreeElementFactory().Create("Element A"_s) iferr_return;
const TreeElementRef elementB = TreeElementFactory().Create("Element B"_s) iferr_return;
const TreeElementRef elementC = TreeElementFactory().Create("Element C"_s) iferr_return;
// insert child elements
root.InsertChildAsFirst(elementA) iferr_return;
root.InsertChildAsFirst(elementB) iferr_return;
// replace element
elementB.Replace(elementC) iferr_return;
// remove element
elementA.Remove();
// check remaining element
const maxon::HierarchyObjectRef<> firstChild = root.GetFirstChild();
const TreeElementRef firstElement = maxon::Cast<TreeElementRef>(firstChild);
DiagnosticOutput("First Child: @", firstElement.GetName());
Definition: hierarchyobject.h:18

Within a given hierarchy level one can navigate with:

// This example gets the first child element of the given "root" element
// and loops through all remaining child elements.
// get first child element
maxon::HierarchyObjectRef<> child = root.GetFirstChild();
while (child)
{
// check type of child
if (child.IsInstanceOf<TreeElementRef>())
{
const TreeElementRef treeElement = maxon::Cast<TreeElementRef>(child);
DiagnosticOutput("Tree Element: @", treeElement.GetName());
}
// get next child
child = child.GetNext();
}

The parent of an element is accessed with:

The child elements of a parent object are accessed with:

// This example inserts and accesses child elements in different branches.
// define branch IDs
const maxon::ConstDataPtr branchA = maxon::ConstDataPtr("a"_s);
const maxon::ConstDataPtr branchB = maxon::ConstDataPtr("b"_s);
// insert child elements into branches
root.InsertChildAsFirst(elementA, branchA) iferr_return;
root.InsertChildAsFirst(elementB, branchB) iferr_return;
// get child elements from branches
const maxon::HierarchyObjectRef<> childA = root.GetFirstChild(branchA);
const maxon::HierarchyObjectRef<> childB = root.GetFirstChild(branchB);
Definition: datatypebase.h:1715

These observables are called on certain events:

  • ObservableHierarchyInsert: Is called when an element was inserted in the hierarchy.
  • ObservableHierarchyRemove: Is called when an element was removed from the hierarchy.

To navigate through a given hierarchy one can use these utility functions:

// This example traverses over all child elements of the given root element and the root element itself.
maxon::TraverseMeAndChildren<TreeElementRef>(root,
[](const TreeElementRef& child, const TreeElementRef& parent, const maxon::ConstDataPtr& branch, maxon::Int depth) -> maxon::Result<maxon::Bool>
{
DiagnosticOutput("Tree Element: @", child.GetName());
return true;
// This example traverses over all child elements of the given root element but not the root element itself.
maxon::TraverseChildren<TreeElementRef>(root,
[](const TreeElementRef& child, const TreeElementRef& parent, const maxon::ConstDataPtr& branch, maxon::Int depth) -> maxon::Result<maxon::Bool>
{
DiagnosticOutput("Tree Element: @", child.GetName());
return true;
Definition: resultbase.h:766
Int64 Int
signed 32/64 bit int, size depends on the platform
Definition: apibase.h:213

It is also possible to iterate over all elements of a hierarchy using maxon::HierarchyObjectIterator:

// This example uses the HierarchyObjectIterator template to iterate over
// all child elements of the given root element and the root element itself.
for (const TreeElementRef& element : maxon::HierarchyObjectIterator<TreeElementRef>(root))
{
DiagnosticOutput("Tree Element: @", element.GetName());
}
Definition: hierarchyobject.h:410
PyObject * element
Definition: unicodeobject.h:1016

Custom Implementations

A custom interface can be based on maxon::HierarchyObjectInterface. The resulting reference object can be organized in a tree. The default implementation of maxon::HierarchyObjectInterface is maxon::HierarchyObjectClass.

An interface based on maxon::HierarchyObjectInterface can implement maxon::HierarchyObjectInterface::ParentChanged() to be informed when the parent of the element has changed. This function must not be called by user code.

// This example shows an implementation of an interface based on HierarchyObjectInterface.
// It implements ParentChanged() and accesses the hierarchy in GetParentName().
// implementation of TreeElementInterface
class TreeElementImplementation : public maxon::Component<TreeElementImplementation, TreeElementInterface>
{
// use the default implementation "HierarchyObjectClass"
MAXON_COMPONENT(NORMAL, maxon::HierarchyObjectClass);
public:
{
_name = name;
}
MAXON_METHOD maxon::String GetName() const
{
return _name;
}
// function that returns the name of the parent element
{
// access parent element
const auto parentObject = super.GetParent();
if (!parentObject)
return maxon::String();
// check type of parent element
if (!parentObject.IsInstanceOf<TreeElementRef>())
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Parent object is no TreeElementRef."_s);
// get name of parent element
const TreeElementRef treeElement = maxon::Cast<TreeElementRef>(parentObject);
return treeElement.GetName();
}
MAXON_METHOD void ParentChanged(maxon::Bool removed)
{
if (removed)
return;
// if a new parent is assigned, print the parent's name
const auto parentObject = super.GetParent();
if (parentObject.IsInstanceOf<TreeElementRef>())
{
const TreeElementRef treeElement = maxon::Cast<TreeElementRef>(parentObject);
DiagnosticOutput("New Parent is @", treeElement.GetName());
}
}
// Factory method
maxon::Result<void> FactoryInit(maxon::FactoryInterface::ConstPtr, maxon::String name)
{
self.SetName(name);
return maxon::OK;
}
private:
maxon::String _name;
};
Definition: objectbase.h:2641
@ NORMAL
Normal Tag morphing.
bool Bool
boolean type, possible values are only false/true, 8 bit
Definition: apibase.h:206
return OK
Definition: apibase.h:2747
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:67
#define MAXON_COMPONENT(KIND,...)
Definition: objectbase.h:2199
#define MAXON_METHOD
Definition: interfacebase.h:1012

Further Reading