Magnum::Ui::AbstractLayouter class new in Git master

Base for layouters.

Derived classes

class SnapLayouter new in Git master
Snap layouter.

Constructors, destructors, conversion operators

AbstractLayouter(LayouterHandle handle) explicit
Constructor.
AbstractLayouter(const AbstractLayouter&) deleted
Copying is not allowed.
AbstractLayouter(AbstractLayouter&&) noexcept
Move constructor.

Public functions

auto operator=(const AbstractLayouter&) -> AbstractLayouter& deleted
Copying is not allowed.
auto operator=(AbstractLayouter&&) -> AbstractLayouter& noexcept
Move assignment.
auto handle() const -> LayouterHandle
Layouter handle.
auto state() const -> LayouterStates
Layouter state.
void setNeedsUpdate()
Mark the layouter with LayouterState::NeedsUpdate.
auto capacity() const -> std::size_t
Current capacity of the layout storage.
auto usedCount() const -> std::size_t
Count of used items in the layout storage.
auto isHandleValid(LayouterDataHandle handle) const -> bool
Whether a layout handle is valid.
auto isHandleValid(LayoutHandle handle) const -> bool
Whether a layout handle is valid.
auto node(LayoutHandle layout) const -> NodeHandle
Node which given layout is assigned to.
auto node(LayouterDataHandle layout) const -> NodeHandle
Node which given layout is assigned to assuming it belongs to this layouter.
auto nodes() const -> Containers::StridedArrayView1D<const NodeHandle>
Nodes which the layouts are assigned to.
auto generations() const -> Containers::StridedArrayView1D<const UnsignedShort>
Generation counters for all data.
void setSize(const Vector2& size)
Set user interface size.
void cleanNodes(const Containers::StridedArrayView1D<const UnsignedShort>& nodeHandleGenerations)
Clean layouts attached to no longer valid nodes.
void update(Containers::BitArrayView layoutIdsToUpdate, const Containers::StridedArrayView1D<const UnsignedInt>& topLevelLayoutIds, const Containers::StridedArrayView1D<const NodeHandle>& nodeParents, const Containers::StridedArrayView1D<Vector2>& nodeOffsets, const Containers::StridedArrayView1D<Vector2>& nodeSizes)
Update selected top-level layouts.

Protected functions

auto add(NodeHandle node) -> LayoutHandle
Add a layout assigned to given node.
void remove(LayoutHandle handle)
Remove a node from this layouter.
void remove(LayouterDataHandle handle)
Remove a node from this layouter assuming it belongs to it.

Private functions

void doSetSize(const Vector2& size) virtual
Set user interface size.
void doClean(Containers::BitArrayView layoutIdsToRemove) virtual
Clean no longer valid layouts.
void doUpdate(Containers::BitArrayView layoutIdsToUpdate, const Containers::StridedArrayView1D<const UnsignedInt>& topLevelLayoutIds, const Containers::StridedArrayView1D<const NodeHandle>& nodeParents, const Containers::StridedArrayView1D<Vector2>& nodeOffsets, const Containers::StridedArrayView1D<Vector2>& nodeSizes) pure virtual
Update selected top-level layouts.

Function documentation

Magnum::Ui::AbstractLayouter::AbstractLayouter(LayouterHandle handle) explicit

Constructor.

Parameters
handle Handle returned by AbstractUserInterface::createLayouter()

Magnum::Ui::AbstractLayouter::AbstractLayouter(AbstractLayouter&&) noexcept

Move constructor.

Performs a destructive move, i.e. the original object isn't usable afterwards anymore.

LayouterHandle Magnum::Ui::AbstractLayouter::handle() const

Layouter handle.

Returns the handle passed to the constructor.

LayouterStates Magnum::Ui::AbstractLayouter::state() const

Layouter state.

See the LayouterState enum for more information. By default no flags are set.

void Magnum::Ui::AbstractLayouter::setNeedsUpdate()

Mark the layouter with LayouterState::NeedsUpdate.

Meant to be called by layouter implementations when the layouts get modified. See the flag for more information.

std::size_t Magnum::Ui::AbstractLayouter::capacity() const

Current capacity of the layout storage.

Can be at most 1048576. If add() is called and there's no free slots left, the internal storage gets grown.

std::size_t Magnum::Ui::AbstractLayouter::usedCount() const

Count of used items in the layout storage.

Always at most capacity(). Expired handles are counted among used as well. The operation is done with a $ \mathcal{O}(n) $ complexity where $ n $ is capacity().

bool Magnum::Ui::AbstractLayouter::isHandleValid(LayouterDataHandle handle) const

Whether a layout handle is valid.

A handle is valid if it has been returned from add() before and remove() wasn't called on it yet. For LayouterDataHandle::Null always returns false.

bool Magnum::Ui::AbstractLayouter::isHandleValid(LayoutHandle handle) const

Whether a layout handle is valid.

A shorthand for extracting a LayouterHandle from handle using layoutHandleLayouter(), comparing it to handle() and if it's the same, calling isHandleValid(LayouterDataHandle) const with a LayouterDataHandle extracted from handle using layoutHandleData(). See these functions for more information. For LayoutHandle::Null, LayouterHandle::Null or LayouterDataHandle::Null always returns false.

NodeHandle Magnum::Ui::AbstractLayouter::node(LayoutHandle layout) const

Node which given layout is assigned to.

Expects that layout is valid. The returned handle is never NodeHandle::Null. See also node(LayouterDataHandle) const which is a simpler operation if the layout is already known to belong to this layouter.

The returned handle may be invalid if either the layout got assigned to an invalid node in the first place or the node or any of its parents were removed and AbstractUserInterface::clean() wasn't called since.

Unlike with layer data, the node assignment cannot be changed after layout creation.

NodeHandle Magnum::Ui::AbstractLayouter::node(LayouterDataHandle layout) const

Node which given layout is assigned to assuming it belongs to this layouter.

Expects that layout is valid. The returned handle is never NodeHandle::Null. See also node(LayoutHandle) const which additionally checks that the layout belongs to this layouter.

The returned handle may be invalid if either the layout got assigned to an invalid node in the first place or the node or any of its parents were removed and AbstractUserInterface::clean() wasn't called since.

Containers::StridedArrayView1D<const NodeHandle> Magnum::Ui::AbstractLayouter::nodes() const

Nodes which the layouts are assigned to.

To be used internally from doUpdate(). Size of the returned view is the same as capacity(). Items that are NodeHandle::Null are corresponding to layouts that are freed.

Containers::StridedArrayView1D<const UnsignedShort> Magnum::Ui::AbstractLayouter::generations() const

Generation counters for all data.

Meant to be used by code that only gets data IDs or masks but needs the full LayoutHandle / LayouterDataHandle. Size of the returned view is the same as capacity().

void Magnum::Ui::AbstractLayouter::setSize(const Vector2& size)

Set user interface size.

Used internally from AbstractUserInterface::setSize() and AbstractUserInterface::setLayouterInstance(). Exposed just for testing purposes, there should be no need to call this function directly. Expects that the size is non-zero. Delegates to doSetSize(), see its documentation for more information about the arguments.

void Magnum::Ui::AbstractLayouter::cleanNodes(const Containers::StridedArrayView1D<const UnsignedShort>& nodeHandleGenerations)

Clean layouts attached to no longer valid nodes.

Used internally from AbstractUserInterface::clean(). Exposed just for testing purposes, there should be no need to call this function directly and doing so may cause internal AbstractUserInterface state update to misbehave. Assumes that nodeHandleGenerations contains handle generation counters for all nodes, where the index is implicitly the handle ID. They're used to decide about node assignment validity, layouts with invalid node assignment are then marked for deletion. Delegates to doClean(), see its documentation for more information about the arguments.

void Magnum::Ui::AbstractLayouter::update(Containers::BitArrayView layoutIdsToUpdate, const Containers::StridedArrayView1D<const UnsignedInt>& topLevelLayoutIds, const Containers::StridedArrayView1D<const NodeHandle>& nodeParents, const Containers::StridedArrayView1D<Vector2>& nodeOffsets, const Containers::StridedArrayView1D<Vector2>& nodeSizes)

Update selected top-level layouts.

Used internally from AbstractUserInterface::update(). Exposed just for testing purposes, there should be no need to call this function directly and doing so may cause internal AbstractUserInterface state update to misbehave. Expects that setSize() was called at least once before this function, the size of layoutIdsToUpdate is the same as capacity(), and that the nodeParents, nodeOffsets and nodeSizes views have all the same size. The nodeParents, nodeOffsets and nodeSizes views should be large enough to contain any valid node ID. Delegates to doUpdate(), see its documentation for more information about the arguments.

Calling this function resets LayouterState::NeedsUpdate and LayouterState::NeedsAssignmentUpdate, however note that behavior of this function is independent of state() — it performs the update always regardless of what flags are set.

LayoutHandle Magnum::Ui::AbstractLayouter::add(NodeHandle node) protected

Add a layout assigned to given node.

Parameters
node Node to assign the layout to
Returns New layout handle

Allocates a new handle in a free slot in the internal storage or grows the storage if there's no free slots left. Expects that there's at most 1048576 layouts. The returned handle can be removed again with remove().

Expects that node is not NodeHandle::Null. The same node shouldn't be added multiple times to the same layouter, doing so will cause the layout to be arbitrary picked for given node when performing the calculation.

Calling this function causes LayouterState::NeedsAssignmentUpdate to be set. The subclass is meant to wrap this function in a public API and perform appropriate initialization work there.

void Magnum::Ui::AbstractLayouter::remove(LayoutHandle handle) protected

Remove a node from this layouter.

Expects that handle is valid. After this call, isHandleValid(LayoutHandle) const returns false for handle. See also remove(LayouterDataHandle) which is a simpler operation if the node is already known to belong to this layouter.

Calling this function causes LayouterState::NeedsAssignmentUpdate to be set. Other than that, no flag is set to trigger a subsequent cleanNodes() — instead the subclass is meant to wrap this function in a public API and perform appropriate cleanup work directly there.

void Magnum::Ui::AbstractLayouter::remove(LayouterDataHandle handle) protected

Remove a node from this layouter assuming it belongs to it.

Expects that handle is valid. After this call, isHandleValid(LayouterDataHandle) const returns false for handle. See also remove(LayouterDataHandle) which additionally checks that the node belongs to this layouter.

Calling this function causes LayouterState::NeedsAssignmentUpdate to be set. Other than that, no flag is set to trigger a subsequent cleanNodes() — instead the subclass is meant to wrap this function in a public API and perform appropriate cleanup work directly there.

void Magnum::Ui::AbstractLayouter::doSetSize(const Vector2& size) virtual private

Set user interface size.

Parameters
size Size of the user interface to which everything is positioned

Implementation for setSize(), which is called from AbstractUserInterface::setSize() whenever the UI size changes, and from AbstractUserInterface::setLayouterInstance(). The implementation is expected to refresh internal state that depends on the UI size.

Note that compared to AbstractLayer::doSetSize(), a followup doUpdate() call isn't implicitly made after UI size changed because the layout may not be depending on it for anything. Explicitly call setNeedsUpdate() in the implementation if the layout is depending on the UI size and requires an update after.

Default implementation does nothing.

void Magnum::Ui::AbstractLayouter::doClean(Containers::BitArrayView layoutIdsToRemove) virtual private

Clean no longer valid layouts.

Parameters
layoutIdsToRemove Layout IDs to remove

Implementation for cleanNodes(), which is called from AbstractUserInterface::clean() (and transitively from AbstractUserInterface::update()) whenever UserInterfaceState::NeedsNodeClean or any of the states that imply it are present in AbstractUserInterface::state().

The layoutIdsToRemove view has the same size as capacity() and is guaranteed to have bits set only for valid layout IDs, i.e. layout IDs that are already removed are not set.

This function may get also called with layoutIdsToRemove having all bits zero.

Default implementation does nothing.

void Magnum::Ui::AbstractLayouter::doUpdate(Containers::BitArrayView layoutIdsToUpdate, const Containers::StridedArrayView1D<const UnsignedInt>& topLevelLayoutIds, const Containers::StridedArrayView1D<const NodeHandle>& nodeParents, const Containers::StridedArrayView1D<Vector2>& nodeOffsets, const Containers::StridedArrayView1D<Vector2>& nodeSizes) pure virtual private

Update selected top-level layouts.

Parameters
layoutIdsToUpdate in Layout IDs to update
topLevelLayoutIds in Top-level layout IDs to update from
nodeParents in Node parents indexed by node ID
nodeOffsets in/out Node offsets indexed by node ID
nodeSizes in/out Node sizes indexed by node ID

Implementation for update(), which is called from AbstractUserInterface::update() whenever UserInterfaceState::NeedsLayoutUpdate or any of the states that imply it are present in AbstractUserInterface::state(). Is always called after doClean(), with at least one doSetSize() call happening at some point before.

The layoutIdsToUpdate view has the same size as capacity() and is guaranteed to have bits set only for valid layout IDs assigned to nodes visible at the time this function is called. Node handles corresponding to topLevelLayoutIds are available in nodes(), node IDs can be then extracted from the handles using nodeHandleId(). The node IDs then index into the nodeParents, nodeOffsets and nodeSizes views, which all have the same size and are guaranteed to be large enough to contain any valid node ID. All nodes() at indices corresponding to topLevelLayoutIds are guaranteed to not be NodeHandle::Null at the time this function is called. The topLevelLayoutIds are mutually disjoint hierarchies that don't depend on each other in any way and thus are and can be processed in an arbitrary order. For each top-level layout, the calculation should be done in a way that satisfies the bounding size in nodeSizes for the node to which the layout is assigned.

The nodeOffsets and nodeSizes arrays contain offsets and sizes set either directly via AbstractUserInterface::setNodeOffset() / setNodeSize() or modified by a layouter ran on the same node in an earlier step. The implementation can then either take the offset and size and modify it, or overwrite it with a completely different value. The arrays contain also offsets and sizes for nodes different than those referenced from layoutIdsToUpdate, such as nodes controlled by different layouters or nodes positioned directly, and the implementation should not modify those in any way. On the other hand it's expected to update all layouts set in the mask, failing to do so will leave particular node offsets and sizes at values that were set initially or at intermediate values coming from a previous layouter.

The nodeOffsets are expected to be relative to the parent node. If the internal layout representation doesn't match the node hierarchy, the implementation can make use of nodeParents to find out appropriate parent node offset to relate to.

Unlike AbstractLayer::doUpdate(), calls to this function may happen several times with different layoutIdsToUpdate and topLevelLayoutIds, ordered relative to calls to other layouters on which output this layouter may depend or wich may depend on output of this layouter. The set of layout IDs in both arguments is disjoint among the calls to this functions, i.e. the function is never called twice with the same ID present. This function may get also called with layoutIdsToUpdate having all bits zero and topLevelLayoutIds being empty, for example when setNeedsUpdate() was called but the layouter doesn't have any layouts currently visible.