ui¶
Namespace-scope declarations of ui from the core headers.
Enumerations¶
Handling¶
Header: winui/core/Callback.hpp.
What a handler asked to act returns: whether it dealt with the event, so it goes no further. Written as the constants ui::Handled and ui::NotHandled. A handler that returns nothing gets its event's default: handled where the handler is the target asked to act (a shortcut, a context-menu request), not handled where it watches events pass by (Window::on_key_preview).
| Value | |
|---|---|
Handled |
Dealt with; the event goes no further. |
NotHandled |
Not this handler's; the event goes on. |
Decision¶
Header: winui/core/Callback.hpp.
What a handler asked before something happens returns: let it go ahead, or stop it (a window closing, an edit starting or being committed, a sort). Written as the constants ui::Proceed and ui::Cancel. A handler that returns nothing lets it proceed.
| Value | |
|---|---|
Proceed |
Go ahead. |
Cancel |
Stop it; nothing changes. |
DirtyFlags¶
Header: winui/core/DirtyFlags.hpp.
Bitmask of what about an Element is out of date and must be redone at the next layout pass.
Setters mark flags on their element and the bits bubble to every ancestor, so a host can ask the root whether anything below it changed. On the element itself Measure and Arrange also say its own last measure or arrange is out of date. On an ancestor they only say something below needs it. Combine with |, test with & or any(), clear with &= ~flags. Read back through Element::is_dirty() / Element::dirty_flags(); Window::layout() clears them.
Example:
// In a custom control, each setter marks what its change invalidates.
class TagControl : public ui::Element
{
public:
void set_label(std::string label)
{
if (label_ != label)
{
label_ = std::move(label);
mark_dirty(ui::DirtyFlags::Layout | ui::DirtyFlags::Visual); // new size and new look
}
}
void set_highlighted(bool highlighted)
{
if (highlighted_ != highlighted)
{
highlighted_ = highlighted;
mark_dirty(ui::DirtyFlags::Visual); // same size and place, only a redraw
}
}
private:
std::string label_;
bool highlighted_ = false;
};
// Outside the element: has anything below the panel changed size since the last layout pass?
bool needs_measure(const ui::Element& panel)
{
return panel.is_dirty(ui::DirtyFlags::Measure); // measured again at the next layout
}
| Value | |
|---|---|
None |
Up to date. |
Measure |
The desired size must be recomputed, and so the arrangement too. |
Visual |
Appearance changed (color, focus ring, scroll offset, ...); size and place unaffected. |
Arrange |
The place of the element or its children changed, its desired size did not. |
Layout |
Measure and arrange: what a size-affecting setter marks. |
All |
Every flag; the default mask of the queries. |
Orientation¶
Header: winui/core/Geometry.hpp.
The axis a control runs along: a stack's direction, a slider's track, a pager's row of pips.
| Value | |
|---|---|
Horizontal |
left to right |
Vertical |
top to bottom |
CursorShape¶
Header: winui/core/Input.hpp.
The system pointer shapes an element can ask for with Element::set_cursor(). Each shows the system cursor of the same name.
Example:
void set_cursors(ui::Element& splitter, ui::Element& link)
{
splitter.set_cursor(ui::CursorShape::SizeWestEast);
link.set_cursor(ui::CursorShape::Hand);
}
| Value | |
|---|---|
Arrow |
The standard arrow; the default. |
Cross |
Crosshair, for precise picking. |
Hand |
Pointing hand, over hyperlinks. |
Help |
Arrow with a question mark. |
IBeam |
Text caret, over editable or selectable text. |
SizeAll |
Four-way arrow, for moving. |
SizeNortheastSouthwest |
Diagonal resize, / direction. |
SizeNorthSouth |
Vertical resize. |
SizeNorthwestSoutheast |
Diagonal resize, \ direction. |
SizeWestEast |
Horizontal resize, e.g. a column splitter. |
UniversalNo |
Slashed circle. The action is not allowed here. |
UpArrow |
Vertical arrow. |
Wait |
Busy. Input is blocked. |
Pin |
Location pin. |
Person |
Person. |
AppStarting |
Arrow with a busy indicator. Input still works. |
PointerButton¶
Header: winui/core/Input.hpp.
Which mouse button a PointerEvent is about.
| Value | |
|---|---|
None |
No button: moves, leaves and wheel turns. |
Left |
The primary button (also a touch or pen contact). |
Right |
The secondary button; context menus open on its Up. |
Middle |
The wheel button. |
PointerAction¶
Header: winui/core/Input.hpp.
What happened in a PointerEvent.
| Value | |
|---|---|
Move |
The pointer moved over the element (hover), with or without a button held. |
Down |
button was pressed; see PointerEvent::click_count for double/triple clicks. |
Up |
button was released. |
Leave |
The pointer left the element (or the window); clears hover state. |
Wheel |
A wheel turn; see PointerEvent::wheel_delta and horizontal_wheel. |
PointerDeviceType¶
Header: winui/core/Input.hpp.
What kind of device a PointerEvent came from.
| Value | |
|---|---|
Mouse |
A mouse or touchpad: the default, and what an event of unknown origin counts as. |
Pen |
A pen or stylus, its tip or its eraser end. |
Touch |
A finger on a touch screen. |
PointerDeviceTypes¶
Header: winui/core/Input.hpp.
A set of pointer devices, for a control that takes input from some kinds of device only, such as ui::InkCanvasControl::set_input_device_types(). Flags.
| Value | |
|---|---|
None |
No device. |
Mouse |
The mouse and the touchpad. |
Touch |
Touch screens. |
Pen |
Pens, tip and eraser end alike. |
All |
Every device. |
Key¶
Header: winui/core/Input.hpp.
The keys a control or a shortcut reads: navigation and editing keys, letters, digits, function keys and the keypad operators. Any other key arrives as Unknown.
Example:
const ui::KeyCombo save = ui::Ctrl + ui::Key::S; // save.text() is "Ctrl+S"
// In an element of your own:
class FileListControl : public ui::Element
{
protected:
bool key_override(const ui::KeyEvent& e) override
{
if (e.action == ui::KeyAction::Down && e.key == ui::Key::Delete)
{
remove_selected();
return true;
}
return false;
}
private:
void remove_selected();
};
| Value | |
|---|---|
Unknown |
A key outside this set; controls ignore it. |
A |
Letter A; TextBox's Ctrl+A select-all. |
B |
Letter B. |
C |
Letter C; TextBox's Ctrl+C copy. |
D |
Letter D. |
E |
Letter E. |
F |
Letter F. |
G |
Letter G. |
H |
Letter H. |
I |
Letter I. |
J |
Letter J. |
K |
Letter K. |
L |
Letter L. |
M |
Letter M. |
N |
Letter N. |
O |
Letter O. |
P |
Letter P. |
Q |
Letter Q. |
R |
Letter R. |
S |
Letter S. |
T |
Letter T. |
U |
Letter U. |
V |
Letter V; TextBox's Ctrl+V paste. |
W |
Letter W. |
X |
Letter X; TextBox's Ctrl+X cut. |
Y |
Letter Y; StandardCommand::Redo's Ctrl+Y. |
Z |
Letter Z; TextBox's Ctrl+Z, which also reverts an autocorrection. |
Number0 |
Digit 0 on the main row. |
Number1 |
Digit 1 on the main row. |
Number2 |
Digit 2 on the main row. |
Number3 |
Digit 3 on the main row. |
Number4 |
Digit 4 on the main row. |
Number5 |
Digit 5 on the main row. |
Number6 |
Digit 6 on the main row. |
Number7 |
Digit 7 on the main row. |
Number8 |
Digit 8 on the main row. |
Number9 |
Digit 9 on the main row. |
F1 |
Function key F1. |
F2 |
Function key F2. |
F3 |
Function key F3. |
F4 |
F4; opens and closes a ComboBox. |
F5 |
Function key F5. |
F6 |
Function key F6. |
F7 |
Function key F7. |
F8 |
Function key F8. |
F9 |
Function key F9. |
F10 |
Function key F10. |
F11 |
F11; the usual full-screen toggle. No control reads it, an app does. |
F12 |
Function key F12. |
Enter |
Activates the focused button (on release); commits a NumberBox edit. |
Space |
Activates the focused button or toggle (on release). |
Tab |
Moves focus; Shift+Tab moves backwards. |
Escape |
Closes the topmost popup, flyout or dialog; leaves a focus scope. |
Backspace |
Deletes before the caret in TextBox and RichEditBox. |
Delete |
Deletes after the caret; StandardCommand::Delete's shortcut. |
Insert |
Insert. |
Home |
Start of line / first item. |
End |
End of line / last item. |
PageUp |
A page up in a scroller; Carousel's previous item. |
PageDown |
A page down in a scroller; Carousel's next item. |
ArrowLeft |
Left arrow: moves the caret, a slider, or between tabs and items. |
ArrowUp |
Up arrow: moves within lists, sliders, menus and text. |
ArrowRight |
Right arrow. |
ArrowDown |
Down arrow; Alt+Down opens a SplitButton's or ComboBox's drop-down. |
Add |
The keypad's +. |
Subtract |
The keypad's -. |
Multiply |
The keypad's *. |
Divide |
The keypad's /. |
Plus |
The main keyboard's + key (with = on a US layout). |
Minus |
The main keyboard's - key. |
Comma |
The main keyboard's , key. |
Period |
The main keyboard's . key. |
Slash |
The key with / and ? on a US layout; other layouts put other characters there. |
KeyAction¶
Header: winui/core/Input.hpp.
Whether a KeyEvent is a press or a release.
| Value | |
|---|---|
Down |
Pressed, or auto-repeated while held. Shortcuts and navigation fire on Down. |
Up |
Released. Button activation by Enter/Space completes on Up. |
RoundingAlgorithm¶
Header: winui/core/NumberFormat.hpp.
How IncrementNumberRounder picks between the two neighboring multiples of its increment.
| Value | |
|---|---|
RoundDown |
toward negative infinity |
RoundUp |
toward positive infinity |
RoundTowardsZero |
truncate: -2.7 becomes -2 |
RoundAwayFromZero |
away from zero: -2.2 becomes -3 |
RoundHalfDown |
nearest; a tie toward negative infinity |
RoundHalfUp |
nearest; a tie toward positive infinity |
RoundHalfTowardsZero |
nearest; a tie toward zero |
RoundHalfAwayFromZero |
nearest; a tie away from zero (school rounding) |
RoundHalfToEven |
nearest; a tie to the even multiple (banker's rounding): 2.5 becomes 2 |
RoundHalfToOdd |
nearest; a tie to the odd multiple: 2.5 becomes 3 |
CollectionChangeKind¶
Header: winui/core/ObservableVector.hpp.
What happened to a collection, as reported by ui::ObservableVector.
| Value | |
|---|---|
Inserted |
count items were inserted at index. |
Removed |
count items were removed, starting at index. |
Replaced |
count items starting at index were replaced by new ones. |
Moved |
The item at index moved to to; both are positions in the collection. |
Reset |
Everything changed at once: the collection was cleared or assigned. |
Aliases¶
Action¶
Header: winui/core/Callback.hpp.
The most common shape, Callback<void()>, named because it reads better in a spec field: .on_click = [&] { save(); }.
Duration¶
Header: winui/core/Duration.hpp.
A length of time: every delay, duration, interval and elapsed time in the API. Milliseconds with a fractional part, so std::chrono_literals write it (800ms, 0.3s, 2s) and a frame step of 16.7 ms keeps its fraction. A bare number does not convert, so a value always says its unit.
Example:
using namespace std::chrono_literals;
ui::Property<std::string> hint{"Saved"};
window.set_content(ui::ToolTip{
.delay = 400ms,
.anchor = ui::Button{ .text = "Refresh" },
.content = ui::Text{ .text = "Reload the list" },
});
ui::Subscription hide_hint = window.after(2s, [&] { hint = ""; });
NativeHandle¶
Header: winui/core/NativeHandle.hpp.
The operating system's own handle of a window or a hosted control, for the calls libwinui does not wrap. On Windows it is the same type as HWND, declared here without <windows.h>, so a real HWND passes in and out unchanged; elsewhere it is an opaque pointer. Null while the window does not exist.
Example:
if (const ui::NativeHandle hwnd = window.native_handle())
{
FlashWindow(hwnd, TRUE); // any Win32 call libwinui doesn't wrap
}
ThreadCheckHandler¶
Header: winui/core/ThreadCheck.hpp.
What set_thread_check_handler() installs: called on the offending thread, before the call it reports goes ahead.
VisualId¶
Header: winui/core/VisualId.hpp.
A stable identity for an Element, unique in the process, assigned at construction and never reused (Element::visual_id()). Use it as a key for data kept about an element elsewhere.
Functions¶
lerp¶
Header: winui/core/Color.hpp.
Channel-wise linear interpolation from a (t = 0) to b (t = 1), alpha included. t is clamped to [0, 1]. Interpolates the stored sRGB values directly, not in linear light.
command_line¶
Header: winui/core/CommandLine.hpp.
Every argument, UTF-8 encoded, the program itself first (argv[0]'s place), so an app that wants only what the user passed starts at index 1. A path argument goes through path_from_utf8() (core/Utf8Path.hpp), not std::filesystem::path's own std::string constructor. Re-reads the process command line on every call; empty only where no source exists.
Example:
int main()
{
const std::vector<std::string> args = ui::command_line();
const std::filesystem::path folder =
args.size() > 1 ? ui::path_from_utf8(args[1]) : std::filesystem::current_path();
// ... open `folder` ...
return 0;
}
regional_date_format¶
Header: winui/core/DateFormat.hpp.
The regional date format: what the date and time controls use. Invariant until a host sets it. Process-wide; UI thread only.
set_regional_date_format¶
Header: winui/core/DateFormat.hpp.
Sets the regional date format. The window host sets it from the user's locale and the Region settings. Raises regional_date_format_changed() when it differs from the current one.
regional_date_format_changed¶
Header: winui/core/DateFormat.hpp.
Raised when the regional date format changes: the date and time controls write their text again. An app that caches formatted dates subscribes here and keeps the Subscription.
format_date¶
std::string format_date(std::chrono::year_month_day date, std::string_view pattern, const DateFormatSymbols& symbols = regional_date_format())
Header: winui/core/DateFormat.hpp.
date written with pattern (see DateFormatSymbols). An invalid date writes nothing.
format_time¶
std::string format_time(std::chrono::minutes time, std::string_view pattern, const DateFormatSymbols& symbols = regional_date_format())
Header: winui/core/DateFormat.hpp.
time (a time of day, from midnight) written with pattern (see DateFormatSymbols). Whole days in time are dropped.
today¶
Header: winui/core/DateFormat.hpp.
The date today on the local clock. Read from the system clock on every call.
operator|¶
Header: winui/core/DirtyFlags.hpp.
Union of two flag sets.
operator&¶
Header: winui/core/DirtyFlags.hpp.
Intersection of two flag sets; pass the result to any() to test a bit.
operator~¶
Header: winui/core/DirtyFlags.hpp.
Complement within DirtyFlags::All, so ~Layout never carries undefined high bits.
operator|=¶
Header: winui/core/DirtyFlags.hpp.
Adds the flags in b to a.
operator&=¶
Header: winui/core/DirtyFlags.hpp.
Keeps only the flags of a that are also in b; a &= ~f clears f.
any¶
Header: winui/core/DirtyFlags.hpp.
True if at least one flag is set.
intersection¶
Header: winui/core/Geometry.hpp.
Intersection of two rectangles (empty rect if they do not overlap).
operator|¶
Header: winui/core/Input.hpp.
Combines two device sets (ui::PointerDeviceTypes::Pen | ui::PointerDeviceTypes::Mouse).
has_device¶
Header: winui/core/Input.hpp.
Whether set includes device.
key_letter_index¶
Header: winui/core/Input.hpp.
Whether key is one of the letters A-Z, and which (0 for A). Unset otherwise.
key_display_name¶
Header: winui/core/Input.hpp.
The name shortcut text gives key ("S", "Delete", "F4", "+" for the keypad Add), the one a menu item shows beside its label and a tooltip after its text. Empty for Key::Unknown. The named keys (Delete, Enter, the arrows, ...) come from strings().keys, and the view stays valid until the next set_strings().
operator+¶
Header: winui/core/Input.hpp.
A key combination of mods and key: ui::Ctrl + ui::Key::S.
shortcut_text¶
Header: winui/core/Input.hpp.
The shortcut text for chord: the modifiers in a fixed order (Win, Ctrl, Alt, Shift) and the key, joined with "+", such as "Ctrl+S", "Ctrl+Shift+N", "Alt+Enter" or "Delete". Empty for an empty key combination. The key names come from strings().keys.
regional_number_format¶
Header: winui/core/NumberFormat.hpp.
The regional format: what a DecimalFormatter without symbols of its own uses. Invariant until a host sets it. Process-wide; UI thread only.
set_regional_number_format¶
Header: winui/core/NumberFormat.hpp.
Sets the regional format. The window host sets it from the user's locale. Raises regional_number_format_changed() when it differs from the current one.
regional_number_format_changed¶
Header: winui/core/NumberFormat.hpp.
Raised when the regional format changes: a NumberBox on the default formatter reformats. An app that caches formatted text subscribes here and keeps the Subscription.
round_significant¶
Header: winui/core/NumberFormat.hpp.
value rounded to digits significant digits. NumberBox rounds its display to 10, which hides the digits floating-point arithmetic leaves behind (0.1 + 0.2 shows as 0.3). digits counts significant digits, not fraction digits. NaN and the infinities pass through.
evaluate_expression¶
std::optional<double> evaluate_expression(std::string_view expression, const DecimalFormatter& parser)
Header: winui/core/NumberFormat.hpp.
Evaluates an arithmetic expression of numbers, + - * / ^, parentheses and spaces. Numbers are read with parser, so in its locale: "1,5 + 2" is 3.5 where the decimal separator is ",". ^ binds tighter than * /, which bind tighter than + -, and each is left-associative. A division by zero is NaN, and anything malformed is nullopt.
bind¶
Header: winui/core/ObservableVector.hpp.
Binding of a collection to an .items field: the field follows every insert, removal, replacement and move, row by row. ui::ForEach then passes each item to .item as T&.
A field that reads the collection in place (ui::ForEach, the views) never copies it. On a field that only takes a whole vector (a shape's .points), the binding delivers a copy of the collection when the field is built and on every change, which needs a copyable item type.
bind¶
template <typename T>
Binding<std::vector<T>> bind(const ObservableVector<T>& source)
requires std::copy_constructible<T>
Header: winui/core/ObservableVector.hpp.
Binding of a collection the caller may only read. The field gets a copy of the whole collection when it is built and again after every change, as from a Property<std::vector<T>>; it never writes to the collection, so a view built from it does not reorder it by drag.
bind¶
Header: winui/core/ObservableVector.hpp.
Deleted: a binding keeps a reference to its source, so a temporary collection cannot be bound.
bind¶
Header: winui/core/ObservableVector.hpp.
Deleted: a binding keeps a reference to its source, so a temporary collection cannot be bound.
item_count¶
Header: winui/core/ObservableVector.hpp.
The size of source, kept current: what an index-based collection spec's .item_count takes to follow a ui::ObservableVector. See ui::ItemCount.
item_count¶
Header: winui/core/ObservableVector.hpp.
Deleted: the count keeps a reference to its source, so a temporary collection cannot be used.
item_count¶
template <typename T, typename K>
ItemCount item_count(const Property<std::vector<T>>& source, K key)
requires std::constructible_from<ItemKey<T>, K> && std::copy_constructible<K>
Header: winui/core/ObservableVector.hpp.
The size of the vector in source, kept current, with each change of the property reported as what happened to the items: what an index-based collection spec's .item_count takes to follow a ui::Property<std::vector<T>> the app assigns as a whole. The typed views (ui::ListView, ui::TileView, ui::TableView) do the same from .items and .key.
key says which item is which (a member pointer or a callable, see ui::ItemKey). An item whose key is still there is reported as moved, not as removed and inserted, so its row stays with it through a sort or a filter. Keys must be unique. The item template reads the property by index.
Example:
struct Contact
{
int id = 0;
std::string name;
friend bool operator==(const Contact&, const Contact&) = default;
};
ui::Property<std::vector<Contact>> contacts{std::vector<Contact>{{1, "Grace"}, {2, "Ada"}}};
ui::ItemCount count = ui::item_count(contacts, &Contact::id);
ui::Subscription following = count.subscribe([&](const ui::CollectionChange& /*change*/) {
// Forward to an index-based control: notify_inserted(), notify_removed(), notify_moved() ...
});
std::vector<Contact> sorted = contacts.get();
std::ranges::sort(sorted, {}, &Contact::name);
contacts = std::move(sorted); // reported as moves
item_count¶
Header: winui/core/ObservableVector.hpp.
As above without a key: the items before and after an edit are kept and those in between are reported as removed, inserted or replaced. That covers appending and removing; a reorder replaces nearly everything.
item_count¶
template <typename T, typename... K>
ItemCount item_count(const Property<std::vector<T>>&& source, K... key) = delete
Header: winui/core/ObservableVector.hpp.
Deleted: the count keeps a reference to its source, so a temporary property cannot be used.
observe¶
template <typename Fn, typename... Ss>
Subscription observe(Fn fn, const Ss& ... sources)
requires (sizeof...(Ss) > 0) && (detail::is_source<Ss> && ...) && std::invocable<Fn&, const detail::source_value_t<Ss>&...> && (std::copy_constructible<detail::source_value_t<Ss>> && ...)
Header: winui/core/Property.hpp.
Observes several sources with one handler: fn(a, b, ...) runs with the latest value of every source whenever any of them changes. Not called for the current values, as Property::observe() is not. The sources are Property or Computed values, in any mix.
The returned Subscription holds every edge, so keeping it keeps fn firing and dropping it ends all of them. It remembers each source's last value, so a source destroyed before the others stops contributing changes.
Example:
ui::Property<std::string> first;
ui::Property<std::string> last;
ui::Subscription greet = ui::observe(
[](const std::string& f, const std::string& l) { std::println("Hello, {} {}", f, l); }, first, last);
first = "Ada"; // prints "Hello, Ada "
observe¶
template <typename Fn, typename... Sources>
Subscription observe(Fn fn, Sources&& ... sources) = delete
requires (sizeof...(Sources) > 0) && (detail::is_source<Sources> && ...) && (std::is_rvalue_reference_v<Sources &&> || ...)
Header: winui/core/Property.hpp.
Deleted: the subscription keeps a reference to each source, so none of them can be a temporary.
Computed¶
template <typename Fn, typename... Ss>
Computed(Fn, const Ss& ...) -> Computed<std::remove_cvref_t<std::invoke_result_t<Fn&, const detail::source_value_t<Ss>& ...>>>
requires (sizeof...(Ss) > 0) && (detail::is_source<Ss> && ...)
Header: winui/core/Property.hpp.
ui::Computed c{fn, a, b} takes its type from what fn returns.
bind¶
Header: winui/core/Property.hpp.
One-source binding: the property's value, verbatim.
Takes the property by const reference, since observing is not writing. A read-only property a host owns binds like one the app owns. The rvalue overloads are deleted because a binding keeps a reference to its source, and a temporary Property would be gone before the first change.
Example:
ui::Property<bool> online{true};
window.set_content(ui::ToggleSwitch{.checked = ui::bind(online)}); // or `.checked = online`
bind¶
template <typename T, typename Fn>
auto bind(const Property<T>& source, Fn fn)
requires std::invocable<Fn&, const T&> && std::copy_constructible<Fn>
Header: winui/core/Property.hpp.
One-source binding with a transform, so a format string exists once in a program instead of once per writer. The result type is whatever fn returns. fn runs once now for the initial value and again on every change.
Example:
ui::Property<int> clicks{0};
ui::Text label{.text = ui::bind(clicks, [](int n) { return std::format("Clicks: {}", n); })};
fn must be copyable, because it is stored once per subscription edge.
bind_one_way¶
Header: winui/core/Property.hpp.
One-way binding of a property, whatever field it lands on: the control shows the property and never writes to it. The way to opt an editable field out of bind()'s two-way default, for an input that only displays state or whose edits the app validates before storing.
Example:
ui::Property<float> level{0.4f};
// The slider follows `level`; dragging it does not change `level` by itself.
// The app stores only the levels it accepts.
window.set_content(ui::Slider{
.value = ui::bind_one_way(level),
.on_value_changed = [&](double v) { if (v <= 0.8) { level = static_cast<float>(v); } },
});
bind_one_way¶
Header: winui/core/Property.hpp.
Deleted: a binding keeps a reference to its source, so a temporary Property cannot be bound.
bind¶
Header: winui/core/Property.hpp.
Binding of a property the app can write, with no conversion. On an editable field (a text box's .text, a slider's .value, a toggle's .checked, a list's .selected_index, ...) it is two-way: the control shows the property, and what the user enters is written back into it, before the field's own on_*_changed handler runs. On a display field it is one-way, as there is nothing to write. A const Property and a bind() with a conversion are always one-way; bind_one_way() opts an editable field out. An editable field that can be unset takes it only from a Property<std::optional<T>>; see TwoWayField.
The equality gate of Property::set() ends the round trip: the value written back equals the one the control already shows.
Example:
ui::Property<std::string> name{"Ada"};
window.set_content(ui::VerticalStack{.content = {
ui::TextBox{.text = ui::bind(name)}, // typing changes `name`
ui::Text{.text = ui::bind(name, [](const std::string& n) { return "Hello, " + n; })},
}});
This overload also keeps ADL from picking std::bind for a non-const lvalue of a std:: type.
selects¶
template <typename T, typename V>
TwoWayBinding<bool> selects(Property<T>& source, V&& value)
requires std::constructible_from<T, V> && std::equality_comparable<T>
Header: winui/core/Property.hpp.
One choice of several, written into a control's checked: the control is checked while source holds value, and checking it sets source to value. Unchecking writes nothing, since a choice is only ever left by making another one.
Every control bound through selects() to the same property is one set of choices, wherever it sits in the tree: checking one unchecks the others through the property. RadioButtons bound this way also act as one group for the keyboard and screen readers: Tab stops once on the group (on the checked button, or the first), the arrow keys move between the buttons and check the one they reach (Ctrl+arrow moves without checking), and each button reports its position in the set. A ToggleButton bound this way stays checked when clicked again, like a radio button. For one control that lists the choices itself (a SelectorBar, RadioButtons), see bind_choice().
Example:
enum class Size { Small, Medium, Large };
ui::Property<Size> size{Size::Medium};
window.set_content(ui::VerticalStack{.content = {
ui::RadioButton{.text = "Small", .checked = ui::selects(size, Size::Small)},
ui::Text{.text = "Fits a phone."},
ui::RadioButton{.text = "Medium", .checked = ui::selects(size, Size::Medium)},
ui::RadioButton{.text = "Large", .checked = ui::selects(size, Size::Large)},
}});
selects¶
template <typename T, typename V>
TwoWayBinding<bool> selects(Property<T>&& source, V&& value) = delete
Header: winui/core/Property.hpp.
Deleted: the binding keeps a reference to its source, so a temporary Property cannot be used.
bind_choice¶
template <typename T>
ChoiceBinding bind_choice(Property<T>& source, std::vector<T> choices)
requires std::equality_comparable<T> && std::copy_constructible<T>
Header: winui/core/Property.hpp.
A property holding one of several values, bound two-way to an index field (selected_index on a SelectorBar, Sections, Carousel, PipsPager, ComboBox, RadioButtons, ListView, ...). choices lists the values in the order of the control's items: the field shows the position of the value source holds, and picking item i sets source to choices[i].
A value that is not in the list shows no selection where the field can show none (a ComboBox, a ListView). A field that always shows a selection (a Sections control, a SelectorBar) keeps the one it has, and starts on the first choice. Clearing the selection writes nothing.
For a choice made with separate controls, one per value, see selects().
Example:
enum class Filter { All, Active, Done };
ui::Property<Filter> filter{Filter::All};
ui::SelectorBar{
.items = {"All", "Active", "Done"},
.selected_index = ui::bind_choice(filter, {Filter::All, Filter::Active, Filter::Done}),
};
filter = Filter::Done; // selects "Done"
bind_choice¶
template <typename T>
ChoiceBinding bind_choice(Property<T>&& source, std::vector<T> choices) = delete
Header: winui/core/Property.hpp.
Deleted: the binding keeps a reference to its source, so a temporary Property cannot be used.
bind¶
template <typename T, typename Fn>
auto bind(Property<T>& source, Fn fn)
requires std::invocable<Fn&, const T&> && std::copy_constructible<Fn>
Header: winui/core/Property.hpp.
Same as bind(const Property
bind¶
template <typename Fn, typename... Ss>
auto bind(Fn fn, const Ss& ... sources)
requires (sizeof...(Ss) > 0) && (detail::is_source<Ss> && ...) && std::invocable<Fn&, const detail::source_value_t<Ss>&...> && std::copy_constructible<Fn> && (std::copy_constructible<detail::source_value_t<Ss>> && ...)
Header: winui/core/Property.hpp.
Several-source binding: fn(a.get(), b.get(), ...), computed again whenever any of the sources changes. The function comes first, so the sources after it can be any number of Property and Computed values. A value used in more than one place is better declared once as a Computed.
The result is one-way. A change that computes the same result costs what the target's setter costs for an unchanged value, which is nothing. The binding remembers each source's last value, so a source destroyed before the others stops contributing changes. fn must be copyable, as for the one-source form.
Example:
ui::Property<bool> dirty{false};
ui::Property<bool> busy{false};
ui::Button save{
.text = "Save",
.enabled = ui::bind([](bool is_dirty, bool is_busy) { return is_dirty && !is_busy; }, dirty, busy),
};
bind¶
Header: winui/core/Property.hpp.
One-way binding of a Computed: its value, verbatim. Same as bind() of a const Property<T>.
bind¶
template <typename T, typename Fn>
auto bind(const Computed<T>& source, Fn fn)
requires std::invocable<Fn&, const T&> && std::copy_constructible<Fn>
Header: winui/core/Property.hpp.
One-way binding of a Computed with a transform, as bind(const Property
bind¶
Header: winui/core/Property.hpp.
Deleted: a binding keeps a reference to its source, so a temporary Property cannot be bound.
bind¶
Header: winui/core/Property.hpp.
Deleted: a binding keeps a reference to its source, so a temporary Property cannot be bound.
bind¶
Header: winui/core/Property.hpp.
Deleted: a binding keeps a reference to its source, so a temporary Computed cannot be bound.
bind¶
Header: winui/core/Property.hpp.
Deleted: a binding keeps a reference to its source, so a temporary Computed cannot be bound.
bind¶
template <typename Fn, typename... Sources>
auto bind(Fn fn, Sources&& ... sources) = delete
requires (sizeof...(Sources) > 0) && (detail::is_source<Sources> && ...) && (std::is_rvalue_reference_v<Sources &&> || ...)
Header: winui/core/Property.hpp.
Deleted: the several-source form keeps a reference to each source, so none of them can be a temporary.
strings¶
Header: winui/core/Strings.hpp.
The text libwinui shows now: English until set_strings() replaces it. Process-wide; UI thread only. The reference stays valid until the next set_strings().
set_strings¶
Header: winui/core/Strings.hpp.
Replaces the text libwinui shows and raises strings_changed(): every window lays out and draws again, and the controls that hold text of their own refresh it.
strings_changed¶
Header: winui/core/Strings.hpp.
Raised by set_strings(). An app that caches text from strings() subscribes here and keeps the Subscription.
set_thread_check_handler¶
Header: winui/core/ThreadCheck.hpp.
Replace what a failed thread check does; nullptr restores the default. Returns the handler it replaced (nullptr for the default). Safe from any thread.
In a build with checks (LIBWINUI_THREAD_CHECKS, on by default without NDEBUG), a mutation from a thread that does not own what it mutates is reported: an element setter (anything that invalidates through Element::mark_dirty()) on an element attached to a Window, from another thread than the one that constructed the Window; a member of Window other than post(); a write to a Property, ObservableVector or Signal that has notified observers before, from another thread than its first notifying write, and a new observer from such a thread. Reading is never checked, so measuring on worker threads is fine. A detached element (built but not yet under a Window) is unchecked, so a tree may be built on a worker and handed over with Window::post().
The default handler writes the message to stderr and the debugger output, then breaks into the debugger when one is attached and aborts otherwise, as a failed assert does: the call is a data race, and what it corrupts shows up far from here.
Example:
// A test that would rather count than stop.
static std::atomic<int> failures{0};
ui::set_thread_check_handler([](const ui::ThreadCheckFailure& f) {
std::fprintf(stderr, "%s\n", f.message.c_str());
++failures;
});
default_thread_check_handler¶
Header: winui/core/ThreadCheck.hpp.
What a failed check does unless set_thread_check_handler() says otherwise: print the message, then break into an attached debugger or abort. Public so a custom handler can fall back to it.
decode_utf8¶
Header: winui/core/Utf8.hpp.
The code point starting at byte pos of text. A malformed sequence decodes to U+FFFD and takes only the bytes that belonged to it, so decoding carries on at the next one. At or past the end the result is {0, 0}.
append_utf8¶
Header: winui/core/Utf8.hpp.
Appends code_point to out as UTF-8. A surrogate or a value beyond U+10FFFF appends U+FFFD.
encode_utf8¶
Header: winui/core/Utf8.hpp.
code_point as a UTF-8 string.
next_code_point¶
Header: winui/core/Utf8.hpp.
The byte offset of the code point after the one at pos; text.size() at or past the end.
previous_code_point¶
Header: winui/core/Utf8.hpp.
The byte offset of the code point before pos; 0 at the start.
is_code_point_boundary¶
Header: winui/core/Utf8.hpp.
True when pos is 0, text.size(), or the first byte of a code point.
floor_code_point¶
Header: winui/core/Utf8.hpp.
pos moved back onto the start of the code point it falls inside, clamped to the text.
code_point_count¶
Header: winui/core/Utf8.hpp.
How many code points text holds, a malformed sequence counting as one.
is_valid_utf8¶
Header: winui/core/Utf8.hpp.
True when text is well-formed UTF-8: no overlong forms, no surrogates, nothing past U+10FFFF.
sanitize_utf8¶
Header: winui/core/Utf8.hpp.
text with every malformed sequence replaced by U+FFFD. libwinui passes text from outside, such as keyboard input, the clipboard, files and the command line, through this once.
to_utf16¶
Header: winui/core/Utf8.hpp.
text as UTF-16, for system and library APIs that take it.
from_utf16¶
Header: winui/core/Utf8.hpp.
text, which is UTF-16, as UTF-8.
utf16_length¶
Header: winui/core/Utf8.hpp.
How many UTF-16 code units text takes: one per code point, two past the BMP. The UTF-16 offset of byte pos is utf16_length(text.substr(0, pos)).
utf8_offset_from_utf16¶
Header: winui/core/Utf8.hpp.
The byte offset of text that lies units UTF-16 code units in, the inverse of utf16_length(). A count that ends between the two halves of a surrogate pair lands before the pair; one past the end lands on text.size().
code_points¶
Header: winui/core/Utf8.hpp.
A CodePoints view over text, for a range-for. text must outlive the loop.
path_from_utf8¶
Header: winui/core/Utf8Path.hpp.
A path from a UTF-8 string. Use it wherever a string becomes a path: std::filesystem::path(std::string) reads the string in the system's legacy code page, which mangles characters outside it.
Example:
// A file name typed into a TextBox is UTF-8; the "ü" survives into the path.
ui::Property<std::string> file_name{"Zürich.png"};
const std::filesystem::path path = ui::path_from_utf8(file_name.get());
const ui::Bitmap picture{16, 16, ui::colors::White};
picture.write_png(path);
// path_to_utf8() goes back the other way, for a label.
ui::Property<std::string> status{"Saved " + ui::path_to_utf8(path.filename())}; // "Saved Zürich.png"
path_to_utf8¶
Header: winui/core/Utf8Path.hpp.
path as UTF-8, the inverse of path_from_utf8().
version_string¶
Header: winui/core/Version.hpp.
The version of the linked library as "major.minor.patch", e.g. "0.1.0". Compare it with VersionMajor, VersionMinor and VersionPatch to detect a header/binary mismatch with the shared library. There is no ABI promise: a shared library only works with the headers of its own version, built by the same compiler with the same options. The string is static; never free it.
allocate_visual_id¶
Header: winui/core/VisualId.hpp.
Returns a new id, unique in the process, counting up from 1. Thread-safe. Element calls this itself, so controls never need to.
Constants¶
| Name | Type | Value | |
|---|---|---|---|
Handled |
Handling |
Handling::Handled |
See ui::Handling. |
NotHandled |
Handling |
Handling::NotHandled |
See ui::Handling. |
Proceed |
Decision |
Decision::Proceed |
See ui::Decision. |
Cancel |
Decision |
Decision::Cancel |
See ui::Decision. |
Unbounded |
float |
std::numeric_limits<float>::infinity() |
The extent of an unbounded axis in a measure offer (Element::measure). |
Ctrl |
ModifierKeys |
{.ctrl = true} |
Ctrl, for writing a key combination: ui::Ctrl + ui::Key::S. |
Shift |
ModifierKeys |
{.shift = true} |
Shift, for writing a key combination: ui::Ctrl + ui::Shift + ui::Key::N. |
Alt |
ModifierKeys |
{.alt = true} |
Alt, for writing a key combination: ui::Alt + ui::Key::Enter. |
Win |
ModifierKeys |
{.win = true} |
The Windows logo key, for writing a key combination. |
ThreadChecksEnabled |
bool |
LIBWINUI_THREAD_CHECKS != 0 |
Whether this build checks thread affinity (see set_thread_check_handler()); LIBWINUI_THREAD_CHECKS as a constant. |
ReplacementCharacter |
char32_t |
0xFFFD |
U+FFFD, what malformed input decodes to. |
VersionMajor |
int |
LIBWINUI_VERSION_MAJOR |
Major version of the headers being compiled against. |
VersionMinor |
int |
LIBWINUI_VERSION_MINOR |
Minor version of the headers being compiled against. |
VersionPatch |
int |
LIBWINUI_VERSION_PATCH |
Patch version of the headers being compiled against. |
InvalidVisualId |
VisualId |
0 |
The id that marks no element. allocate_visual_id() never returns 0. |