RadioButton¶
Headers: winui/ui/input/RadioButton.hpp, winui/ui/input/RadioGroup.hpp. Spec: winui/ui/input/RadioButton.hpp.
A round option button with a label, one of a set of mutually exclusive choices.
Clicking it (or Space while focused) checks it; clicking an already-checked RadioButton does nothing, so the user can turn a lone button on but never off. The button doesn't uncheck the others by itself. Register the buttons with a RadioGroup, which doesn't own them, or use RadioButtons, which owns and lays out a whole set. ui::RadioButton is the declarative form of a single button.
Example:
auto stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
ui::RadioButtonControl* small = stack->add(std::make_unique<ui::RadioButtonControl>("Small", true));
ui::RadioButtonControl* large = stack->add(std::make_unique<ui::RadioButtonControl>("Large"));
ui::RadioGroup group;
group.add(small); // already checked: becomes the initial selection
group.add(large);
group.on_change([](ui::RadioButtonControl* chosen) { /* chosen->text() */ });
large->on_checked_changed([](bool checked) { /* fires for checks and unchecks */ });
window.set_content(std::move(stack));
ui::RadioButton¶
One radio button. Buttons that choose one value of a property are bound with ui::selects(): checking one sets the property, the others follow it, and the buttons act as one group for the keyboard (one Tab stop, arrow keys between them) wherever they sit in the tree. For a plain list of options, ui::RadioButtons is the whole group in one spec; imperative code can still tie loose buttons together with a RadioGroup.
Example:
enum class Size { Small, Large };
ui::Property<Size> size{Size::Small};
window.set_content(ui::VerticalStack{.content = {
ui::RadioButton{.text = "Small", .checked = ui::selects(size, Size::Small)},
ui::RadioButton{.text = "Large", .checked = ui::selects(size, Size::Large)},
}});
Every field, in the order a designated initializer names them:
ui::RadioButton{
.text, .checked, .style, .margin, .width, .height, .min_width, .min_height, .max_width,
.max_height, .horizontal_alignment, .vertical_alignment, .visible, .tool_tip, .enabled,
.accessibility, .on_checked_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 | |
|---|---|---|---|
text |
ui::Binding<std::string> |
The label right of the dot. | |
checked |
ui::TwoWayField<bool> |
{false} |
Whether the button is selected; seeding it raises nothing. ui::selects() makes it one choice of a property's values and groups it with the other buttons bound to that property. |
on_checked_changed |
ui::Callback<void(bool)> |
The new checked state, whenever it changes (a click, the group, 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::RadioButton> |
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::RadioButtonControl; the caller owns it.
ui::RadioButtonControl¶
Derives from ui::Element, ui::SelectionItemProvider.
A round option button with a label, one of a set of mutually exclusive choices.
Clicking it (or Space while focused) checks it; clicking an already-checked RadioButton does nothing, so the user can turn a lone button on but never off. The button doesn't uncheck the others by itself. Register the buttons with a RadioGroup, which doesn't own them, or use RadioButtons, which owns and lays out a whole set. ui::RadioButton is the declarative form of a single button.
Example:
auto stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
ui::RadioButtonControl* small = stack->add(std::make_unique<ui::RadioButtonControl>("Small", true));
ui::RadioButtonControl* large = stack->add(std::make_unique<ui::RadioButtonControl>("Large"));
ui::RadioGroup group;
group.add(small); // already checked: becomes the initial selection
group.add(large);
group.on_change([](ui::RadioButtonControl* chosen) { /* chosen->text() */ });
large->on_checked_changed([](bool checked) { /* fires for checks and unchecks */ });
window.set_content(std::move(stack));
RadioButtonControl¶
An unchecked, enabled button with no label.
RadioButtonControl¶
A button labeled text (UTF-8). Seeding checked fires nothing, since no handler is attached yet.
text¶
The label right of the dot; also the automation name when none is set.
set_text¶
Sets the label. The button is measured again and redrawn.
checked¶
Whether the button is selected; false by default.
set_checked¶
Sets the checked flag without unchecking the other buttons of a RadioGroup. RadioGroup::select() calls it to update every member. Call it yourself only on a standalone RadioButton with no group.
on_checked_changed¶
Invoked with the new state whenever checked changes. Replaces any previous handler.
parallel_measure_safe¶
True: measuring reads only the button's own state, the measurer and the theme.
focused¶
Whether the button has keyboard focus.
focusable¶
Whether this element can take keyboard focus (a leaf control opts in).
is_pressed¶
Whether a press is in progress: the pointer held down over the button, or Space held.
automation_role¶
Exposed to UI Automation as a RadioButton with a SelectionItem pattern.
automation_name_fallback¶
automation_name()'s fallback when accessibility().name is empty. Default: no inherent name, correct for controls with no visible text of their own (Slider, ProgressBar), which need an explicit accessibility().name from the caller. A control with its own visible text (Button, CheckBox, TextControl, ...) overrides this to return it.
selection_group¶
The property this button was bound to with ui::selects(), which groups it with the other buttons bound to it (Element::selection_group()); nullptr otherwise.
visual_state¶
The state the button is drawn in: Disabled, Pressed, Hover or Normal, in that priority.
measure_override¶
The dot plus the measured label.
pointer_override¶
A left click released over the button checks it (through its group, if any).
render_override¶
Draws the ring, the checked dot and the label.
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¶
Losing focus cancels a Space press in progress.
key_override¶
Space pressed and released while focused checks the button, like a click.
draws_focus_ring¶
Not while a RadioButtons owns it: the group rings it.
focus_ring_rect¶
Around dot and label, or the dot alone in Metro's era.
focus_ring_corner_radius¶
The ring's corner radius: the theme's control radius by default.
class RadioGroup¶
Makes a set of loose RadioButtons mutually exclusive. Not an element: it holds non-owning observers of buttons owned elsewhere in the tree.
Every registered button that is clicked (or activated with Space or UI Automation) is routed through select(), which checks it and unchecks the rest. The group and its buttons may be destroyed in either order: a button that goes leaves the group, and a group that goes leaves its buttons plain radio buttons. For a headed, laid-out group selected by index, use RadioButtons instead.
Example:
ui::RadioGroup group;
auto stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
ui::RadioButtonControl* a = stack->add(std::make_unique<ui::RadioButtonControl>("A", true));
ui::RadioButtonControl* b = stack->add(std::make_unique<ui::RadioButtonControl>("B"));
group.add(a); // already checked: the initial selection
group.add(b);
group.on_change([](ui::RadioButtonControl* now) { /* now->text() */ });
group.select(b); // programmatic: checks B, unchecks A, fires on_change once
window.set_content(std::move(stack));
RadioGroup¶
A group with no members.
~RadioGroup¶
Lets go of every member; the buttons stay as they are.
RadioGroup¶
Not copyable or movable: its buttons point at it.
operator=¶
Not copyable or movable: its buttons point at it.
add¶
Registers button (a non-owning observer) with this group. If the button is already checked and no member has been selected yet, it becomes the initial selection. Otherwise the selection waits for select() or a click. A button belongs to one group: adding it takes it out of the one it was in.
remove¶
Takes button out of the group, keeping its checked state. False when it is not a member. A member that is destroyed leaves by itself.
select¶
Checks selected and unchecks every other member, then fires on_change() once. Does nothing if selected is already the current selection, so clicking the checked button again changes nothing. A click on a member calls it, and an app may call it to select a member from code.
selected¶
The current selection (non-owning), or nullptr before anything was selected.
on_change¶
Fired once per selection change with the newly selected button, after every member's checked state is updated. Replaces any previous handler.
Tests¶
tests/test_radio_button.cpp