Widgets
Generated from engine/ui/widget.h at 862e08b. The text under each declaration is the header's own comment, word for word. About the reference says how these pages are made.
#include "engine/ui/widget.h" · namespace labrador
class UiObject
Section titled “class UiObject”A named, hideable thing in a user interface.
NO RESCALE. A scale_size_and_position() on every widget, with a container walking the tree to apply it, is a layout policy - and an engine base class is not where a game's answer to "what happens at 1280x720" belongs (T1). It is also destructive: the factor is recorded nowhere, so after the walk no authoritative geometry is left to write against, and any later absolute setter writes design-space units into a rescaled widget. A screen mixing the two gets bars 1.5x too wide for the box they sit in, because the box was shrunk and the bars were not.
A widget holds one geometry, in whatever space the game authored it in, and nothing ever rewrites it. The mapping to the screen is a Camera, and it is set on the draw list once for the whole menu rather than passed to every widget in turn (renderer.h, DrawList::set_camera).
UiObject · name
Section titled “UiObject · name”explicit UiObject(const std::string& name, bool hidden = false);const std::string& name() const;set_hidden · hidden
Section titled “set_hidden · hidden”void set_hidden(bool hidden);bool hidden() const;update · draw · bounds
Section titled “update · draw · bounds”void update(float dt) override = 0;set_colour
Section titled “set_colour”Painting a thing that has no colour is nothing, not an error, which is why this is a no-op here and pure one level down.
It is on this class at all so that a container can forward it to children it knows only as UiObjects. The two alternatives are both worse: a container that asked at runtime which of its children were colourable would be putting a cast on the path, and a container that could only hold colourable children would be a narrower container than anyone asked for.
class UiWidget
Section titled “class UiWidget”A UiObject that has a colour, which is what the focus machinery traffics in: FocusGroup::add takes one of these, because paint is how a menu shows where the cursor is (focus.h).
UiWidget · ~UiWidget
Section titled “UiWidget · ~UiWidget”explicit UiWidget(const std::string& name, bool hidden = false);~UiWidget() override = default;update · draw · bounds
Section titled “update · draw · bounds”void update(float dt) override = 0;set_colour
Section titled “set_colour”Pure again. UiObject's no-op is for a thing that is drawn and not coloured; a widget is the other kind, and being the other kind is the whole of what this class adds.
class UiContainer
Section titled “class UiContainer”A widget that is its children.
IT IS A UiWidget AND NOT A UiObject, which is the difference between a compound widget being writable and not. FocusGroup::add takes a UiWidget*, so a container that was only a UiObject could not be focused - and a row that is a label and a value side by side, which is what every options screen is made of, is exactly a container the cursor lands on. A client without this recovers the label-to-value relationship by comparing the focused pointer against each label in turn, and cannot write a slider at all.
SO IT IS NOT final EITHER, and deriving from it is how a compound widget is written: build the parts in the constructor, hand them to add_child, and inherit update, draw, bounds and set_colour already written. set_colour reaches every child, so a focus group holding one of these paints the whole row.
Children are loans, and the container outlives nothing. A deriving class that owns its children holds them as members and calls add_child from its constructor body: members are built after the base, so there is nothing to add during the initialiser list, and destruction runs the other way - the members go first, and the container destroyed after them drops their pointers without reading any of them.
UiContainer · add_child · remove_child · remove_all_children · child_count · children
Section titled “UiContainer · add_child · remove_child · remove_all_children · child_count · children”explicit UiContainer(const std::string& name);void remove_child(const std::string& name);void remove_child(const UiObject* child);void remove_all_children();size_t child_count() const;std::vector<std::pair<std::string, UiObject*>> children();update · draw · bounds · cull_bounds
Section titled “update · draw · bounds · cull_bounds”void update(float dt) override;mattmath::RectangleF cull_bounds(float units_per_pixel) const override;set_colour
Section titled “set_colour”Every child, in the order they were added, and whatever a child makes of it - a nested container passes it down, and a child with no colour ignores it.
class UiTexture
Section titled “class UiTexture”THE THREE LEAVES ARE NOT final, deliberately: PHILOSOPHY (UI) has every leaf open to derivation. A client wanting a text object with one extra behaviour - a line that builds itself from a list of parts, say - derives from UiText, where composing one would mean forwarding update, draw, bounds and set_colour to it by hand: four functions of boilerplate to add one.
Deriving costs nothing structural. The destructor is virtual from GameObject down, so these are safe to hold and delete as UiWidget*, and each leaf is that plus a render-side base that already does the drawing.
WHAT A DERIVING CLASS OWES: if it overrides draw(), it early-outs on hidden() itself. That check is written into each leaf's draw rather than into a wrapper around it, so an override replaces it rather than running after it.
UiTexture
Section titled “UiTexture”UiTexture(const std::string& name, const std::string& sheet_name, const std::string& frame_name, bool hidden = false, float rotation = 0.0f, float layer_depth = 0.0f);update · draw · bounds · cull_bounds
Section titled “update · draw · bounds · cull_bounds”void update(float dt) override;mattmath::RectangleF cull_bounds(float units_per_pixel) const override;set_texture · set_sprite_frame · set_colour · set_position · set_position_at_center · set_width · set_height · set_size · set_position_from_top_right_origin
Section titled “set_texture · set_sprite_frame · set_colour · set_position · set_position_at_center · set_width · set_height · set_size · set_position_from_top_right_origin”void set_texture(const std::string& sheet_name, const std::string& frame_name);void set_sprite_frame(const std::string& frame_name);void set_position_at_center(const mattmath::Vector2F& position);void set_width(float width);void set_height(float height);void set_size(const mattmath::Vector2F& size);void set_position_from_top_right_origin(const mattmath::Vector2F& position);rectangle
Section titled “rectangle”class UiText
Section titled “class UiText”UiText
Section titled “UiText”UiText(const std::string& name, const std::wstring& text, const std::string& font_name, bool hidden = false, float scale = 1.0f, float rotation = 0.0f, float layer_depth = 0.0f);update · draw · bounds · set_colour
Section titled “update · draw · bounds · set_colour”void update(float dt) override;class UiTextDropShadow
Section titled “class UiTextDropShadow”UiTextDropShadow
Section titled “UiTextDropShadow”UiTextDropShadow(const std::string& name, const std::wstring& text, const std::string& font_name, const Colour& shadow_color = Colour::black, const mattmath::Vector2F& shadow_offset = { 2.0f, 2.0f }, bool hidden = false, float scale = 1.0f, float shadow_scale = 1.0f, float rotation = 0.0f, float layer_depth = 0.0f);update · draw · bounds · set_colour
Section titled “update · draw · bounds · set_colour”void update(float dt) override;Related types
Section titled “Related types”Named in the public declarations above: Colour, DrawList, GameObject, RectangleF, RenderResources, SpriteFlip, Text, TextDropShadow, TextureObject, Vector2F.
In the samples and tests
Section titled “In the samples and tests”The files that include this header directly. A file can also reach it through another header.
samples/linesweeper/states/pause_state.htests/scene/cull_tests.cpptests/ui/stub_widget.h,widget_tests.cpp
Development documentation (unreleased). Built from Labrador 862e08b of 2026-10-08.