GenericLayouter class new in Git master
#include <Magnum/Ui/GenericLayouter.h>
Generic layouter.
Each layout is a function that gets called on a particular node, allowing to arbitrarily modify the node offset and size as well as any associated data.
Setting up a generic layouter instance
If you create a UserInterfaceGL with a style and don't exclude StyleFeature::
ui.setGenericLayouterInstance( Containers::pointer<Ui::GenericLayouter>(ui.createLayouter()));
In comparison, if you want to set up a custom generic layouter that's independent of the one exposed through UserInterface::
Ui::GenericLayouter& layouter = ui.setLayouterInstance( Containers::pointer<Ui::GenericLayouter>(ui.createLayouter()));
Afterwards, with either of the above, assuming AbstractUserInterface::
Adding layouts
A layout is created by calling add() with a NodeHandle to which the layout is assigned, and a function taking a reference to the layouter instance along with mutable references to the associated node offset and size. The node offset and size can be arbitrarily modified, the layouter can be used to query current layout properties of various nodes using nodeOffset(), nodeSize(), nodeMinSize(), nodeMaxSize(), nodeAspectRatio(), nodePadding() and nodeMargin(). For example, the following would scale the filled part of a progress bar to be given percentage of its actual width:
Ui::NodeHandle background = ui.createNode(…); Ui::NodeHandle fill = ui.createNode(background, …); Float percentage = 38.4f; layouter.add(fill, [background, &percentage](const Ui::GenericLayouter& layouter, Vector2&, Vector2& nodeSize) { nodeSize.x() = layouter.nodeSize(background).x()*percentage/100.0f; });
Instead of the percentage being accessed through captured state, you can encode it to the initial node size, which the layouter then just updates. This way you can also animate percentage changes using NodeAnimator, for example.
ui.setNodeSizeX(fill, 38.4f); layouter.add(fill, [background](const Ui::GenericLayouter& layouter, Vector2&, Vector2& nodeSize) { nodeSize.x() *= layouter.nodeSize(background).x()/100.0f; });
The layout isn't required to update the node offset and size at all — in the following snippet, the progress bar is made out of a single node with a BaseLayer data, and the progress is visualized by outline on the right edge:
Ui::BaseLayer& baseLayer = …; Ui::NodeHandle progressbar = ui.createNode(…); Ui::DataHandle progressbarData = baseLayer.create(…, progressbar); baseLayer.setOutlineWidth(progressbarData, {0.0f, 0.0f, 100.0f - 38.4f, 0.0f}); layouter.add(progressbar, [&baseLayer, progressbarData](const Ui::GenericLayouter& layouter, Vector2&, Vector2&) { Float progressbarWidth = layouter.nodeSize(baseLayer.node(progressbarData)).x(); Float inversePercentage = baseLayer.outlineWidth(progressbarData)[3]; baseLayer.setOutlineWidth(progressbarData, {0.0f, 0.0f, progressbarWidth*inversePercentage/100.0f, 0.0f}); });
Layout execution order
Unlike e.g. SnapLayouter, which performs the layout according to node hierarchy, the GenericLayouter gives no guarantee about the order in which the functions are executed, not even in respect to the sequence in which they were added.
If you require certain ordering, create additional layouter instances and put layout functions that need to be executed after the previous ones into these.
Base classes
- class AbstractLayouter new in Git master
- Base for layouters.
Constructors, destructors, conversion operators
- GenericLayouter(LayouterHandle handle) explicit
- Constructor.
- GenericLayouter(const GenericLayouter&) deleted
- Copying is not allowed.
- GenericLayouter(GenericLayouter&&) noexcept
- Move constructor.
Public functions
- auto operator=(const GenericLayouter&) -> GenericLayouter& deleted
- Copying is not allowed.
- auto operator=(GenericLayouter&&) -> GenericLayouter& noexcept
- Move assignment.
-
auto usedAllocatedCount() const -> std::
size_t - Count of allocated layout functions.
-
auto add(NodeHandle node,
Containers::
Function<void(const GenericLayouter&layouter, Vector2&nodeOffset, Vector2&nodeSize)>&& layout) -> LayoutHandle - Add a layout assigned to given node.
- void remove(LayoutHandle handle)
- Remove a layout.
- void remove(LayouterDataHandle handle)
- Remove a layout assuming it belongs to this layer.
- auto isAllocated(LayoutHandle handle) const -> bool
- Whether given layout function is allocated.
- auto isAllocated(LayouterDataHandle handle) const -> bool
- Whether given layout function is allocated assuming it belongs to this layouter.
- auto nodeOffset(NodeHandle node) const -> Vector2
- Node offset in current layout, relative to its parent.
- auto nodeSize(NodeHandle node) const -> Vector2
- Node size in current layout.
- auto nodeMinSize(NodeHandle node) const -> Vector2
- Minimal node size in current layout.
- auto nodeMaxSize(NodeHandle node) const -> Vector2
- Maximal node size in current layout.
- auto nodeAspectRatio(NodeHandle node) const -> Float
- Node aspect ratio in current layout.
- auto nodePadding(NodeHandle node) const -> Vector4
- Padding inside a node in current layout.
- auto nodeMargin(NodeHandle node) const -> Vector4
- Margin inside a node in current layout.
Function documentation
Magnum:: Ui:: GenericLayouter:: GenericLayouter(LayouterHandle handle) explicit
Constructor.
| Parameters | |
|---|---|
| handle | Layouter handle returned from AbstractUserInterface:: |
Magnum:: Ui:: GenericLayouter:: GenericLayouter(GenericLayouter&&) noexcept
Move constructor.
Performs a destructive move, i.e. the original object isn't usable afterwards anymore.
std:: size_t Magnum:: Ui:: GenericLayouter:: usedAllocatedCount() const
Count of allocated layout functions.
Always at most usedCount(). Counts all layout functions that capture non-trivially-copyable state or state that's too large to be stored in-place. The operation is done with a complexity where is capacity().
LayoutHandle Magnum:: Ui:: GenericLayouter:: add(NodeHandle node,
Containers:: Function<void(const GenericLayouter&layouter, Vector2&nodeOffset, Vector2&nodeSize)>&& layout)
Add a layout assigned to given node.
| Parameters | |
|---|---|
| node | Node to assign the layout to |
| layout | Function to perform the layout operation |
| Returns | New layout handle |
Expects that the layout is not nullptr. The function gets called as part of layout update if node is visible. When executed, the function can query nodeOffset(), nodeSize(), nodeMinSize(), nodeMaxSize(), nodeAspectRatio(), nodePadding() and nodeMargin() functions on the passed layouter instance and use that information to update the nodeOffset and nodeSize arguments. Leaving either or both untouched is allowed as well, for example if the layout affects something else than node positioning.
Delegates to AbstractLayouter::
void Magnum:: Ui:: GenericLayouter:: remove(LayoutHandle handle)
Remove a layout.
Expects that handle is valid. Calls a destructor on the captured layout function state, if it's not trivially destructible. Delegates to AbstractLayouter::
void Magnum:: Ui:: GenericLayouter:: remove(LayouterDataHandle handle)
Remove a layout assuming it belongs to this layer.
Compared to remove(LayoutHandle) delegates to AbstractLayouter::
bool Magnum:: Ui:: GenericLayouter:: isAllocated(LayoutHandle handle) const
Whether given layout function is allocated.
Returns true if given layout function captures non-trivially-copyable state or state that's too large to be stored in-place, false otherwise. Expects that handle is valid.
bool Magnum:: Ui:: GenericLayouter:: isAllocated(LayouterDataHandle handle) const
Whether given layout function is allocated assuming it belongs to this layouter.
Like isAllocated(LayoutHandle) const but without checking that handle indeed belongs to this animator. See its documentation for more information.
Vector2 Magnum:: Ui:: GenericLayouter:: nodeOffset(NodeHandle node) const
Node offset in current layout, relative to its parent.
Compared to AbstractUserInterface::node is valid, can only be called from within the layout functions passed to add().
Vector2 Magnum:: Ui:: GenericLayouter:: nodeSize(NodeHandle node) const
Node size in current layout.
Compared to AbstractUserInterface::node is valid, can only be called from within the layout functions passed to add().
Vector2 Magnum:: Ui:: GenericLayouter:: nodeMinSize(NodeHandle node) const
Minimal node size in current layout.
Contains the value calculated by all layers advertising LayerFeature::0.0f. Expects that node is valid, can only be called from within the layout functions passed to add().
Vector2 Magnum:: Ui:: GenericLayouter:: nodeMaxSize(NodeHandle node) const
Maximal node size in current layout.
Contains the value calculated by all layers advertising LayerFeature::node is valid, can only be called from within the layout functions passed to add().
Float Magnum:: Ui:: GenericLayouter:: nodeAspectRatio(NodeHandle node) const
Node aspect ratio in current layout.
Contains the value calculated by all layers advertising LayerFeature::0.0f. Expects that node is valid, can only be called from within the layout functions passed to add().
Vector4 Magnum:: Ui:: GenericLayouter:: nodePadding(NodeHandle node) const
Padding inside a node in current layout.
Contains the value calculated by all layers advertising LayerFeature::0.0f. Expects that node is valid, can only be called from within the layout functions passed to add().
Vector4 Magnum:: Ui:: GenericLayouter:: nodeMargin(NodeHandle node) const
Margin inside a node in current layout.
Contains the value calculated by all layers advertising LayerFeature::0.0f. Expects that node is valid, can only be called from within the layout functions passed to add().