RelativePanel¶
Header: winui/ui/panels/RelativePanel.hpp. Spec: winui/ui/panels/RelativePanel.hpp.
Lays out children relative to each other and to the panel's edges.
Each child carries a ui::RelativePanelConstraints (sixteen constraints). A child is measured in the room its constraints leave it, then pinned: stretched between two anchored edges, placed against one, centered, or in the top-left corner when nothing is set. On the same side, a panel alignment wins over a sibling alignment, which wins over left_of/right_of. Siblings are resolved before the children that refer to them, whatever order they were added in. A constraint that would make a cycle, or that names a non-child, is ignored. The panel asks for the widest and tallest dependency chain plus its border and padding. ui::RelativePanel is the declarative form, referring to siblings by name.
Example:
auto panel = std::make_unique<ui::RelativePanelControl>();
panel->set_padding(ui::Thickness{12.0f});
auto* title = panel->add(std::make_unique<ui::TextControl>("Title"));
auto* ok = panel->add(std::make_unique<ui::ButtonControl>("OK"), {.align_right_with_panel = true});
auto* cancel = panel->add(std::make_unique<ui::ButtonControl>("Cancel"), {.left_of = ok});
panel->add(std::make_unique<ui::TextControl>("Body"), {.below = title});
panel->set_constraints(ok, {.below = title, .align_right_with_panel = true}); // re-pin later
cancel->on_click([] { /* ... */ });
window.set_content(std::move(panel));
// Declaratively:
auto node = ui::build(ui::RelativePanel{.content = {
ui::RelativeItem{.name = "a", .content = ui::Text{.text = "A"}},
ui::RelativeItem{.right_of = "a", .content = ui::Text{.text = "B"}},
}});
ui::RelativePanel¶
Children placed relative to each other and to the panel. Builds a ui::RelativePanelControl.
Example:
window.set_content(ui::RelativePanel{
.padding = ui::Thickness{12.0f},
.width = 280.0f,
.content = {
ui::RelativeItem{.name = "image",
.align_left_with_panel = true,
.align_top_with_panel = true,
.content = ui::Image{.source = ui::Bitmap::read("cover.jpg"), .width = 80.0f}},
ui::RelativeItem{.name = "title", .right_of = "image", .align_top_with = "image",
.content = ui::Text{.text = "Title", .role = ui::TextRole::BodyStrong}},
ui::RelativeItem{.right_of = "image", .below = "title", .content = ui::Text{.text = "Subtitle"}},
},
});
Every field, in the order a designated initializer names them:
ui::RelativePanel{
.background, .border_brush, .border_thickness, .corner_radius, .padding, .style, .margin,
.width, .height, .min_width, .min_height, .max_width, .max_height, .horizontal_alignment,
.vertical_alignment, .visible, .tool_tip, .enabled, .accessibility, .on_pointer_entered,
.on_pointer_exited, .on_got_focus, .on_lost_focus, .on_key_down, .on_wheel, .control,
.content
}
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
background |
ui::Binding<ui::Paint> |
Background: a Color, or a ThemeColor read from the theme; empty (the default) draws none. | |
border_brush |
ui::Binding<ui::Paint> |
Border color, a Color or a ThemeColor; empty (the default) draws no border. | |
border_thickness |
ui::Binding<ui::Thickness> |
Border width per edge, DIPs. | |
corner_radius |
ui::Binding<float> |
{0.0f} |
Corner radius, DIPs. |
padding |
ui::Binding<ui::Thickness> |
Padding between the border and the children, DIPs. | |
on_pointer_entered |
ui::Action |
The pointer moved onto the control. | |
on_pointer_exited |
ui::Action |
The pointer left the control. | |
on_got_focus |
ui::Action |
Keyboard focus arrived on the control, or on anything inside it, from outside it. A control with nothing focusable in it never gets focus, and never raises this. | |
on_lost_focus |
ui::Action |
Keyboard focus left the control and everything inside it. | |
on_key_down |
ui::Callback<ui::Handling(const ui::KeyEvent&)> |
A key pressed while focus is on the control or inside it, before the control's own handling; ui::Handled stops it there (Element::on_key_down()). | |
on_wheel |
ui::Callback<ui::Handling(const ui::PointerEvent&)> |
A wheel turn over the control, before the control scrolls; ui::Handled stops it there (Element::on_wheel()). | |
control |
ui::ControlOut<ui::RelativePanel> |
Out: the handle that receives the built control. | |
content |
ui::RelativeItemList |
The constrained children; see ui::RelativeItem. |
Plus the common fields style, margin, width, height, min_width, min_height, max_width, max_height, horizontal_alignment, vertical_alignment, visible, tool_tip, enabled, accessibility every spec carries (conventions).
build¶
Consumes the spec and returns the built ui::RelativePanelControl; the caller owns it.
ui::RelativeItem¶
One child of a RelativePanel. name is what a sibling's constraints refer to it by. A constraint must name a sibling in the same panel. A name that matches none is a bug, caught by an assert in a debug build and otherwise left unset. Each string field is the ui::RelativePanelConstraints member of the same name; see ui::RelativePanel for an example.
Every field, in the order a designated initializer names them:
ui::RelativeItem{
.name, .left_of, .above, .right_of, .below, .align_horizontal_center_with,
.align_vertical_center_with, .align_left_with, .align_top_with, .align_right_with,
.align_bottom_with, .align_left_with_panel, .align_top_with_panel, .align_right_with_panel,
.align_bottom_with_panel, .align_horizontal_center_with_panel,
.align_vertical_center_with_panel, .content
}
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
name |
std::string |
This child's name, for siblings to refer to. | |
left_of |
std::string |
Sit left of the named sibling. | |
above |
std::string |
Sit above the named sibling. | |
right_of |
std::string |
Sit right of the named sibling. | |
below |
std::string |
Sit below the named sibling. | |
align_horizontal_center_with |
std::string |
Share the named sibling's horizontal center. | |
align_vertical_center_with |
std::string |
Share the named sibling's vertical center. | |
align_left_with |
std::string |
Align left edges with the named sibling. | |
align_top_with |
std::string |
Align top edges with the named sibling. | |
align_right_with |
std::string |
Align right edges with the named sibling. | |
align_bottom_with |
std::string |
Align bottom edges with the named sibling. | |
align_left_with_panel |
bool |
false |
Pin to the panel's left edge. |
align_top_with_panel |
bool |
false |
Pin to the panel's top edge. |
align_right_with_panel |
bool |
false |
Pin to the panel's right edge. |
align_bottom_with_panel |
bool |
false |
Pin to the panel's bottom edge. |
align_horizontal_center_with_panel |
bool |
false |
Center horizontally in the panel. |
align_vertical_center_with_panel |
bool |
false |
Center vertically in the panel. |
content |
ui::Spec |
The placed child. |
ui::RelativePanelControl¶
Derives from ui::Panel.
Lays out children relative to each other and to the panel's edges.
Each child carries a ui::RelativePanelConstraints (sixteen constraints). A child is measured in the room its constraints leave it, then pinned: stretched between two anchored edges, placed against one, centered, or in the top-left corner when nothing is set. On the same side, a panel alignment wins over a sibling alignment, which wins over left_of/right_of. Siblings are resolved before the children that refer to them, whatever order they were added in. A constraint that would make a cycle, or that names a non-child, is ignored. The panel asks for the widest and tallest dependency chain plus its border and padding. ui::RelativePanel is the declarative form, referring to siblings by name.
Example:
auto panel = std::make_unique<ui::RelativePanelControl>();
panel->set_padding(ui::Thickness{12.0f});
auto* title = panel->add(std::make_unique<ui::TextControl>("Title"));
auto* ok = panel->add(std::make_unique<ui::ButtonControl>("OK"), {.align_right_with_panel = true});
auto* cancel = panel->add(std::make_unique<ui::ButtonControl>("Cancel"), {.left_of = ok});
panel->add(std::make_unique<ui::TextControl>("Body"), {.below = title});
panel->set_constraints(ok, {.below = title, .align_right_with_panel = true}); // re-pin later
cancel->on_click([] { /* ... */ });
window.set_content(std::move(panel));
// Declaratively:
auto node = ui::build(ui::RelativePanel{.content = {
ui::RelativeItem{.name = "a", .content = ui::Text{.text = "A"}},
ui::RelativeItem{.right_of = "a", .content = ui::Text{.text = "B"}},
}});
RelativePanelControl¶
An empty panel with no border or padding.
add¶
Takes ownership of child with its constraints and returns a non-owning observer. Constraints may name siblings added later (set them with set_constraints()).
add¶
The declarative overload: builds spec (or takes the node a ui::Spec holds) and adds it as add() does a control. Returns the built node as an Element, or nullptr for an empty ui::Spec, which adds nothing; a spec's .control field gives a typed observer.
add¶
add() with no constraints set.
add¶
The declarative add() with no constraints set.
set_constraints¶
Replaces a child's constraints; an element that is not a child is ignored.
constraints¶
A child's constraints; all unset for an element that is not a child.
parallel_measure_safe¶
True: measuring touches only the panel and its children. The children are measured in dependency order on one thread.
border_brush¶
The outline color; nullopt (the default) draws no border even with a non-zero border_thickness(). Nullopt as well while a ThemeColor is set.
border_brush_resource¶
The theme resource the border is drawn from, or null.
border_thickness¶
The border width in DIPs per side (default zero); it insets the children like padding.
corner_radius¶
The corner radius in DIPs, uniform for all four corners (default 0, square).
padding¶
The padding in DIPs between the border and the children (default zero).
set_border_brush¶
A fixed outline color; replaces any resource. Marks the panel for redraw.
set_border_brush¶
An outline color read from the theme each time the panel is drawn; replaces any fixed color. Marks the panel for redraw.
set_border_thickness¶
Sets the border width; marks the panel for layout and redraw.
set_corner_radius¶
Sets the corner radius; marks the panel for redraw.
set_padding¶
Sets the padding; marks the panel for layout.
measure_override¶
Resolves the dependency graph, measures each child in the room its constraints leave, and returns the widest and tallest chain plus border and padding.
arrange_override¶
Pins every child per its constraints inside the border and padding.
struct RelativePanelConstraints¶
The placement constraints of one child of a ui::RelativePanelControl. A sibling reference is an observer of another child of the same panel; nullptr leaves that constraint unset.
| Field | Type | Default | |
|---|---|---|---|
left_of |
const Element* |
nullptr |
Right edge against this sibling's left edge. |
above |
const Element* |
nullptr |
Bottom edge against this sibling's top edge. |
right_of |
const Element* |
nullptr |
Left edge against this sibling's right edge. |
below |
const Element* |
nullptr |
Top edge against this sibling's bottom edge. |
align_horizontal_center_with |
const Element* |
nullptr |
Horizontal center on this sibling's. |
align_vertical_center_with |
const Element* |
nullptr |
Vertical center on this sibling's. |
align_left_with |
const Element* |
nullptr |
Left edge in line with this sibling's. |
align_top_with |
const Element* |
nullptr |
Top edge in line with this sibling's. |
align_right_with |
const Element* |
nullptr |
Right edge in line with this sibling's. |
align_bottom_with |
const Element* |
nullptr |
Bottom edge in line with this sibling's. |
align_left_with_panel |
bool |
false |
Left edge on the panel's content edge. |
align_top_with_panel |
bool |
false |
Top edge on the panel's content edge. |
align_right_with_panel |
bool |
false |
Right edge on the panel's content edge. |
align_bottom_with_panel |
bool |
false |
Bottom edge on the panel's content edge. |
align_horizontal_center_with_panel |
bool |
false |
Centered horizontally in the panel. |
align_vertical_center_with_panel |
bool |
false |
Centered vertically in the panel. |
class RelativeItemList¶
A RelativePanel's children, built; the names are resolved when the panel is. Callers write it as a braced list of ui::RelativeItem{...}.
items_¶
The placed children, in declaration order.
RelativeItemList¶
An empty list.
RelativeItemList¶
template <typename... S>
RelativeItemList(S&& ... items)
requires (sizeof...(S) > 0 && (std::same_as<S, RelativeItem> && ...))
Builds every item's content and takes ownership of it, keeping the constraints.
RelativeItemList¶
operator=¶
RelativeItemList¶
operator=¶
add¶
Builds item's content and appends it, as one more entry of the braced list would.
struct Placed¶
One built child with its constraints; the node is already owned by the list.
| Field | Type | Default | |
|---|---|---|---|
names |
RelativeItem |
The constraints; its content is already taken. | |
node |
std::unique_ptr<Element> |
The built child. |
Tests¶
tests/test_layout_panels.cpp