Skip to content

TimePicker

Header: winui/ui/datetime/TimePicker.hpp. Spec: winui/ui/datetime/TimePicker.hpp.

A field that shows a time of day in its parts (hour, minute and, on a 12-hour clock, AM or PM) and opens a flyout of spinning columns to pick one.

It works like DatePicker: the flyout opens on the time, or on now while there is none, and Enter or the check mark keeps the choice. minute_increment sets the minutes offered: 15 offers 00, 15, 30 and 45, and a time set in between is rounded down to one of them. The clock follows the short time pattern of regional_date_format() unless the picker sets its own.

Each theme era draws its own: Fluent's field and flyout, Windows 8.1's drop-down lists under Metro, and comctl32's time picker under Aero, Luna and the classic eras, with spin buttons.

ui::TimePicker is the declarative form.

Example:

ui::TimePickerControl picker;
picker.set_header("Alarm");
picker.set_minute_increment(5);
picker.set_selected_time(std::chrono::hours{7} + std::chrono::minutes{30});

ui::TimePicker

The declarative form of TimePickerControl: a time of day picked from spinning columns.

Example:

ui::Property<std::optional<std::chrono::minutes>> arrival;

window.set_content(ui::TimePicker{
    .header           = "Arrival time",
    .selected_time    = arrival,
    .minute_increment = 15,
});

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

ui::TimePicker{
    .header, .selected_time, .clock, .minute_increment, .style, .margin, .width, .height,
    .min_width, .min_height, .max_width, .max_height, .horizontal_alignment,
    .vertical_alignment, .visible, .tool_tip, .enabled, .accessibility,
    .on_selected_time_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
header ui::Binding<std::string> The label above the field. Empty shows none.
selected_time ui::TwoWayField<std::optional<std::chrono::minutes>> The picked time of day, from midnight; unset until one is picked.
clock ui::Binding<std::optional<ui::TimePickerClock>> The clock shown; unset follows regional_date_format().
minute_increment ui::Binding<int> {1} The step of the minutes offered, 1 to 59; 0 offers only the full hour.
on_selected_time_changed ui::Callback<void(std::optional<std::chrono::minutes>)> The new time (unset when cleared), from the flyout or 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.
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; ui::Handled stops it there (Element::on_wheel()).
control ui::ControlOut<ui::TimePicker> 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::TimePickerControl; the caller owns it.

ui::TimePickerControl

Derives from ui::Element, ui::InvokeProvider, ui::ValueProvider.

A field that shows a time of day in its parts (hour, minute and, on a 12-hour clock, AM or PM) and opens a flyout of spinning columns to pick one.

It works like DatePicker: the flyout opens on the time, or on now while there is none, and Enter or the check mark keeps the choice. minute_increment sets the minutes offered: 15 offers 00, 15, 30 and 45, and a time set in between is rounded down to one of them. The clock follows the short time pattern of regional_date_format() unless the picker sets its own.

Each theme era draws its own: Fluent's field and flyout, Windows 8.1's drop-down lists under Metro, and comctl32's time picker under Aero, Luna and the classic eras, with spin buttons.

ui::TimePicker is the declarative form.

Example:

ui::TimePickerControl picker;
picker.set_header("Alarm");
picker.set_minute_increment(5);
picker.set_selected_time(std::chrono::hours{7} + std::chrono::minutes{30});

TimePickerControl

TimePickerControl()

A picker with no time, on the regional clock, offering every minute.

~TimePickerControl

~TimePickerControl() override

TimePickerControl

TimePickerControl(const TimePickerControl&) = delete

operator=

TimePickerControl& operator=(const TimePickerControl&) = delete

selected_time

std::optional<std::chrono::minutes> selected_time() const

The picked time of day, from midnight; unset until one is picked.

set_selected_time

void set_selected_time(std::optional<std::chrono::minutes> time)

Sets the time: whole days are dropped and the minutes rounded down to the increment. Raises the change callback when it differs.

on_selected_time_changed

void on_selected_time_changed(Callback<void(std::optional<std::chrono::minutes>)> handler)

Called after the time changed, from the flyout or a setter, with the new time.

clock

TimePickerClock clock() const

The clock shown: the regional one until set.

set_clock

void set_clock(std::optional<TimePickerClock> clock)

See clock().

minute_increment

int minute_increment() const

The minutes offered step by this many, 1 to 59; 0 offers only the full hour.

set_minute_increment

void set_minute_increment(int increment)

See minute_increment(). A value outside 0 to 59 is ignored.

set_header

void set_header(std::string text)

The label above the field. Empty shows none.

is_open

bool is_open() const

Whether the flyout is open.

set_open

void set_open(bool open)

Opens or closes the flyout.

focusable

bool focusable() const override

Whether this element can take keyboard focus (a leaf control opts in).

automation_role

AutomationRole automation_role() const override

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

std::string automation_name_fallback() const override

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.

for_each_child

void for_each_child(ChildVisitor visit) const override

Call visit once for each child this element owns, in order (back to front where they overlap). The one override a container needs beyond measure, arrange and render. The default of every tree-wide walk recurses through it (collect_focusables(), the popup walk, clear_dirty(), build_visual_tree(), sync_composition(), sync_native(), tick() and automation_children()), so a custom container that lists its children here gets focus, popups, dirty clearing, ticks, composition, native controls and automation right without forwarding any of them. Default: no children, a leaf.

List the children the walks should reach, normally every one this element owns. A walk that must see a different set overrides that walk alone: a composite that is one tab stop and one automation node, a split view leaving its closed pane out of focus and popups. A control that parks parts (an unselected page, a hidden button) may leave them out here instead and clear them in clear_dirty_override() (and tick them in tick_override()), so a parked part never stays dirty.

Const so the const walks can use it, though it hands out mutable children: they are owned objects of their own, not part of this element's state. A tick can run a handler that adds or removes children, so a container that allows that walks its list by index.

Example:

class Row : public ui::Element
{
    void for_each_child(ui::ChildVisitor visit) const override
    {
        for (const auto& child : children_)
        {
            visit(*child);
        }
    }

    std::vector<std::unique_ptr<ui::Element>> children_;
};

collect_focusables

void collect_focusables(std::vector<Element*>& out) override

Append focusable elements in tab order, so the Window can build a flat focus ring over the whole tree. The default pushes this element when focusable(), then recurses into every child for_each_child() lists. Override it when the ring differs from the children: a composite that is one tab stop pushes only itself, a focus scope stops recursing (see collect_scope_focusables()), a pager leaves out its hidden pages.

automation_children

void automation_children(std::vector<Element*>& out) const override

The children an automation client sees under this node, immediate children only. A client walks the tree one level at a time, and the parent comes from parent(). Defaults to every child for_each_child() lists. Override it only to show a client something else: the children in a different order, or without parts that are only decoration. A composite that is one automation node lists nothing.

measure_override

Size measure_override(Size available, const MeasureContext& context) const 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

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

Position children within the rect arrange() settled on (also in bounds(), window DIPs). Default: nothing, for a leaf.

render_override

void render_override(Renderer& renderer, const RenderContext& context) const 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

bool pointer_override(const PointerEvent& e) override

A pointer event for this element: the element under the pointer, one inside it that did not handle the event, or the element holding the capture. The position is in layout coordinates (handle_pointer()). Return true when the event did something here, and it goes no further up; a handled press also captures the pointer until its release. A control that acts on a press (a click, a toggle, a caret placed, a drag started) returns true for the press and its release, so a list row or a card around it does not act on the same click. Default: false.

key_override

bool key_override(const KeyEvent& e) 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

bool text_override(const TextInputEvent& e) override

Typed text for this element, routed like key_override(). Default: false.

tick_override

void tick_override(Duration delta) override

This element's own part of tick(): a clock of its own (ToolTip's hover delay, an animation's phase, a caret blink). Runs after the visual layer has advanced and before the children are ticked, which tick() does by itself. Tick only parts that for_each_child() does not list here. Default: nothing.

enabled_changed

void enabled_changed() override

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

void focus_changed(bool focused) override

Keyboard focus arrived (true) or left (false); is_focused() already says so. The element is redrawn either way. No-op by default.

Enumerations

TimePickerClock

enum class TimePickerClock

Which clock a TimePicker shows.

Value
TwelveHour 12 hours and an AM/PM column.
TwentyFourHour 0 to 23 hours.

Tests

  • tests/test_time_picker.cpp