Slider¶
Header: winui/ui/input/Slider.hpp. Spec: winui/ui/input/Slider.hpp.
A thumb dragged along a track to pick a value in [min(), max()].
A click on the track jumps the thumb there and starts a drag; the drag snaps to step_frequency() (or the ticks, see set_snaps_to()). The arrow keys move by step(), Home and End jump to the ends, and on_value_changed() fires live on every change. An optional header sits above the track. The declarative form is ui::Slider.
Example:
auto panel = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* label = panel->add(std::make_unique<ui::TextControl>("50"));
auto* volume = panel->add(std::make_unique<ui::SliderControl>(ui::Orientation::Horizontal,
0.0f, 100.0f, 50.0f));
volume->set_header("Volume");
volume->set_step(5.0f);
volume->set_tick_frequency(10.0f);
volume->set_tick_placement(ui::SliderTickPlacement::BottomRight);
volume->on_value_changed([label](double v) { label->set_text(std::format("{:.0f}", v)); });
window.set_content(std::move(panel));
ui::Slider¶
A draggable thumb over a continuous range. Builds a ui::SliderControl.
orientation, the range and the initial value go to the control's constructor, so the value is clamped against the right range from the start and seeding it raises nothing.
Example:
ui::Property<double> volume{40.0};
window.set_content(ui::VerticalStack{
.spacing = 8,
.content = {
ui::Slider{.header = "Volume",
.value = volume,
.max = 100.0,
.step = 5.0,
.tick_frequency = 10.0,
.tick_placement = ui::SliderTickPlacement::BottomRight,
.width = 240.0f},
ui::Text{.text = ui::bind(volume, [](double v) { return std::format("{:.0f}%", v); })},
},
});
Every field, in the order a designated initializer names them:
ui::Slider{
.header, .value, .min, .max, .step, .tick_frequency, .tick_placement, .step_frequency,
.snaps_to, .orientation, .direction_reversed, .style, .margin, .width, .height, .min_width,
.min_height, .max_width, .max_height, .horizontal_alignment, .vertical_alignment, .visible,
.tool_tip, .enabled, .accessibility, .on_value_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 control. Empty draws none. | |
value |
ui::TwoWayField<double> |
{0.0} |
Value, clamped to [min, max]. ui::bind(prop) is two-way: dragging writes the property. |
min |
double |
0.0 |
Minimum, the value at the start of the track. |
max |
double |
100.0 |
Maximum, the value at the end of the track. |
step |
ui::Binding<double> |
{1.0} |
What an arrow key adds or takes away; 0 turns arrow stepping off. |
tick_frequency |
ui::Binding<double> |
{0.0} |
See ui::SliderControl::set_tick_frequency: 0 draws no ticks, except under the classic look. |
tick_placement |
ui::Binding<ui::SliderTickPlacement> |
{ui::SliderTickPlacement::Inline} |
Where the ticks go relative to the track; Inline (across it) by default. |
step_frequency |
ui::Binding<double> |
{1.0} |
What a drag snaps to: 1 by default, 0 for a continuous drag. step stays the arrow-key increment. |
snaps_to |
ui::Binding<ui::SliderSnapsTo> |
{ui::SliderSnapsTo::StepValues} |
A drag lands on step_frequency multiples, or on ticks (which the arrow keys then move by too). |
orientation |
ui::Orientation |
ui::Orientation::Horizontal |
Horizontal or Vertical; fixed at build time (the control has no setter for it). |
direction_reversed |
ui::Binding<bool> |
{false} |
Min at the right (horizontal) or the top (vertical). |
on_value_changed |
ui::Callback<void(double)> |
The new value, live on every change during a drag, click or key press. | |
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::Slider> |
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¶
Consumes the spec and returns the built ui::SliderControl; the caller owns it.
ui::SliderControl¶
Derives from ui::Element, ui::RangeValueProvider.
A thumb dragged along a track to pick a value in [min(), max()].
A click on the track jumps the thumb there and starts a drag; the drag snaps to step_frequency() (or the ticks, see set_snaps_to()). The arrow keys move by step(), Home and End jump to the ends, and on_value_changed() fires live on every change. An optional header sits above the track. The declarative form is ui::Slider.
Example:
auto panel = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* label = panel->add(std::make_unique<ui::TextControl>("50"));
auto* volume = panel->add(std::make_unique<ui::SliderControl>(ui::Orientation::Horizontal,
0.0f, 100.0f, 50.0f));
volume->set_header("Volume");
volume->set_step(5.0f);
volume->set_tick_frequency(10.0f);
volume->set_tick_placement(ui::SliderTickPlacement::BottomRight);
volume->on_value_changed([label](double v) { label->set_text(std::format("{:.0f}", v)); });
window.set_content(std::move(panel));
SliderControl¶
SliderControl(Orientation orientation = Orientation::Horizontal, double min = 0.0, double max = 100.0, double value = 0.0)
A slider over [min, max] starting at value (clamped into the range). Raises nothing.
orientation¶
The orientation given at construction; there is no setter.
header¶
The header text; empty when none is shown.
set_header¶
The label above the slider. Empty draws none.
min¶
The value at the start of the track.
max¶
The value at the end of the track; never below min().
set_range¶
Sets the range and clamps the current value into it, firing on_value_changed if that moves it. A max below min is taken as min.
value¶
Value, always within [min(), max()].
set_value¶
Clamps to [min, max]. Fires on_value_changed only if the clamped value differs from the current one.
step¶
The arrow-key increment, 1 by default. Also UI Automation's small change.
set_step¶
The amount each arrow-key press moves the value by. Zero disables keyboard stepping (Home/End still jump to min/max). Negative is 0.
tick_frequency¶
The tick interval in value units; 0 (the default) means none is set.
set_tick_frequency¶
How often a tick mark is drawn along the track, in value units. Ticks sit at whole multiples of it counted from min(), one at min() and one per full interval after, so a range the frequency does not divide gets no tick at max(). Ticks closer than 20 DIPs are thinned to every n-th one.
At zero the Fluent look draws no ticks, while the classic look still draws the two ticks marking the ends of the range. Negative is 0. Redraws only.
tick_placement¶
Where the ticks go relative to the track; Inline by default.
set_tick_placement¶
Redraws only.
step_frequency¶
The drag snapping interval, 1 by default.
set_step_frequency¶
The interval a pointer click or drag snaps to under SliderSnapsTo::StepValues. It is 1 by default, so a drag lands on whole values. Give a range narrower than a few units a finer step. Zero makes the drag continuous. Snapping lands on whole multiples of the interval counted from 0, not from min(), clamped into the range. Keyboard stepping uses step() and is unaffected. set_value() never snaps.
snaps_to¶
What a drag snaps to; StepValues by default.
set_snaps_to¶
SliderSnapsTo::Ticks snaps a drag to tick_frequency() instead and makes the arrow keys move by it, ignoring step(). With no tick frequency set it behaves as StepValues.
direction_reversed¶
Reverses the direction: min at the right of a horizontal slider and at the top of a vertical one, with the value fill, the ticks, a click, a drag and the arrow keys all following (Left and Down then increase, Right and Up decrease). False by default.
set_direction_reversed¶
Redraws; the value itself does not change.
set_track_gradient¶
Draws the whole track with gradient, in place of the neutral track and the accent fill up to the thumb. checkerboard draws a 50% checkerboard (Pattern::Checkerboard50) behind the gradient first, so a channel whose stops carry partial alpha looks translucent. std::nullopt restores the default track. The retro (95/98/2000) bevel track ignores the gradient.
on_value_changed¶
Fired whenever value changes, from a drag, a click-to-jump, or a keyboard step alike. A drag fires on every change, not only on release.
parallel_measure_safe¶
True: measuring reads only the slider's own state, the measurer and the theme.
focused¶
Whether the slider holds keyboard focus (the focus ring is drawn).
focusable¶
A tab stop while enabled.
hovered¶
Whether the pointer is over the slider (false while disabled).
dragging¶
Whether a pointer drag is in progress.
is_pressed¶
Enabled and dragging.
automation_role¶
Slider. The header names it when set. Without a header, set accessibility().name, as for an icon-only Button.
automation_name_fallback¶
The header text.
visual_state¶
The state the thumb is drawn in: Disabled, then Pressed while dragging, then Hover, else Normal.
measure_override¶
The header, when set, is stacked above the track (ControlHeader). The track asks for 200 DIPs along its axis (less if less is offered) and at least 32 across it.
arrange_override¶
Places the header; the track takes the rest of the bounds.
pointer_override¶
Press on the track jumps the value there and starts a drag; moves while dragging update the value (snapped per snaps_to()); release ends the drag.
render_override¶
Draws the header, the track (or set_track_gradient()'s gradient), the value fill, the ticks and the thumb, or the classic track and thumb under a retro theme.
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.
focus_changed¶
Called by Window as focus moves; redraws.
key_override¶
Arrow keys step by step() (or the tick frequency under SliderSnapsTo::Ticks), Home/End jump to min()/max().
focus_ring_rect¶
Around the thumb, around the track's row in the Fluent eras, or around the whole control in the classic look. None where focus shows on the thumb's face.
focus_ring_corner_radius¶
The ring's corner radius: the theme's control radius by default.
Enumerations¶
SliderTickPlacement¶
Where tick marks are drawn relative to the track. No placement draws ticks until tick_frequency() is above zero, except under the classic look. The classic look only tells None (no ticks) from the rest, which all draw its one row of ticks on the far side (see set_tick_frequency()).
| Value | |
|---|---|
None |
no ticks |
TopLeft |
above a horizontal track, left of a vertical one |
BottomRight |
below a horizontal track, right of a vertical one |
Outside |
both of the above |
Inline |
notches cut across the track itself (the default) |
SliderSnapsTo¶
What a pointer drag lands on.
| Value | |
|---|---|
StepValues |
multiples of step_frequency() |
Ticks |
multiples of tick_frequency(); the arrow keys move by it too |
Tests¶
tests/test_slider.cpp