InfoBar¶
Header: winui/ui/status/InfoBar.hpp. Spec: winui/ui/status/InfoBar.hpp.
An inline, closable banner that shows an app-wide status message with a severity color and icon.
A freshly built bar is closed: it takes no room and draws nothing until set_open(true). Title, message and the optional action button sit on one line when they fit and stack (wrapping at whole words) when they don't; the bar is at least 48 DIPs tall. Optional custom content (set_content()) gets a row of its own below them. The InfoBar itself is never a tab stop. Its action button, its content's controls and its close button are.
Closing runs in a fixed order: a close-button click first raises on_close_button_click(), then on_closing() (return ui::Cancel to keep it open, leaving is_open() true). Only a close that goes ahead flips is_open() to false and raises on_closed(). set_open(false) runs the same on_closing() and on_closed() sequence with reason Programmatic. Reopening raises nothing.
Example:
// Declarative, with the open state in a Property:
ui::Property<bool> open{true};
window.set_content(ui::InfoBar{
.title = "Update available",
.message = "Restart the app to apply the update.",
.is_open = open,
.severity = ui::InfoBarSeverity::Success,
.on_closed = [&open](ui::PopupCloseReason) { open = false; },
.action_button_content = ui::Button{.text = "Restart", .on_click = [] { restart_app(); }},
});
// Imperative:
auto stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* bar = stack->add(std::make_unique<ui::InfoBarControl>("Offline", "Changes will sync later.",
ui::InfoBarSeverity::Warning, true));
bar->on_closing([](const ui::PopupClosingArgs& args) {
return args.reason == ui::PopupCloseReason::Programmatic ? ui::Cancel : ui::Proceed; // keep it open
});
bar->set_action_button_content(std::make_unique<ui::ButtonControl>("Retry"))->on_click([] { save(); });
ui::InfoBar¶
An inline status banner. Builds a ui::InfoBarControl. Closed by default, matching the control.
The handlers are installed before is_open is bound, so a bound is_open flipping back to false raises .on_closing/.on_closed like any other close.
Example:
ui::Property<bool> update_ready{true};
window.set_content(ui::InfoBar{
.title = "Update available",
.message = "Restart to install.",
.is_open = update_ready, // two-way: closing the bar writes false
.severity = ui::InfoBarSeverity::Success,
.action_button_content = ui::Button{.text = "Restart", .on_click = [&] { restart_app(); }},
});
Every field, in the order a designated initializer names them:
ui::InfoBar{
.title, .message, .is_open, .severity, .closable, .icon_visible, .style, .margin, .width,
.height, .min_width, .min_height, .max_width, .max_height, .horizontal_alignment,
.vertical_alignment, .visible, .tool_tip, .enabled, .accessibility, .on_close_button_click,
.on_closing, .on_closed, .on_pointer_entered, .on_pointer_exited, .on_got_focus,
.on_lost_focus, .on_key_down, .on_wheel, .control, .action_button_content, .content
}
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
title |
ui::Binding<std::string> |
The bold title, first on the line. | |
message |
ui::Binding<std::string> |
The message after the title. | |
is_open |
ui::TwoWayField<bool> |
{false} |
A closed bar takes no room. ui::bind(prop) is two-way: closing the bar writes false into the property, and a false that on_closing cancels is put back to true. |
severity |
ui::Binding<ui::InfoBarSeverity> |
{ui::InfoBarSeverity::Informational} |
Picks the background color and the status icon. |
closable |
ui::Binding<bool> |
{true} |
Shows the close button. |
icon_visible |
ui::Binding<bool> |
{true} |
Shows the severity icon. |
on_close_button_click |
ui::Action |
The close button was clicked, before .on_closing. |
|
on_closing |
ui::Callback<ui::Decision(const ui::PopupClosingArgs&)> |
Why it is about to close; return ui::Cancel to keep it open. | |
on_closed |
ui::Callback<void(ui::PopupCloseReason)> |
The bar has closed, and why. | |
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::InfoBar> |
Out: the handle that receives the built control. | |
action_button_content |
ui::Spec |
A button placed after the message, usually a ui::Button, with ButtonVariant::Hyperlink for a link. |
|
content |
ui::Spec |
Custom content on a row of its own below the title, message and action (in their place when all three are empty), across the full width up to the close button. |
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::InfoBarControl; the caller owns it.
ui::InfoBarControl¶
Derives from ui::Element.
An inline, closable banner that shows an app-wide status message with a severity color and icon.
A freshly built bar is closed: it takes no room and draws nothing until set_open(true). Title, message and the optional action button sit on one line when they fit and stack (wrapping at whole words) when they don't; the bar is at least 48 DIPs tall. Optional custom content (set_content()) gets a row of its own below them. The InfoBar itself is never a tab stop. Its action button, its content's controls and its close button are.
Closing runs in a fixed order: a close-button click first raises on_close_button_click(), then on_closing() (return ui::Cancel to keep it open, leaving is_open() true). Only a close that goes ahead flips is_open() to false and raises on_closed(). set_open(false) runs the same on_closing() and on_closed() sequence with reason Programmatic. Reopening raises nothing.
Example:
// Declarative, with the open state in a Property:
ui::Property<bool> open{true};
window.set_content(ui::InfoBar{
.title = "Update available",
.message = "Restart the app to apply the update.",
.is_open = open,
.severity = ui::InfoBarSeverity::Success,
.on_closed = [&open](ui::PopupCloseReason) { open = false; },
.action_button_content = ui::Button{.text = "Restart", .on_click = [] { restart_app(); }},
});
// Imperative:
auto stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* bar = stack->add(std::make_unique<ui::InfoBarControl>("Offline", "Changes will sync later.",
ui::InfoBarSeverity::Warning, true));
bar->on_closing([](const ui::PopupClosingArgs& args) {
return args.reason == ui::PopupCloseReason::Programmatic ? ui::Cancel : ui::Proceed; // keep it open
});
bar->set_action_button_content(std::make_unique<ui::ButtonControl>("Retry"))->on_click([] { save(); });
InfoBarControl¶
A closed bar, which takes no room and draws nothing until opened.
InfoBarControl¶
InfoBarControl(std::string title, std::string message, InfoBarSeverity severity = InfoBarSeverity::Informational, bool is_open = false)
A bar with its title, message and severity set, open or (by default) closed.
title¶
The bold title, first on the line; empty by default.
set_title¶
Sets the title (UTF-8). Updates the layout.
message¶
The message after the title, wrapped at whole words when the bar stacks.
set_message¶
Sets the message (UTF-8). Updates the layout.
severity¶
The severity; Informational by default.
set_severity¶
Sets the severity, changing the background and icon; redraws.
is_icon_visible¶
Whether the severity icon shows at the left; true by default.
set_icon_visible¶
Shows or hides the severity icon. Updates the layout.
is_open¶
Whether the bar shows; false by default.
set_open¶
Setting false runs the closing sequence, which on_closing() can cancel, with reason Programmatic. Setting true always reopens. Does nothing, and raises nothing, if the value is unchanged.
is_closable¶
Whether the close button shows; true by default.
set_closable¶
Shows/hides the owned close button; true by default.
enabled¶
A disabled bar grays out its close button, which then takes no input. The action button and the content keep their own state.
set_action_button_content¶
Takes ownership of the action element (normally a Button, or one with ButtonVariant::Hyperlink) and returns a non-owning observer. It sits after the message.
action_button_content¶
The action element (non-owning), or nullptr.
clear_action_button_content¶
Removes and destroys the action element. Updates the layout.
set_content¶
Takes ownership of custom content and returns a non-owning observer; a null content clears it. The content gets the full width between the icon and the close button, on its own row below the title, message and action. With no title, message or action it moves up into their row instead, centered against the icon and close button. The bar never stacks or wraps it as it does the message. The content lays itself out in the width it is given.
content¶
The custom content (non-owning), or nullptr.
clear_content¶
Removes and destroys the custom content. Updates the layout.
on_close_button_click¶
Fired on every close-button click, before on_closing(), whether or not the close is then canceled.
on_closing¶
Runs before is_open() flips to false. Returning ui::Cancel keeps the bar open, and is_open() stays true throughout.
on_closed¶
Fired once a close goes ahead, that is when on_closing() did not cancel it.
close_button_bounds¶
The close button's own rect from the most recent arrange(), for hit-testing. Empty while the close button is hidden.
title_bounds¶
The title's rect from the most recent arrange().
message_bounds¶
The message's rect from the most recent arrange().
content_bounds¶
The slot the custom content was last arranged into (before its own margin and alignment): below the title row, or the title row itself when the bar has no title, message or action. Empty without content.
is_vertical¶
Whether the last measure() stacked title, message and action.
for_each_child¶
Every owned child that currently takes part in input, focus and rendering, in tab order: the action, then the custom content, while open; the close button while open and closable.
automation_role¶
What screen readers and other assistive tools see of this node: the role, name, help text and children here, and what a client can do with the node through the providers automation_providers() lists (ui/Automation.hpp).
automation_role() is the role this node reports; Group by default.
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.
measure_override¶
At least 48 DIPs tall, taller when the content stacks (see is_vertical()) or custom content adds its row. Zero size while closed.
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().
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¶
A key for this element: the focused one, or one inside it that did not handle it. Return true when the key did something here, and it goes no further; false lets it bubble on to the parent and then to the shortcuts, a dialog's default button and arrow-key focus moves. Default: false.
Enumerations¶
InfoBarSeverity¶
How serious an InfoBar's message is; picks the bar's background color and its status icon.
| Value | |
|---|---|
Informational |
neutral background, info icon (the default) |
Success |
success background, check-mark icon |
Warning |
caution background, warning icon |
Error |
critical background, error icon |
Tests¶
tests/test_info_bar.cpp