RadioButtons¶
Header: winui/ui/input/RadioButtons.hpp. Spec: winui/ui/input/RadioButtons.hpp.
A headed group of mutually exclusive string options, as one element.
The control owns one RadioButton per item (RadioGroup coordinates loose buttons instead), lays them out column-major in up to max_columns() equal-sized columns, and selects by index. The group is a single tab stop; focus lands on the selected (or first enabled) item. Up/Down move to the previous/next enabled item and select it, Left/Right move between columns, Ctrl+arrow moves focus without selecting (Space then selects), and an arrow with nowhere to go inside the group moves focus out of it. ui::RadioButtons is the declarative form.
Example:
ui::Property<std::string> message{"Nothing selected"};
window.set_content(ui::VerticalStack{
.spacing = 12,
.content = {
ui::RadioButtons{
.header = "Options:",
.items = {"Option 1", "Option 2", "Option 3"},
.max_columns = 2,
.on_selection_changed = [&message](std::optional<std::size_t> index) {
message = index ? std::format("You selected Option {}", *index + 1) : "";
},
},
ui::Text{.text = message},
},
});
// Imperatively:
auto colors = std::make_unique<ui::RadioButtonsControl>(
std::vector<std::string>{"Red", "Green", "Blue"}, /*selected_index=*/0);
colors->set_header("Color");
colors->item(2)->set_enabled(false); // disable a single option
colors->on_selection_changed([](std::optional<std::size_t> index) { /* unset when cleared */ });
ui::RadioButtons¶
A headed group of mutually exclusive options, one tab stop, selected by index. Builds a ui::RadioButtonsControl.
The initial selection is in place before any handler is installed, so it raises nothing.
Example:
ui::Property<std::optional<std::size_t>> background{0};
window.set_content(ui::RadioButtons{
.header = "Background",
.items = {"Green", "Yellow", "White"},
.selected_index = background,
.max_columns = 3,
});
Every field, in the order a designated initializer names them:
ui::RadioButtons{
.header, .items, .selected_index, .max_columns, .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
}
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
header |
ui::Binding<std::string> |
The label above the group. Empty draws none. | |
items |
ui::Binding<std::vector<std::string>> |
One radio button per string, in order. Bound, a new list replaces the buttons and clears the selection. | |
selected_index |
ui::TwoWayField<std::optional<std::size_t>> |
Unset (the default) selects nothing. | |
max_columns |
ui::Binding<std::size_t> |
{1} |
The most columns (at least 1). Items fill a column top to bottom before starting the next. |
on_selection_changed |
ui::Callback<void(std::optional<std::size_t>)> |
The newly selected index (unset when cleared), after a click, Space or a bound value. | |
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::RadioButtons> |
Out: the handle that receives the built control. |
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::RadioButtonsControl; the caller owns it.
ui::RadioButtonsControl¶
Derives from ui::Element.
A headed group of mutually exclusive string options, as one element.
The control owns one RadioButton per item (RadioGroup coordinates loose buttons instead), lays them out column-major in up to max_columns() equal-sized columns, and selects by index. The group is a single tab stop; focus lands on the selected (or first enabled) item. Up/Down move to the previous/next enabled item and select it, Left/Right move between columns, Ctrl+arrow moves focus without selecting (Space then selects), and an arrow with nowhere to go inside the group moves focus out of it. ui::RadioButtons is the declarative form.
Example:
ui::Property<std::string> message{"Nothing selected"};
window.set_content(ui::VerticalStack{
.spacing = 12,
.content = {
ui::RadioButtons{
.header = "Options:",
.items = {"Option 1", "Option 2", "Option 3"},
.max_columns = 2,
.on_selection_changed = [&message](std::optional<std::size_t> index) {
message = index ? std::format("You selected Option {}", *index + 1) : "";
},
},
ui::Text{.text = message},
},
});
// Imperatively:
auto colors = std::make_unique<ui::RadioButtonsControl>(
std::vector<std::string>{"Red", "Green", "Blue"}, /*selected_index=*/0);
colors->set_header("Color");
colors->item(2)->set_enabled(false); // disable a single option
colors->on_selection_changed([](std::optional<std::size_t> index) { /* unset when cleared */ });
RadioButtonsControl¶
An empty group with no header and nothing selected.
RadioButtonsControl¶
RadioButtonsControl(std::vector<std::string> items, std::optional<std::size_t> selected_index = std::nullopt)
One RadioButton per string, in order, with selected_index checked (unset for none; no callback fires).
header¶
The header above the items; also the automation name when none is set.
set_header¶
The label above the options. Empty draws none and reserves no room for one.
item_count¶
The number of options.
item¶
The button for item index, owned by this control; nullptr past the end.
set_items¶
Replaces every item and clears the selection (firing on_selection_changed if there was one). The new buttons take this control's enabled state.
selected_index¶
The checked item; unset when none is.
set_selected_index¶
Checks that item and unchecks the one before. Unset, or anything outside [0, item_count()), clears the selection. No-op, and no callback, when it does not change.
selected_item¶
The selected item's text, or an empty string.
on_selection_changed¶
Fired once per change with the new index (unset when cleared), whether a click, an arrow key, set_items() or set_selected_index() caused it. Replaces any previous handler.
max_columns¶
The most columns items are laid out in; 1 by default. Fewer are used when the offered width cannot hold them.
set_max_columns¶
Clamped to >= 1.
focused¶
Whether the group has keyboard focus.
focused_index¶
The item that has the keyboard's attention while the group is focused; unset otherwise.
focusable¶
A tab stop while enabled with at least one enabled item.
for_each_child¶
The items, in order.
collect_focusables¶
Lists only the group, as one tab stop. The arrow keys move between the items.
automation_role¶
Group; each item is its own SelectionItem.
automation_name_fallback¶
The header, when no Accessibility::name is set.
measure_override¶
The header plus a column-major grid of cells, each the size of the largest item, with 7 DIP column and 8 DIP row spacing.
arrange_override¶
Position children within the rect arrange() settled on (also in bounds(), window DIPs). Default: nothing, for a leaf.
pointer_override¶
Routes clicks to the owned buttons.
render_override¶
Draws the header and every item.
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.
focus_changed¶
Keyboard focus arrived (true) or left (false); is_focused() already says so. The element is redrawn either way. No-op by default.
key_override¶
Arrow keys move the focused item (and select it unless Ctrl is held); Space selects it.
focus_ring_rect¶
Around the focused item, as that item would ring itself.
focus_ring_corner_radius¶
The ring's corner radius: the theme's control radius by default.
Tests¶
tests/test_radio_buttons.cpp