Sections¶
Header: winui/ui/navigation/Sections.hpp. Spec: winui/ui/navigation/Sections.hpp.
A row of large text headers over the selected item's content.
An optional title sits above the header row, and optional left/right header elements flank it. When the headers do not all fit, they form a carousel by default. The selected header leads the row and the rest follow it, wrapping around. Only then do the keyboard and the navigation buttons shown on hover wrap too. The selected header is underlined with an accent bar. A change of selection flies the old content out and the new one in from the side the selection moved to. The header row is the tab stop. Left/Right select the previous/next item and Home/End the first/last. Ctrl+Tab, Ctrl+Shift+Tab, Ctrl+PageDown and Ctrl+PageUp step the selection from anywhere inside. ui::Sections is the declarative form.
Example:
window.set_content(ui::Sections{
.title = std::string{"EMAIL"},
.min_height = 400.0f,
.on_selection_changed = [](std::size_t index) { /* e.g. mark items read */ },
.items = {
ui::Section{.header = "All", .content = ui::Text{.text = "all emails go here."}},
ui::Section{.header = "Unread", .content = ui::Text{.text = "unread emails go here."}},
ui::Section{.header = "Flagged", .content = ui::Text{.text = "flagged emails go here."}},
},
});
// Imperatively:
auto sections = std::make_unique<ui::SectionsControl>();
sections->set_title("EMAIL");
ui::TextControl* all = sections->add_item("All", std::make_unique<ui::TextControl>("all emails"));
sections->add_item("Unread", std::make_unique<ui::TextControl>("unread emails"));
sections->on_selection_changed([](std::size_t index) { /* ... */ });
sections->set_selected_index(1);
ui::Sections¶
Large text headers over swappable content. Builds a ui::SectionsControl.
Example:
ui::Property<std::size_t> current_folder{0};
window.set_content(ui::Sections{
.title = "EMAIL",
.on_selection_changed = [&](std::size_t i) { current_folder = i; },
.items = {
ui::Section{ .header = "All", .content = ui::Text{ .text = "all emails go here." } },
ui::Section{ .header = "Unread", .content = ui::Text{ .text = "unread emails go here." } },
ui::Section{ .header = "Flagged", .content = ui::Text{ .text = "flagged emails go here." } },
},
});
Every field, in the order a designated initializer names them:
ui::Sections{
.title, .selected_index, .header_carousel_enabled, .style, .margin, .width, .height,
.min_width, .min_height, .max_width, .max_height, .horizontal_alignment,
.vertical_alignment, .visible, .tool_tip, .enabled, .accessibility, .on_selection_changed,
.on_pointer_entered, .on_pointer_exited, .on_got_focus, .on_lost_focus, .on_key_down,
.on_wheel, .control, .items, .left_header_content, .right_header_content
}
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
title |
ui::Binding<std::string> |
The small caption above the headers; empty draws none. | |
selected_index |
ui::TwoWayField<std::size_t> |
{0} |
The selected item; clamped to the items. |
header_carousel_enabled |
ui::Binding<bool> |
{true} |
Headers that do not fit rotate so the selected one leads. False scrolls the row instead. |
on_selection_changed |
ui::Callback<void(std::size_t)> |
Called with the new index whenever the selection moves. | |
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::Sections> |
Out: the handle that receives the built control. | |
items |
ui::SectionList |
The items, in header order. | |
left_header_content |
ui::Spec |
An element left of the headers. | |
right_header_content |
ui::Spec |
An element right of the headers. |
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::SectionsControl; the caller owns it.
ui::Section¶
One section: a header and the content shown while it is selected. Written inside the .items of a ui::Sections.
Every field, in the order a designated initializer names them:
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
header |
std::string |
The item's header text in the header row. | |
content |
ui::Spec |
What the Sections shows while this item is selected. |
ui::SectionList¶
A built, owned list of Sections items. Callers never name it, since a braced list of ui::Section{...} converts to it.
Every field, in the order a designated initializer names them:
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
entries |
std::vector<Entry> |
The items, in header order. |
operator=¶
operator=¶
struct Entry¶
One item with its content already built.
| Field | Type | Default | |
|---|---|---|---|
header |
std::string |
||
node |
std::unique_ptr<Element> |
ui::SectionsControl¶
Derives from ui::Element, ui::ValueProvider.
A row of large text headers over the selected item's content.
An optional title sits above the header row, and optional left/right header elements flank it. When the headers do not all fit, they form a carousel by default. The selected header leads the row and the rest follow it, wrapping around. Only then do the keyboard and the navigation buttons shown on hover wrap too. The selected header is underlined with an accent bar. A change of selection flies the old content out and the new one in from the side the selection moved to. The header row is the tab stop. Left/Right select the previous/next item and Home/End the first/last. Ctrl+Tab, Ctrl+Shift+Tab, Ctrl+PageDown and Ctrl+PageUp step the selection from anywhere inside. ui::Sections is the declarative form.
Example:
window.set_content(ui::Sections{
.title = std::string{"EMAIL"},
.min_height = 400.0f,
.on_selection_changed = [](std::size_t index) { /* e.g. mark items read */ },
.items = {
ui::Section{.header = "All", .content = ui::Text{.text = "all emails go here."}},
ui::Section{.header = "Unread", .content = ui::Text{.text = "unread emails go here."}},
ui::Section{.header = "Flagged", .content = ui::Text{.text = "flagged emails go here."}},
},
});
// Imperatively:
auto sections = std::make_unique<ui::SectionsControl>();
sections->set_title("EMAIL");
ui::TextControl* all = sections->add_item("All", std::make_unique<ui::TextControl>("all emails"));
sections->add_item("Unread", std::make_unique<ui::TextControl>("unread emails"));
sections->on_selection_changed([](std::size_t index) { /* ... */ });
sections->set_selected_index(1);
SectionsControl¶
An empty Sections: no title, no items, carousel enabled.
add_item¶
Appends an item, taking ownership of its content, and returns a non-owning observer to the content. The first item added becomes selected.
add_item¶
Appends item, taking ownership of its content (which may be null for a header-only item). The first item added becomes selected.
item_count¶
The number of items added.
header¶
The header text of item index; an empty string when out of range.
title¶
The title above the header row; empty collapses the title row.
set_title¶
Sets the title, updates the layout as the title row appears or collapses, and redraws.
selected_index¶
The selected item; unset while there are no items.
set_selected_index¶
Selects item index, clamped to the items. Does nothing, and fires nothing, if the item is already selected.
on_selection_changed¶
Fired with the new index whenever the selection changes, by click, keyboard, the navigation buttons or set_selected_index(). Replaces any previous handler.
header_carousel_enabled¶
Whether the headers form a carousel, true by default. Headers that do not fit then rotate so the selected one leads. False keeps them in order and scrolls the row to the selection.
set_header_carousel_enabled¶
Updates the layout and redraws.
set_left_header_content¶
An element left of the headers. Takes ownership (replacing any previous one) and returns a non-owning observer.
set_right_header_content¶
Like set_left_header_content(), for the right end of the header row.
static_headers¶
Whether the headers all fit, so they stay in place instead of rotating.
header_bounds¶
The header of item index as drawn, or nullopt if it is clipped out of the row.
header_row¶
The header row's rect.
content_bounds¶
The area the selected item's content is arranged in, below the header row.
previous_button_bounds¶
The navigation buttons, while they show.
next_button_bounds¶
Like previous_button_bounds(), for the next button.
handle_shortcut¶
Ctrl+Tab / Ctrl+Shift+Tab and Ctrl+PageDown / Ctrl+PageUp, from anywhere inside the Sections.
focused¶
Whether the header row has keyboard focus.
focusable¶
The header row is a tab stop while enabled and non-empty.
takes_focus_at¶
Only a press on the header row focuses the Sections. The selected item's content takes focus on its own.
collect_focusables¶
Tab order: the left header, the header row, the right header, then the selected content.
for_each_child¶
Lists the left header, the right header and the selected item's content. An unselected item's content is set aside, and nothing reaches it until it is selected again.
automation_role¶
Exposed to accessibility tools as a tab control whose value is the selected header.
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.
render_override¶
What the control draws, in layout coordinates; render() has already applied the visual layer. A container draws its children through their render(), never their render_override().
pointer_override¶
A click on a header selects it, and a click on a navigation button moves by one. Other input goes to the selected content.
hit_test_children¶
The children p (in this element's layout coordinates) is tested against, topmost first. Default: what for_each_child() lists, last first. A container that draws in another order (Panel's z-index), a control with parts for_each_child() does not list, or one whose parts cover others in places (a pane drawn over the content) lists them here.
clear_dirty_override¶
Also clears the content still flying out after a selection change.
tick_override¶
Advances the selection-change fly-in/fade animation.
enabled_changed¶
is_enabled() flipped, through set_enabled() here or on an ancestor, or a move to another parent. Drop any press or hover state. The element is redrawn either way. No-op by default.
key_override¶
Left/Right select the previous/next item, Home/End the first/last.
focus_changed¶
Keyboard focus arrived (true) or left (false); is_focused() already says so. The element is redrawn either way. No-op by default.
focus_ring_rect¶
Around the header row, square.
focus_ring_corner_radius¶
The ring's corner radius: the theme's control radius by default.
ui::Section¶
One section: a header and the content shown while it is selected. Written inside the .items of a ui::Sections.
| Field | Type | Default | |
|---|---|---|---|
header |
std::string |
The item's header text in the header row. | |
content |
Spec |
What the Sections shows while this item is selected. |
struct SectionsControlItem¶
One section: a header and the content shown while it is selected. Passed to SectionsControl::add_item(), which takes ownership of the content.
| Field | Type | Default | |
|---|---|---|---|
header |
std::string |
The header text in the header row. | |
content |
std::unique_ptr<Element> |
Shown below the headers while the item is selected. |
Tests¶
tests/test_sections.cpp