mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-02 14:51:15 +00:00
add property for slider to support vertical orientation (#3236)
This commit is contained in:
parent
12e064b07d
commit
4b9fb89332
6 changed files with 109 additions and 44 deletions
|
@ -7,6 +7,7 @@
|
||||||
- **`value`** (_in-out_ _float_): The value.
|
- **`value`** (_in-out_ _float_): The value.
|
||||||
- **`minimum`** (_in_ _float_): The minimum value (default: 0)
|
- **`minimum`** (_in_ _float_): The minimum value (default: 0)
|
||||||
- **`maximum`** (_in_ _float_): The maximum value (default: 100)
|
- **`maximum`** (_in_ _float_): The maximum value (default: 100)
|
||||||
|
- **`vertical`** (_in_ _bool_): If set to true the Slider is displayed vertical (default: false).
|
||||||
|
|
||||||
### Callbacks
|
### Callbacks
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ impl Item for NativeScrollView {
|
||||||
cpp!(unsafe [] -> qttypes::QMargins as "QMargins" {
|
cpp!(unsafe [] -> qttypes::QMargins as "QMargins" {
|
||||||
ensure_initialized();
|
ensure_initialized();
|
||||||
QStyleOptionSlider option;
|
QStyleOptionSlider option;
|
||||||
initQSliderOptions(option, false, true, 0, 0, 1000, 1000);
|
initQSliderOptions(option, false, true, 0, 0, 1000, 1000, false);
|
||||||
|
|
||||||
int extent = qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent, &option, nullptr);
|
int extent = qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent, &option, nullptr);
|
||||||
int sliderMin = qApp->style()->pixelMetric(QStyle::PM_ScrollBarSliderMin, &option, nullptr);
|
int sliderMin = qApp->style()->pixelMetric(QStyle::PM_ScrollBarSliderMin, &option, nullptr);
|
||||||
|
@ -157,7 +157,7 @@ impl Item for NativeScrollView {
|
||||||
] -> u32 as "int" {
|
] -> u32 as "int" {
|
||||||
ensure_initialized();
|
ensure_initialized();
|
||||||
QStyleOptionSlider option;
|
QStyleOptionSlider option;
|
||||||
initQSliderOptions(option, pressed, true, active_controls, 0, max, -value);
|
initQSliderOptions(option, pressed, true, active_controls, 0, max, -value, false);
|
||||||
option.pageStep = page_size;
|
option.pageStep = page_size;
|
||||||
if (!horizontal) {
|
if (!horizontal) {
|
||||||
option.state ^= QStyle::State_Horizontal;
|
option.state ^= QStyle::State_Horizontal;
|
||||||
|
@ -383,7 +383,7 @@ impl Item for NativeScrollView {
|
||||||
QStyleOptionSlider option;
|
QStyleOptionSlider option;
|
||||||
option.state |= QStyle::State(initial_state);
|
option.state |= QStyle::State(initial_state);
|
||||||
option.rect = QRect(QPoint(), r.size());
|
option.rect = QRect(QPoint(), r.size());
|
||||||
initQSliderOptions(option, pressed, true, active_controls, 0, max / dpr, -value / dpr);
|
initQSliderOptions(option, pressed, true, active_controls, 0, max / dpr, -value / dpr, false);
|
||||||
option.subControls = QStyle::SC_All;
|
option.subControls = QStyle::SC_All;
|
||||||
option.pageStep = page_size / dpr;
|
option.pageStep = page_size / dpr;
|
||||||
if (has_focus)
|
if (has_focus)
|
||||||
|
|
|
@ -26,6 +26,7 @@ pub struct NativeSlider {
|
||||||
pub y: Property<LogicalLength>,
|
pub y: Property<LogicalLength>,
|
||||||
pub width: Property<LogicalLength>,
|
pub width: Property<LogicalLength>,
|
||||||
pub height: Property<LogicalLength>,
|
pub height: Property<LogicalLength>,
|
||||||
|
pub vertical: Property<bool>,
|
||||||
pub enabled: Property<bool>,
|
pub enabled: Property<bool>,
|
||||||
pub value: Property<f32>,
|
pub value: Property<f32>,
|
||||||
pub minimum: Property<f32>,
|
pub minimum: Property<f32>,
|
||||||
|
@ -38,10 +39,15 @@ pub struct NativeSlider {
|
||||||
}
|
}
|
||||||
|
|
||||||
cpp! {{
|
cpp! {{
|
||||||
void initQSliderOptions(QStyleOptionSlider &option, bool pressed, bool enabled, int active_controls, float minimum, float maximum, float float_value) {
|
void initQSliderOptions(QStyleOptionSlider &option, bool pressed, bool enabled, int active_controls, float minimum, float maximum, float float_value, bool vertical) {
|
||||||
option.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle;
|
option.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle;
|
||||||
option.activeSubControls = { active_controls };
|
option.activeSubControls = { active_controls };
|
||||||
|
if (vertical) {
|
||||||
|
option.orientation = Qt::Vertical;
|
||||||
|
} else {
|
||||||
option.orientation = Qt::Horizontal;
|
option.orientation = Qt::Horizontal;
|
||||||
|
option.state |= QStyle::State_Horizontal;
|
||||||
|
}
|
||||||
// Slint slider supports floating point ranges, while Qt uses integer. To support (0..1) ranges
|
// Slint slider supports floating point ranges, while Qt uses integer. To support (0..1) ranges
|
||||||
// of values, scale up a little, before truncating to integer values.
|
// of values, scale up a little, before truncating to integer values.
|
||||||
option.maximum = maximum * 1024;
|
option.maximum = maximum * 1024;
|
||||||
|
@ -54,7 +60,6 @@ void initQSliderOptions(QStyleOptionSlider &option, bool pressed, bool enabled,
|
||||||
} else {
|
} else {
|
||||||
option.palette.setCurrentColorGroup(QPalette::Disabled);
|
option.palette.setCurrentColorGroup(QPalette::Disabled);
|
||||||
}
|
}
|
||||||
option.state |= QStyle::State_Horizontal;
|
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
option.state |= QStyle::State_Sunken | QStyle::State_MouseOver;
|
option.state |= QStyle::State_Sunken | QStyle::State_MouseOver;
|
||||||
}
|
}
|
||||||
|
@ -88,6 +93,7 @@ impl Item for NativeSlider {
|
||||||
let data = self.data();
|
let data = self.data();
|
||||||
let active_controls = data.active_controls;
|
let active_controls = data.active_controls;
|
||||||
let pressed = data.pressed;
|
let pressed = data.pressed;
|
||||||
|
let vertical = self.vertical();
|
||||||
let widget: NonNull<()> = SlintTypeErasedWidgetPtr::qwidget_ptr(&self.widget_ptr);
|
let widget: NonNull<()> = SlintTypeErasedWidgetPtr::qwidget_ptr(&self.widget_ptr);
|
||||||
|
|
||||||
let size = cpp!(unsafe [
|
let size = cpp!(unsafe [
|
||||||
|
@ -97,24 +103,39 @@ impl Item for NativeSlider {
|
||||||
max as "float",
|
max as "float",
|
||||||
active_controls as "int",
|
active_controls as "int",
|
||||||
pressed as "bool",
|
pressed as "bool",
|
||||||
|
vertical as "bool",
|
||||||
widget as "QWidget*"
|
widget as "QWidget*"
|
||||||
] -> qttypes::QSize as "QSize" {
|
] -> qttypes::QSize as "QSize" {
|
||||||
ensure_initialized();
|
ensure_initialized();
|
||||||
QStyleOptionSlider option;
|
QStyleOptionSlider option;
|
||||||
initQSliderOptions(option, pressed, enabled, active_controls, min, max, value);
|
initQSliderOptions(option, pressed, enabled, active_controls, min, max, value, vertical);
|
||||||
auto style = qApp->style();
|
auto style = qApp->style();
|
||||||
auto thick = style->pixelMetric(QStyle::PM_SliderThickness, &option, widget);
|
auto thick = style->pixelMetric(QStyle::PM_SliderThickness, &option, widget);
|
||||||
return style->sizeFromContents(QStyle::CT_Slider, &option, QSize(0, thick), widget);
|
return style->sizeFromContents(QStyle::CT_Slider, &option, QSize(0, thick), widget);
|
||||||
});
|
});
|
||||||
match orientation {
|
match orientation {
|
||||||
Orientation::Horizontal => {
|
Orientation::Horizontal => {
|
||||||
|
if !vertical {
|
||||||
LayoutInfo { min: size.width as f32, stretch: 1., ..LayoutInfo::default() }
|
LayoutInfo { min: size.width as f32, stretch: 1., ..LayoutInfo::default() }
|
||||||
}
|
} else {
|
||||||
Orientation::Vertical => LayoutInfo {
|
LayoutInfo {
|
||||||
min: size.height as f32,
|
min: size.height as f32,
|
||||||
max: size.height as f32,
|
max: size.height as f32,
|
||||||
..LayoutInfo::default()
|
..LayoutInfo::default()
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Orientation::Vertical => {
|
||||||
|
if !vertical {
|
||||||
|
LayoutInfo {
|
||||||
|
min: size.height as f32,
|
||||||
|
max: size.height as f32,
|
||||||
|
..LayoutInfo::default()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LayoutInfo { min: size.width as f32, stretch: 1., ..LayoutInfo::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +163,7 @@ impl Item for NativeSlider {
|
||||||
let mut data = self.data();
|
let mut data = self.data();
|
||||||
let active_controls = data.active_controls;
|
let active_controls = data.active_controls;
|
||||||
let pressed: bool = data.pressed != 0;
|
let pressed: bool = data.pressed != 0;
|
||||||
|
let vertical = self.vertical();
|
||||||
let pos = event
|
let pos = event
|
||||||
.position()
|
.position()
|
||||||
.map(|p| qttypes::QPoint { x: p.x as _, y: p.y as _ })
|
.map(|p| qttypes::QPoint { x: p.x as _, y: p.y as _ })
|
||||||
|
@ -157,11 +179,12 @@ impl Item for NativeSlider {
|
||||||
max as "float",
|
max as "float",
|
||||||
active_controls as "int",
|
active_controls as "int",
|
||||||
pressed as "bool",
|
pressed as "bool",
|
||||||
|
vertical as "bool",
|
||||||
widget as "QWidget*"
|
widget as "QWidget*"
|
||||||
] -> u32 as "int" {
|
] -> u32 as "int" {
|
||||||
ensure_initialized();
|
ensure_initialized();
|
||||||
QStyleOptionSlider option;
|
QStyleOptionSlider option;
|
||||||
initQSliderOptions(option, pressed, enabled, active_controls, min, max, value);
|
initQSliderOptions(option, pressed, enabled, active_controls, min, max, value, vertical);
|
||||||
auto style = qApp->style();
|
auto style = qApp->style();
|
||||||
option.rect = { QPoint{}, size };
|
option.rect = { QPoint{}, size };
|
||||||
return style->hitTestComplexControl(QStyle::CC_Slider, &option, pos, widget);
|
return style->hitTestComplexControl(QStyle::CC_Slider, &option, pos, widget);
|
||||||
|
@ -176,7 +199,7 @@ impl Item for NativeSlider {
|
||||||
button: PointerEventButton::Left,
|
button: PointerEventButton::Left,
|
||||||
click_count: _,
|
click_count: _,
|
||||||
} => {
|
} => {
|
||||||
data.pressed_x = pos.x as f32;
|
data.pressed_x = if vertical { pos.y as f32 } else { pos.x as f32 };
|
||||||
data.pressed = 1;
|
data.pressed = 1;
|
||||||
data.pressed_val = value;
|
data.pressed_val = value;
|
||||||
InputEventResult::GrabMouse
|
InputEventResult::GrabMouse
|
||||||
|
@ -186,10 +209,12 @@ impl Item for NativeSlider {
|
||||||
InputEventResult::EventAccepted
|
InputEventResult::EventAccepted
|
||||||
}
|
}
|
||||||
MouseEvent::Moved { position: pos } => {
|
MouseEvent::Moved { position: pos } => {
|
||||||
|
let (coord, size) =
|
||||||
|
if vertical { (pos.y, size.height) } else { (pos.x, size.width) };
|
||||||
if data.pressed != 0 {
|
if data.pressed != 0 {
|
||||||
// FIXME: use QStyle::subControlRect to find out the actual size of the groove
|
// FIXME: use QStyle::subControlRect to find out the actual size of the groove
|
||||||
let new_val = data.pressed_val
|
let new_val = data.pressed_val
|
||||||
+ ((pos.x as f32) - data.pressed_x) * (max - min) / size.width as f32;
|
+ ((coord as f32) - data.pressed_x) * (max - min) / size as f32;
|
||||||
let new_val = new_val.max(min).min(max);
|
let new_val = new_val.max(min).min(max);
|
||||||
self.value.set(new_val);
|
self.value.set(new_val);
|
||||||
Self::FIELD_OFFSETS.changed.apply_pin(self).call(&(new_val,));
|
Self::FIELD_OFFSETS.changed.apply_pin(self).call(&(new_val,));
|
||||||
|
@ -242,6 +267,7 @@ impl Item for NativeSlider {
|
||||||
let data = this.data();
|
let data = this.data();
|
||||||
let active_controls = data.active_controls;
|
let active_controls = data.active_controls;
|
||||||
let pressed = data.pressed;
|
let pressed = data.pressed;
|
||||||
|
let vertical = this.vertical();
|
||||||
|
|
||||||
cpp!(unsafe [
|
cpp!(unsafe [
|
||||||
painter as "QPainterPtr*",
|
painter as "QPainterPtr*",
|
||||||
|
@ -253,6 +279,7 @@ impl Item for NativeSlider {
|
||||||
size as "QSize",
|
size as "QSize",
|
||||||
active_controls as "int",
|
active_controls as "int",
|
||||||
pressed as "bool",
|
pressed as "bool",
|
||||||
|
vertical as "bool",
|
||||||
dpr as "float",
|
dpr as "float",
|
||||||
initial_state as "int"
|
initial_state as "int"
|
||||||
] {
|
] {
|
||||||
|
@ -260,7 +287,7 @@ impl Item for NativeSlider {
|
||||||
option.initFrom(widget);
|
option.initFrom(widget);
|
||||||
option.state |= QStyle::State(initial_state);
|
option.state |= QStyle::State(initial_state);
|
||||||
option.rect = QRect(QPoint(), size / dpr);
|
option.rect = QRect(QPoint(), size / dpr);
|
||||||
initQSliderOptions(option, pressed, enabled, active_controls, min, max, value);
|
initQSliderOptions(option, pressed, enabled, active_controls, min, max, value, vertical);
|
||||||
auto style = qApp->style();
|
auto style = qApp->style();
|
||||||
style->drawComplexControl(QStyle::CC_Slider, &option, painter->get(), widget);
|
style->drawComplexControl(QStyle::CC_Slider, &option, painter->get(), widget);
|
||||||
});
|
});
|
||||||
|
|
|
@ -440,6 +440,7 @@ export component NativeSlider {
|
||||||
in-out property <float> value;
|
in-out property <float> value;
|
||||||
in property <float> minimum;
|
in property <float> minimum;
|
||||||
in property <float> maximum: 100;
|
in property <float> maximum: 100;
|
||||||
|
in property <bool> vertical: false;
|
||||||
callback changed(float);
|
callback changed(float);
|
||||||
//-is_internal
|
//-is_internal
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,17 @@ import { Palette } from "styling.slint";
|
||||||
export component Slider {
|
export component Slider {
|
||||||
callback changed(float /* value */);
|
callback changed(float /* value */);
|
||||||
|
|
||||||
|
in property<bool> vertical: false;
|
||||||
in property<float> maximum: 100;
|
in property<float> maximum: 100;
|
||||||
in property<float> minimum: 0;
|
in property<float> minimum: 0;
|
||||||
in property<bool> enabled <=> i-touch-area.enabled;
|
in property<bool> enabled <=> i-touch-area.enabled;
|
||||||
out property<bool> has-focus: i-focus-scope.has-focus;
|
out property<bool> has-focus: i-focus-scope.has-focus;
|
||||||
in-out property<float> value;
|
in-out property<float> value;
|
||||||
|
|
||||||
min-height: 20px;
|
min-width: vertical ? 20px : 0px;
|
||||||
vertical-stretch: 0;
|
min-height: vertical ? 0px : 20px;
|
||||||
horizontal-stretch: 1;
|
vertical-stretch: vertical ? 1 : 0;
|
||||||
|
horizontal-stretch: vertical ? 0 : 1;
|
||||||
accessible-role: slider;
|
accessible-role: slider;
|
||||||
accessible-value: root.value;
|
accessible-value: root.value;
|
||||||
accessible-value-minimum: root.minimum;
|
accessible-value-minimum: root.minimum;
|
||||||
|
@ -22,21 +24,24 @@ export component Slider {
|
||||||
accessible-value-step: (root.maximum - root.minimum) / 100;
|
accessible-value-step: (root.maximum - root.minimum) / 100;
|
||||||
|
|
||||||
i-rail := Rectangle {
|
i-rail := Rectangle {
|
||||||
height: 4px;
|
width: vertical ? 4px : parent.width;
|
||||||
|
height: vertical ? parent.height : 4px;
|
||||||
background: Palette.control-stroke;
|
background: Palette.control-stroke;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
i-track := Rectangle {
|
i-track := Rectangle {
|
||||||
x: 0;
|
x: vertical ? (parent.width - self.width) / 2 : 0;
|
||||||
height: i-rail.height;
|
y: vertical ? 0 : (parent.height - self.height) / 2;
|
||||||
|
width: vertical ? i-rail.width : i-thumb.x + (i-thumb.width / 2);
|
||||||
|
height: vertical ? i-thumb.y + (i-thumb.height / 2) : i-rail.height;
|
||||||
background: Palette.accent-default;
|
background: Palette.accent-default;
|
||||||
border-radius: i-rail.border-radius;
|
border-radius: i-rail.border-radius;
|
||||||
width: i-thumb.x + (i-thumb.width / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i-thumb := Rectangle {
|
i-thumb := Rectangle {
|
||||||
x: (parent.width - self.width) * (root.value - root.minimum) / (root.maximum - root.minimum);
|
x: vertical ? (parent.width - self.width) / 2 : (parent.width - self.width) * (root.value - root.minimum) / (root.maximum - root.minimum);
|
||||||
|
y: vertical ? (parent.height - self.height) * (root.value - root.minimum) / (root.maximum - root.minimum) : (parent.height - self.height) / 2;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: self.width;
|
height: self.width;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
@ -75,23 +80,36 @@ export component Slider {
|
||||||
}
|
}
|
||||||
|
|
||||||
moved => {
|
moved => {
|
||||||
if (self.enabled && self.pressed) {
|
if (!vertical && self.enabled && self.pressed) {
|
||||||
root.value = max(root.minimum, min(root.maximum,
|
root.value = max(root.minimum, min(root.maximum,
|
||||||
self.pressed-value + (i-touch-area.mouse-x - i-touch-area.pressed-x) * (root.maximum - root.minimum) / (root.width - i-thumb.width)));
|
self.pressed-value + (i-touch-area.mouse-x - i-touch-area.pressed-x) * (root.maximum - root.minimum) / (root.width - i-thumb.width)));
|
||||||
root.changed(root.value);
|
root.changed(root.value);
|
||||||
}
|
}
|
||||||
|
if (vertical && self.enabled && self.pressed) {
|
||||||
|
root.value = max(root.minimum, min(root.maximum,
|
||||||
|
self.pressed-value + (i-touch-area.mouse-y - i-touch-area.pressed-y) * (root.maximum - root.minimum) / (root.height - i-thumb.height)));
|
||||||
|
root.changed(root.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i-focus-scope := FocusScope {
|
i-focus-scope := FocusScope {
|
||||||
x: 0;
|
x: 0;
|
||||||
|
y: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
|
||||||
key-pressed(event) => {
|
key-pressed(event) => {
|
||||||
if (self.enabled && event.text == Key.RightArrow) {
|
if (!vertical && self.enabled && event.text == Key.RightArrow) {
|
||||||
root.value = Math.min(root.value + 1, root.maximum);
|
root.value = Math.min(root.value + 1, root.maximum);
|
||||||
accept
|
accept
|
||||||
} else if (self.enabled && event.text == Key.LeftArrow) {
|
} else if (!vertical && self.enabled && event.text == Key.LeftArrow) {
|
||||||
|
root.value = Math.max(root.value - 1, root.minimum);
|
||||||
|
accept
|
||||||
|
} else if (vertical && self.enabled && event.text == Key.DownArrow) {
|
||||||
|
root.value = Math.min(root.value + 1, root.maximum);
|
||||||
|
accept
|
||||||
|
} else if (vertical && self.enabled && event.text == Key.UpArrow) {
|
||||||
root.value = Math.max(root.value - 1, root.minimum);
|
root.value = Math.max(root.value - 1, root.minimum);
|
||||||
accept
|
accept
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,13 +8,15 @@ import { Palette, Elevation } from "styling.slint";
|
||||||
export component Slider {
|
export component Slider {
|
||||||
callback changed(float /* value */);
|
callback changed(float /* value */);
|
||||||
|
|
||||||
|
in property<bool> vertical: false;
|
||||||
in property <float> maximum: 100;
|
in property <float> maximum: 100;
|
||||||
in property <bool> enabled <=> i-touch-area.enabled;
|
in property <bool> enabled <=> i-touch-area.enabled;
|
||||||
in property <float> minimum: 0;
|
in property <float> minimum: 0;
|
||||||
out property <bool> has-focus: i-focus-scope.has-focus;
|
out property <bool> has-focus: i-focus-scope.has-focus;
|
||||||
in-out property <float> value;
|
in-out property <float> value;
|
||||||
|
|
||||||
min-height: 20px;
|
min-width: vertical ? 20px : 0px;
|
||||||
|
min-height: vertical ? 0px : 20px;
|
||||||
|
|
||||||
accessible-role: slider;
|
accessible-role: slider;
|
||||||
accessible-value: root.value;
|
accessible-value: root.value;
|
||||||
|
@ -25,26 +27,27 @@ export component Slider {
|
||||||
i-background := Rectangle {
|
i-background := Rectangle {
|
||||||
background: Palette.surface-variant;
|
background: Palette.surface-variant;
|
||||||
opacity: 0.38;
|
opacity: 0.38;
|
||||||
|
x: (parent.width - self.width) / 2;
|
||||||
y: (parent.height - self.height) / 2;
|
y: (parent.height - self.height) / 2;
|
||||||
width: 100%;
|
width: vertical ? 4px : parent.width;
|
||||||
height: 4px;
|
height: vertical ? parent.height : 4px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
i-track := Rectangle {
|
i-track := Rectangle {
|
||||||
background: Palette.primary;
|
background: Palette.primary;
|
||||||
x: i-background.x;
|
x: vertical ? (parent.width - self.width) / 2 : i-background.x;
|
||||||
y: (parent.height - self.height) / 2;
|
y: vertical ? i-background.y : (parent.height - self.height) / 2;
|
||||||
width: i-handle.x + (i-handle.width / 2);
|
width: vertical? i-background.width : i-handle.x + (i-handle.width / 2);
|
||||||
height: i-background.height;
|
height: vertical? i-handle.y + (i-handle.height / 2) : i-background.height;
|
||||||
border-radius: i-background.border-radius;
|
border-radius: i-background.border-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
i-state-layer := Rectangle {
|
i-state-layer := Rectangle {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
background: Palette.primary;
|
background: Palette.primary;
|
||||||
x: i-handle.x - (self.width - i-handle.width) / 2;
|
x: vertical ? (parent.width - self.width) / 2 : i-handle.x - (self.width - i-handle.width) / 2;
|
||||||
y: (parent.height - self.height) / 2;
|
y: vertical ? i-handle.y - (self.height - i-handle.height) / 2 : (parent.height - self.height) / 2;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: max(self.width, self.height) / 2;
|
border-radius: max(self.width, self.height) / 2;
|
||||||
|
@ -54,10 +57,10 @@ export component Slider {
|
||||||
|
|
||||||
i-handle := Rectangle {
|
i-handle := Rectangle {
|
||||||
background: Palette.primary;
|
background: Palette.primary;
|
||||||
x: (parent.width - i-handle.width) * (root.value - root.minimum) / (root.maximum - root.minimum);
|
x: vertical ? (parent.width - self.width) / 2 : (parent.width - i-handle.width) * (root.value - root.minimum) / (root.maximum - root.minimum);
|
||||||
y: (parent.height - self.height) / 2;
|
y: vertical ? (parent.height - i-handle.height) * (root.value - root.minimum) / (root.maximum - root.minimum) : (parent.height - self.height) / 2;
|
||||||
width: root.height;
|
width: i-state-layer.width;
|
||||||
height: root.height;
|
height: i-state-layer.height;
|
||||||
border-radius: max(self.width, self.height) / 2;
|
border-radius: max(self.width, self.height) / 2;
|
||||||
drop-shadow-color: Palette.shadow;
|
drop-shadow-color: Palette.shadow;
|
||||||
drop-shadow-blur: Elevation.level1;
|
drop-shadow-blur: Elevation.level1;
|
||||||
|
@ -70,29 +73,44 @@ export component Slider {
|
||||||
property <float> pressed-value;
|
property <float> pressed-value;
|
||||||
property <bool> i-handle-hover: self.has-hover && self.mouse-x >= i-handle.x && self.mouse-x <= i-handle.x + i-handle.width
|
property <bool> i-handle-hover: self.has-hover && self.mouse-x >= i-handle.x && self.mouse-x <= i-handle.x + i-handle.width
|
||||||
&& self.mouse-y >= i-handle.y && self.mouse-y <= i-handle.y + i-handle.height;
|
&& self.mouse-y >= i-handle.y && self.mouse-y <= i-handle.y + i-handle.height;
|
||||||
|
|
||||||
pointer-event(event) => {
|
pointer-event(event) => {
|
||||||
if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
|
if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
|
||||||
self.pressed-value = root.value;
|
self.pressed-value = root.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
moved => {
|
moved => {
|
||||||
if (self.enabled && self.pressed) {
|
if (!vertical && self.enabled && self.pressed) {
|
||||||
root.value = max(root.minimum, min(root.maximum,
|
root.value = max(root.minimum, min(root.maximum,
|
||||||
self.pressed-value + (i-touch-area.mouse-x - i-touch-area.pressed-x) * (root.maximum - root.minimum) / (root.width - i-handle.width)));
|
self.pressed-value + (i-touch-area.mouse-x - i-touch-area.pressed-x) * (root.maximum - root.minimum) / (root.width - i-handle.width)));
|
||||||
root.changed(root.value);
|
root.changed(root.value);
|
||||||
}
|
}
|
||||||
|
if (vertical && self.enabled && self.pressed) {
|
||||||
|
root.value = max(root.minimum, min(root.maximum,
|
||||||
|
self.pressed-value + (i-touch-area.mouse-y - i-touch-area.pressed-y) * (root.maximum - root.minimum) / (root.height - i-handle.height)));
|
||||||
|
root.changed(root.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i-focus-scope := FocusScope {
|
i-focus-scope := FocusScope {
|
||||||
x: 0;
|
x: 0;
|
||||||
|
y: 0;
|
||||||
width: 0px;
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
|
||||||
key-pressed(event) => {
|
key-pressed(event) => {
|
||||||
if (self.enabled && event.text == Key.RightArrow) {
|
if (!vertical && self.enabled && event.text == Key.RightArrow) {
|
||||||
root.value = Math.min(root.value + 1, root.maximum);
|
root.value = Math.min(root.value + 1, root.maximum);
|
||||||
accept
|
accept
|
||||||
} else if (self.enabled && event.text == Key.LeftArrow) {
|
} else if (!vertical && self.enabled && event.text == Key.LeftArrow) {
|
||||||
|
root.value = Math.max(root.value - 1, root.minimum);
|
||||||
|
accept
|
||||||
|
} else if (vertical && self.enabled && event.text == Key.DownArrow) {
|
||||||
|
root.value = Math.min(root.value + 1, root.maximum);
|
||||||
|
accept
|
||||||
|
} else if (vertical && self.enabled && event.text == Key.UpArrow) {
|
||||||
root.value = Math.max(root.value - 1, root.minimum);
|
root.value = Math.max(root.value - 1, root.minimum);
|
||||||
accept
|
accept
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue