ToolTip¶
Header: winui/ui/dialogs/ToolTip.hpp. Spec: winui/ui/dialogs/ToolTip.hpp.
Hover text for an element, opened after the pointer rests on the anchor and closed when the pointer leaves or clicks.
A ToolTip wraps its anchor. It takes the anchor's place in the tree and passes layout, rendering, input, focus and automation through, so the anchor behaves as it would unwrapped. The tip content lives outside the main tree. The window lays it out and draws it on the theme's tooltip surface. The open delay counts down in tick_override(), so the host must tick the Window, as the built-in window host does. A tip opened by the mouse docks to the pointer, inflated by the offsets. For plain text on any element, Element::set_tool_tip() is shorter.
Example:
auto toolbar = std::make_unique<ui::StackControl>(ui::Orientation::Horizontal);
auto tip = std::make_unique<ui::ToolTipControl>();
auto* save = tip->set_anchor(std::make_unique<ui::ButtonControl>("Save"));
tip->set_content(std::make_unique<ui::TextControl>("Saves the current document"));
tip->set_placement(ui::PopupPlacement::Below);
save->on_click([] { save_document(); });
toolbar->add(std::move(tip)); // the ToolTip takes the Button's place in the tree
// Declaratively:
toolbar->add(ui::ToolTip{
.anchor = ui::Button{.text = "Save"},
.content = ui::Text{.text = "Saves the current document"},
}.build());
ui::ToolTip¶
A hover tip over an anchor. Builds a ui::ToolTipControl.
The built element wraps the anchor, which lays out and takes input as usual; the tip shows after the pointer rests on it for .delay and hides on a press, a key or the pointer leaving.
Example:
window.set_content(ui::ToolTip{
.placement = ui::PopupPlacement::Below,
.anchor = ui::Button{ .text = "Open", .on_click = [&] { open_file(); } },
.content = ui::Text{ .text = "Open a document from disk" },
});
Every field, in the order a designated initializer names them:
ui::ToolTip{
.delay, .placement, .horizontal_offset, .vertical_offset, .placement_rect, .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,
.anchor, .content
}
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
delay |
ui::Binding<ui::Duration> |
{ui::Duration{800.0}} |
How long the pointer must rest on the anchor before the tip opens; 800 ms by default. |
placement |
ui::Binding<ui::PopupPlacement> |
{ui::PopupPlacement::Above} |
Which side of the pointer (or placement_rect) the tip sits on. |
horizontal_offset |
ui::Binding<float> |
{20.0f} |
How far the dock rect is inflated on the left and right, in DIPs. |
vertical_offset |
ui::Binding<float> |
{20.0f} |
How far the dock rect is inflated on the top and bottom, in DIPs. |
placement_rect |
ui::Binding<std::optional<ui::Rect>> |
A rect in the anchor's coordinates to dock to instead of the pointer. | |
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::ToolTip> |
Out: the handle that receives the built control. | |
anchor |
ui::Spec |
The element the tip belongs to; it takes the ToolTip's place in the layout. | |
content |
ui::Spec |
What the tip shows, usually a ui::Text. |
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¶
Consumes the spec and returns the built ui::ToolTipControl; the caller owns it.
ui::ToolTipControl¶
Derives from ui::Element.
Hover text for an element, opened after the pointer rests on the anchor and closed when the pointer leaves or clicks.
A ToolTip wraps its anchor. It takes the anchor's place in the tree and passes layout, rendering, input, focus and automation through, so the anchor behaves as it would unwrapped. The tip content lives outside the main tree. The window lays it out and draws it on the theme's tooltip surface. The open delay counts down in tick_override(), so the host must tick the Window, as the built-in window host does. A tip opened by the mouse docks to the pointer, inflated by the offsets. For plain text on any element, Element::set_tool_tip() is shorter.
Example:
auto toolbar = std::make_unique<ui::StackControl>(ui::Orientation::Horizontal);
auto tip = std::make_unique<ui::ToolTipControl>();
auto* save = tip->set_anchor(std::make_unique<ui::ButtonControl>("Save"));
tip->set_content(std::make_unique<ui::TextControl>("Saves the current document"));
tip->set_placement(ui::PopupPlacement::Below);
save->on_click([] { save_document(); });
toolbar->add(std::move(tip)); // the ToolTip takes the Button's place in the tree
// Declaratively:
toolbar->add(ui::ToolTip{
.anchor = ui::Button{.text = "Save"},
.content = ui::Text{.text = "Saves the current document"},
}.build());
ToolTipControl¶
An empty tooltip: no anchor, no content, 800 ms delay, placed Above.
set_anchor¶
Takes ownership of the anchor element, the element the tip describes, and returns a non-owning observer, as FlyoutControl::set_anchor() and ScrollControl::set_child() do. Replaces and destroys any previous anchor.
anchor¶
The anchor, or null before set_anchor(). Owned by this ToolTip.
set_content¶
Takes ownership of the floating hover content and returns a non-owning observer. The content is not part of the main tree. The window lays it out and draws it separately. The tooltip's background, border and padding come from the theme, so the content needs none.
content¶
The floating content, or null before set_content(). Owned by this ToolTip.
is_open¶
Whether the tip is showing. It opens once the hover delay elapses or show_at() is called. It closes when the pointer leaves, on a click, on close(), or when the popup is dismissed.
delay¶
How long the pointer must stay over the anchor before the tooltip opens; 800 ms by default.
set_delay¶
Sets the delay. It also applies to a countdown already running, which keeps its elapsed time.
placement¶
Which side of the dock rect the tooltip opens against; Above by default. It flips to Below near the top edge of the window.
set_placement¶
Sets the side. Takes effect the next time the popup is placed.
horizontal_offset¶
How far the dock rect is inflated on the left and right before the tooltip is placed against it, in DIPs; 20 by default. vertical_offset() does the same for the top and bottom.
set_horizontal_offset¶
Sets the horizontal inflation in DIPs. A negative value shrinks the dock rect, pulling the tip over it.
vertical_offset¶
The vertical inflation in DIPs; 20 by default. See horizontal_offset().
set_vertical_offset¶
Sets the vertical inflation in DIPs.
placement_rect¶
The placement rect, in the anchor's own coordinates. The tooltip docks to it instead of the pointer, so it opens beside the rect and doesn't cover what it describes.
set_placement_rect¶
Sets or clears the placement rect. nullopt docks to the pointer again.
focusable¶
Focusable exactly when the anchor is; focus itself goes to the anchor.
for_each_child¶
The anchor, if any. The tip's content is popup content, outside the tree.
collect_focusables¶
The tip stands in for its anchor as one tab stop. Focus itself goes to the anchor.
automation_children¶
No automation children: the anchor is not listed under the tip.
automation_role¶
The anchor's role, name and providers, so screen readers see the anchor. With no anchor, a Group with nothing to act on.
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.
show_at¶
Opens the tip now, docked to pointer (window DIPs) as a tip opened by the mouse is, whatever the pointer does over the anchor. The window shows Element::set_tool_tip() text this way. Calling it while open moves the dock point.
close¶
Closes the tip and resets the hover countdown. Nothing changes on screen when it is already closed.
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¶
Forwards every event to the anchor and tracks hover. A move starts the countdown, leaving cancels it or closes the tip, and a press closes the tip.
handled_pointer_override¶
A press the anchor took closes the tip too.
tick_override¶
Ticks the anchor, then advances the hover countdown and opens the tip once it reaches delay().
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.
text_override¶
Typed text for this element, routed like key_override(). Default: false.
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_visible_changed¶
focus_visible() changed; the element is redrawn either way. No-op by default.
draws_focus_ring¶
None of its own: the anchor inside it draws its own focus ring.
Tests¶
tests/test_tool_tip.cpp