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

Snap layouter.

Allows explicitly snapping particular nodes to corners or edges of other nodes as well as common row and column layouts with size propagation.

Setting up a snap layouter instance

If you create a UserInterfaceGL with a theme and don't exclude ThemeFeature::SnapLayouter, an implicit instance is already provided and available through UserInterface::snapLayouter(). Otherwise, the layouter doesn't have any shared state or configuration, so it's just about constructing it from a fresh AbstractUserInterface::createLayouter() handle and passing it to UserInterface::setSnapLayouterInstance():

ui.setSnapLayouterInstance(
    Containers::pointer<Ui::SnapLayouter>(ui.createLayouter()));

In comparison, if you want to set up a custom snap layouter that's independent of the one exposed through UserInterface::snapLayouter(), pass the newly created instance to AbstractUserInterface::setLayouterInstance() instead:

Ui::SnapLayouter& layouter = ui.setLayouterInstance(
    Containers::pointer<Ui::SnapLayouter>(ui.createLayouter()));

Afterwards, with either of the above, assuming AbstractUserInterface::draw() is called in an appropriate place, the layouter is ready to use.

Core concepts

Internally, the layout calculation works with nodes being snapped to target nodes according to a combination of Snap values. With the target node shown as the blue rectangle below, snapping to its edges and corners can be achieved by combining Snap::Left, Top, Right, Bottom with Snap::InsideX and InsideY. For convenience there are various aliases, such as Snap::TopLeft being a combination of Top and Left, or Snap::Inside being InsideX and InsideY together.

TopInside BottomInside RightInside LeftInside Top|RightInside Bottom|RightInside Bottom|LeftInside Top|LeftInside Top|LeftInsideX Top Top|RightInsideX Top|RightInsideY Right Bottom|RightInsideY Bottom|RightInsideX Bottom Bottom|LeftInsideX Bottom|LeftInsideY Left Top|LeftInsideY Top|Left Top|Right Bottom|Left Bottom|Right Inside

Additionally, it's possible to make the snapped node fill the whole edge using Snap::FillX and FillY. The Snap::FillX is just a convenience combination of Left and Right, and Snap::FillY is Top and Bottom together. Snap::Fill is then FillX and FillY together.

Top|FillXInside Bottom|FillXInside Right|FillYInside Left|FillYInside Top|FillX Right|FillY Bottom|FillX Left|FillY FillInside

The layout by default takes into account margin between nodes and padding inside nodes, as supplied for example by the LayoutLayer. In the diagram below, the blue rectangle has both a padding, shown as a yellow outline outside, and margin, shown as a green outline inside, other nodes have just paddings. Neighboring padding and margins collapse together, picking the larger of the two.

Margin: 8NoPadX Margin: 8NoPad Padding: 16Margin: 8 Margin: 8NoPadY Margin: 16 Margin: 8 Margin: 12

In rare cases it may be needed to ignore the padding and margin, which can be done by specifying Snap::NoPadX, NoPadY or their combination, NoPad. This is however considered a workaround and layouts in general shouldn't need to use these.

Note that in the above diagram the margins and paddings are the same for all sides for simplicity, however they can be specified differently for each side. See documentation of LayoutLayer for more examples.

Adding and removing layouts

An explicitly snapped layout is added by calling addExplicit() with a NodeHandle to which the layout is assigned, Snaps describing how to snap the node and a target LayoutHandle to which to snap. The target layout has to be either a sibling or a parent layout, and passing LayoutHandle::Null allows snapping a root node to the whole UI. In the following snippet, a popup node with a concrete size is centered inside the UI (where empty Snaps mean center), an accept child node is placed to the bottom right corner of it, and a reject to the left next to the accept.

Ui::NodeHandle popupNode = ui.createNode({}, {400, 250});
Ui::NodeHandle acceptNode = ui.createNode(popupNode, {-10, -10}, {150, 50});
Ui::NodeHandle rejectNode = ui.createNode(popupNode, {}, {150, 50});

Ui::LayoutHandle popup = layouter.addExplicit(popupNode,
                                        Ui::Snaps{}, Ui::LayoutHandle::Null);
Ui::LayoutHandle accept = layouter.addExplicit(acceptNode,
                                        Ui::Snap::BottomRight, popup);
Ui::LayoutHandle reject = layouter.addExplicit(rejectNode, Ui::Snap::Left, accept);

Note that Snap::Inside is automatic when snapping a child node to its parent, which is the case both with the root popup node that's a child of the UI it's being snapped to, and accept which is a child of the popup it's being snapped to. You can pass Snap::Inside in those cases but it's unnecessary. If an offset is specified in addition to node size, such as {-10, -10} in case of accept, it's added to the final layout offset, and affects also dependent layouts. When visualizing node placement, for example with Ui::DebugLayer node highlight, the layout will look like this:

Image

SnapLayouter layouts are unique, meaning a particular node can have only at most one layout from given layouter instance assigned. This in turn means you don't strictly need to remember a LayoutHandle in order to use it later, but can retrieve it back from its NodeHandle using AbstractUserInterface::nodeUniqueLayout():

Ui::LayouterDataHandle popup = ui.nodeUniqueLayout(popupNode, layouter);

Layouts can be subsequently removed either as a consequence of removing the node they're assigned to, or by calling remove(). Note that only layouts that don't have sibling layouts explicitly snapped to them can be removed — i.e., while the reject layout or its node can be removed, attempting to remove the accept layout is an error because reject would then have nowhere to snap to.

Implicitly snapped layouts

While explicit snapping offers the most flexibility, it may get tedius when forming long chains of snapped nodes. Insertion or removal of a layout in the middle of such a chain also isn't possible. An alternative approach in such cases is specifying an implicit child snap using setChildSnap(), and then calling add() for all child nodes without specifying anything else for them:

Ui::NodeHandle contentsNode = ui.createNode(popupNode, {}, {});
Ui::NodeHandle titleNode = ui.createNode(contentsNode, {}, {300, 30});
Ui::NodeHandle detailsNode = ui.createNode(contentsNode, {}, {300, 40});

Ui::LayoutHandle contents = layouter.addExplicit(contentsNode, Ui::Snaps{}, popup);
layouter.setChildSnap(contents, Ui::Snap::Bottom|Ui::Snap::FillX);

/* Implicit child layouts */
Ui::LayoutHandle title = layouter.add(titleNode);
Ui::LayoutHandle details = layouter.add(detailsNode);

In the above snippet, a contents layout is explicitly snapped to the center of the popup, and inside a title and details are placed. The child snap for those is configured so that subsequent children will be added to the bottom of the previous and fill the parent horizontally. The result is the following:

Image

By default new child layouts are appended after all previous, insertion in the middle can be done by passing a LayoutHandle to the add() function, saying before which existing layout to insert the new one. For example, inserting a subtitle between the title and details, which would then look like this:

Ui::NodeHandle subtitleNode = ui.createNode(contentsNode, {}, {300, 20});
Ui::LayoutHandle subtitle = layouter.add(subtitleNode, /*before*/ details);
Image

Unlike with explicitly snapped layouts, calling remove() on an implicitly snapped layout simply causes it to be removed from the sequence, with following layouts shifting into its place.

Finally, calling the implicit add() on a node that has no parent layout allows using this node as a target or parent of other layouts but doesn't cause the node offset to be affected by the layout process in any way. For example, if we'd want to have the original popup node movable by the user and placed to the center of the UI just initially, not changing its position from the layout in any way afterwards, such as when the window resizes, we'd do this instead:

ui.setNodeOffset(popupNode, (ui.size() - ui.nodeSize(popupNode))*0.5f);

Ui::LayoutHandle popup = layouter.add(popupNode);

Size propagation

You might have noticed that the contentsNode above didn't have any size specified. Its size was calculated automatically based on size of its (implicitly snapped) children, resulting in a size of {300, 90}. The same works for explicitly snapped children, however at the moment only the direct children are counted, nodes snapped to them as neighbors are not. The resulting size is always a maximum of the hardcoded node size and size of the contents including also any margin and padding as well as min sizes, coming for example from the LayoutLayer.

If size propagation is undesirable, for example when the contents should be clipped instead, pass SnapLayoutFlag::IgnoreOverflowX, IgnoreOverflowY or the combined IgnoreOverflow. This will cause the layout to ignore size of children in given direction, leaving the node at its size given originally.

Margin propagation

With more complex UIs, the layouts commonly start nesting within each other, such as a column layout having row layouts inside each column:

/* A root column layout */
Ui::NodeHandle rootNode = ;
Ui::LayoutHandle root = layouter.add(rootNode);
layouter.setChildSnap(root, Ui::Snap::Bottom|Ui::Snap::FillX);

/* First row layout inside */
Ui::NodeHandle firstNode = ui.createNode(rootNode, {}, {});
Ui::LayoutHandle first = layouter.add(firstNode);
layouter.setChildSnap(first, Ui::Snap::Right);

/* Second row layout inside */
Ui::NodeHandle secondNode = ui.createNode(rootNode, {}, {});
Ui::LayoutHandle second = layouter.add(secondNode);
layouter.setChildSnap(second, Ui::Snap::Right);

/* Child nodes in both */
Ui::NodeHandle childNodes[]{
    ui.createNode(firstNode, {}, {200, 80}),
    ui.createNode(firstNode, {}, {200, 80}),
    ui.createNode(secondNode, {}, {140, 60}),
    ui.createNode(secondNode, {}, {140, 60}),
    ui.createNode(secondNode, {}, {140, 60}),
};
for(Ui::NodeHandle node: childNodes)
    layouter.add(node);

However, if the actual nodes within then define their own margins, as shown here by attaching a LayoutLayer data with a margin to each, the margin will collapse as expected between neighboring nodes, but not across layouts:

Ui::LayoutLayer& layoutLayer = ;
/* A single style with a 20-unit margin around the node */
layoutLayer.setStyle({}, {}, {}, {}, {Vector4{20.0f}});

/* Apply it to all children */
for(Ui::NodeHandle node: childNodes)
    layoutLayer.create(0, node);
Image

While that may be desirable in certain cases, such as when either row would be actually some visual frame around its items, often you may want to have the items evenly spaced. Applying SnapLayoutFlag::PropagateMargin (or again the direction-specific PropagateMarginX / PropagateMarginY variants) to both first and second makes the total margin of its children propagated outside — note how the respective visualization rectangles shrink to tightly wrap the contents —, where it gets collapsed between neighboring layouts:

layouter.addFlags(first, Ui::SnapLayoutFlag::PropagateMargin);
layouter.addFlags(second, Ui::SnapLayoutFlag::PropagateMargin);
Image

Supported layout properties

At the moment, min size, padding and margin layout properties coming from LayoutLayer and other layers exposing LayerFeature::Layout are taken into account. The implementation currently doesn't take max size or aspect ratio into account in any way.

High-level APIs for widget placement

To be written.

Base classes

class AbstractLayouter new in Git master
Base for layouters.

Constructors, destructors, conversion operators

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

Public functions

auto operator=(const SnapLayouter&) -> SnapLayouter& deleted
Copying is not allowed.
auto operator=(SnapLayouter&&) -> SnapLayouter& noexcept
Move assignment.
auto add(NodeHandle node, LayoutHandle before = LayoutHandle::Null, SnapLayoutFlags flags = {}) -> LayoutHandle
Add a layout assigned to given node.
auto add(NodeHandle node, SnapLayoutFlags flags) -> LayoutHandle
auto add(NodeHandle node, LayouterDataHandle before, SnapLayoutFlags flags = {}) -> LayoutHandle
Add a layout assigned to given node, and before given layout assuming the layout belongs to this layouter.
auto addExplicit(NodeHandle node, Snaps snap, LayoutHandle snapTarget, SnapLayoutFlags flags = {}) -> LayoutHandle
Add a layout snapping explicitly to given target.
auto addExplicit(NodeHandle node, Snaps snap, LayouterDataHandle snapTarget, SnapLayoutFlags flags = {}) -> LayoutHandle
Add a layout snapping explicitly to given target, assuming the target belongs to this layouter.
void remove(LayoutHandle handle)
Remove a layout.
void remove(LayouterDataHandle handle)
Remove a layout assuming it belongs to this layer.
auto flags(LayoutHandle handle) const -> SnapLayoutFlags
Layout flags.
auto flags(LayouterDataHandle handle) const -> SnapLayoutFlags
Layout flags assuming it belongs to this layouter.
void setFlags(LayoutHandle handle, SnapLayoutFlags flags)
Set layout flags.
void setFlags(LayouterDataHandle handle, SnapLayoutFlags flags)
Set layout flags assuming it belongs to this layouter.
void addFlags(LayoutHandle handle, SnapLayoutFlags flags)
Add layout flags.
void addFlags(LayouterDataHandle handle, SnapLayoutFlags flags)
Add layout flags assuming it belongs to this layouter.
void clearFlags(LayoutHandle handle, SnapLayoutFlags flags)
Clear layout flags.
void clearFlags(LayouterDataHandle handle, SnapLayoutFlags flags)
Clear layout flags assuming it belongs to this layouter.
auto childSnap(LayoutHandle handle) const -> Snaps
Snap for child layouts.
auto childSnap(LayouterDataHandle handle) const -> Snaps
Snap for child layouts assuming it belongs to this layouter.
void setChildSnap(LayoutHandle handle, Snaps snap)
Set snap for child layouts.
void setChildSnap(LayouterDataHandle handle, Snaps snap)
Set snap for child layouts assuming it belongs to this layouter.
auto firstChild(LayoutHandle handle) const -> LayoutHandle
First child layout.
auto firstChild(LayouterDataHandle handle) const -> LayoutHandle
First child layout assuming it belongs to this layouter.
auto firstExplicitSnap(LayoutHandle handle) const -> LayoutHandle
First layout explicitly snapped to this one.
auto firstExplicitSnap(LayouterDataHandle handle) const -> LayoutHandle
First layout explicitly snapped to this one assuming it belongs to this layouter.
auto hasExplicitSnap(LayoutHandle handle) const -> bool
Whether the layout has an explicit snap.
auto hasExplicitSnap(LayouterDataHandle handle) const -> bool
Whether the layout has an explicit snap assuming it belongs to this layouter.
auto parent(LayoutHandle handle) const -> LayoutHandle
Parent layout.
auto parent(LayouterDataHandle handle) const -> LayoutHandle
Parent layout assuming it belongs to this layouter.
auto previous(LayoutHandle handle) const -> LayoutHandle
Previous layout.
auto previous(LayouterDataHandle handle) const -> LayoutHandle
Previous layout assuming it belongs to this layouter.
auto next(LayoutHandle handle) const -> LayoutHandle
Next layout.
auto next(LayouterDataHandle handle) const -> LayoutHandle
Next sibling layout assuming it belongs to this layouter.
auto explicitSnap(LayoutHandle handle) const -> Snaps
Explicit layout snap.
auto explicitSnap(LayouterDataHandle handle) const -> Snaps
Explicit layout snap assuming it belongs to this layouter.
auto explicitSnapTarget(LayoutHandle handle) const -> LayoutHandle
Explicit layout snap target.
auto explicitSnapTarget(LayouterDataHandle handle) const -> LayoutHandle
Explicit layout snap target node assuming it belongs to this layouter.

Function documentation

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

Constructor.

Parameters
handle Layouter handle returned from AbstractUserInterface::createLayouter()

Magnum::Ui::SnapLayouter::SnapLayouter(SnapLayouter&&) noexcept

Move constructor.

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

LayoutHandle Magnum::Ui::SnapLayouter::add(NodeHandle node, LayoutHandle before = LayoutHandle::Null, SnapLayoutFlags flags = {})

Add a layout assigned to given node.

Parameters
node Node to assign the layout to
before A layout to order before or LayoutHandle::Null if ordered as last
flags Layout flags
Returns New layout handle

The node is expected to not have a layout assigned from this layouter yet. If before is not LayoutHandle::Null, it's expected to be valid, belong to the same layouter and have the same non-null parent layout as node.

If node parent has a layout coming from this layouter, the positioning is done according to childSnap() defined by the parent layout, and the total size and padding of all child layouts then affects parent layout size and padding according to flags. If node parent doesn't have a layout coming from this layouter, the layout acts as a parent for child layouts or as a target for explicitly snapped layouts and isn't affected by layout calculation.

Use addExplicit() for explicitly snapping to given layout without taking childSnap() into account and without affecting the parent layout size.

Delegates to AbstractLayouter::add(), see its documentation for detailed description of all constraints.

LayoutHandle Magnum::Ui::SnapLayouter::add(NodeHandle node, SnapLayoutFlags flags)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

LayoutHandle Magnum::Ui::SnapLayouter::add(NodeHandle node, LayouterDataHandle before, SnapLayoutFlags flags = {})

Add a layout assigned to given node, and before given layout assuming the layout belongs to this layouter.

Like add(NodeHandle, LayoutHandle, SnapLayoutFlags) but without checking that before indeed belongs to this layouter. See its documentation for more information.

LayoutHandle Magnum::Ui::SnapLayouter::addExplicit(NodeHandle node, Snaps snap, LayoutHandle snapTarget, SnapLayoutFlags flags = {})

Add a layout snapping explicitly to given target.

Parameters
node Node to assign the layout to
snap How to snap
snapTarget Target layout to snap to or LayoutHandle::Null to snap a root node to the UI itself
flags Layout flags
Returns New layout handle

If node is root, snapTarget can be LayoutHandle::Null to snap to the whole UI. Otherwise snapTarget is expected to be coming from the same layouter and assigned to either a parent or a sibling of node. If snapTarget is a parent, Snap::Inside is implicitly used in addition to what's specified in snap.

Note that explicitly snapped layouts aren't fully considered when calculating parent layout sizes and paddings and thus may overflow the parent node area in certain cases. In particular, only sizes of explicitly snapped child layouts are considered, not explicitly snapped neighbors. Additionally, if SnapLayoutFlag::PropagateMargin is enabled, margins of explicitly snapped layouts are completely ignored and don't propagate anywhere. Use add() for implicit child layouts which propagate their total size and margin to the parent in all cases.

Delegates to AbstractLayouter::add(), see its documentation for detailed description of all constraints.

LayoutHandle Magnum::Ui::SnapLayouter::addExplicit(NodeHandle node, Snaps snap, LayouterDataHandle snapTarget, SnapLayoutFlags flags = {})

Add a layout snapping explicitly to given target, assuming the target belongs to this layouter.

Like addExplicit(NodeHandle, Snaps, LayoutHandle, SnapLayoutFlags) but without checking that snapTarget indeed belongs to this layouter. See its documentation for more information.

void Magnum::Ui::SnapLayouter::remove(LayoutHandle handle)

Remove a layout.

Expects that handle is valid and has no child layouts or explicitly snapped layouts from the same layouter. To remove a layout that has dependent layouts, either remove the dependent layouts first or remove the whole node along with its children using Ui::AbstractUserInterface::removeNode().

Delegates to AbstractLayouter::remove(LayoutHandle), see its documentation for detailed description of all constraints.

void Magnum::Ui::SnapLayouter::remove(LayouterDataHandle handle)

Remove a layout assuming it belongs to this layer.

Compared to remove(LayoutHandle) delegates to AbstractLayouter::remove(LayouterDataHandle) instead.

SnapLayoutFlags Magnum::Ui::SnapLayouter::flags(LayoutHandle handle) const

Layout flags.

Expects that handle is valid.

SnapLayoutFlags Magnum::Ui::SnapLayouter::flags(LayouterDataHandle handle) const

Layout flags assuming it belongs to this layouter.

Like flags(LayoutHandle) const but without checking that handle indeed belongs to this layouter. See its documentation for more information.

void Magnum::Ui::SnapLayouter::setFlags(LayoutHandle handle, SnapLayoutFlags flags)

Set layout flags.

Expects that handle is valid. Initially, a layout has the flags that were passed to add(), which are by default none.

Calling this function causes LayouterState::NeedsUpdate to be set.

void Magnum::Ui::SnapLayouter::setFlags(LayouterDataHandle handle, SnapLayoutFlags flags)

Set layout flags assuming it belongs to this layouter.

Like setFlags(LayoutHandle, SnapLayoutFlags) but without checking that handle indeed belongs to this layouter. See its documentation for more information.

void Magnum::Ui::SnapLayouter::addFlags(LayoutHandle handle, SnapLayoutFlags flags)

Add layout flags.

Calls setFlags() with the existing flags ORed with flags. Useful for preserving previously set flags.

void Magnum::Ui::SnapLayouter::addFlags(LayouterDataHandle handle, SnapLayoutFlags flags)

Add layout flags assuming it belongs to this layouter.

Like addFlags(LayoutHandle, SnapLayoutFlags) but without checking that handle indeed belongs to this layouter. See its documentation for more information.

void Magnum::Ui::SnapLayouter::clearFlags(LayoutHandle handle, SnapLayoutFlags flags)

Clear layout flags.

Calls setFlags() with the existing flags ANDed with the inverse of flags. Useful for removing a subset of previously set flags.

void Magnum::Ui::SnapLayouter::clearFlags(LayouterDataHandle handle, SnapLayoutFlags flags)

Clear layout flags assuming it belongs to this layouter.

Like addFlags(LayoutHandle, SnapLayoutFlags) but without checking that handle indeed belongs to this layouter. See its documentation for more information.

Snaps Magnum::Ui::SnapLayouter::childSnap(LayoutHandle handle) const

Snap for child layouts.

Expects that handle is valid.

Snaps Magnum::Ui::SnapLayouter::childSnap(LayouterDataHandle handle) const

Snap for child layouts assuming it belongs to this layouter.

Like childSnap(LayoutHandle) const but without checking that handle indeed belongs to this layouter. See its documentation for more information.

void Magnum::Ui::SnapLayouter::setChildSnap(LayoutHandle handle, Snaps snap)

Set snap for child layouts.

Expects that handle is valid and that snap produces a non-overlapping purely horizontal or vertical order. Default is Snap::Bottom, i.e. child nodes get placed one after each other in a column.

Calling this function causes LayouterState::NeedsUpdate to be set.

void Magnum::Ui::SnapLayouter::setChildSnap(LayouterDataHandle handle, Snaps snap)

Set snap for child layouts assuming it belongs to this layouter.

Like setChildSnap(LayouterDataHandle, Snaps) but without checking that handle indeed belongs to this layouter. See its documentation for more information.

LayoutHandle Magnum::Ui::SnapLayouter::firstChild(LayoutHandle handle) const

First child layout.

Expects that handle is valid. If the layout has no children or if all nested layouts have an explicit snap, returns LayoutHandle::Null. Otherwise, the handle is always valid and belonging to this layouter.

LayoutHandle Magnum::Ui::SnapLayouter::firstChild(LayouterDataHandle handle) const

First child layout assuming it belongs to this layouter.

Like firstChild(LayoutHandle) const but without checking that handle indeed belongs to this layouter. See its documentation for more information.

LayoutHandle Magnum::Ui::SnapLayouter::firstExplicitSnap(LayoutHandle handle) const

First layout explicitly snapped to this one.

Expects that handle is valid. If no other layouts are explicitly snapped to this layout, returns LayoutHandle::Null. Otherwise, the handle is always valid and belonging to this layouter.

LayoutHandle Magnum::Ui::SnapLayouter::firstExplicitSnap(LayouterDataHandle handle) const

First layout explicitly snapped to this one assuming it belongs to this layouter.

Like firstExplicitSnap(LayoutHandle) const but without checking that handle indeed belongs to this layouter. See its documentation for more information.

bool Magnum::Ui::SnapLayouter::hasExplicitSnap(LayoutHandle handle) const

Whether the layout has an explicit snap.

Expects that handle is valid. Returns true if the layout was created using addExplicit(), false otherwise.

bool Magnum::Ui::SnapLayouter::hasExplicitSnap(LayouterDataHandle handle) const

Whether the layout has an explicit snap assuming it belongs to this layouter.

Like hasExplicitSnap(LayoutHandle) const but without checking that handle indeed belongs to this layouter. See its documentation for more information.

LayoutHandle Magnum::Ui::SnapLayouter::parent(LayoutHandle handle) const

Parent layout.

Expects that handle is valid and doesn't have an explicit snap. Layouts with an explicit snap are not following any parent/child hierarchy. If there was no layout assigned to the parent node at the time handle was created, or handle is assigned to a root node, returns LayoutHandle::Null. Otherwise, the handle is always valid and belonging to this layouter.

LayoutHandle Magnum::Ui::SnapLayouter::parent(LayouterDataHandle handle) const

Parent layout assuming it belongs to this layouter.

Like parent(LayoutHandle) const but without checking that handle indeed belongs to this layouter. See its documentation for more information.

LayoutHandle Magnum::Ui::SnapLayouter::previous(LayoutHandle handle) const

Previous layout.

Expects that handle is valid. If the handle doesn't have an explicit snap, returns a previous sibling with the same parent() in layout order. If the handle has an explicit snap, returns a previous layout with the same explicitSnapTarget(), but their relative order doesn't affect the layouting result in any way. If the layout is first in given list, returns LayoutHandle::Null. Otherwise, the handle is always valid and belonging to this layouter.

LayoutHandle Magnum::Ui::SnapLayouter::previous(LayouterDataHandle handle) const

Previous layout assuming it belongs to this layouter.

Like previous(LayoutHandle) const but without checking that handle indeed belongs to this layouter. See its documentation for more information.

LayoutHandle Magnum::Ui::SnapLayouter::next(LayoutHandle handle) const

Next layout.

Expects that handle is valid. If the handle doesn't have an explicit snap, returns a next sibling with the same parent() in layout order. If the handle has an explicit snap, returns a next layout with the same explicitSnapTarget(), but their relative order doesn't affect the layouting result in any way. If the layout is last among its siblings, returns LayoutHandle::Null. Otherwise, the handle is always valid and belonging to this layouter.

LayoutHandle Magnum::Ui::SnapLayouter::next(LayouterDataHandle handle) const

Next sibling layout assuming it belongs to this layouter.

Like next(LayoutHandle) const but without checking that handle indeed belongs to this layouter. See its documentation for more information.

Snaps Magnum::Ui::SnapLayouter::explicitSnap(LayoutHandle handle) const

Explicit layout snap.

Expects that handle is valid and has an explicit snap. Note that if explicitSnapTarget() is NodeHandle::Null, Snap::Inside is implicitly considered to be included as well, even if not part of the actual value.

Similarly to node() and explicitSnapTarget(), the snap cannot be changed after creation as it could break internal constraints.

Snaps Magnum::Ui::SnapLayouter::explicitSnap(LayouterDataHandle handle) const

Explicit layout snap assuming it belongs to this layouter.

Like explicitSnap(LayoutHandle) const but without checking that handle indeed belongs to this layouter. See its documentation for more information.

LayoutHandle Magnum::Ui::SnapLayouter::explicitSnapTarget(LayoutHandle handle) const

Explicit layout snap target.

Expects that handle is valid and has an explicit snap. Returns LayoutHandle::Null if the layout is assigned to a root node and is snapped relative to the whole user interface. Note that the returned handle may be invalid if AbstractUserInterface::removeNode() was called on the target node or its parents and AbstractUserInterface::update() hasn't been called since.

Similarly to node() and explicitSnap(), the target cannot be changed after creation as it could break internal constraints.

LayoutHandle Magnum::Ui::SnapLayouter::explicitSnapTarget(LayouterDataHandle handle) const

Explicit layout snap target node assuming it belongs to this layouter.

Like explicitSnapTarget(LayoutHandle) const but without checking that handle indeed belongs to this layouter. See its documentation for more information.