LayoutPanel¶
Header: winui/ui/panels/LayoutPanel.hpp. Spec: winui/ui/panels/LayoutPanel.hpp.
A panel whose measure and arrange are delegated to an attachable Layout.
Use it for a fixed set of children with a layout that no built-in panel offers. That is a custom NonVirtualizingLayout, or a StackLayoutEngine, TileLayoutEngine, WrapLayoutEngine or LinedFlowLayoutEngine applied to ordinary children, where every child counts as realized. Border and padding come off the room before the layout sees it. With no layout, every child fills the whole content box, stacked on top of each other.
Example:
// Declarative:
window.set_content(ui::LayoutPanel{
.layout = ui::TileLayout{},
.padding = ui::Thickness{12.0f},
.content = {ui::Text{.text = "A"}, ui::Text{.text = "B"}, ui::Text{.text = "C"}},
});
// Imperative:
auto panel = std::make_unique<ui::LayoutPanelControl>();
auto* stack = panel->set_layout(std::make_unique<ui::StackLayoutEngine>());
stack->set_spacing(8.0f);
panel->add(std::make_unique<ui::TextControl>("First"));
panel->add(std::make_unique<ui::TextControl>("Second"));
panel->set_padding(ui::Thickness{12.0f});
window.set_content(std::move(panel));
ui::LayoutPanel¶
Children measured and arranged by a Layout object. Builds a ui::LayoutPanelControl. The panel takes ownership of .layout; reach it again through .control's layout().
The counterpart of ui::ForEach for hand-written children: every child is realized, and any ui::Layout (a stock one or the app's own subclass) places them.
Example:
auto grid = std::make_unique<ui::TileLayoutEngine>();
grid->set_min_row_spacing(8.0f);
grid->set_min_column_spacing(8.0f);
window.set_content(ui::LayoutPanel{
.layout = std::move(grid),
.padding = ui::Thickness{12.0f},
.content = {
ui::Button{.text = "One"},
ui::Button{.text = "Two"},
ui::Button{.text = "Three"},
},
});
Every field, in the order a designated initializer names them:
ui::LayoutPanel{
.layout, .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 | |
|---|---|---|---|
layout |
ui::LayoutSpec |
The layout that measures and arranges the children; the panel takes ownership. | |
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> |
{ui::Thickness{}} |
Padding between the border and the laid-out 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::LayoutPanel> |
Out: the handle that receives the built control. | |
content |
ui::SpecList |
The children, in the order the layout sees them. |
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::LayoutPanelControl; the caller owns it.
ui::LayoutPanelControl¶
Derives from ui::Panel, ui::LayoutOwner.
A panel whose measure and arrange are delegated to an attachable Layout.
Use it for a fixed set of children with a layout that no built-in panel offers. That is a custom NonVirtualizingLayout, or a StackLayoutEngine, TileLayoutEngine, WrapLayoutEngine or LinedFlowLayoutEngine applied to ordinary children, where every child counts as realized. Border and padding come off the room before the layout sees it. With no layout, every child fills the whole content box, stacked on top of each other.
Example:
// Declarative:
window.set_content(ui::LayoutPanel{
.layout = ui::TileLayout{},
.padding = ui::Thickness{12.0f},
.content = {ui::Text{.text = "A"}, ui::Text{.text = "B"}, ui::Text{.text = "C"}},
});
// Imperative:
auto panel = std::make_unique<ui::LayoutPanelControl>();
auto* stack = panel->set_layout(std::make_unique<ui::StackLayoutEngine>());
stack->set_spacing(8.0f);
panel->add(std::make_unique<ui::TextControl>("First"));
panel->add(std::make_unique<ui::TextControl>("Second"));
panel->set_padding(ui::Thickness{12.0f});
window.set_content(std::move(panel));
LayoutPanelControl¶
An empty panel with no layout.
~LayoutPanelControl¶
add¶
Takes ownership of child, appends it after the existing children, and returns a non-owning observer. Updates the layout.
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.
set_layout¶
Takes ownership of the layout, destroying any previous one, and returns an observer to it. nullptr leaves the panel with none.
layout¶
The current layout (non-owning), or nullptr when the panel has none.
parallel_measure_safe¶
True without a layout, otherwise what the layout answers (Layout::parallel_measure_safe()).
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¶
Implement these instead of measure() and arrange(). The base class has already applied margin, size limits and alignment by the time these run. measure_override() is pure (every concrete Element must size itself); arrange_override() defaults to a no-op since most leaves need nothing beyond having bounds() set, which the base already did.
arrange_override¶
Position children within the rect arrange() settled on (also in bounds(), window DIPs). Default: nothing, for a leaf.
Tests¶
tests/test_layout_panels.cpp