class new in Git master
#include <Magnum/Ui/AbstractUserInterface.h>
AbstractUserInterface Base implementation of the main user interface.
Owns the whole user interface, providing everything from input event handling to animation and drawing.
Setting up a user interface instance
Unless you're building a UI fully consisting of custom widgets, you'll want to instantiate the user interface through the UserInterfaceGL subclass, which by default includes everything that's needed by builtin widgets. The constructor takes a UI size, in respect to which all contents as well as input events get positioned, and a style instance describing how the widgets will look like. At the moment, McssDarkStyle is the only style provided by the library itself.
Ui::UserInterfaceGL ui{{800, 600}, Ui::McssDarkStyle{}};
Then, at the very least, the UI needs to be (re)drawn when needed. The renderer uses a premultiplied alpha workflow, so it expects an appropriate GL::
GL::Renderer::setBlendFunction( GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha);
The draw() function draws to the currently bound framebuffer, clearing is left upon the application so it can draw other contents underneath the UI. The actual enablement of blending and other state during a draw() is taken care of by a RendererGL instance internally.
GL::defaultFramebuffer.clear(GL::FramebufferClear::Color); … ui.draw();
For actual interactivity, the user interface needs to receive input events via pointerPressEvent(), pointerReleaseEvent(), pointerMoveEvent(), keyPressEvent(), keyReleaseEvent() and textInputEvent(). They take a PointerEvent, PointerMoveEvent, KeyEvent or TextInputEvent instances containing the actual event data such as the pointer or key being pressed, and in case of pointer events also a position at which the event happens. For example:
Ui::PointerEvent event{{}, Ui::PointerEventSource::Mouse, Ui::Pointer::MouseLeft, true, 0}; if(!ui.pointerPressEvent({123, 456}, event)) { // Not handled by the UI, pass further ... }
Integration with application libraries
Unless you're using a custom windowing toolkit, you'll likely want to make the UI drawing and event handling directly tied to a Platform::
… #include <Magnum/Ui/Application.h> class MyApplication: public Platform::Application { public: explicit MyApplication(const Arguments& arguments): Platform::Application{arguments}, _ui{*this, …} { … } void viewportEvent(ViewportEvent& event) override { _ui.setSize(event); } void drawEvent() override { GL::defaultFramebuffer.clear(GL::FramebufferClear::Color); _ui.draw(); swapBuffers(); if(_ui.state()) redraw(); } … private: Ui::UserInterfaceGL _ui; };
With the code below, events coming from the application 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, matching Platform::
void MyApplication::pointerPressEvent(PointerEvent& event) { if(!_ui.pointerPressEvent(event)) { … } if(_ui.state()) redraw(); } void MyApplication::pointerReleaseEvent(PointerEvent& event) { if(!_ui.pointerReleaseEvent(event)) { … } if(_ui.state()) redraw(); } void MyApplication::pointerMoveEvent(PointerMoveEvent& event) { if(!_ui.pointerMoveEvent(event)) { … } if(_ui.state()) redraw(); } void MyApplication::keyPressEvent(KeyEvent& event) { if(!_ui.keyPressEvent(event)) { … } if(_ui.state()) redraw(); } void MyApplication::keyReleaseEvent(KeyEvent& event) { if(!_ui.keyReleaseEvent(event)) { … } if(_ui.state()) redraw(); } void MyApplication::textInputEvent(TextInputEvent& event) { if(!_ui.textInputEvent(event)) { … } if(_ui.state()) redraw(); }
Note that in general the UI needing a redraw is unrelated to whether an event was accepted by it, so the checks are separate — for example a Home key press may be accepted by a text input, but if the cursor is already at the begin of the text, it doesn't cause any visual change and thus there's no need to redraw anything.
Handles and resource ownership
Unlike traditional UI toolkits, which commonly use pointer-like abstractions to reference data, all resources in the Ui library are referenced by handles, such as a NodeHandle or an AnimatorHandle. Much like a raw pointer, a handle is a trivially copyable type (an enum
in this case), but compared to a pointer it's not usable on its own. Getting the actual resource means passing the handle to a corresponding interface that actually owns given resource.
The handle consists of an index and a generation counter. Internally, the index points into a contiguous array (or several arrays) containing data for resources of given type. When a new resource is created, the handle gets an index of the next free item in that array; when it's removed, item at given index gets put back into a list of free items. Additionally, the generation counter gets incremented on every removal, which in turn causes existing handles pointing to the same index but with old generation counter to be treated as invalid.
Compared to pointers that can point basically anywhere, handles have several advantages. The contiguous array simplifies memory management and makes batch processing efficient, and the handle types can be only large enough to store the typical amount of data (for example NodeHandle is just 32 bits, AnimatorHandle just 16). The clear ownership model together with the generation counter then solves the problem of dangling references and resource leaks.
While in most cases you'll treat handles as opaque identifiers, it's possible to make use of the contiguous nature of their indices when storing any extra data associated with a particular handle type. For example, in case you'd want to name node handles, instead of creating a (hash)map with NodeHandle as a key, you can extract the handle index with nodeHandleId() and use a plain array instead:
struct Name { Containers::String name; UnsignedInt generation = 0; }; Containers::Array<Name> names; … void setNodeName(Ui::NodeHandle node, Containers::StringView name) { UnsignedInt id = Ui::nodeHandleId(node); if(id >= names.size()) arrayResize(names, id + 1); names[id].name = name; names[id].generation = Ui::nodeHandleGeneration(node); } Containers::StringView nodeName(Ui::NodeHandle node) { UnsignedInt id = Ui::nodeHandleId(node); if(id < names.size() && names[id].generation == Ui::nodeHandleGeneration(node)) return names[id].name; return {}; }
The above snippet also makes use of the handle generation, extracted with nodeHandleGeneration(), to ensure stale names aren't returned for handles that recycle a previously used index. The generation is remembered when setting the name, and it's compared against the handle when retrieving. If it doesn't match, it's the same as if the name wouldn't be present at all. The generation counter is 0
only for NodeHandle::Name
entries above aren't referring to valid nodes either.
Node hierarchy
At the core of the user interface, defining both the visuals and event propagation, is a hierarchy of nodes. A node is by itself just a rectangle defined by a size, an offset relative to its parent, opacity and a few behavior flags. Everything else — visuals, interactivity, layouting behavior, animation, persistent state — is handled by data, layouts and animations optionally attached to particular nodes. Those are explained further below.
A node is created using createNode() by passing an offset and size. You get a NodeHandle back, which can be then used to query and modify the node properties such as setNodeOffset() or setNodeSize().
Ui::NodeHandle panel = ui.createNode({50, 50}, {200, 150}); Ui::NodeHandle title = ui.createNode(panel, {10, 10}, {180, 20}); Ui::NodeHandle content = ui.createNode(panel, {10, 40}, {180, 100});
The first line creates a root node, which is positioned relatively to the UI itself. The other nodes then specify it as a parent, and are positioned relatively to it, so e.g. content
is at offset {60, 90}
. Besides positioning hierarchy, the parent/child relationship also has effect on lifetime. While a root node exists until removeNode() is called on it or until the end of the UI instance lifetime, child nodes additionally get removed if their parent is removed. Continuing from the above, if you remove the panel
, the title
and content
will get subsequently cleaned up as well. Currently, node parent is specified during creation and cannot be subsequently changed.
Node opacity
Node opacity, controlled with setNodeOpacity(), has similar nesting behavior as node offsets. By default, all nodes are fully opaque, and the opacity gets multiplied with the parent's. In the snippet below, the effective opacity of title
will be 0.6f
and content
will inherit the 0.8f
opacity from the panel
. This feature is mainly for convenient fade-in / fade-out of various parts of the UI without having to laboriously update each and every individual UI element.
ui.setNodeOpacity(panel, 0.8f); ui.setNodeOpacity(title, 0.75f);
Top-level node hierarchies and visibility order
A root node along with all its children — in this case panel
along with title
and contents
— is called a top-level node hierarchy. Each top-level node hierarchy is ordered relatively to other top-level hierarchies, allowing stacking of various UI elements such as dialogs, tooltips and menus. When a root node is created, it's by default put in front of all other top-level node hierarchies. Its order can be then adjusted using setNodeOrder() where the second argument is a top-level node behind which the node should be placed. Specifying NodeHandle::
Ui::NodeHandle anotherPanel = ui.createNode({200, 130}, {120, 80}); /* Put the new panel behind the first one, instead of being on top */ ui.setNodeOrder(anotherPanel, panel);
It's also possible to completely remove the hierarchy from the top-level node order with clearNodeOrder(). Doing so doesn't remove any nodes, just excludes then from the visible set, and calling setNodeOrder() with that top-level node puts it back into the visibility order. This is a useful alternative to recreating a short-lived popup many times over, for example.
ui.clearNodeOrder(panel); … /* Show the panel again, on top of everything else */ ui.setNodeOrder(panel, Ui::NodeHandle::Null);
In addition to the top-level node order, visibility is defined by the node hierarchy. Parents are always behind their children (so, from the snippet above, the panel
background will be visible underneath the title
and content
), however there's no order specified between siblings (i.e., one can't rely on title
being drawn before content
or vice versa). The assumption here is that majority of UIs are non-overlapping hierarchies for which such an ordering would be a costly extra step without significant benefits.
Nested top-level node hierarchies
Besides root nodes, nested nodes can be made top-level as well. They'll stay positioned relative to the parent node offset, which makes it convenient for placing various popups and tooltips next to UI elements they come from. As with root nodes, a nested node can be made top-level by calling setNodeOrder(), clearNodeOrder() then again excludes it from the visibility order.
/* Tooltip rectangle overlapping the title, shown on the top */ Ui::NodeHandle titleTooltip = ui.createNode(title, {105, 25}, {100, 20}); ui.setNodeOrder(titleTooltip, Ui::NodeHandle::Null); … /* Hide the tooltip when no longer meant to be visible */ ui.clearNodeOrder(titleTooltip);
Compared to root nodes, nested top-level nodes are tied to the node hierarchy they come from — in particular, they can be only ordered relative to other nested top-level nodes under the same top-level node hierarchy. Changing order of the enclosing top-level nodes then brings the nested top-level hierarchies along. In the above example, assuming the tooltip
wouldn't get hidden, raising the anotherPanel
in front of panel
would make it ordered in front of the tooltip
as well.
Top-level hierarchies, nested or otherwise, can be also used to circumvent the visibility order limitations in cases where UI elements actually end up overlapping each other. One such case might be drag & drop, or various list reordering animations. Affected node sub-hierarchy can be made top-level for the time it's being moved and when it's back in place, flattenNodeOrder() puts it back to the visibility order defined by the hierarchy.
Node behavior flags
Finally, nodes can have various flags set that affect their visibility and event handling behavior. By passing NodeFlag::
Visibility of individual nodes can be toggled with NodeFlag::
NodeFlag::
Event handling
Commonly, the UI is visible on top of any other content in the application (such as a game, or a model / image in case of an editor or viewer) and so the expectations is that input events should go to the UI first, as shown in the snippets above. The event handler then returns true
if the event was consumed by the UI (such as a button being pressed by a pointer, or a key press causing an action on a focused input), false
if not and it should fall through to the rest of the application or to the OS, browser etc.
void MyApplication::pointerMoveEvent(PointerMoveEvent& event) { if(_ui.pointerMoveEvent(event)) return; if(_modelLoaded && event.pointers()) { rotateModel(event.relativePosition()); event.setAccepted(); return; } /* Otherwise propagating the event to the OS */ }
Node hierarchy event propagation
Inside the UI, pointer and position-dependent key events are directed to concrete nodes based on their position. Top-level nodes get iterated in a front-to-back order, and if the (appropriately scaled) event position is within the rectangle of any of those, it recurses into given hierarchy, checking the position against a rectangle of each child. The search continues until a leaf node under given position is found, to which the event is directed. If given event is accepted on that node via PointerEvent::
If the event is accepted on any node, that particular event function returns true
. If it isn't accepted on any node, or if there isn't any node at given position in the first place, false
is returned.
Pointer capture, pressed and hovered node tracking
Especially with touch input where the aiming precision is rather coarse, it commonly happens that the finger moves between a tap press and a release, sometimes even outside of the tapped element. Another similar is when a mouse cursor gets dragged outside of the narrow area of a scrollbar. In such cases it would be annoying if the UI would cancel the action or, worse, performed some other action entirely, and that's what pointer capture is designed to solve.
When a node press happens as a result of pointerPressEvent(), the node gets remembered. By default that enables pointer capture, so if a pointerMoveEvent() then drags the pointer outside, the events are still sent to the original node (marked as A in the above diagram), and A is still considered to be pressed, but not hovered. In comparison, with capture disabled, a drag outside would lose the pressed state, and the events would be sent to whatever other node is underneath (marked as B above), and said to be hovered on that node instead. Note that B isn't considered to be pressed in that case in order to distinguish drags that originated on given node from drags that originated outside.
When the (still pressed) pointer returns to A, in the captured case it's the same as if it would never leave. A release from a pointerReleaseEvent() could then generate a tap or click in given event handler, for example. With capture disabled, a tap or click would happen only if the pointer would never leave. Ultimately, pointer release implicitly removes the capture again.
All this state is exposed via PointerEvent::
While pointer capture is a good default, in certain use cases such as drag & drop it's desirable to know the node the pointer is being dragged to instead of the events being always sent to the originating node. For that, the press and move event handlers can toggle the capture using PointerEvent::
Key and text input and node focus
By default, keyPressEvent() and keyReleaseEvent() is directed to a node under pointer, based on the location at which the last pointer event happened. This is useful for implementing workflows common in 2D/3D editing software, where simply hovering a particular UI element and pressing a key performs an action, without having to activate the element first by a click. As with pointer events, if KeyEvent::false
, signalling that the event should be propagated elsewhere.
Text editing however has usually a different workflow — clicking an input element makes it focused, after which it accepts keyboard input regardless of pointer position. Only nodes that are marked with NodeFlag::false
always.
Information about whether a node the event is called on is focused is available via KeyEvent::
Pointer event fallthrough
By default, a pointer event is directed only to a single node, either as a result of the hierarchy propagation, or because given node captures the event, and as soon as the event is accepted it's not sent to any other node.
Sometimes it's however desirable to have events fall through to outer nodes, for example to allow scrolling an area that's otherwise full of active elements. This can be achieved by marking given node with NodeFlag::true
.
The node can then either just observe the event without accepting, in which case the event outcome isn't any different compared to when the node isn't marked with NodeFlag::
Or, instead of observing, the fallthrough event can be accepted. Accepting the fallthrough event makes the node inherit the pressed, hovered and captured properties from the original one, and the original node gets a PointerCancelEvent in exchange. The fallthrough works across nested top-level nodes as well. Continuing from the event propagation example above and assuming the panel
node is marked as fallthrough, such as to implement a "pull down to refresh" behavior, the event handling could look like this:
It's possible for multiple nodes in a hierarchy chain to be marked with NodeFlag::
DPI awareness
If you use the application integration shown above, in particular the constructor and setSize() overloads taking an application instance, the UI is already made DPI-aware and no extra steps need to be done. Nevertheless, it may be useful to know what happens underneath. 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.
With the Platform::
Ui::UserInterfaceGL ui{ Vector2{windowSize()}/dpiScaling(), Vector2{windowSize()}, framebufferSize(), …};
Or, for example, to have the UI size derived from window size while gracefully dealing with extremely small or extremely large windows, you can apply Math::
Ui::UserInterfaceGL ui{ Math::clamp({640.0f, 360.0f}, {1920.0f, 1080.0f}, Vector2{windowSize()}/dpiScaling()), Vector2{windowSize()}, framebufferSize(), …};
Ultimately, if you want the UI to have the same size and just scale with bigger window sizes, pass a fixed value to the UI size:
Ui::UserInterfaceGL ui( {800, 600}, Vector2{windowSize()}, framebufferSize(), …);
With all variants above, the input events will still be dealt with correctly, being scaled from the window coordinates to the actual UI size.
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.
-
template<class Application, class = decltype(Implementation::ApplicationSizeConverter<Application>::set(std::AbstractUserInterface(const Application& application) explicit
declval<AbstractUserInterface&>(), std:: declval<const Application&>()))> - Construct with properties taken from an application instance.
- 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.
-
template<class ApplicationOrViewportEvent, class = decltype(Implementation::ApplicationSizeConverter<ApplicationOrViewportEvent>::set(std::auto setSize(const ApplicationOrViewportEvent& applicationOrViewportEvent) -> AbstractUserInterface&
declval<AbstractUserInterface&>(), std:: declval<const ApplicationOrViewportEvent&>()))> - Set user interface size from an application or a viewport event instance.
- 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::auto pointerPressEvent(Event& event, Args && ... args) -> bool
declval<AbstractUserInterface&>(), std:: declval<Event&>(), std:: declval<Args>()...))> - 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::auto pointerReleaseEvent(Event& event, Args && ... args) -> bool
declval<AbstractUserInterface&>(), std:: declval<Event&>(), std:: declval<Args>()...))> - 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::auto pointerMoveEvent(Event& event, Args && ... args) -> bool
declval<AbstractUserInterface&>(), std:: declval<Event&>(), std:: declval<Args>()...))> - 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::auto keyPressEvent(Event& event, Args && ... args) -> bool
declval<AbstractUserInterface&>(), std:: declval<Event&>(), std:: declval<Args>()...))> - 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::auto keyReleaseEvent(Event& event, Args && ... args) -> bool
declval<AbstractUserInterface&>(), std:: declval<Event&>(), std:: declval<Args>()...))> - 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::auto textInputEvent(Event& event, Args && ... args) -> bool
declval<AbstractUserInterface&>(), std:: declval<Event&>(), std:: declval<Args>()...))> - 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 nodeOpacity(NodeHandle handle) const -> Float
- Node opacity.
- void setNodeOpacity(NodeHandle handle, Float opacity)
- Set node opacity.
- 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 behind)
- 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.
template<class Application, class = decltype(Implementation::ApplicationSizeConverter<Application>::set(std:: declval<AbstractUserInterface&>(), std:: declval<const Application&>()))>
Magnum:: Ui:: AbstractUserInterface:: AbstractUserInterface(const Application& application) explicit
Construct with properties taken from an application instance.
Parameters | |
---|---|
application | Application instance to query properties from |
Equivalent to constructing with AbstractUserInterface(NoCreateT) and then calling setSize(const ApplicationOrViewportEvent&). 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::size
is passed through to AbstractLayouter::
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::size
changes, AbstractLayouter::size
changes and any nodes were already created, UserInterfaceState::
template<class ApplicationOrViewportEvent, class = decltype(Implementation::ApplicationSizeConverter<ApplicationOrViewportEvent>::set(std:: declval<AbstractUserInterface&>(), std:: declval<const ApplicationOrViewportEvent&>()))>
AbstractUserInterface& Magnum:: Ui:: AbstractUserInterface:: setSize(const ApplicationOrViewportEvent& applicationOrViewportEvent)
Set user interface size from an application or a viewport event instance.
Parameters | |
---|---|
applicationOrViewportEvent | Application or a viewport event instance to query properties from |
Delegates to setSize(const Vector2&, const Vector2&, const Vector2i&) using window size, framebuffer size and DPI scaling queried from the applicationOrViewportEvent
instance. See its documentation, Integration with application libraries and DPI awareness for more information.
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::
- Removes nodes with an invalid (removed) parent node
- Calls AbstractLayer::
cleanNodes() with updated node generations, causing removal of data attached to invalid nodes - Calls AbstractLayouter::
cleanNodes() with updated node generations, causing removal of layouts assigned to invalid nodes - Calls AbstractAnimator::
cleanNodes() on all animators supporting AnimatorFeature:: NodeAttachment with updated node generations, causing removal of animations attached to invalid nodes - For all layers marked with LayerState::
NeedsDataClean calls AbstractLayer:: cleanData() with all animators supporting AnimatorFeature:: DataAttachment associated with given layer, causing removal of animations attached to invalid data
After calling this function, state() doesn't contain UserInterfaceState::
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::
Calling this function updates animationTime(). Afterwards, state() may still contain UserInterfaceState::
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::
- Orders visible nodes back-to-front for drawing and front-to-back for event processing
- Orders layouts assigned to nodes by their dependency
- Performs layout calculation
- Calculates absolute offsets for visible nodes
- Culls invisible nodes, calculates clip rectangles
- Propagates NodeFlag::
Disabled and NodeFlag:: NoEvents to child nodes - Orders data attachments in each layer by draw order
- Resets currentPressedNode(), currentCapturedNode(), currentHoveredNode() or currentFocusedNode() if they no longer exist
- Calls AbstractLayer::
visibilityLostEvent() and resets currentPressedNode(), currentCapturedNode(), currentHoveredNode() or currentFocusedNode() if they are not visible or have NodeFlag:: NoEvents or NodeFlag:: Disabled set on them or their parents, or if the currently focused node is no longer NodeFlag:: Focusable. - Goes in a back to front order through layers that have instances set and calls AbstractLayer::
update() with the ordered data
After calling this function, state() is empty apart from UserInterfaceState::
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:
- Calls AbstractRenderer::
transition() with RendererTargetState:: Initial - Peforms draw calls by going through draws collected by update() for each top level node and all its visible children in a back to front order, and then for each layer that supports LayerFeature::
Draw in a back to front order: - If a layer advertises LayerFeature::
Composite, calls AbstractRenderer:: transition() with RendererTargetState:: Composite, and then AbstractLayer:: composite() - Calls AbstractRenderer::
transition() with RendererTargetState:: Draw and appropriate RendererDrawStates based on whether given layer advertises LayerFeature:: DrawUsesBlending or DrawUsesScissor - Calls AbstractLayer::
draw()
- If a layer advertises LayerFeature::
- Calls AbstractRenderer::
transition() with RendererTargetState:: Final
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, propagates it to nodes under (scaled) globalPosition
and calls AbstractLayer::
If the press happened with Pointer::
If the event is primary, the node that accepted the event is remembered as pressed. 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::
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.
After the above, if the event was accepted on any node or wasn't but is still captured on any node, it falls through upwards the parent hierarchy, calling AbstractLayer::true
and the isNodePressed(), isNodeHovered(), isNodeFocused() and isCaptured() properties inherited as described in Pointer event fallthrough. If any data accept the event, AbstractLayer::
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.
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(const Vector2&, PointerEvent&), 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::
Otherwise, if a node wasn't captured, propagates the event to nodes under (scaled) globalPosition
and calls AbstractLayer::
If the event is primary and a node is captured, the capture is implicitly released after calling this function independently of whether PointerEvent::
After the above, if the event was accepted on any node or wasn't but is still captured on any node, it falls through upwards the parent hierarchy, calling AbstractLayer::true
and the isNodePressed(), isNodeHovered(), isNodeFocused() and isCaptured() properties inherited as described in Pointer event fallthrough. If any data accept the event, AbstractLayer::
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.
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(const Vector2&, PointerEvent&), 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::event
except for PointerMoveEvent::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, propagates the event to nodes under (scaled) globalPosition
and calls AbstractLayer::event
except for PointerMoveEvent::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::
After the above, if the event was accepted on any node or wasn't but is still captured on any node, it falls through upwards the parent hierarchy, calling AbstractLayer::true
and the isNodePressed(), isNodeHovered(), isNodeFocused() and isCaptured() properties inherited as described in Pointer event fallthrough. If any data accept the event, AbstractLayer::
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.
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(const Vector2&, 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::
If node
is non-null and is or any of its parents are not visible either due to NodeFlag::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::node
. Then, if any of them accept the event, the node is set as currently focused, and AbstractLayer::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::node
and the current focused node is set to NodeHandle::
If node
is NodeHandle::
Returns true
if the AbstractLayer::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::
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::
Otherwise, if currentGlobalPointerPosition() is not Containers::
Returns true
if the event was accepted by at least one data; false
if it wasn't, if currentFocusedNode() is NodeHandle::
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(KeyEvent&), 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::
Otherwise, if currentGlobalPointerPosition() is not Containers::
Returns true
if the event was accepted by at least one data; false
if it wasn't, if currentFocusedNode() is NodeHandle::
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(KeyEvent&), 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::
Returns true
if the event was accepted by at least one data; false
if it wasn't or if currentFocusedNode() is NodeHandle::
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(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 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::
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::
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::
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::
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::
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::
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 complexity where 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::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::handle
using dataHandleData(). See these functions for more information. For DataHandle::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::
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::
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::
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::
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:: |
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::
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::
Calling this function causes UserInterfaceState::
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::node
is either valid or NodeHandle::
Calling this function transitively causes UserInterfaceState::
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 complexity where 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::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::handle
using layoutHandleData(). See these functions for more information. For LayoutHandle::false
.
LayouterHandle Magnum:: Ui:: AbstractUserInterface:: layouterFirst() const
First layouter in the layout calculation order.
This layouter gets executed before all others. Returns LayouterHandle::
LayouterHandle Magnum:: Ui:: AbstractUserInterface:: layouterLast() const
Last layouter in the layout calculation order.
This layouter gets executed after all others. Returns LayouterHandle::
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::
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::
LayouterHandle Magnum:: Ui:: AbstractUserInterface:: createLayouter(LayouterHandle before = LayouterHandle:: Null)
Create a layouter.
Parameters | |
---|---|
before | A layouter to order before for layout calculation or LayouterHandle:: |
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::
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::
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 complexity where 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::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::handle
using animationHandleData(). See these functions for more information. For AnimationHandle::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::instance
, expects that AbstractGenericAnimator::
Internally, the instance is inserted into a list partitioned by animator type, which is done with a complexity where 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::
Internally, the instance is inserted into a list partitioned by animator type, which is done with a complexity where 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::
Internally, the instance is inserted into a list partitioned by animator type, which is done with a complexity where 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::
Internally, the instance is inserted into a list partitioned by animator type, which is done with a complexity where 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 complexity where 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::node
is either valid or NodeHandle::
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::data
is either valid with the layer portion matching AbstractAnimator::
Note that unlike AbstractAnimator::
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 complexity where 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::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:: |
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::
Calling this function causes UserInterfaceState::
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::
NodeHandle Magnum:: Ui:: AbstractUserInterface:: nodeParent(NodeHandle handle) const
Node parent.
Expects that handle
is valid. Returns NodeHandle::
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. Absolute offset after all layout calculation is passed to AbstractLayer::
Expects that handle
is valid.
void Magnum:: Ui:: AbstractUserInterface:: setNodeOffset(NodeHandle handle,
const Vector2& offset)
Set node offset relative to its parent.
If the node has a layout assigned, the value is subsequently used for layout calculation and it's up to the particular layouter implementation how the initial offset value is used. If the node doesn't have a layout assigned, the offset is used as-is. Expects that handle
is valid. Initially, a node has the offset that was passed to createNode().
Calling this function causes UserInterfaceState::
Vector2 Magnum:: Ui:: AbstractUserInterface:: nodeSize(NodeHandle handle) const
Node size.
The returned value is before any layout calculation is done. Size after all layout calculations is available through PointerEvent::
Expects that handle
is valid.
void Magnum:: Ui:: AbstractUserInterface:: setNodeSize(NodeHandle handle,
const Vector2& size)
Set node size.
If the node has a layout assigned, the value is subsequently used for layout calculation and it's up to the particular layouter implementation how the initial size value is used. If the node doesn't have a layout assigned, the size is used as-is. Expects that handle
is valid. Initially, a node has the size that was passed to createNode().
Calling this function causes UserInterfaceState::
Float Magnum:: Ui:: AbstractUserInterface:: nodeOpacity(NodeHandle handle) const
Node opacity.
The returned value is only the opacity set on the node itself, without considering opacity inherited from parents. Expects that handle
is valid.
void Magnum:: Ui:: AbstractUserInterface:: setNodeOpacity(NodeHandle handle,
Float opacity)
Set node opacity.
The value is subsequently multiplied with opacity of all parents and passed to layers to affect rendering. Opacity of 1.0f
makes a node opaque and 0.0f
fully transparent, although values outside of this range are allowed as well. Note that it's up to the particular layer implementation how the opacity value is actually used, and if at all — the layer may for example have additional options that affect the opacity either way. Expects that handle
is valid. Initially, a node has the opacity set to 1.0f
.
Calling this function causes UserInterfaceState::
NodeFlags Magnum:: Ui:: AbstractUserInterface:: nodeFlags(NodeHandle handle) const
Node flags.
The returned value is only flags set directly on the node itself, without considering flags such as NodeFlag::handle
is valid.
void Magnum:: Ui:: AbstractUserInterface:: setNodeFlags(NodeHandle handle,
NodeFlags flags)
Set node flags.
Expects that handle
is valid. Initially, a node has the flags that were passed to createNode(), which are by default none.
If NodeFlag::
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 complexity, where is the count of nested top-level hierarchies.
Calling this function causes UserInterfaceState::
std:: size_t Magnum:: Ui:: AbstractUserInterface:: nodeOrderCapacity() const
Capacity of the top-level node order storage.
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 complexity where 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::
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::
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::
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::
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 behind)
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 behind
. Expects that handle
is valid and behind
is either NodeHandle::
If handle
is a root node, expects that behind
is also a root node, if not null. If null, the handle
is ordered as drawn last. The operation is done with an complexity in this case.
If handle
is not a root node, expects that both handle
and behind
have a common parent that's the closest top-level or root node for both, if behind
is not null. If null, the handle
is ordered after all other top-level nodes under its closest top-level or root parent. NodeFlag::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::
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 complexity. If handle
is not a root node, the operation is done with an complexity, where 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::
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 complexity, where 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::