Skip to content

AppBarButton

Header: winui/ui/menus/AppBarButton.hpp. Spec: winui/ui/menus/AppBarButton.hpp.

A command-bar button: an icon over a small label that changes shape with where it sits.

On its own it is full size: 68 DIPs wide, at least 64 tall, with the label under the icon. Inside a CommandBar the bar sets its look. It is compact while the bar is closed, with the label on the right or hidden as the bar's default says, or a full-width row in the overflow menu with icon, check and shortcut columns. A Command fills in the text, icon, shortcut and tooltip the button leaves unset and follows their changes. The command runs after the click handler and disables the button while the command is disabled. The shortcut fires app-wide. Clicking a command in a bar closes the bar.

Example:

auto bar = std::make_unique<ui::CommandBarControl>();
auto* save = bar->add_primary(std::make_unique<ui::AppBarButtonControl>("Save", ui::Symbol::Save));
save->set_shortcut(ui::Ctrl + ui::Key::S); // tooltip reads "Save (Ctrl+S)"
save->on_click([] { /* save */ });

auto* share = bar->add_secondary(std::make_unique<ui::AppBarButtonControl>("Share", ui::Symbol::Share));
share->set_text_position(ui::CommandBarTextPosition::Collapsed);
window.set_content(std::move(bar));

// Declaratively:
window.set_content(ui::CommandBar{
    .primary = {ui::AppBarButton{.text     = "Save",
                                 .icon     = ui::Symbol::Save,
                                 .shortcut = ui::Ctrl + ui::Key::S,
                                 .on_click = [] { /* save */ }}},
});

ui::AppBarButton

A command-bar button: an icon over a small label. Builds a ui::AppBarButtonControl. On its own it is full size (68 by 64 DIPs, the label under the icon). In a ui::CommandBar the bar sets its look.

Example:

window.set_content(ui::CommandBar{
    .primary = {
        ui::AppBarButton{ .text     = "Save",
                          .icon     = ui::Symbol::Save,
                          .shortcut = ui::Ctrl + ui::Key::S,
                          .on_click = [&] { save(); } },
        ui::AppBarButton{ .text = "Share", .icon = ui::Symbol::Share },
    },
});

Every field, in the order a designated initializer names them:

ui::AppBarButton{
    .text, .icon, .text_position, .compact, .shortcut, .dynamic_overflow_order, .style,
    .margin, .width, .height, .min_width, .min_height, .max_width, .max_height,
    .horizontal_alignment, .vertical_alignment, .visible, .tool_tip, .enabled, .accessibility,
    .command, .command_parameter, .on_click, .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 text under (or beside) the icon, and the default tooltip and accessible name.
icon ui::Binding<ui::IconSource> A Symbol, an IconGlyph, or any other IconSource.
text_position ui::Binding<ui::CommandBarTextPosition> {ui::CommandBarTextPosition::Default} Collapsed hides this button's text whatever the bar's default says.
compact bool false Draws the button without its text. A CommandBar sets this itself while closed.
shortcut ui::Binding<ui::KeyCombo> The keyboard shortcut, which fires app-wide and clicks the button.
dynamic_overflow_order ui::Binding<int> {0} When the bar runs out of room, the lowest positive order moves into the overflow first (a whole group at once); 0 moves last, from the right.
command ui::CommandRef The command, which also fills the text, icon, shortcut and tooltip left unset.
command_parameter std::string Handed to the command's execute.
on_click ui::Action Fires on a pointer click, Enter/Space, or the shortcut. In an open bar it also closes it.
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::AppBarButton> 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

std::unique_ptr<Element> build()&&

Consumes the spec and returns the built ui::AppBarButtonControl; the caller owns it.

ui::AppBarToggleButton

A command-bar button that stays pressed. Builds a ui::AppBarToggleButtonControl. Apart from the checked state it works like ui::AppBarButton. .checked bound with ui::bind() to a Property<std::optional<bool>> is two-way: a click writes the new state back.

Example:

ui::Property<std::optional<bool>> bold{false};

window.set_content(ui::CommandBar{
    .primary = {
        ui::AppBarToggleButton{ .text     = "Bold",
                                .checked  = bold,
                                .icon     = ui::Symbol::Bold,
                                .shortcut = ui::Ctrl + ui::Key::B },
    },
});

Every field, in the order a designated initializer names them:

ui::AppBarToggleButton{
    .text, .checked, .three_state, .icon, .text_position, .compact, .shortcut,
    .dynamic_overflow_order, .style, .margin, .width, .height, .min_width, .min_height,
    .max_width, .max_height, .horizontal_alignment, .vertical_alignment, .visible, .tool_tip,
    .enabled, .accessibility, .command, .command_parameter, .on_click, .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 text under (or beside) the icon, and the default tooltip and accessible name.
checked ui::CheckedField {false} True, false, or std::nullopt for indeterminate. Seeding it raises nothing. Two-way with a Property<bool> (a click writes true or false; an indeterminate state set on the control writes nothing) or a Property<std::optional<bool>> (every state). See ui::CheckedField.
three_state bool false A click also reaches indeterminate: unchecked, checked, indeterminate, unchecked. Without it, a click on an indeterminate box checks it. Needs checked bound to a Property<std::optional<bool>> (or one-way), since a Property<bool> cannot hold the third state; a debug build asserts on that. Read once, when the spec is built.
icon ui::Binding<ui::IconSource> A Symbol, an IconGlyph, or any other IconSource.
text_position ui::Binding<ui::CommandBarTextPosition> {ui::CommandBarTextPosition::Default} Collapsed hides this button's text whatever the bar's default says.
compact bool false Draws the button without its text. A CommandBar sets this itself while closed.
shortcut ui::Binding<ui::KeyCombo> The keyboard shortcut, which fires app-wide and toggles the button.
dynamic_overflow_order ui::Binding<int> {0} The overflow order; see ui::AppBarButton::dynamic_overflow_order.
command ui::CommandRef The command, which also fills the text, icon, shortcut and tooltip left unset.
command_parameter std::string Handed to the command's execute.
on_click ui::Action Fires on a click, after the state has toggled.
on_checked_changed ui::Callback<void(std::optional<bool>)> Fires with the new state on every change.
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::AppBarToggleButton> 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

std::unique_ptr<Element> build()&&

Consumes the spec and returns the built ui::AppBarToggleButtonControl; the caller owns it.

ui::AppBarSeparator

The rule between groups of commands. Builds a ui::AppBarSeparatorControl.

Example:

window.set_content(ui::CommandBar{
    .primary = { ui::AppBarButton{ .text = "Cut", .icon = ui::Symbol::Cut },
                 ui::AppBarButton{ .text = "Copy", .icon = ui::Symbol::Copy },
                 ui::AppBarSeparator{},
                 ui::AppBarButton{ .text = "Delete", .icon = ui::Symbol::Delete } },
});

Every field, in the order a designated initializer names them:

ui::AppBarSeparator{
    .style, .margin, .width, .height, .min_width, .min_height, .max_width, .max_height,
    .horizontal_alignment, .vertical_alignment, .visible, .tool_tip, .accessibility,
    .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
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::AppBarSeparator> 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, accessibility every spec carries (conventions).

build

std::unique_ptr<Element> build()&&

Consumes the spec and returns the built ui::AppBarSeparatorControl; the caller owns it.

ui::AppBarButtonControl

Derives from ui::ButtonControl, ui::CommandBarElement.

A command-bar button: an icon over a small label that changes shape with where it sits.

On its own it is full size: 68 DIPs wide, at least 64 tall, with the label under the icon. Inside a CommandBar the bar sets its look. It is compact while the bar is closed, with the label on the right or hidden as the bar's default says, or a full-width row in the overflow menu with icon, check and shortcut columns. A Command fills in the text, icon, shortcut and tooltip the button leaves unset and follows their changes. The command runs after the click handler and disables the button while the command is disabled. The shortcut fires app-wide. Clicking a command in a bar closes the bar.

Example:

auto bar = std::make_unique<ui::CommandBarControl>();
auto* save = bar->add_primary(std::make_unique<ui::AppBarButtonControl>("Save", ui::Symbol::Save));
save->set_shortcut(ui::Ctrl + ui::Key::S); // tooltip reads "Save (Ctrl+S)"
save->on_click([] { /* save */ });

auto* share = bar->add_secondary(std::make_unique<ui::AppBarButtonControl>("Share", ui::Symbol::Share));
share->set_text_position(ui::CommandBarTextPosition::Collapsed);
window.set_content(std::move(bar));

// Declaratively:
window.set_content(ui::CommandBar{
    .primary = {ui::AppBarButton{.text     = "Save",
                                 .icon     = ui::Symbol::Save,
                                 .shortcut = ui::Ctrl + ui::Key::S,
                                 .on_click = [] { /* save */ }}},
});

AppBarButtonControl

AppBarButtonControl()

An empty button, aligned left and top in whatever slot it gets.

AppBarButtonControl

AppBarButtonControl(std::string text, IconSource icon = {})

A button showing text under icon (a Symbol, an IconGlyph or any other IconSource).

text

std::string text() const

The text under (or beside) the icon, also the default tooltip and accessible name. Falls back to the command's text. Set it with ButtonControl::set_text().

icon

const IconSource& icon() const

The icon, 16 DIPs in the bar. Falls back to the command's icon.

set_icon

void set_icon(IconSource icon)

Sets the icon; updates the layout and redraws.

text_position

CommandBarTextPosition text_position() const

Collapsed hides the text whatever the bar's default; Default (the default) follows the bar.

set_text_position

void set_text_position(CommandBarTextPosition position)

Sets the text position; updates the layout and redraws.

is_compact

bool is_compact() const

Whether the button is drawn compact, without its text. A CommandBar sets it while closed.

set_compact

void set_compact(bool compact)

Sets the compact flag through set_app_bar_look(); updates the layout and redraws.

shortcut

KeyCombo shortcut() const

The keyboard shortcut, which fires app-wide and clicks the button. Falls back to the command's.

set_shortcut

void set_shortcut(KeyCombo shortcut)

Sets the shortcut; updates the layout, since the overflow sizes its shortcut column by it, and redraws.

set_shortcut_text

void set_shortcut_text(std::string text)

The shortcut text shown in the overflow and the tooltip in place of the one derived from shortcut() (e.g. "Ctrl+Shift+Del" for a custom binding). Empty uses the derived text.

set_app_bar_look

void set_app_bar_look(const AppBarLook& look) override

Takes the holding bar's look; updates the layout and redraws.

has_text

bool has_text() const override

True when text() (own or the command's) is non-empty.

shortcut_text

std::string shortcut_text() const override

The shortcut text override, or the shortcut formatted as "Ctrl+S"; empty for none.

has_icon

bool has_icon() const override

True when icon() (own or the command's) is set.

parallel_measure_safe

bool parallel_measure_safe() const override

True: the button can be measured in parallel with other elements, since measuring reads only its text and icon.

tool_tip

std::string tool_tip() const override

An explicit tooltip, else the command's description, else "Text (Ctrl+S)" outside the overflow (empty inside it).

handle_global_shortcut

bool handle_global_shortcut(const KeyEvent& e) override

Clicks the button when e matches shortcut() and the button is enabled; true if handled.

automation_name_fallback

std::string automation_name_fallback() const override

The text, when no accessible name was set.

on_activated

void on_activated() override

Tells the command host a command ran, which closes the bar (not when the button opens a flyout).

toggle_state

virtual std::optional<std::optional<bool>> toggle_state() const

The toggle's checked state; nullopt for a plain button. AppBarToggleButton overrides it so the shared rendering can draw the checked look.

plate_rect

Rect plate_rect() const

The hover plate: the part of the button that takes a background.

measure_override

Size measure_override(Size available, const MeasureContext& context) const override

Sizes for the current mode: full size, compact, label on the right, collapsed or an overflow row.

arrange_override

void arrange_override(const Rect& final_rect, const ArrangeContext& context) override

Positions the icon, label and hover plate for the current mode.

render_override

void render_override(Renderer& renderer, const RenderContext& context) const override

Draws the hover plate, icon, label, flyout chevron, and in the overflow the check and shortcut.

focus_ring_rect

Rect focus_ring_rect(const Theme&) const override

Around the hover plate inside the button.

class AppBarToggleButtonControl

Derives from ui::AppBarButtonControl, ui::ToggleProvider.

An app-bar button with a checked state, drawn as the accent button in the bar and as a check mark in the overflow.

A click advances the checked state (unchecked, checked, then indeterminate when three_state()) and fires on_checked_changed().

Example:

auto bar  = std::make_unique<ui::CommandBarControl>();
auto* bold = bar->add_primary(std::make_unique<ui::AppBarToggleButtonControl>("Bold", ui::Symbol::Bold));
bold->set_shortcut(ui::Ctrl + ui::Key::B);
bold->on_checked_changed([](std::optional<bool> on) { /* apply bold when on == true */ });
window.set_content(std::move(bar));

// Declaratively, bound to state:
ui::Property<std::optional<bool>> is_bold{false};
window.set_content(ui::CommandBar{
    .primary = {ui::AppBarToggleButton{.text               = "Bold",
                                       .checked            = is_bold,
                                       .icon               = ui::Symbol::Bold,
                                       .on_checked_changed = [&](std::optional<bool> on) { is_bold = on; }}},
});

AppBarToggleButtonControl

AppBarToggleButtonControl()

An empty, unchecked toggle.

AppBarToggleButtonControl

AppBarToggleButtonControl(std::string text, IconSource icon = {}, std::optional<bool> checked = false)

A toggle showing text under icon, starting at checked (nullopt is indeterminate).

checked

std::optional<bool> checked() const

The checked state: true, false, or nullopt for indeterminate. Default false.

set_checked

void set_checked(std::optional<bool> checked)

Sets the checked state; redraws and fires on_checked_changed() when it changed.

three_state

bool three_state() const

Whether a click can reach indeterminate (checked, then indeterminate, then unchecked).

set_three_state

void set_three_state(bool three_state)

Enables the indeterminate step in the click cycle.

on_checked_changed

void on_checked_changed(Callback<void(std::optional<bool>)> handler)

Called with the new state whenever the checked state changes.

is_toggle

bool is_toggle() const override

Always true.

on_activated

void on_activated() override

Advances the checked state, then closes the holding bar as AppBarButton does.

toggle_state

std::optional<std::optional<bool>> toggle_state() const override

checked(), so the shared rendering draws the checked look.

class AppBarSeparatorControl

Derives from ui::Element, ui::CommandBarElement.

A 1px rule in the theme's divider color: vertical between groups of commands in the bar (padding 2,8,2,8), horizontal across the overflow menu (0,4,0,4 around it).

Example:

auto bar = std::make_unique<ui::CommandBarControl>();
bar->add_primary(std::make_unique<ui::AppBarButtonControl>("Cut", ui::Symbol::Cut));
bar->add_primary(std::make_unique<ui::AppBarButtonControl>("Copy", ui::Symbol::Copy));
bar->add_primary(std::make_unique<ui::AppBarSeparatorControl>());
bar->add_primary(std::make_unique<ui::AppBarButtonControl>("Delete", ui::Symbol::Delete));

AppBarSeparatorControl

AppBarSeparatorControl() = default

A separator; its orientation follows the look the bar sets.

set_app_bar_look

void set_app_bar_look(const AppBarLook& look) override

Switches between the bar's vertical rule and the overflow's horizontal one, and updates the layout.

is_separator

bool is_separator() const override

Always true.

automation_role

AutomationRole automation_role() const override

Exposed to UI Automation as a separator.

measure_override

Size measure_override(Size available, const MeasureContext& context) const override

5 DIPs wide in the bar (1px rule plus padding); a 9 DIP tall row in the overflow.

render_override

void render_override(Renderer& renderer, const RenderContext& context) const override

Draws the 1px rule in the theme's divider color.

class CommandBarElement

What a CommandBar needs of the things in it: the look it pushes down, the overflow order and the facts the overflow menu sizes its columns by. Mixed into AppBarButton, AppBarToggleButton and AppBarSeparator; use command_bar_element() to reach it from an Element.

look_

AppBarLook look_ {}

command_host_

AppBarCommandHost* command_host_ = nullptr

dynamic_overflow_order_

int dynamic_overflow_order_ = 0

~CommandBarElement

virtual ~CommandBarElement() = default

app_bar_look

const AppBarLook& app_bar_look() const

The look the holding bar last set (the default look on its own).

set_app_bar_look

virtual void set_app_bar_look(const AppBarLook& look) = 0

Applies a new look from the holding bar; implementations update their layout and redraw.

dynamic_overflow_order

int dynamic_overflow_order() const

Which commands move into the overflow first when the bar runs out of room. The lowest positive order goes first, a whole group at once, and 0 goes last, from the right.

set_dynamic_overflow_order

void set_dynamic_overflow_order(int order)

Sets the overflow order, which takes effect on the bar's next layout.

is_in_overflow

bool is_in_overflow() const

Whether the bar currently shows this element as an overflow-menu row.

has_text

virtual bool has_text() const

Whether there is text for a bar with Bottom text to reveal on opening. False by default.

shortcut_text

virtual std::string shortcut_text() const

The shortcut as display text ("Ctrl+S"), empty for none; sizes the overflow's shortcut column.

has_icon

virtual bool has_icon() const

Whether the element draws an icon; the overflow then reserves an icon column.

is_toggle

virtual bool is_toggle() const

True for AppBarToggleButton; the overflow then reserves a check column.

is_separator

virtual bool is_separator() const

True for AppBarSeparator.

set_command_host

void set_command_host(AppBarCommandHost* host)

Set by the CommandBar (or CommandBarFlyout) that holds the element: a click on a command closes the bar. Non-owning; null (the default) for a command on its own.

struct AppBarLook

How the CommandBar holding an app-bar element wants it drawn. A button on its own keeps the default: full size, text at the bottom. The bar pushes one down with CommandBarElement::set_app_bar_look() whenever its state changes; apps rarely build one.

Field Type Default
compact bool false the bar is closed
text_position CommandBarDefaultTextPosition CommandBarDefaultTextPosition::Bottom the bar's text position
overflow bool false a row of the overflow menu
overflow_icons bool false some overflow item has an icon
overflow_toggles bool false some overflow item is a toggle button
overflow_shortcut_width float 0.0f the widest shortcut text in the overflow
flyout_primary bool false a CommandBarFlyout's primary row: icon-only, 40x40
flyout_overflow bool false With overflow: a row of a CommandBarFlyout's secondary menu, which is laid out a little differently from a CommandBar's overflow row.

class AppBarCommandHost

What holds app-bar commands (a CommandBar, a CommandBarFlyout): told when one is clicked, so a bar can close after a click on one of its commands. Implement it only for a custom command container, and register it on each element with CommandBarElement::set_command_host().

command_invoked

virtual void command_invoked(CommandBarElement& command) = 0

Called after command's own click handler and command have run.

~AppBarCommandHost

~AppBarCommandHost() = default

Enumerations

CommandBarDefaultTextPosition

enum class CommandBarDefaultTextPosition

Where a CommandBar puts its buttons' text.

Value
Bottom Under the icon, revealed when the bar opens; the default.
Right Beside the icon, always visible.
Collapsed No text at all.

CommandBarTextPosition

enum class CommandBarTextPosition

Where one button puts its text. Collapsed hides it wherever the bar puts text, Default follows the bar.

Value
Default Follow the bar's CommandBarDefaultTextPosition.
Collapsed Never show this button's text.

Functions

command_bar_element

CommandBarElement* command_bar_element(Element* element)

The app-bar element element is, or wraps: an AppBarButton, AppBarToggleButton or AppBarSeparator, or the trigger of a flyout wrapped around one (an AppBarButton with a flyout, where the flyout owns its button). Null for anything else.

command_bar_element

const CommandBarElement* command_bar_element(const Element* element)

Const overload of command_bar_element().

Tests

  • tests/test_command_bar.cpp