LObject Class

#include <Layers/lobject.h>
Inherited By: LAttribute, LLayer

Public Functions

LObject()
~LObject()
LObject * add_child(std::unique_ptr<LObject> child)
const std::vector<std::unique_ptr<LObject>> & children()
std::uint64_t children_version()
void destroy_child(LObject * child)
void disconnect_destroyed(const LConnectionID & connection)
std::vector<T *> find_children(bool recursive = false)
const LString & object_name()
LConnectionID on_destroyed(std::function<void ()> callback)
LObject * parent()
void reorder_children(const std::vector<LObject *> & order)
void set_object_name(const LString & new_name)

Detailed Description

An object is a named, hierarchical component of the runtime engine. Everything in a loaded tree is an LObject.

LObject           base for parent/child ownership rules
├── LLayer        object described by attributes and other layers
└── LAttribute    object storing a data value or link

The loader (see LLoader) constructs the tree from a set of .lyr files. Hand construction of objects is usually not necessary.

Parents and children

Objects own their children. To add a child to an object, pass it to add_child() as a std::unique_ptr instance. add_child() uses a move operation making the object responsible for the child's lifetime.

auto parent = std::make_unique<LObject>();
auto child  = std::make_unique<LObject>();

LObject* child_ptr = child.get();
parent->add_child(std::move(child));  // `parent` now owns `child`;
                                      // the `child` object becomes null

After add_child() establishes the relationship, the child knows who its parent is; calling parent() from the child acquires it. parent() returns a raw pointer to the parent object for observation. Do not attempt to manage it since its lifetime is already handled by std::unique_ptr.

LObject* parent_ptr = child_ptr->parent();  // Returns observational,
                                            // raw pointer to `parent`

Creating objects with lMake factory

lMake<T>() creates the child and parents it in one step. Here's an example creating LLayer and LAttribute objects:

LLayer* button   = lMake<LLayer>(engine.root(), "Button");
            // Create `Button` layer and parent it to the engine's root

LAttribute* fill = lMake<LAttribute>(button, "Fill");
            // Create `Fill` attribute and parent it to `Button`

Why not pass the parent to the constructor?

An object cannot parent itself during construction. add_child() needs the std::unique_ptr that owns the object, which doesn't exist while constructing since std::make_unique hasn't returned. So the order is to construct, then parent.

If you're coming from Qt, then you're used to QObject(QObject* parent). Layers objects are owned using unique_ptr instead of raw pointers, so parenting has to work differently. lMake<T>() should help make the process more familiar.

Member Function Documentation

LObject()

Constructs an object.

~LObject()

No description available.

LObject * add_child(std::unique_ptr<LObject> child)

Adds child to this object's children list, returning an observational pointer to the child.

const std::vector<std::unique_ptr<LObject>> & children()

Returns an immutable reference to the vector of std::unique_ptrs containing this object's children.

std::uint64_t children_version()

Returns a counter that increments whenever the child set changes (add_child / destroy_child).

Callers that derive data from the child set (e.g. LLayer's attribute lookup cache) can record this value and treat their derivation as valid while it is unchanged.

void destroy_child(LObject * child)

Destroys child if it's actually this object's child.

void disconnect_destroyed(const LConnectionID & connection)

Disconnects the callback associated with connection to stop it from processing when this object gets destroyed.

template<typename T>
std::vector<T *> find_children(bool recursive = false)

Returns a vector of pointers to this object's type T children.

If recursive is true, then the returned vector will include children of children.

Children maintain their declaration order, and with recursive enabled, each child is followed immediately by its descendants.

const LString & object_name()

Returns the name of the object.

LConnectionID on_destroyed(std::function<void ()> callback)

Stores callback and processes it whenever this object gets destroyed.

Returns an LConnectionID which can be used to disconnect the callback later through disconnect_destroyed().

LObject * parent()

Returns a pointer to the object's parent.

Returns nullptr if no parent has been set.

void reorder_children(const std::vector<LObject *> & order)

Reorders a subset of this object's children.

Each child in order is placed, in that order, into the slots those children currently occupy. Children not listed keep their positions.

Every pointer in order must be a current child of this object.

void set_object_name(const LString & new_name)

Sets the object's name to new_name.

Appearance
Theme
—