LayoutLayer class new in Git master
#include <Magnum/Ui/LayoutLayer.h>
Layout properties layer.
Allows attaching layout properties such as min/max sizes, aspect ratios, paddings and margins to particular nodes.
Setting up a layout layer instance
If you create a UserInterfaceGL instance with a theme and don't exclude ThemeFeature::
Otherwise, the layout layer is constructed from a fresh AbstractUserInterface::3u in the following snippet. Afterwards, pass the newly created layer to UserInterface::
ui.setLayoutLayerInstance( Containers::pointer<Ui::LayoutLayer>(ui.createLayer(), 3u));
In comparison, if you want to set up a custom layout layer that's independent of the one exposed through UserInterface::
Ui::LayoutLayer& layer = ui.setLayerInstance( Containers::pointer<Ui::LayoutLayer>(ui.createLayer(), 3u));
Afterwards, in order to be able to actually use the layer, a style has to be set with setStyle(). As an example, let's create a style with layout properties for a menu bar — the menu bar itself, icons and (textual) menu entries inside, i.e. the 3 styles we specified when constructing the layer above. For the purpose of this example let's specify just min sizes, paddings and margins for the style, and leave max sizes and aspect ratios at their defaults. See the setStyle() function documentation for details about each property. Similarly to how styles are commonly used with e.g. BaseLayer, we'll have an enum with them:
enum class LayoutStyle { Menu, MenuIcon, MenuEntry, Count }; struct Style { Vector2 minSize; Vector4 padding; Vector4 margin; } styles[Int(LayoutStyle::Count)]; /* What isn't set stays at the default (zero) value */ styles[Int(LayoutStyle::Menu)].padding = {25.0f, 10.0f, 25.0f, 10.0f}; styles[Int(LayoutStyle::MenuEntry)].minSize = {100.0f, 40.0f}; styles[Int(LayoutStyle::MenuIcon)].minSize = {60.0f, 60.0f}; styles[Int(LayoutStyle::MenuEntry)].margin = Vector4{5.0f}; styles[Int(LayoutStyle::MenuIcon)].margin = Vector4{5.0f}; layer.setStyle( Containers::stridedArrayView(styles).slice(&Style::minSize), {}, /* max sizes not specified */ {}, /* aspect ratios not specified */ Containers::stridedArrayView(styles).slice(&Style::padding), Containers::stridedArrayView(styles).slice(&Style::margin));
With this, assuming AbstractUserInterface::
Attaching layout properties to nodes
A node is equipped with layout properties by calling create() with desired style index and the corresponding NodeHandle. Continuing with the menu bar example from above, the following creates a menu with two icons and three entries inside:
Ui::NodeHandle menuNode = ui.createNode({}, {}); layer.create(LayoutStyle::Menu, menuNode); Ui::NodeHandle iconNode1 = ui.createNode(menuNode, {}, {}); layer.create(LayoutStyle::MenuIcon, iconNode1); Ui::NodeHandle entryNode1 = ui.createNode(menuNode, {}, {}); layer.create(LayoutStyle::MenuEntry, entryNode1); /* An entry that's deliberately wider */ Ui::NodeHandle entryNode2 = ui.createNode(menuNode, {}, {150, 0}); layer.create(LayoutStyle::MenuEntry, entryNode2); Ui::NodeHandle iconNode2 = ui.createNode(menuNode, {}, {}); layer.create(LayoutStyle::MenuIcon, iconNode2); Ui::NodeHandle entryNode3 = ui.createNode(menuNode, {}, {}); layer.create(LayoutStyle::MenuEntry, entryNode3);
The layout properties however don't do anything on their own, they only get used when actual layouts are assigned to these nodes. With a SnapLayouter set up, we can turn the menu bar into a simple row layout:
Ui::SnapLayouter& layouter = …; Ui::LayoutHandle menu = layouter.add(menuNode); layouter.setChildSnap(menu, Ui::Snap::Right); for(Ui::NodeHandle i: {iconNode1, entryNode1, entryNode2, iconNode2, entryNode3}) layouter.add(i);
Afterwards, when visualizing node placement, for example with Ui::

Unlike layouts, multiple layout properties can be assigned to a particular node, and they'll be combined together — in particular, picking the max of specified min sizes, paddings and margins. Note also that not all properties may be respected by every layouter and each layouter may implement different logic for conflict resolution. Consult particular layouter documentation for more information. For example, in case of the GenericLayouter, the layout properties are exposed by the API, but it's up to the concrete callback implementation to actually use them.
Debug layer integration
When using DebugLayer node inspect and DebugLayerSource::
Node {0x18, 0x1} Data {0x0, 0x1} from layer {0x9, 0x1} Layout with style 9
By default only style IDs are shown, but the DebugIntegration constructor accepts an optional function to map them from an UnsignedInt to a Containers::LayoutStyle enum is used by given layer, the function could look like this, resulting in the output below:
debugLayer.setLayerName(layoutLayer, "Layout", [](UnsignedInt style) { using namespace Containers::Literals; switch(LayoutStyle(style)) { case LayoutStyle::Button: return "Button"_s; case LayoutStyle::Label: return "Label"_s; case LayoutStyle::Panel: return "Panel"_s; … } return ""_s; });
Node {0x18, 0x1} Data {0x0, 0x1} from layer {0x9, 0x1} Layout with style Panel (9)
Base classes
- class AbstractLayer new in Git master
- Base for data layers.
Public types
- class DebugIntegration
- Debug layer integration.
Constructors, destructors, conversion operators
- LayoutLayer(LayerHandle handle, UnsignedInt styleCount) explicit
- Constructor.
- LayoutLayer(const LayoutLayer&) deleted
- Copying is not allowed.
- LayoutLayer(LayoutLayer&&) noexcept
- Move constructor.
Public functions
- auto operator=(const LayoutLayer&) -> LayoutLayer& deleted
- Copying is not allowed.
- auto operator=(LayoutLayer&&) -> LayoutLayer& noexcept
- Move assignment.
- auto styleCount() const -> UnsignedInt
- Style count.
-
auto styleMinSizes() const -> Containers::
StridedArrayView1D<const Vector2> - Minimal node size for each style.
-
auto styleMaxSizes() const -> Containers::
StridedArrayView1D<const Vector2> - Maximal node size for each style.
-
auto styleAspectRatios() const -> Containers::
StridedArrayView1D<const Float> - Node aspect ratio for each style.
-
auto stylePaddings() const -> Containers::
StridedArrayView1D<const Vector4> - Node padding for each style.
-
auto styleMargins() const -> Containers::
StridedArrayView1D<const Vector4> - Node margin for each style.
-
void setStyle(const Containers::
StridedArrayView1D<const Vector2>& minSizes, const Containers:: StridedArrayView1D<const Vector2>& maxSizes, const Containers:: StridedArrayView1D<const Float>& aspectRatios, const Containers:: StridedArrayView1D<const Vector4>& paddings, const Containers:: StridedArrayView1D<const Vector4>& margins) - Set style data.
-
void setStyle(std::
initializer_list<Vector2> minSizes, std:: initializer_list<Vector2> maxSizes, std:: initializer_list<Float> aspectRatios, std:: initializer_list<Vector4> paddings, std:: initializer_list<Vector4> margins) -
auto create(UnsignedInt style,
NodeHandle node = NodeHandle::
Null) -> DataHandle - Create a data with given style index.
-
template<class StyleIndex>auto create(StyleIndex style, NodeHandle node = NodeHandle::
Null) -> DataHandle - Create a data with given style index in a concrete enum type.
- void remove(DataHandle handle)
- Remove a data.
- void remove(LayerDataHandle handle)
- Remove a data assuming it belongs to this layer.
- auto style(DataHandle handle) const -> UnsignedInt
- Type-erased data style index.
-
template<class StyleIndex>auto style(DataHandle handle) const -> StyleIndex
- Data style index in a concrete enum type.
- auto style(LayerDataHandle handle) const -> UnsignedInt
- Type-erased data style index assuming it belongs to this layer.
-
template<class StyleIndex>auto style(LayerDataHandle handle) const -> StyleIndex
- Data style index in a concrete enum type assuming it belongs to this layer.
- void setStyle(DataHandle handle, UnsignedInt style)
- Set data style index.
-
template<class StyleIndex>void setStyle(DataHandle handle, StyleIndex style)
- Set data style index in a concrete enum type.
- void setStyle(LayerDataHandle handle, UnsignedInt style)
- Set data style index assuming it belongs to this layer.
-
template<class StyleIndex>void setStyle(LayerDataHandle handle, StyleIndex style)
- Set data style index in a concrete enum type assuming it belongs to this layer.
Function documentation
Magnum:: Ui:: LayoutLayer:: LayoutLayer(LayerHandle handle,
UnsignedInt styleCount) explicit
Constructor.
| Parameters | |
|---|---|
| handle | Layer handle returned from AbstractUserInterface:: |
| styleCount | Number of distinct styles to use |
Expects that styleCount is not 0. In order to update the UI containing this layer it's expected that setStyle() was called.
Magnum:: Ui:: LayoutLayer:: LayoutLayer(LayoutLayer&&) noexcept
Move constructor.
Performs a destructive move, i.e. the original object isn't usable afterwards anymore.
Containers:: StridedArrayView1D<const Vector2> Magnum:: Ui:: LayoutLayer:: styleMinSizes() const
Minimal node size for each style.
Expects that setStyle() was called.
Containers:: StridedArrayView1D<const Vector2> Magnum:: Ui:: LayoutLayer:: styleMaxSizes() const
Maximal node size for each style.
Expects that setStyle() was called.
Containers:: StridedArrayView1D<const Float> Magnum:: Ui:: LayoutLayer:: styleAspectRatios() const
Node aspect ratio for each style.
Expects that setStyle() was called.
Containers:: StridedArrayView1D<const Vector4> Magnum:: Ui:: LayoutLayer:: stylePaddings() const
Node padding for each style.
Expects that setStyle() was called.
Containers:: StridedArrayView1D<const Vector4> Magnum:: Ui:: LayoutLayer:: styleMargins() const
Node margin for each style.
Expects that setStyle() was called.
void Magnum:: Ui:: LayoutLayer:: setStyle(const Containers:: StridedArrayView1D<const Vector2>& minSizes,
const Containers:: StridedArrayView1D<const Vector2>& maxSizes,
const Containers:: StridedArrayView1D<const Float>& aspectRatios,
const Containers:: StridedArrayView1D<const Vector4>& paddings,
const Containers:: StridedArrayView1D<const Vector4>& margins)
Set style data.
| Parameters | |
|---|---|
| minSizes | Minimal node size for each style, or an empty view for no style-specific minimal node sizes |
| maxSizes | Maximal node size for each style, or an empty view for no style-specific maximal node sizes |
| aspectRatios | Node aspect ratio for each style, or an empty view for no style-specific node aspect ratios |
| paddings | Padding inside a node for child node placement for each style, in order left, top, right, bottom, or an empty view for no style-specific node padding |
| margins | Margin outside nodes for placement within parents and next to neighbor nodes for each style, in order left, top, right, bottom, or an empty view for no style-specific node margin |
All views are expected to either have the same size as styleCount(), or be empty, in which case a default value will be used. If all views are empty, default values will be set for all properties. For a data with a particular style attached to a particular node, the properties are interpreted as follows:
- A max of the value coming from
minSizesfor given style and min sizes reported by any other data attached to the same node is used as a minimal node size. Specifying a min size of0.0fin either axis doesn't affect the final node min size in given axis in any way. The defaults if nominSizesare specified are all0.0f. - A min of the value coming from
maxSizesfor given style and min sizes reported by any other data attached to the same node is used as a maximal node size. Specifying a max size of Constants::inf() in either axis doesn't affect the final node max size in given axis in any way. The defaults if no maxSizesare specified are all Constants::inf(). - A first non-zero value coming from
aspectRatiosfor given style and aspect ratios reported by any other data attached to the same node is used as a node aspect ratio. Specifying an aspect ratio of0.0fdoesn't affect the final node aspect ratio in any way. The defaults if noaspectRatiosare specified are all0.0f. - A max of the value coming from
paddingsfor given style and paddings reported by any other data attached to the same node is used as a node padding. Specifying a padding of0.0fat given edge doesn't affect the final node padding at given edge in any way. The defaults if nopaddingsare specified are all0.0f. - A max of the value coming from
marginsfor given style and margins reported by any other data attached to the same node is used as a node margin. Specifying a margin of0.0fat given edge doesn't affect the final node margin at given edge in any way. The defaults if nomarginsare specified are all0.0f.
Calling this function causes LayerState::
void Magnum:: Ui:: LayoutLayer:: setStyle(std:: initializer_list<Vector2> minSizes,
std:: initializer_list<Vector2> maxSizes,
std:: initializer_list<Float> aspectRatios,
std:: initializer_list<Vector4> paddings,
std:: initializer_list<Vector4> margins)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
DataHandle Magnum:: Ui:: LayoutLayer:: create(UnsignedInt style,
NodeHandle node = NodeHandle:: Null)
Create a data with given style index.
| Parameters | |
|---|---|
| style | Style index |
| node | Node to attach to |
| Returns | New data handle |
Expects that style is less than styleCount(). It is allowed to call this function before any styles are set with setStyle(). Once a style is set, layout properties are driven from given style. There is currently no way to customize the layout properties on a per-data basis.
Delegates to AbstractLayer::
template<class StyleIndex>
DataHandle Magnum:: Ui:: LayoutLayer:: create(StyleIndex style,
NodeHandle node = NodeHandle:: Null)
Create a data with given style index in a concrete enum type.
Casts style to UnsignedInt and delegates to create(UnsignedInt, NodeHandle).
void Magnum:: Ui:: LayoutLayer:: remove(DataHandle handle)
Remove a data.
Delegates to AbstractLayer::
void Magnum:: Ui:: LayoutLayer:: remove(LayerDataHandle handle)
Remove a data assuming it belongs to this layer.
Compared to remove(DataHandle) delegates to AbstractLayer::
UnsignedInt Magnum:: Ui:: LayoutLayer:: style(DataHandle handle) const
Type-erased data style index.
Expects that handle is valid. The index is guaranteed to be less than styleCount().
template<class StyleIndex>
StyleIndex Magnum:: Ui:: LayoutLayer:: style(DataHandle handle) const
Data style index in a concrete enum type.
Expects that handle is valid. The index is guaranteed to be less than styleCount().
UnsignedInt Magnum:: Ui:: LayoutLayer:: style(LayerDataHandle handle) const
Type-erased data style index assuming it belongs to this layer.
Like style(DataHandle) const but without checking that handle indeed belongs to this layer. See its documentation for more information.
template<class StyleIndex>
StyleIndex Magnum:: Ui:: LayoutLayer:: style(LayerDataHandle handle) const
Data style index in a concrete enum type assuming it belongs to this layer.
Like style(DataHandle) const but without checking that handle indeed belongs to this layer. See its documentation for more information.
void Magnum:: Ui:: LayoutLayer:: setStyle(DataHandle handle,
UnsignedInt style)
Set data style index.
Expects that handle is valid and style is less than styleCount().
If handle is attached to a non-null node, calling this function causes LayerState::
template<class StyleIndex>
void Magnum:: Ui:: LayoutLayer:: setStyle(DataHandle handle,
StyleIndex style)
Set data style index in a concrete enum type.
Casts style to UnsignedInt and delegates to setStyle(DataHandle, UnsignedInt).
void Magnum:: Ui:: LayoutLayer:: setStyle(LayerDataHandle handle,
UnsignedInt style)
Set data style index assuming it belongs to this layer.
Like setStyle(DataHandle, UnsignedInt) but without checking that handle indeed belongs to this layer. See its documentation for more information.
template<class StyleIndex>
void Magnum:: Ui:: LayoutLayer:: setStyle(LayerDataHandle handle,
StyleIndex style)
Set data style index in a concrete enum type assuming it belongs to this layer.
Casts style to UnsignedInt and delegates to setStyle(LayerDataHandle, UnsignedInt).