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

Base for the main user interface.

Doesn't contain any implicit layers, layouters or animators. You'll most likely want to instantiate the UserInterface subclass instead.

Integration with application libraries

By including Magnum/Ui/Application.h it's possible to pass event instances from Platform::*Application classes directly to event handlers. They get internally converted to a corresponding PointerEvent, PointerMoveEvent, KeyEvent or TextInputEvent instance with a subset of information given application provides. Then, if the event is accepted by the user interface, the original application event is marked as accepted as well, to prevent it from propagating further in certain circumstances (such as to the browser window when compiling for the web). Example usage:

#include <Magnum/Ui/Application.h>



void MyApplication::pointerPressEvent(PointerEvent& event) {
    if(!_ui.pointerPressEvent(event)) {
        /* Handle an event that wasn't accepted by the UI */
    }

    
}

void MyApplication::pointerReleaseEvent(PointerEvent& event) {
    if(!_ui.pointerReleaseEvent(event)) {
        /* Handle an event that wasn't accepted by the UI */
    }

    
}

void MyApplication::pointerMoveEvent(PointerMoveEvent& event) {
    if(!_ui.pointerMoveEvent(event)) {
        /* Handle an event that wasn't accepted by the UI */
    }

    
}

void MyApplication::keyPressEvent(KeyEvent& event) {
    if(!_ui.keyPressEvent(event)) {
        /* Handle an event that wasn't accepted by the UI */
    }

    
}

void MyApplication::keyReleaseEvent(KeyEvent& event) {
    if(!_ui.keyReleaseEvent(event)) {
        /* Handle an event that wasn't accepted by the UI */
    }

    
}

void MyApplication::textInputEvent(TextInputEvent& event) {
    if(!_ui.textInputEvent(event)) {
        /* Handle an event that wasn't accepted by the UI */
    }

    
}

Currently, none of the application classes expose event timestamps and thus PointerEvent::time() and the corresponding field in all other events is default-constructed. If timestamps are needed, for example for animations, they can be supplied as a second Nanoseconds argument when calling pointerPressEvent(Event&, Args&&... args) and others.

DPI awareness

There are three separate concepts for DPI-aware UI rendering:

  • UI size — size of the user interface to which all widgets are positioned
  • Window size — size of the window to which all input events are related
  • Framebuffer size — size of the framebuffer the UI is being rendered to

Depending on the platform and use case, each of these three values can be different. For example, a game menu screen can have the UI size the same regardless of window size. Or on Retina macOS you can have different window and framebuffer size and the UI size might be related to window size but independent on the framebuffer size.

When using for example Platform::Sdl2Application or other *Application implementations, you usually have three values at your disposal — windowSize(), framebufferSize() and dpiScaling(). If you want the UI to have the same layout and just scale on bigger window sizes, pass a fixed value to the UI size:

Ui::AbstractUserInterface ui(
    {800, 600},
    Vector2{windowSize()}, framebufferSize());

If you want the UI to get more room with larger window sizes and behave properly with different DPI scaling values, pass a ratio of window size and DPI scaling to the UI size:

Ui::AbstractUserInterface ui(
    Vector2{windowSize()}/dpiScaling(),
    Vector2{windowSize()}, framebufferSize());

Finally, to gracefully deal with extremely small or extremely large windows, you can apply Math::clamp() on top with some defined bounds. Windows outside of the reasonable size range will then get a scaled version of the UI at boundary size:

Ui::AbstractUserInterface ui(
    Math::clamp({640.0f, 360.0f}, {1920.0f, 1080.0f},
        Vector2{windowSize()}/dpiScaling()),
    Vector2{windowSize()}, framebufferSize());

Derived classes

class UserInterface new in Git master
Main user interface.

Constructors, destructors, conversion operators

AbstractUserInterface(NoCreateT) explicit
Construct without creating the user interface with concrete parameters.
AbstractUserInterface(const Vector2& size, const Vector2& windowSize, const Vector2i& framebufferSize) explicit
Construct.
AbstractUserInterface(const Vector2i& size) explicit
Construct with an unscaled size.
AbstractUserInterface(const AbstractUserInterface&) deleted
Copying is not allowed.
AbstractUserInterface(AbstractUserInterface&&) noexcept
Move constructor.

Public functions

auto operator=(const AbstractUserInterface&) -> AbstractUserInterface& deleted
Copying is not allowed.
auto operator=(AbstractUserInterface&&) -> AbstractUserInterface& noexcept
Move assignment.
auto size() const -> Vector2
User interface size.
auto windowSize() const -> Vector2
Window size.
auto framebufferSize() const -> Vector2i
Framebuffer size.
auto setSize(const Vector2& size, const Vector2& windowSize, const Vector2i& framebufferSize) -> AbstractUserInterface&
Set user interface size.
auto setSize(const Vector2i& size) -> AbstractUserInterface&
Set unscaled user interface size.
auto state() const -> UserInterfaceStates
User interface state.
auto animationTime() const -> Nanoseconds
Animation time.
auto clean() -> AbstractUserInterface&
Clean orphaned nodes, data and no longer valid data attachments.
auto advanceAnimations(Nanoseconds time) -> AbstractUserInterface&
Advance active animations.
auto update() -> AbstractUserInterface&
Update node hierarchy, data order and data contents for drawing and event processing.
auto draw() -> AbstractUserInterface&
Draw the user interface.
auto pointerPressEvent(const Vector2& globalPosition, PointerEvent& event) -> bool
Handle a pointer press event.
template<class Event, class ... Args, class = decltype(Implementation::PointerEventConverter<Event>::press(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
auto pointerPressEvent(Event& event, Args && ... args) -> bool
Handle an external pointer press event.
auto pointerReleaseEvent(const Vector2& globalPosition, PointerEvent& event) -> bool
Handle a pointer release event.
template<class Event, class ... Args, class = decltype(Implementation::PointerEventConverter<Event>::release(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
auto pointerReleaseEvent(Event& event, Args && ... args) -> bool
Handle an external pointer release event.
auto pointerMoveEvent(const Vector2& globalPosition, PointerMoveEvent& event) -> bool
Handle a pointer move event.
template<class Event, class ... Args, class = decltype(Implementation::PointerMoveEventConverter<Event>::move(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
auto pointerMoveEvent(Event& event, Args && ... args) -> bool
Handle an external pointer move event.
auto focusEvent(NodeHandle node, FocusEvent& event) -> bool
Handle a focus event.
auto keyPressEvent(KeyEvent& event) -> bool
Handle a key press event.
template<class Event, class ... Args, class = decltype(Implementation::KeyEventConverter<Event>::press(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
auto keyPressEvent(Event& event, Args && ... args) -> bool
Handle an external key press event.
auto keyReleaseEvent(KeyEvent& event) -> bool
Handle a key release event.
template<class Event, class ... Args, class = decltype(Implementation::KeyEventConverter<Event>::release(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
auto keyReleaseEvent(Event& event, Args && ... args) -> bool
Handle an external key release event.
auto textInputEvent(TextInputEvent& event) -> bool
Handle a text input event.
template<class Event, class ... Args, class = decltype(Implementation::TextInputEventConverter<Event>::trigger(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
auto textInputEvent(Event& event, Args && ... args) -> bool
Handle an external text input event.
auto currentPressedNode() const -> NodeHandle
Node pressed by last pointer event.
auto currentCapturedNode() const -> NodeHandle
Node captured by last pointer event.
auto currentHoveredNode() const -> NodeHandle
Node hovered by last pointer event.
auto currentFocusedNode() const -> NodeHandle
Node focused by last pointer or focus event.
auto currentGlobalPointerPosition() const -> Containers::Optional<Vector2>
Position of last pointer event.

Renderer management

auto setRendererInstance(Containers::Pointer<AbstractRenderer>&& instance) -> AbstractRenderer&
Set renderer instance.
template<class T>
auto setRendererInstance(Containers::Pointer<T>&& instance) -> T&
auto hasRenderer() const -> bool
Whether a renderer instance has been set.
auto renderer() -> AbstractRenderer&
Renderer instance.
auto renderer() const -> const AbstractRenderer&
template<class T>
auto renderer() -> T&
Renderer instance in a concrete type.
template<class T>
auto renderer() const -> const T&

Layer and data management

auto layerCapacity() const -> std::size_t
Capacity of the layer storage.
auto layerUsedCount() const -> std::size_t
Count of used items in the layer storage.
auto isHandleValid(LayerHandle handle) const -> bool
Whether a layer handle is valid.
auto isHandleValid(DataHandle handle) const -> bool
Whether a data handle is valid.
auto layerFirst() const -> LayerHandle
First layer in draw and event processing order.
auto layerLast() const -> LayerHandle
Last layer in draw and event processing order.
auto layerPrevious(LayerHandle handle) const -> LayerHandle
Previous layer in draw and event processing order.
auto layerNext(LayerHandle handle) const -> LayerHandle
Next layer in draw and event processing order.
auto createLayer(LayerHandle before = LayerHandle::Null) -> LayerHandle
Create a layer.
auto setLayerInstance(Containers::Pointer<AbstractLayer>&& instance) -> AbstractLayer&
Set a layer instance.
template<class T>
auto setLayerInstance(Containers::Pointer<T>&& instance) -> T&
auto layer(LayerHandle handle) -> AbstractLayer&
Layer instance.
auto layer(LayerHandle handle) const -> const AbstractLayer&
template<class T>
auto layer(LayerHandle handle) -> T&
Layer instance in a concrete type.
template<class T>
auto layer(LayerHandle handle) const -> const T&
void removeLayer(LayerHandle handle)
Remove a layer.
void attachData(NodeHandle node, DataHandle data)
Attach data to a node.

Node layouter management

auto layouterCapacity() const -> std::size_t
Capacity of the layouter storage.
auto layouterUsedCount() const -> std::size_t
Count of used items in the layouter storage.
auto isHandleValid(LayouterHandle handle) const -> bool
Whether a layouter handle is valid.
auto isHandleValid(LayoutHandle handle) const -> bool
Whether a layout handle is valid.
auto layouterFirst() const -> LayouterHandle
First layouter in the layout calculation order.
auto layouterLast() const -> LayouterHandle
Last layouter in the layout calculation order.
auto layouterPrevious(LayouterHandle handle) const -> LayouterHandle
Previous layouter in the layout calculation order.
auto layouterNext(LayouterHandle handle) const -> LayouterHandle
Next layouter in the layout calculation order.
auto createLayouter(LayouterHandle before = LayouterHandle::Null) -> LayouterHandle
Create a layouter.
auto setLayouterInstance(Containers::Pointer<AbstractLayouter>&& instance) -> AbstractLayouter&
Set a layouter instance.
template<class T>
auto setLayouterInstance(Containers::Pointer<T>&& instance) -> T&
auto layouter(LayouterHandle handle) -> AbstractLayouter&
Layouter instance.
auto layouter(LayouterHandle handle) const -> const AbstractLayouter&
template<class T>
auto layouter(LayouterHandle handle) -> T&
Layouter instance in a concrete type.
template<class T>
auto layouter(LayouterHandle handle) const -> const T&
void removeLayouter(LayouterHandle handle)
Remove a layouter.

Animator management

auto animatorCapacity() const -> std::size_t
Capacity of the animator storage.
auto animatorUsedCount() const -> std::size_t
Count of used items in the animator storage.
auto isHandleValid(AnimatorHandle handle) const -> bool
Whether an animator handle is valid.
auto isHandleValid(AnimationHandle handle) const -> bool
Whether an animation handle is valid.
auto createAnimator() -> AnimatorHandle
Create an animator.
auto setGenericAnimatorInstance(Containers::Pointer<AbstractGenericAnimator>&& instance) -> AbstractGenericAnimator&
Set a generic animator instance.
template<class T>
auto setGenericAnimatorInstance(Containers::Pointer<T>&& instance) -> T&
auto setNodeAnimatorInstance(Containers::Pointer<AbstractNodeAnimator>&& instance) -> AbstractNodeAnimator&
Set a node animator instance.
template<class T>
auto setNodeAnimatorInstance(Containers::Pointer<T>&& instance) -> T&
auto setDataAnimatorInstance(Containers::Pointer<AbstractDataAnimator>&& instance) -> AbstractDataAnimator&
Set a data animator instance.
template<class T>
auto setDataAnimatorInstance(Containers::Pointer<T>&& instance) -> T&
auto setStyleAnimatorInstance(Containers::Pointer<AbstractStyleAnimator>&& instance) -> AbstractStyleAnimator&
Set a style animator instance.
template<class T>
auto setStyleAnimatorInstance(Containers::Pointer<T>&& instance) -> T&
auto animator(AnimatorHandle handle) -> AbstractAnimator&
Animator instance.
auto animator(AnimatorHandle handle) const -> const AbstractAnimator&
template<class T>
auto animator(AnimatorHandle handle) -> T&
Animator instance in a concrete type.
template<class T>
auto animator(AnimatorHandle handle) const -> const T&
void removeAnimator(AnimatorHandle handle)
Remove an animator.
void attachAnimation(NodeHandle node, AnimationHandle animation)
Attach an animation to a node.
void attachAnimation(DataHandle data, AnimationHandle animation)
Attach an animation to a data.

Node management

auto nodeCapacity() const -> std::size_t
Current capacity of the node storage.
auto nodeUsedCount() const -> std::size_t
Count of used items in the node storage.
auto isHandleValid(NodeHandle handle) const -> bool
Whether a node handle is valid.
auto createNode(NodeHandle parent, const Vector2& offset, const Vector2& size, NodeFlags flags = {}) -> NodeHandle
Create a node.
auto createNode(const Vector2& offset, const Vector2& size, NodeFlags flags = {}) -> NodeHandle
Create a root node.
auto nodeParent(NodeHandle handle) const -> NodeHandle
Node parent.
auto nodeOffset(NodeHandle handle) const -> Vector2
Node offset relative to its parent.
void setNodeOffset(NodeHandle handle, const Vector2& offset)
Set node offset relative to its parent.
auto nodeSize(NodeHandle handle) const -> Vector2
Node size.
void setNodeSize(NodeHandle handle, const Vector2& size)
Set node size.
auto nodeFlags(NodeHandle handle) const -> NodeFlags
Node flags.
void setNodeFlags(NodeHandle handle, NodeFlags flags)
Set node flags.
void addNodeFlags(NodeHandle handle, NodeFlags flags)
Add node flags.
void clearNodeFlags(NodeHandle handle, NodeFlags flags)
Clear node flags.
void removeNode(NodeHandle handle)
Remove a node.

Top-level node draw and event processing order management

auto nodeOrderCapacity() const -> std::size_t
Capacity of the top-level node order storage.
auto nodeOrderUsedCount() const -> std::size_t
Count of used items in the top-level node order storage.
auto nodeOrderFirst() const -> NodeHandle
First top-level node in draw and event processing order.
auto nodeOrderLast() const -> NodeHandle
Last top-level node in draw and event processing order.
auto isNodeTopLevel(NodeHandle handle) const -> bool
Whether a node is top-level for draw and event processing.
auto isNodeOrdered(NodeHandle handle) const -> bool
Whether a node is top-level and is included in a draw and event processing order.
auto nodeOrderPrevious(NodeHandle handle) const -> NodeHandle
Previous node in draw and event processing order.
auto nodeOrderNext(NodeHandle handle) const -> NodeHandle
Next node in draw and event processing order.
auto nodeOrderLastNested(NodeHandle handle) const -> NodeHandle
Last node in draw and event processing order nested under this node.
void setNodeOrder(NodeHandle handle, NodeHandle before)
Order a top-level node for draw and event processing.
void clearNodeOrder(NodeHandle handle)
Clear a node from the draw and event processing order.
void flattenNodeOrder(NodeHandle handle)
Flatten a non-root top-level node back to the usual order defined by the node hierarchy.

Function documentation

Magnum::Ui::AbstractUserInterface::AbstractUserInterface(NoCreateT) explicit

Construct without creating the user interface with concrete parameters.

You're expected to call setSize() afterwards in order to define scaling of event coordinates, node positions and projection matrices for drawing.

Magnum::Ui::AbstractUserInterface::AbstractUserInterface(const Vector2& size, const Vector2& windowSize, const Vector2i& framebufferSize) explicit

Construct.

Parameters
size Size of the user interface to which everything is positioned
windowSize Size of the window to which all input events are related
framebufferSize Size of the window framebuffer. On some platforms with HiDPI screens may be different from window size.

Equivalent to constructing with AbstractUserInterface(NoCreateT) and then calling setSize(const Vector2&, const Vector2&, const Vector2i&). See its documentation for more information.

Magnum::Ui::AbstractUserInterface::AbstractUserInterface(const Vector2i& size) explicit

Construct with an unscaled size.

Delegates to AbstractUserInterface(const Vector2&, const Vector2&, const Vector2i&) with all sizes set to size. Doing so assumes that the coordinate system in which events are passed matches framebuffer size.

Magnum::Ui::AbstractUserInterface::AbstractUserInterface(AbstractUserInterface&&) noexcept

Move constructor.

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

Vector2 Magnum::Ui::AbstractUserInterface::size() const

User interface size.

Node positioning is in respect to this size. If setSize() or AbstractUserInterface(const Vector2&, const Vector2&, const Vector2i&) wasn't called yet, initial value is a zero vector.

Vector2 Magnum::Ui::AbstractUserInterface::windowSize() const

Window size.

Global event position in pointerPressEvent(), pointerReleaseEvent() and pointerMoveEvent() is in respect to this size. If setSize() or AbstractUserInterface(const Vector2&, const Vector2&, const Vector2i&) wasn't called yet, initial value is a zero vector.

Vector2i Magnum::Ui::AbstractUserInterface::framebufferSize() const

Framebuffer size.

Rendering performed by layers is in respect to this size. If setSize() or AbstractUserInterface(const Vector2&, const Vector2&, const Vector2i&) wasn't called yet, initial value is a zero vector.

AbstractUserInterface& Magnum::Ui::AbstractUserInterface::setSize(const Vector2& size, const Vector2& windowSize, const Vector2i& framebufferSize)

Set user interface size.

Parameters
size Size of the user interface to which everything is positioned
windowSize Size of the window to which all input events are related
framebufferSize Size of the window framebuffer. On some platforms with HiDPI screens may be different from window size.
Returns Reference to self (for method chaining)

All sizes are expected to be non-zero, origin is top left for all.

After calling this function, the pointerPressEvent(), pointerReleaseEvent() and pointerMoveEvent() functions take the global event position with respect to windowSize, which is then rescaled to match size when exposed through PointerEvent. The size and framebufferSize is passed through to AbstractLayer::setSize() to all layers with LayerFeature::Draw so they can set appropriate projection and other framebuffer-related properties, similarly the size is passed through to AbstractLayouter::setSize() to all layouters.

There's no default size and this function is expected to be called before the first update() happens, either directly or through the AbstractUserInterface(const Vector2&, const Vector2&, const Vector2i&) constructor. It's allowed to call this function for the first time even after node, layers or data were created.

Calling this function with new values will update the event position scaling accordingly. If size or framebufferSize changes, AbstractLayer::setSize() is called on all layers; if size changes, AbstractLayouter::setSize() is called on all layouters. If size changes and any nodes were already created, UserInterfaceState::NeedsNodeClipUpdate is set. If a renderer instance is set, AbstractRenderer::setupFramebuffers() is called to make the renderer populate or update its internal state. If a renderer instance isn't set yet when calling this function, the framebuffer setup is performed in the next setRendererInstance() call instead.

AbstractUserInterface& Magnum::Ui::AbstractUserInterface::setSize(const Vector2i& size)

Set unscaled user interface size.

Returns Reference to self (for method chaining)

Calls setSize(const Vector2&, const Vector2&, const Vector2i&) with all sizes set to size. Doing so assumes that the coordinate system in which events are passed matches framebuffer size.

UserInterfaceStates Magnum::Ui::AbstractUserInterface::state() const

User interface state.

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

Nanoseconds Magnum::Ui::AbstractUserInterface::animationTime() const

Animation time.

Time value last passed to advanceAnimations(). Initial value is 0_nsec.

AbstractUserInterface& Magnum::Ui::AbstractUserInterface::clean()

Clean orphaned nodes, data and no longer valid data attachments.

Returns Reference to self (for method chaining)

Called implicitly from update() and subsequently also from draw() and all event processing functions. If state() contains neither UserInterfaceState::NeedsNodeClean nor UserInterfaceState::NeedsDataClean, this function is a no-op, otherwise it performs a subset of the following depending on the state:

After calling this function, state() doesn't contain UserInterfaceState::NeedsNodeClean anymore; nodeUsedCount() and AbstractLayer::usedCount() may get smaller.

AbstractUserInterface& Magnum::Ui::AbstractUserInterface::advanceAnimations(Nanoseconds time)

Advance active animations.

Returns Reference to self (for method chaining)

Implicitly calls clean(), should be called before any update() or draw() for given frame. Expects that time is greater or equal to animationTime(). If state() contains UserInterfaceState::NeedsAnimationAdvance, this function delegates to AbstractAnimator::update() and then a corresponding animator-specific advance function such as AbstractGenericAnimator::advance(), AbstractNodeAnimator::advance() or layer-specific AbstractLayer::advanceAnimations() on all animator instances that have AnimatorState::NeedsAdvance set.

Calling this function updates animationTime(). Afterwards, state() may still contain UserInterfaceState::NeedsAnimationAdvance, signalling that animation advance is still needed the next fram. It may also have other states added depending on what all the animators touched, and a subsequent call to draw() (or directly to clean() and update() before that) for given frame will take care of correctly updating the internal state.

AbstractUserInterface& Magnum::Ui::AbstractUserInterface::update()

Update node hierarchy, data order and data contents for drawing and event processing.

Returns Reference to self (for method chaining)

Expects that either setSize() was called or the AbstractUserInterface(const Vector2&, const Vector2&, const Vector2i&) constructor was used.

Implicitly calls clean(); called implicitly from draw() and all event processing functions. If state() contains none of UserInterfaceState::NeedsDataUpdate, UserInterfaceState::NeedsDataAttachmentUpdate, UserInterfaceState::NeedsNodeEnabledUpdate, UserInterfaceState::NeedsNodeClipUpdate, UserInterfaceState::NeedsLayoutUpdate, UserInterfaceState::NeedsLayoutAssignmentUpdate or UserInterfaceState::NeedsNodeUpdate, this function is a no-op, otherwise it performs a subset of the following depending on the state, in order:

After calling this function, state() is empty apart from UserInterfaceState::NeedsAnimationAdvance, which may be present if there are any animators for which advanceAnimations() should be called.

AbstractUserInterface& Magnum::Ui::AbstractUserInterface::draw()

Draw the user interface.

Returns Reference to self (for method chaining)

Implicitly calls update(), which in turn implicitly calls clean(). Performs the following:

bool Magnum::Ui::AbstractUserInterface::pointerPressEvent(const Vector2& globalPosition, PointerEvent& event)

Handle a pointer press event.

Implicitly calls update(), which in turn implicitly calls clean(). The globalPosition is assumed to be in respect to windowSize(), and is internally scaled to match size() before being set to PointerEvent.

If the event is not primary and a node was captured by a previous pointerPressEvent(), pointerMoveEvent() or a non-primary pointerReleaseEvent(), calls pointerPressEvent() on all data attached to that node even if the event happens outside of its area, with the event position made relative to the node.

Otherwise, if either the event is primary or no node is captured, finds the front-most node under (scaled) globalPosition and calls AbstractLayer::pointerPressEvent() on all data attached to it belonging to layers that support LayerFeature::Event. If no data accept the event, continues to other nodes under the position in a front-to-back order and then to parent nodes. For each such node, the event is always called on all attached data, regardless of the accept status. For each call the event position is made relative to the node to which given data is attached.

If the press happened with Pointer::MouseLeft, primary Pointer::Finger or Pointer::Pen, the currently focused node is affected as well. If the node the event was accepted on is different from currently focused node (if there's any), AbstractLayer::blurEvent() is called on all data attached to that node. Then, if the node has NodeFlag::Focusable set, AbstractLayer::focusEvent() is called on all data attached to it. If any data accept the focus event, the node is treated as focused and receives all following key events until a primary pointerPressEvent() outside of this node happens or until a different node is made focused using focusEvent(). If the node is not NodeFlag::Focusable or the focus event was not accepted by any data, the currently focused node is reset. If a primary press event happens on a NodeFlag::Focusable node that's already focused, AbstractLayer::focusEvent() gets called on it again, without any preceding AbstractLayer::blurEvent(). If that focus event is not accepted however, the node subsequently receives an AbstractLayer::blurEvent(). If the event isn't primary, the current focused node isn't affected in any way.

Returns true if the press event was accepted by at least one data, false if it wasn't or there wasn't any visible event handling node at given position and thus the event should be propagated further. Accept status of the focus and blur events doesn't have any effect on the return value.

If the event is primary, the node that accepted the event is remembered and is subsequently used by pointerReleaseEvent() to emit a AbstractLayer::pointerTapOrClickEvent(), if a primary release happens on it as well. The node that accepted the primary event also implicitly captures all further pointer events until and including a primary pointerReleaseEvent() even if they happen outside of its area, unless PointerEvent::setCaptured() is called by the implementation to disable this behavior. The capture can be also removed from a later pointerMoveEvent() or a non-primary pointerReleaseEvent(). Any node that was already captured when calling this function with a primary event is ignored. If the event isn't primary, the node isn't rememebered for any subsequent tap or click event and neither it captures any further events.

If no node accepted the event or there wasn't any visible event handling node at given position, the previously remembered pressed and captured nodes are reset if and only if the event is primary.

Expects that the event is not accepted yet.

template<class Event, class ... Args, class = decltype(Implementation::PointerEventConverter<Event>::press(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
bool Magnum::Ui::AbstractUserInterface::pointerPressEvent(Event& event, Args && ... args)

Handle an external pointer press event.

Converts the event to a PointerEvent and delegates to pointerPressEvent(), see its documentation and Integration with application libraries for more information. The args allow passing optional extra arguments to a particular event converter.

bool Magnum::Ui::AbstractUserInterface::pointerReleaseEvent(const Vector2& globalPosition, PointerEvent& event)

Handle a pointer release event.

Implicitly calls update(), which in turn implicitly calls clean(). The globalPosition is assumed to be in respect to windowSize(), and is internally scaled to match size() before being set to PointerEvent.

If a node was captured by a previous pointerPressEvent(), pointerMoveEvent() or a non-primary pointerReleaseEvent(), calls AbstractLayer::pointerReleaseEvent() on all data attached to that node even if the event happens outside of its area, with the event position made relative to the node.

Otherwise, if a node wasn't captured, finds the front-most node under (scaled) globalPosition and calls AbstractLayer::pointerReleaseEvent() on all data attached to it belonging to layers that support LayerFeature::Event. If no data accept the event, continues to other nodes under the position in a front-to-back order and then to parent nodes. For each such node, the event is always called on all attached data, regardless of the accept status. For each call the event position is made relative to the node to which given data is attached.

If the event is primary and a node is captured, the capture is implicitly released after calling this function independently of whether PointerEvent::setCaptured() was set by the implementation. If the event isn't primary, the current captured node isn't affected by default, but the implementation can both release the existing capture or make the containing node capture future events by setting PointerEvent::setCaptured().

Returns true if the event was accepted by at least one data, false if it wasn't or there wasn't any visible event handling node at given position and thus the event should be propagated further.

If the node that accepted the event is the same as the node on which a previous pointerPressEvent() happened, the event is primary and the pointer was either captured or didn't leave the node area since, calls also AbstractLayer::pointerTapOrClickEvent() on all data attached to it.

Expects that the event is not accepted yet.

template<class Event, class ... Args, class = decltype(Implementation::PointerEventConverter<Event>::release(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
bool Magnum::Ui::AbstractUserInterface::pointerReleaseEvent(Event& event, Args && ... args)

Handle an external pointer release event.

Converts the event to a PointerEvent and delegates to pointerReleaseEvent(), see its documentation and Integration with application libraries for more information. The args allow passing optional extra arguments to a particular event converter.

bool Magnum::Ui::AbstractUserInterface::pointerMoveEvent(const Vector2& globalPosition, PointerMoveEvent& event)

Handle a pointer move event.

Implicitly calls update(), which in turn implicitly calls clean(). The globalPosition is assumed to be in respect to windowSize(), and is internally scaled to match size() before being set to PointerEvent.

If a node was captured by a previous pointerPressEvent() or pointerMoveEvent(), pointerReleaseEvent() wasn't called yet and the node wasn't removed since, calls AbstractLayer::pointerMoveEvent() on all data attached to that node even if it happens outside of its area, with the event position made relative to the node. If the move event is primary, happened inside the node area and is accepted by at least one data, the node is treated as hovered, otherwise as not hovered. An AbstractLayer::pointerEnterEvent() or pointerLeaveEvent() is then called for all data attached to the captured node if the node hover status changed with the same event except for PointerMoveEvent::relativePosition() which is reset to a zero vector. No corresponding leave / enter event is called for any other node in this case. If the move event isn't primary, the current hovered node isn't affected in any way. Returns true if the move event was accepted by at least one data attached to the captured node, false if it wasn't and thus the event should be propagated further; accept status of the enter and leave events is ignored. If the move, enter or leave event implementations called PointerMoveEvent::setCaptured() resulting in it being false, the capture is released after this function, otherwise it stays unchanged. For primary events the capture reset is performed regardless of the event accept status, for non-primary events only if they're accepted.

Otherwise, if a node wasn't captured, finds the front-most node under (scaled) globalPosition and calls AbstractLayer::pointerMoveEvent() on all data attached to it belonging to layers that support LayerFeature::Event. If no data accept the event, continues to other nodes under the position in a front-to-back order and then to parent nodes. For each such node, the event is always called on all attached data, regardless of the accept status. If the move event is primary, the node on which the data accepted the event is then treated as hovered; if no data accepted the event, there's no hovered node. For each call the event position is made relative to the node to which given data is attached. If the currently hovered node changed, an AbstractLayer::pointerLeaveEvent() is then called for all data attached to a previously hovered node if it exists, and then a corresponding AbstractLayer::pointerEnterEvent() is called for all data attached to the currently hovered node if it exists, in both cases with the same event except for PointerMoveEvent::position() which is made relative to the particular node it's called on and PointerMoveEvent::relativePosition() which is reset to a zero vector. If the move event isn't primary, the current hovered node isn't affected in any way. Returns true if the event was accepted by at least one data, false if it wasn't or there wasn't any visible event handling node at given position and thus the event should be propagated further; accept status of the enter and leave events is ignored. If any accepted move event or any enter event called PointerMoveEvent::setCaptured() resulting in it being true, the containing node implicitly captures all further pointer events until and including a pointerReleaseEvent() even if they happen outside of its area, or until the capture is released in a pointerMoveEvent() again. Calling PointerMoveEvent::setCaptured() in the leave event has no effect in this case.

Expects that the event is not accepted yet.

template<class Event, class ... Args, class = decltype(Implementation::PointerMoveEventConverter<Event>::move(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
bool Magnum::Ui::AbstractUserInterface::pointerMoveEvent(Event& event, Args && ... args)

Handle an external pointer move event.

Converts the event to a PointerMoveEvent and delegates to pointerMoveEvent(), see its documentation and Integration with application libraries for more information. The args allow passing optional extra arguments to a particular event converter.

bool Magnum::Ui::AbstractUserInterface::focusEvent(NodeHandle node, FocusEvent& event)

Handle a focus event.

Implicitly calls update(), which in turn implicitly calls clean(). The node is expected to be either NodeHandle::Null or valid with NodeFlag::Focusable set.

If node is non-null and is or any of its parents are not visible either due to NodeFlag::Hidden set or due to the node hierarchy not being in the top-level node order, or have NodeFlag::Disabled or NodeFlag::NoEvents set, the function is a no-op and returns false. Note that this does not apply to nodes that are clipped or otherwise out of view.

If the node is visible and can be focused, calls AbstractLayer::focusEvent() on all attached data, regardless of the accept status, and even if the current focused node is the same as node. Then, if any of them accept the event, the node is set as currently focused, and AbstractLayer::blurEvent() is called on the previously focused node if different from node. If none of them accept the event and the previously focused node is different from node, the previously focused node stays. If none of them accept the event and the previously focused node is the same as node, AbstractLayer::blurEvent() is called on node and the current focused node is set to NodeHandle::Null.

If node is NodeHandle::Null and current focused node is non-null, calls AbstractLayer::blurEvent() on it and sets the current focused node to NodeHandle::Null.

Returns true if the AbstractLayer::focusEvent() was called at all and accepted by at least one data, false otherwise.

Compared to pointerPressEvent(), where pressing on a non-focusable node blurs the previously focused node, this function preserves the previously focused node if node is cannot be focused for any of the above reasons. Given this function is meant to be called by the application itself, this gives it more control — for example to try to focus the next active control, if there's any, and stay on the previous one if not. To achieve the same behavior as pointerPressEvent(), call the function with NodeHandle::Null if a call with a non-null handle fails:

if(!ui.focusEvent(node, event))
    ui.focusEvent(Ui::NodeHandle::Null, event);

bool Magnum::Ui::AbstractUserInterface::keyPressEvent(KeyEvent& event)

Handle a key press event.

Implicitly calls update(), which in turn implicitly calls clean().

If currentFocusedNode() is not NodeHandle::Null, calls AbstractLayer::keyPressEvent() on all data attached to it belonging to layers that support LayerFeature::Event.

Otherwise, if currentGlobalPointerPosition() is not Containers::NullOpt, finds the front-most node under it and calls AbstractLayer::keyPressEvent() on all data attached to it belonging to layers that support LayerFeature::Event. If no data accept the event, continues to other nodes under the position in a front-to-back order and then to parent nodes. For each such node, the event is always called on all attached data, regardless of the accept status. For each call the event contains the currentGlobalPointerPosition() made relative to the node to which given data is attached.

Returns true if the event was accepted by at least one data; false if it wasn't, if currentFocusedNode() is NodeHandle::Null and there either wasn't any visible event handling node at given position or currentGlobalPointerPosition() is Containers::NullOpt, and thus the event should be propagated further.

Expects that the event is not accepted yet.

template<class Event, class ... Args, class = decltype(Implementation::KeyEventConverter<Event>::press(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
bool Magnum::Ui::AbstractUserInterface::keyPressEvent(Event& event, Args && ... args)

Handle an external key press event.

Converts the event to a KeyEvent and delegates to keyPressEvent(), see its documentation and Integration with application libraries for more information. The args allow passing optional extra arguments to a particular event converter.

bool Magnum::Ui::AbstractUserInterface::keyReleaseEvent(KeyEvent& event)

Handle a key release event.

Implicitly calls update(), which in turn implicitly calls clean().

If currentFocusedNode() is not NodeHandle::Null, calls AbstractLayer::keyReleaseEvent() on all data attached to it belonging to layers that support LayerFeature::Event.

Otherwise, if currentGlobalPointerPosition() is not Containers::NullOpt, finds the front-most node under it and calls AbstractLayer::keyReleaseEvent() on all data attached to it belonging to layers that support LayerFeature::Event. If no data accept the event, continues to other nodes under the position in a front-to-back order and then to parent nodes. For each such node, the event is always called on all attached data, regardless of the accept status. For each call the event contains the currentGlobalPointerPosition() made relative to the node to which given data is attached.

Returns true if the event was accepted by at least one data; false if it wasn't, if currentFocusedNode() is NodeHandle::Null and there either wasn't any visible event handling node at given position or currentGlobalPointerPosition() is Containers::NullOpt, and thus the event should be propagated further.

Expects that the event is not accepted yet.

template<class Event, class ... Args, class = decltype(Implementation::KeyEventConverter<Event>::release(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
bool Magnum::Ui::AbstractUserInterface::keyReleaseEvent(Event& event, Args && ... args)

Handle an external key release event.

Converts the event to a KeyEvent and delegates to keyReleaseEvent(), see its documentation and Integration with application libraries for more information. The args allow passing optional extra arguments to a particular event converter.

bool Magnum::Ui::AbstractUserInterface::textInputEvent(TextInputEvent& event)

Handle a text input event.

Implicitly calls update(), which in turn implicitly calls clean().

If currentFocusedNode() is not NodeHandle::Null, calls AbstractLayer::textInputEvent() on all data attached to it belonging to layers that support LayerFeature::Event.

Returns true if the event was accepted by at least one data; false if it wasn't or if currentFocusedNode() is NodeHandle::Null, and thus the event should be propagated further.

Expects that the event is not accepted yet.

template<class Event, class ... Args, class = decltype(Implementation::TextInputEventConverter<Event>::trigger(std::declval<AbstractUserInterface&>(), std::declval<Event&>(), std::declval<Args>()...))>
bool Magnum::Ui::AbstractUserInterface::textInputEvent(Event& event, Args && ... args)

Handle an external text input event.

Converts the event to a TextInputEvent and delegates to textInputEvent(), see its documentation and Integration with application libraries for more information. The args allow passing optional extra arguments to a particular event converter.

NodeHandle Magnum::Ui::AbstractUserInterface::currentPressedNode() const

Node pressed by last pointer event.

Returns handle of a node that was under the pointer for the last pointerPressEvent(), the pointer wasn't released since and the pointer is either captured on that node or didn't leave its area since. If a pointerReleaseEvent() then happens on the node area, all data attached to it will receive a AbstractLayer::pointerTapOrClickEvent().

If no pointer press event was called yet, if the event wasn't accepted by any data, if pointerReleaseEvent() was called since or the pointer was uncaptured and left the node area, returns NodeHandle::Null. It also becomes NodeHandle::Null if the node or any of its parents were removed, hidden or have NodeFlag::NoEvents or NodeFlag::Disabled set and update() was called since.

The returned handle may be invalid if the node or any of its parents were removed and clean() wasn't called since.

NodeHandle Magnum::Ui::AbstractUserInterface::currentCapturedNode() const

Node captured by last pointer event.

Returns handle of a node that captured the last pointerPressEvent() or pointerMoveEvent(). All data attached to the captured node then receive all following pointer events until and including a pointerReleaseEvent() even if they happen outside of its area, or until the capture is released in a pointerMoveEvent() again.

If no pointer press event was called yet, if the event wasn't accepted by any data, if the capture was disabled or subsequently released with PointerEvent::setCaptured() or if a pointerReleaseEvent() was called since, returns NodeHandle::Null. It also becomes NodeHandle::Null if the node or any of its parents were removed, hidden or have NodeFlag::NoEvents or NodeFlag::Disabled set and update() was called since.

The returned handle may be invalid if the node or any of its parents were removed and clean() wasn't called since.

NodeHandle Magnum::Ui::AbstractUserInterface::currentHoveredNode() const

Node hovered by last pointer event.

Returns handle of a node that was under the pointer for the last pointerMoveEvent(). All data attached to such node already received a AbstractLayer::pointerEnterEvent(). Once a pointerMoveEvent() leaves its area, all data attached to that node will receive a AbstractLayer::pointerLeaveEvent(), and this either becomes NodeHandle::Null, or another node becomes hovered, receiving an enter event. It's also NodeHandle::Null if no pointer move event was called yet or if the node or any of its parents were removed, hidden or have NodeFlag::NoEvents or NodeFlag::Disabled set and update() was called since.

The returned handle may be invalid if the node or any of its parents were removed and clean() wasn't called since.

NodeHandle Magnum::Ui::AbstractUserInterface::currentFocusedNode() const

Node focused by last pointer or focus event.

Returns handle of a NodeFlag::Focusable node that was under the pointer for the last pointerPressEvent() or for which focusEvent() was called and at least one data attached to such node accepted the AbstractLayer::focusEvent(). Once the node becomes hidden (either due to NodeFlag::Hidden set or due to the node hierarchy not being in the top-level node order), NodeFlag::NoEvents or NodeFlag::Disabled is set on it or it loses NodeFlag::Focusable, the data receive AbstractLayer::blurEvent() and this becomes NodeHandle::Null. It's also NodeHandle::Null if no node was focused yet or if the node or any of its parents were removed or hidden and update() was called since.

The returned handle may be invalid if the node or any of its parents were removed and clean() wasn't called since.

Containers::Optional<Vector2> Magnum::Ui::AbstractUserInterface::currentGlobalPointerPosition() const

Position of last pointer event.

Returns a position passed to the last primary pointerPressEvent(), pointerReleaseEvent() or pointerMoveEvent(), scaled to match size() instead of windowSize(). If no primary pointer event happened yet, returns Containers::NullOpt.

AbstractRenderer& Magnum::Ui::AbstractUserInterface::setRendererInstance(Containers::Pointer<AbstractRenderer>&& instance)

Set renderer instance.

Expects that the instance hasn't been set yet. A renderer instance has to be set in order to draw anything, it's the user responsibility to ensure that the GPU API used by the renderer matches the GPU API used by all layer instances, such as RendererGL being used for BaseLayerGL and TextLayerGL. The instance is subsequently available through renderer().

If framebuffer size was set with setSize() already, calling this function causes AbstractRenderer::setupFramebuffers() to be called. Otherwise the setup gets performed in the next setSize() call.

template<class T>
T& Magnum::Ui::AbstractUserInterface::setRendererInstance(Containers::Pointer<T>&& instance)

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

bool Magnum::Ui::AbstractUserInterface::hasRenderer() const

Whether a renderer instance has been set.

AbstractRenderer& Magnum::Ui::AbstractUserInterface::renderer()

Renderer instance.

Expects that setRendererInstance() was called.

const AbstractRenderer& Magnum::Ui::AbstractUserInterface::renderer() const

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

template<class T>
T& Magnum::Ui::AbstractUserInterface::renderer()

Renderer instance in a concrete type.

Expected that setRendererInstance() was called. It's the user responsibility to ensure that T matches the actual instance type.

template<class T>
const T& Magnum::Ui::AbstractUserInterface::renderer() const

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

std::size_t Magnum::Ui::AbstractUserInterface::layerCapacity() const

Capacity of the layer storage.

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

std::size_t Magnum::Ui::AbstractUserInterface::layerUsedCount() const

Count of used items in the layer storage.

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

bool Magnum::Ui::AbstractUserInterface::isHandleValid(LayerHandle handle) const

Whether a layer handle is valid.

A handle is valid if it has been returned from createLayer() before and removeLayer() wasn't called on it yet. Note that a handle is valid even if the layer instance wasn't set with setLayerInstance() yet. For LayerHandle::Null always returns false.

bool Magnum::Ui::AbstractUserInterface::isHandleValid(DataHandle handle) const

Whether a data handle is valid.

A shorthand for extracting a LayerHandle from handle using dataHandleLayer(), calling isHandleValid(LayerHandle) const on it, if it's valid and set then retrieving the particular layer instance using layer() and then calling AbstractLayer::isHandleValid(LayerDataHandle) const with a LayerDataHandle extracted from handle using dataHandleData(). See these functions for more information. For DataHandle::Null, LayerHandle::Null or LayerDataHandle::Null always returns false.

LayerHandle Magnum::Ui::AbstractUserInterface::layerFirst() const

First layer in draw and event processing order.

The first layer gets drawn first (thus is at the back) and reacts to events after all others. Returns LayerHandle::Null if there's no layers yet. The returned handle is always either valid or null.

LayerHandle Magnum::Ui::AbstractUserInterface::layerLast() const

Last layer in draw and event processing order.

The last layer gets drawn last (thus is at the front) and reacts to event before all others. Returns LayerHandle::Null if there's no layers yet. The returned handle is always either valid or null.

LayerHandle Magnum::Ui::AbstractUserInterface::layerPrevious(LayerHandle handle) const

Previous layer in draw and event processing order.

The previous layer gets drawn earlier (thus is behind) and reacts to events later. Expects that handle is valid. Returns LayerHandle::Null if the layer is first. The returned handle is always either valid or null.

LayerHandle Magnum::Ui::AbstractUserInterface::layerNext(LayerHandle handle) const

Next layer in draw and event processing order.

The next layer gets drawn later (thus is in front) and reacts to events earlier. Expects that handle is valid. Returns LayerHandle::Null if the layer is last. The returned handle is always either valid or null.

LayerHandle Magnum::Ui::AbstractUserInterface::createLayer(LayerHandle before = LayerHandle::Null)

Create a layer.

Parameters
before A layer to order before for draw and event processing or LayerHandle::Null if ordered as last (i.e., at the front, being drawn last and receiving events first). Expected to be valid if not null.
Returns New layer 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 256 layers. The returned handle is meant to be used to construct an AbstractLayer subclass and the instance then passed to setLayerInstance(). A layer can be removed again with removeLayer().

AbstractLayer& Magnum::Ui::AbstractUserInterface::setLayerInstance(Containers::Pointer<AbstractLayer>&& instance)

Set a layer instance.

Returns Reference to instance

Expects that instance was created with a LayerHandle returned from createLayer() earlier, the handle is valid and setLayerInstance() wasn't called for the same handle yet.

Calls AbstractLayer::setSize() on the layer, unless neither setSize() nor AbstractUserInterface(const Vector2&, const Vector2&, const Vector2i&) was called yet.

template<class T>
T& Magnum::Ui::AbstractUserInterface::setLayerInstance(Containers::Pointer<T>&& instance)

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

AbstractLayer& Magnum::Ui::AbstractUserInterface::layer(LayerHandle handle)

Layer instance.

Expects that handle is valid and that setLayerInstance() was called for it.

const AbstractLayer& Magnum::Ui::AbstractUserInterface::layer(LayerHandle handle) const

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

template<class T>
T& Magnum::Ui::AbstractUserInterface::layer(LayerHandle handle)

Layer instance in a concrete type.

Expects that handle is valid and that setLayerInstance() was called for it. It's the user responsibility to ensure that T matches the actual instance type.

template<class T>
const T& Magnum::Ui::AbstractUserInterface::layer(LayerHandle handle) const

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

void Magnum::Ui::AbstractUserInterface::removeLayer(LayerHandle handle)

Remove a layer.

Expects that handle is valid. After this call, isHandleValid(LayerHandle) const returns false for handle and isHandleValid(DataHandle) const returns false for all data associated with handle.

Animators with AnimatorFeature::DataAttachment that were associated with this layers are kept, but are excluded from any further processing in clean() or advanceAnimations(). Calling removeAnimator() on these is left to the user.

Calling this function causes UserInterfaceState::NeedsDataAttachmentUpdate to be set.

void Magnum::Ui::AbstractUserInterface::attachData(NodeHandle node, DataHandle data)

Attach data to a node.

A shorthand for extracting a LayerHandle from data using dataHandleLayer(), retrieving the particular layer instance using layer() and then calling AbstractLayer::attach(LayerDataHandle, NodeHandle) with a LayerDataHandle extracted with dataHandleData(). See these functions for more information. In addition to AbstractLayer::attach(LayerDataHandle, NodeHandle), this function checks that node is either valid or NodeHandle::Null.

Calling this function transitively causes UserInterfaceState::NeedsDataAttachmentUpdate to be set, which is a consequence of LayerState::NeedsAttachmentUpdate being set by AbstractLayer::attach().

std::size_t Magnum::Ui::AbstractUserInterface::layouterCapacity() const

Capacity of the layouter storage.

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

std::size_t Magnum::Ui::AbstractUserInterface::layouterUsedCount() const

Count of used items in the layouter storage.

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

bool Magnum::Ui::AbstractUserInterface::isHandleValid(LayouterHandle handle) const

Whether a layouter handle is valid.

A handle is valid if it has been returned from createLayouter() before and removeLayouter() wasn't called on it yet. Note that a handle is valid even if the layouter instance wasn't set with setLayouterInstance() yet. For LayouterHandle::Null always returns false.

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

Whether a layout handle is valid.

A shorthand for extracting a LayouterHandle from handle using layoutHandleLayouter(), calling isHandleValid(LayouterHandle) const on it, if it's valid and set then retrieving the particular layouter instance using layouter() and then calling AbstractLayouter::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.

LayouterHandle Magnum::Ui::AbstractUserInterface::layouterFirst() const

First layouter in the layout calculation order.

This layouter gets executed before all others. Returns LayouterHandle::Null if there's no layouters. The returned handle is always either valid or null.

LayouterHandle Magnum::Ui::AbstractUserInterface::layouterLast() const

Last layouter in the layout calculation order.

This layouter gets executed after all others. Returns LayouterHandle::Null if there's no layouters. The returned handle is always either valid or null.

LayouterHandle Magnum::Ui::AbstractUserInterface::layouterPrevious(LayouterHandle handle) const

Previous layouter in the layout calculation order.

The previous layouter gets executed earlier. Expects that handle is valid. Returns LayouterHandle::Null if the layouter is first. The returned handle is always either valid or null.

LayouterHandle Magnum::Ui::AbstractUserInterface::layouterNext(LayouterHandle handle) const

Next layouter in the layout calculation order.

The next layouter gets executed later. Expects that handle is valid. Returns LayouterHandle::Null if the layouter is last. The returned handle is always either valid or null.

LayouterHandle Magnum::Ui::AbstractUserInterface::createLayouter(LayouterHandle before = LayouterHandle::Null)

Create a layouter.

Parameters
before A layouter to order before for layout calculation or LayouterHandle::Null if ordered as last. Expected to be valid if not null.
Returns New layouter 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 256 layouters. The returned handle is meant to be used to construct an AbstractLayouter subclass and the instance then passed to setLayouterInstance(). A layouter can be removed again with removeLayer().

AbstractLayouter& Magnum::Ui::AbstractUserInterface::setLayouterInstance(Containers::Pointer<AbstractLayouter>&& instance)

Set a layouter instance.

Returns Reference to instance

Expects that instance was created with a LayouterHandle returned from createLayouter() earlier, the handle is valid and setLayouterInstance() wasn't called for the same handle yet.

Calls AbstractLayouter::setSize() on the layouter, unless neither setSize() nor AbstractUserInterface(const Vector2&, const Vector2&, const Vector2i&) was called yet.

template<class T>
T& Magnum::Ui::AbstractUserInterface::setLayouterInstance(Containers::Pointer<T>&& instance)

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

AbstractLayouter& Magnum::Ui::AbstractUserInterface::layouter(LayouterHandle handle)

Layouter instance.

Expects that handle is valid and that setLayouterInstance() was called for it.

const AbstractLayouter& Magnum::Ui::AbstractUserInterface::layouter(LayouterHandle handle) const

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

template<class T>
T& Magnum::Ui::AbstractUserInterface::layouter(LayouterHandle handle)

Layouter instance in a concrete type.

Expects that handle is valid and that setLayouterInstance() was called for it. It's the user responsibility to ensure that T matches the actual instance type.

template<class T>
const T& Magnum::Ui::AbstractUserInterface::layouter(LayouterHandle handle) const

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

void Magnum::Ui::AbstractUserInterface::removeLayouter(LayouterHandle handle)

Remove a layouter.

Expects that handle is valid. After this call, isHandleValid(LayouterHandle) const returns false for handle and isHandleValid(LayoutHandle) const returns false for all layouts associated with handle.

Calling this function causes UserInterfaceState::NeedsLayoutAssignmentUpdate to be set.

std::size_t Magnum::Ui::AbstractUserInterface::animatorCapacity() const

Capacity of the animator storage.

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

std::size_t Magnum::Ui::AbstractUserInterface::animatorUsedCount() const

Count of used items in the animator storage.

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

bool Magnum::Ui::AbstractUserInterface::isHandleValid(AnimatorHandle handle) const

Whether an animator handle is valid.

A handle is valid if it has been returned from createAnimator() before and removeAnimator() wasn't called on it yet. Note that a handle is valid even if the animator instance wasn't set with setGenericAnimatorInstance(), setNodeAnimatorInstance(), setDataAnimatorInstance() or setStyleAnimatorInstance() yet. For AnimatorHandle::Null always returns false.

bool Magnum::Ui::AbstractUserInterface::isHandleValid(AnimationHandle handle) const

Whether an animation handle is valid.

A shorthand for extracting an AnimatorHandle from handle using animationHandleAnimator(), calling isHandleValid(AnimatorHandle) const on it, if it's valid and set then retrieving the particular animator instance using animator() and then calling AbstractAnimator::isHandleValid(AnimatorDataHandle) const with an AnimatorDataHandle extracted from handle using animationHandleData(). See these functions for more information. For AnimationHandle::Null, AnimatorHandle::Null or AnimatorDataHandle::Null always returns false.

AnimatorHandle Magnum::Ui::AbstractUserInterface::createAnimator()

Create an animator.

Returns New animator 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 256 animators. The returned handle is meant to be used to construct an AbstractAnimator subclass and the instance then passed to setGenericAnimatorInstance(), setNodeAnimatorInstance(), setDataAnimatorInstance() or setStyleAnimatorInstance(). An animator can be removed again with removeAnimator().

AbstractGenericAnimator& Magnum::Ui::AbstractUserInterface::setGenericAnimatorInstance(Containers::Pointer<AbstractGenericAnimator>&& instance)

Set a generic animator instance.

Returns Reference to instance

Expects that instance was created with an AnimatorHandle returned from createAnimator() earlier, the handle is valid and none of setGenericAnimatorInstance(), setNodeAnimatorInstance(), setDataAnimatorInstance() or setStyleAnimatorInstance() was called for the same handle yet. Additionally, if AnimatorFeature::DataAttachment is supported by instance, expects that AbstractGenericAnimator::setLayer() has already been called on it.

Internally, the instance is inserted into a list partitioned by animator type, which is done with a $ \mathcal{O}(n) $ complexity where $ n $ is animatorCapacity().

template<class T>
T& Magnum::Ui::AbstractUserInterface::setGenericAnimatorInstance(Containers::Pointer<T>&& instance)

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

AbstractNodeAnimator& Magnum::Ui::AbstractUserInterface::setNodeAnimatorInstance(Containers::Pointer<AbstractNodeAnimator>&& instance)

Set a node animator instance.

Returns Reference to instance

Expects that instance was created with an AnimatorHandle returned from createAnimator() earlier, the handle is valid and none of setGenericAnimatorInstance(), setNodeAnimatorInstance(), setDataAnimatorInstance() or setStyleAnimatorInstance() was called for the same handle yet. The AbstractNodeAnimator is expected to advertise AnimatorFeature::NodeAttachment.

Internally, the instance is inserted into a list partitioned by animator type, which is done with a $ \mathcal{O}(n) $ complexity where $ n $ is animatorCapacity().

template<class T>
T& Magnum::Ui::AbstractUserInterface::setNodeAnimatorInstance(Containers::Pointer<T>&& instance)

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

AbstractDataAnimator& Magnum::Ui::AbstractUserInterface::setDataAnimatorInstance(Containers::Pointer<AbstractDataAnimator>&& instance)

Set a data animator instance.

Returns Reference to instance

Expects that instance was created with an AnimatorHandle returned from createAnimator() earlier, the handle is valid and none of setGenericAnimatorInstance(), setNodeAnimatorInstance(), setDataAnimatorInstance() or setStyleAnimatorInstance() was called for the same handle yet. The AbstractDataAnimator is expected to advertise AnimatorFeature::DataAttachment and it's expected that AbstractLayer::assignAnimator(AbstractDataAnimator&) const has already been called for it.

Internally, the instance is inserted into a list partitioned by animator type, which is done with a $ \mathcal{O}(n) $ complexity where $ n $ is animatorCapacity().

template<class T>
T& Magnum::Ui::AbstractUserInterface::setDataAnimatorInstance(Containers::Pointer<T>&& instance)

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

AbstractStyleAnimator& Magnum::Ui::AbstractUserInterface::setStyleAnimatorInstance(Containers::Pointer<AbstractStyleAnimator>&& instance)

Set a style animator instance.

Returns Reference to instance

Expects that instance was created with an AnimatorHandle returned from createAnimator() earlier, the handle is valid and none of setGenericAnimatorInstance(), setNodeAnimatorInstance(), setDataAnimatorInstance() or setStyleAnimatorInstance() was called for the same handle yet. The AbstractStyleAnimator is expected to advertise AnimatorFeature::DataAttachment and it's expected that AbstractLayer::assignAnimator(AbstractStyleAnimator&) const has already been called for it.

Internally, the instance is inserted into a list partitioned by animator type, which is done with a $ \mathcal{O}(n) $ complexity where $ n $ is animatorCapacity().

template<class T>
T& Magnum::Ui::AbstractUserInterface::setStyleAnimatorInstance(Containers::Pointer<T>&& instance)

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

AbstractAnimator& Magnum::Ui::AbstractUserInterface::animator(AnimatorHandle handle)

Animator instance.

Expects that handle is valid and that one of setGenericAnimatorInstance(), setNodeAnimatorInstance(), setDataAnimatorInstance() or setStyleAnimatorInstance() was called for it.

const AbstractAnimator& Magnum::Ui::AbstractUserInterface::animator(AnimatorHandle handle) const

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

template<class T>
T& Magnum::Ui::AbstractUserInterface::animator(AnimatorHandle handle)

Animator instance in a concrete type.

Expects that handle is valid and that one of setGenericAnimatorInstance(), setNodeAnimatorInstance(), setDataAnimatorInstance() or setStyleAnimatorInstance() was called for it. It's the user responsibility to ensure that T matches the actual instance type.

template<class T>
const T& Magnum::Ui::AbstractUserInterface::animator(AnimatorHandle handle) const

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

void Magnum::Ui::AbstractUserInterface::removeAnimator(AnimatorHandle handle)

Remove an animator.

Expects that handle is valid. After this call, isHandleValid(AnimatorHandle) const returns false for handle and isHandleValid(AnimationHandle) const returns false for all animations associated with handle.

Internally, if the removed animator had an instance set, the instance is removed from a list partitioned by animator type, which is done with a $ \mathcal{O}(n) $ complexity where $ n $ is animatorCapacity().

void Magnum::Ui::AbstractUserInterface::attachAnimation(NodeHandle node, AnimationHandle animation)

Attach an animation to a node.

A shorthand for extracting a AnimatorHandle from animation using animationHandleAnimator(), retrieving the particular animator instance using animator() and then calling AbstractAnimator::attach(AnimatorDataHandle, NodeHandle) with a AnimatorDataHandle extracted with animationHandleData(). See these functions for more information. In addition to AbstractAnimator::attach(AnimatorDataHandle, NodeHandle), this function checks that node is either valid or NodeHandle::Null.

void Magnum::Ui::AbstractUserInterface::attachAnimation(DataHandle data, AnimationHandle animation)

Attach an animation to a data.

A shorthand for extracting a AnimatorHandle from animation using animationHandleAnimator(), retrieving the particular animator instance using animator() and then calling AbstractAnimator::attach(AnimatorDataHandle, DataHandle) with a AnimatorDataHandle extracted with animationHandleData(). See these functions for more information. In addition to AbstractAnimator::attach(AnimatorDataHandle, DataHandle), this function checks that data is either valid with the layer portion matching AbstractAnimator::layer() of given animator or DataHandle::Null.

Note that unlike AbstractAnimator::attach(AnimationHandle, LayerDataHandle), here's no convenience function that would take a LayerDataHandle as it wouldn't be able to provide any extra checks over calling the AbstractAnimator API directly.

std::size_t Magnum::Ui::AbstractUserInterface::nodeCapacity() const

Current capacity of the node storage.

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

std::size_t Magnum::Ui::AbstractUserInterface::nodeUsedCount() const

Count of used items in the node storage.

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

bool Magnum::Ui::AbstractUserInterface::isHandleValid(NodeHandle handle) const

Whether a node handle is valid.

A handle is valid if it has been returned from createNode() before, removeNode() wasn't called on it yet and it wasn't removed inside update() due to a parent node being removed earlier. For NodeHandle::Null always returns false.

NodeHandle Magnum::Ui::AbstractUserInterface::createNode(NodeHandle parent, const Vector2& offset, const Vector2& size, NodeFlags flags = {})

Create a node.

Parameters
parent Parent node to attach to or NodeHandle::Null for a new root node. Expected to be valid if not null.
offset Offset relative to the parent node
size Size of the node contents. Used for layouting, clipping and event handling.
flags Initial node flags
Returns New node 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 nodes. The returned handle can be then removed again with removeNode().

If parent is NodeHandle::Null, the node is added at the back of the draw and event processing list, i.e. drawn last (thus at the front) and reacting to events before all others. Use setNodeOrder() and clearNodeOrder() to adjust the draw and event processing order or remove it from the list of visible top-level nodes.

Calling this function causes UserInterfaceState::NeedsNodeUpdate to be set.

NodeHandle Magnum::Ui::AbstractUserInterface::createNode(const Vector2& offset, const Vector2& size, NodeFlags flags = {})

Create a root node.

Equivalent to calling createNode(NodeHandle, const Vector2&, const Vector2&, NodeFlags) with NodeHandle::Null as the parent.

NodeHandle Magnum::Ui::AbstractUserInterface::nodeParent(NodeHandle handle) const

Node parent.

Expects that handle is valid. Returns NodeHandle::Null if it's a root node. Note that the returned handle may be invalid if removeNode() was called on one of the parent nodes and update() hasn't been called since.

Unlike other node properties, the parent cannot be changed after creation.

Vector2 Magnum::Ui::AbstractUserInterface::nodeOffset(NodeHandle handle) const

Node offset relative to its parent.

The returned value is before any layout calculation is done. Expects that handle is valid.

void Magnum::Ui::AbstractUserInterface::setNodeOffset(NodeHandle handle, const Vector2& offset)

Set node offset relative to its parent.

The value is subsequently used for layout calculation. Expects that handle is valid.

Calling this function causes UserInterfaceState::NeedsLayoutUpdate to be set.

Vector2 Magnum::Ui::AbstractUserInterface::nodeSize(NodeHandle handle) const

Node size.

The returned value is before any layout calculation is done. Expects that handle is valid.

void Magnum::Ui::AbstractUserInterface::setNodeSize(NodeHandle handle, const Vector2& size)

Set node size.

The value is subsequently used for layout calculation. Expects that handle is valid.

Calling this function causes UserInterfaceState::NeedsLayoutUpdate to be set.

NodeFlags Magnum::Ui::AbstractUserInterface::nodeFlags(NodeHandle handle) const

Node flags.

Expects that handle is valid.

void Magnum::Ui::AbstractUserInterface::setNodeFlags(NodeHandle handle, NodeFlags flags)

Set node flags.

Expects that handle is valid.

If NodeFlag::Hidden was added or cleared by calling this function, it causes UserInterfaceState::NeedsNodeUpdate to be set. If NodeFlag::Clip was added or cleared by calling this function, it causes UserInterfaceState::NeedsNodeClipUpdate to be set. If NodeFlag::NoEvents, NodeFlag::Disabled or NodeFlag::Focusable was added or cleared by calling this function, it causes UserInterfaceState::NeedsNodeEnabledUpdate to be set.

void Magnum::Ui::AbstractUserInterface::addNodeFlags(NodeHandle handle, NodeFlags flags)

Add node flags.

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

void Magnum::Ui::AbstractUserInterface::clearNodeFlags(NodeHandle handle, NodeFlags flags)

Clear node flags.

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

void Magnum::Ui::AbstractUserInterface::removeNode(NodeHandle handle)

Remove a node.

Expects that handle is valid. Nested nodes and data attached to any of the nodes are then removed during the next call to update(). After this call, isHandleValid(NodeHandle) const returns false for handle.

If handle is a top-level node, the operation is done with an $ \mathcal{O}(n) $ complexity, where $ n $ is the count of nested top-level hierarchies.

Calling this function causes UserInterfaceState::NeedsNodeClean to be set.

std::size_t Magnum::Ui::AbstractUserInterface::nodeOrderCapacity() const

Capacity of the top-level node order storage.

nodeOrderUsedCount()

std::size_t Magnum::Ui::AbstractUserInterface::nodeOrderUsedCount() const

Count of used items in the top-level node order storage.

Always at most nodeOrderCapacity(). The operation is done with a $ \mathcal{O}(n) $ complexity where $ n $ is nodeOrderCapacity(). When a root node is created or setNodeOrder() is called for the first time on a non-root node, a slot in the node order storage is used for it, and gets recycled only when the node is removed again or when flattenNodeOrder() is called on a non-root node.

NodeHandle Magnum::Ui::AbstractUserInterface::nodeOrderFirst() const

First top-level node in draw and event processing order.

The first node gets drawn first (thus is at the back) and reacts to events after all others. Returns NodeHandle::Null if there's no nodes included in the draw and event processing order. The returned handle is always either valid or null.

NodeHandle Magnum::Ui::AbstractUserInterface::nodeOrderLast() const

Last top-level node in draw and event processing order.

The last node gets drawn last (thus is at the front) and reacts to events before all others. Returns NodeHandle::Null if there's no nodes included in the draw and event processing order. The returned handle is always either valid or null.

bool Magnum::Ui::AbstractUserInterface::isNodeTopLevel(NodeHandle handle) const

Whether a node is top-level for draw and event processing.

If not top-level, it's in the usual order defined by the node hierarchy. If top-level, it's ordered respective to other top-level nodes. Expects that handle is valid.

Always returns true for root nodes. If isNodeOrdered() returns true, it implies the node is top-level. If this function returns true, it doesn't necessarily mean the node is visible — the node or any of its parents could be excluded from the order or it could be hidden.

bool Magnum::Ui::AbstractUserInterface::isNodeOrdered(NodeHandle handle) const

Whether a node is top-level and is included in a draw and event processing order.

If not included, the node and all its children are not drawn and don't react to events. Expects that handle is valid.

If this function returns true, isNodeTopLevel() is true as well. For non-root nodes the function returning true means the node is included in the order respective to its parent top-level node. It doesn't necessarily mean the node is visible — the parents can themselves be excluded from the order or they could be hidden.

NodeHandle Magnum::Ui::AbstractUserInterface::nodeOrderPrevious(NodeHandle handle) const

Previous node in draw and event processing order.

The previous node gets drawn earlier (thus is behind) and reacts to events later. Expects that handle is valid. Returns NodeHandle::Null if the node is first in the draw and processing order, is a root node that's not included in the draw and event processing order, or is a non-root node that's drawn in a regular hierarchy-defined order. The returned handle is always either valid or null.

NodeHandle Magnum::Ui::AbstractUserInterface::nodeOrderNext(NodeHandle handle) const

Next node in draw and event processing order.

The next node gets drawn later (thus is in front) and reacts to events earlier. Expects that handle is valid. Returns NodeHandle::Null if the node is last in the draw and processing order, is a root node that's not included in the draw and event processing order, or is a non-root node that's drawn in a regular hierarchy-defined order. The returned handle is always either valid or null.

NodeHandle Magnum::Ui::AbstractUserInterface::nodeOrderLastNested(NodeHandle handle) const

Last node in draw and event processing order nested under this node.

Expects that handle is valid. If any children are top-level nodes as well, points to the last of them, including any nested top-level hierarchies. If there are no child top-level hierarchies, returns handle itself.

The order of child top-level hierarchies relative to the handle gets preserved when modifying the top-level order of handle using setNodeOrder() or clearNodeOrder().

void Magnum::Ui::AbstractUserInterface::setNodeOrder(NodeHandle handle, NodeHandle before)

Order a top-level node for draw and event processing.

The handle gets ordered to be drawn earlier (thus behind) and react to event later than before. Expects that handle is valid and before is either NodeHandle::Null or a valid node that's included in the draw and event processing order.

If handle is a root node, expects that before is also a root node, if not null. If null, the handle is ordered as drawn last. The operation is done with an $ \mathcal{O}(1) $ complexity in this case.

If handle is not a root node, expects that both handle and before have a common parent that's the closest top-level or root node for both, if before is not null. If null, the handle is ordered after all other top-level nodes under its closest top-level or root parent. NodeFlag::Hidden set on any parent node affects the top-level node, NodeFlag::Clip, NoEvents or Disabled doesn't. The operation is done with an $ \mathcal{O}(n) $ complexity in this case, where $ n $ is the depth at which handle is in the node hierarchy.

If the node was previously in a different position in the draw and event processing order, it's moved, if it wasn't previously a top-level node or if it wasn't included in the draw and event processing order, it's inserted. Use clearNodeOrder() to exclude the node from the order afterwards and flattenNodeOrder() to integrate a non-root node back into the usual order defined by the node hierarchy.

Calling this function causes UserInterfaceState::NeedsNodeUpdate to be set.

void Magnum::Ui::AbstractUserInterface::clearNodeOrder(NodeHandle handle)

Clear a node from the draw and event processing order.

Expects that handle is valid. If the node isn't top-level or wasn't previously in the draw and processing order, the function is a no-op. After calling this function, isNodeOrdered() returns false for handle.

If handle is a root node, the operation is done with an $ \mathcal{O}(1) $ complexity. If handle is not a root node, the operation is done with an $ \mathcal{O}(n) $ complexity, where $ n $ is the depth at which handle is in the node hierarchy.

If the node contains any child top-level hierarchies, their order relative to the handle gets preserved, i.e. they get inserted back alongside it next time setNodeOrder() is called. Use flattenNodeOrder() to integrate a non-root node back into the usual order defined by the node hierarchy.

If not a no-op, calling this function causes UserInterfaceState::NeedsNodeUpdate to be set.

void Magnum::Ui::AbstractUserInterface::flattenNodeOrder(NodeHandle handle)

Flatten a non-root top-level node back to the usual order defined by the node hierarchy.

Expects that handle is valid and isn't a root node. Undoes the operation done by calling setNodeOrder() on a non-root node, i.e. the node is again drawn alongside its neighbors. If the node isn't top-level, the function is a no-op. After calling this function, isNodeTopLevel() returns false for handle.

The operation is done with an $ \mathcal{O}(n) $ complexity, where $ n $ is the depth at which handle is in the node hierarchy.

If the node contains nested top-level nodes, they stay top-level. Use clearNodeOrder() if you want to exclude a top-level node including all its children from the draw and event processing order.

If not a no-op, calling this function causes UserInterfaceState::NeedsNodeUpdate to be set.