Canvas¶
Header: winui/ui/panels/Canvas.hpp. Spec: winui/ui/panels/Canvas.hpp.
Children placed at absolute left/top offsets (DIPs) from its top-left corner, drawn in z-index order.
Every child is measured with unbounded room and arranged at its own desired size. The Canvas itself asks for no room at all. It takes the size its width/height or its slot give it. It does not clip, so a child placed past its edge still draws there. Children draw lowest z-index first, ties in the order added, and the topmost child gets the wheel first. The background comes from Panel::set_background().
Example:
auto canvas = std::make_unique<ui::CanvasControl>();
canvas->set_width(140.0f);
canvas->set_height(140.0f);
canvas->set_background(ui::Color::from_rgba(128, 128, 128));
auto square = std::make_unique<ui::RectangleControl>();
square->set_width(40.0f);
square->set_height(40.0f);
square->set_fill(ui::Color::from_rgba(255, 0, 0));
ui::RectangleControl* red = canvas->add(std::move(square), 20.0f, 30.0f);
canvas->set_z_index(red, 5); // drawn above every child with a lower z-index
canvas->set_left(red, 60.0f); // moves it and updates the layout
window.set_content(std::move(canvas));
// Declaratively, with bindable placements:
ui::Property<float> left{20.0f};
window.set_content(ui::Canvas{
.width = 140.0f,
.height = 140.0f,
.content = {
ui::CanvasItem{.left = left,
.top = 30.0f,
.content = ui::Rectangle{.fill = ui::colors::Black, .width = 40.0f, .height = 40.0f}},
ui::CanvasItem{.left = 60.0f, .top = 60.0f, .z_index = 1, .content = ui::Text{.text = "On top"}},
},
});
ui::Canvas¶
Children at absolute offsets. Builds a ui::CanvasControl.
A canvas does not size to its children; give it a width/height (or a stretching slot).
Example:
ui::Property<float> x{0.0f};
window.set_content(ui::VerticalStack{.spacing = 8, .content = {
ui::Canvas{
.background = ui::Color::from_rgba(200, 200, 200),
.width = 140.0f,
.height = 140.0f,
.content = {
ui::CanvasItem{.left = x, .top = 10.0f, .z_index = 2,
.content = ui::Border{.background = ui::colors::Black, .width = 40.0f, .height = 40.0f}},
ui::CanvasItem{.left = 20.0f, .top = 20.0f, .z_index = 1,
.content = ui::Border{.background = ui::colors::White, .width = 40.0f, .height = 40.0f}},
},
},
ui::Button{.text = "Move", .on_click = [&] { x += 10.0f; }},
}});
Every field, in the order a designated initializer names them:
ui::Canvas{
.background, .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. | |
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::Canvas> |
Out: the handle that receives the built control. | |
content |
ui::CanvasItemList |
The positioned children; see ui::CanvasItem. |
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::CanvasControl; the caller owns it.
ui::CanvasItem¶
One child of a Canvas with its left and top offsets and z-index, each bindable. Written inline in a ui::Canvas's .content; see ui::Canvas for an example.
Every field, in the order a designated initializer names them:
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
left |
ui::Binding<float> |
{0.0f} |
Offset from the canvas's left, DIPs. |
top |
ui::Binding<float> |
{0.0f} |
Offset from the canvas's top, DIPs. |
z_index |
ui::Binding<int> |
{0} |
Higher draws on top. |
content |
ui::Spec |
The placed child. |
ui::CanvasControl¶
Derives from ui::Panel.
Children placed at absolute left/top offsets (DIPs) from its top-left corner, drawn in z-index order.
Every child is measured with unbounded room and arranged at its own desired size. The Canvas itself asks for no room at all. It takes the size its width/height or its slot give it. It does not clip, so a child placed past its edge still draws there. Children draw lowest z-index first, ties in the order added, and the topmost child gets the wheel first. The background comes from Panel::set_background().
Example:
auto canvas = std::make_unique<ui::CanvasControl>();
canvas->set_width(140.0f);
canvas->set_height(140.0f);
canvas->set_background(ui::Color::from_rgba(128, 128, 128));
auto square = std::make_unique<ui::RectangleControl>();
square->set_width(40.0f);
square->set_height(40.0f);
square->set_fill(ui::Color::from_rgba(255, 0, 0));
ui::RectangleControl* red = canvas->add(std::move(square), 20.0f, 30.0f);
canvas->set_z_index(red, 5); // drawn above every child with a lower z-index
canvas->set_left(red, 60.0f); // moves it and updates the layout
window.set_content(std::move(canvas));
// Declaratively, with bindable placements:
ui::Property<float> left{20.0f};
window.set_content(ui::Canvas{
.width = 140.0f,
.height = 140.0f,
.content = {
ui::CanvasItem{.left = left,
.top = 30.0f,
.content = ui::Rectangle{.fill = ui::colors::Black, .width = 40.0f, .height = 40.0f}},
ui::CanvasItem{.left = 60.0f, .top = 60.0f, .z_index = 1, .content = ui::Text{.text = "On top"}},
},
});
CanvasControl¶
An empty canvas; with no width/height set it takes whatever its slot gives it.
add¶
template <typename T>
T* add(std::unique_ptr<T> child, float left = 0.0f, float top = 0.0f, int z_index = 0)
Takes ownership of a child placed at (left, top), DIPs from the canvas' top-left, at z_index, and returns a non-owning observer, as StackControl::add() does. Updates the layout. A null child is ignored and returns nullptr.
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_left¶
Sets the left offset of child, DIPs, and updates the layout. Ignored for an element that is not a child of this canvas.
set_top¶
Sets the top offset of child, DIPs, and updates the layout. Ignored for a non-child.
set_z_index¶
Sets the z-index of child. A higher z-index draws later, on top, and gets input first. Redraws. Ignored for a non-child.
left¶
The left offset of child, DIPs; 0 for an element that is not a child of this canvas.
top¶
The top offset of child, DIPs; 0 for a non-child.
z_index¶
The z-index of child; 0 for a non-child.
parallel_measure_safe¶
True: measuring touches only the canvas and its children.
render_order¶
The children sorted by z-index (stable, so ties keep insertion order), bottom first.
measure_override¶
Measures every child with unbounded room and asks for zero itself.
arrange_override¶
Places each child at its offset from final_rect's top-left, at its desired size.
class CanvasItemList¶
A Canvas' children, built, in the same shape as CellList. Callers write it as a braced list of ui::CanvasItem{...}.
items_¶
The placed children, in declaration order.
CanvasItemList¶
An empty list.
CanvasItemList¶
template <typename... S>
CanvasItemList(S&& ... items)
requires (sizeof...(S) > 0 && (std::same_as<S, CanvasItem> && ...))
Builds every item's content and takes ownership of it.
CanvasItemList¶
operator=¶
CanvasItemList¶
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 position; the node is already owned by the list.
| Field | Type | Default | |
|---|---|---|---|
left |
Binding<float> |
Left offset, possibly bound. | |
top |
Binding<float> |
Top offset, possibly bound. | |
z_index |
Binding<int> |
Z-index, possibly bound. | |
node |
std::unique_ptr<Element> |
The built child. |
Tests¶
tests/test_layout_panels.cpp