From e31ad9f84cad2a68e44d16dd8605c5e706c89754 Mon Sep 17 00:00:00 2001 From: Gordon Shieh Date: Sun, 2 Jan 2022 00:19:37 -0800 Subject: [PATCH 1/9] Make slider scrollable by mouse wheel --- druid/src/widget/slider.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/druid/src/widget/slider.rs b/druid/src/widget/slider.rs index 7b09afb3f3..6b5d3941c4 100644 --- a/druid/src/widget/slider.rs +++ b/druid/src/widget/slider.rs @@ -162,6 +162,20 @@ impl Slider { let mapping = self.mapping; Annotated::new(self, mapping, named_steps, unnamed_steps) } + + fn calculate_scroll_value(&self, mouse_delta: f64) -> f64 { + let increment = if let Some(step) = self.mapping.step { + step + } else { + 0.1 + }; + + if mouse_delta < 0.0 { + increment + } else { + -increment + } + } } impl Widget for Slider { @@ -184,6 +198,15 @@ impl Widget for Slider { ctx.set_active(true); } } + if let Event::Wheel(me) = event { + if !ctx.is_disabled() { + *data = (*data + self.calculate_scroll_value(me.wheel_delta.y)) + .max(self.mapping.min) + .min(self.mapping.max); + ctx.request_paint(); + ctx.set_handled(); + } + } } } From 978f995a9dcbc99837e0c5c207a120dfefff6b4d Mon Sep 17 00:00:00 2001 From: Gordon Shieh Date: Tue, 4 Jan 2022 19:26:24 -0800 Subject: [PATCH 2/9] Use 10% steps based off the min and max range of slider --- druid/src/widget/slider.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/druid/src/widget/slider.rs b/druid/src/widget/slider.rs index 6b5d3941c4..f1842f3755 100644 --- a/druid/src/widget/slider.rs +++ b/druid/src/widget/slider.rs @@ -167,7 +167,7 @@ impl Slider { let increment = if let Some(step) = self.mapping.step { step } else { - 0.1 + (self.max - self.min) / 10.0 }; if mouse_delta < 0.0 { From 0d715ed2e0ebb02f3d9396aa7fc712cbae522c80 Mon Sep 17 00:00:00 2001 From: Gordon Shieh Date: Tue, 4 Jan 2022 19:30:03 -0800 Subject: [PATCH 3/9] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2bd2fa5a9..2b90822478 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ You can find its changes [documented below](#070---2021-01-01). - Scope: expose scoped state using state() and state_mut() ([#2082] by [@rjwittams] - Tabs: allow getting and setting the tab index of a Tabs widget ([#2082] by [@rjwittams] - `RangeSlider` and `Annotated` ([#1979] by [@xarvic]) +- `Slider` widget now scrollable by mouse wheel ([#2104] by [@gordonshieh]) ### Changed From 052174109936a6356a85082cadac9fdf82ae4ea5 Mon Sep 17 00:00:00 2001 From: Gordon Shieh Date: Sat, 8 Jan 2022 00:43:14 -0800 Subject: [PATCH 4/9] Fix missing mapping field --- druid/src/widget/slider.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/druid/src/widget/slider.rs b/druid/src/widget/slider.rs index f1842f3755..78665c663a 100644 --- a/druid/src/widget/slider.rs +++ b/druid/src/widget/slider.rs @@ -167,7 +167,7 @@ impl Slider { let increment = if let Some(step) = self.mapping.step { step } else { - (self.max - self.min) / 10.0 + (self.mapping.max - self.mapping.min) / 10.0 }; if mouse_delta < 0.0 { From 5e9923167addee0548e14ed040d96234c70c771e Mon Sep 17 00:00:00 2001 From: Gordon Shieh Date: Sat, 8 Jan 2022 00:48:39 -0800 Subject: [PATCH 5/9] Don't move slider when mousedown and knob is active --- druid/src/widget/slider.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/druid/src/widget/slider.rs b/druid/src/widget/slider.rs index 78665c663a..1579ce31ef 100644 --- a/druid/src/widget/slider.rs +++ b/druid/src/widget/slider.rs @@ -199,7 +199,7 @@ impl Widget for Slider { } } if let Event::Wheel(me) = event { - if !ctx.is_disabled() { + if !self.knob.active { *data = (*data + self.calculate_scroll_value(me.wheel_delta.y)) .max(self.mapping.min) .min(self.mapping.max); From 1dc943c9b4d341959cd3da043bddff313b646f43 Mon Sep 17 00:00:00 2001 From: Gordon Shieh Date: Sat, 8 Jan 2022 19:30:30 -0800 Subject: [PATCH 6/9] Move calculate_scroll_value to SliderValueMapping --- druid/src/widget/slider.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/druid/src/widget/slider.rs b/druid/src/widget/slider.rs index 1579ce31ef..69e6073910 100644 --- a/druid/src/widget/slider.rs +++ b/druid/src/widget/slider.rs @@ -162,20 +162,6 @@ impl Slider { let mapping = self.mapping; Annotated::new(self, mapping, named_steps, unnamed_steps) } - - fn calculate_scroll_value(&self, mouse_delta: f64) -> f64 { - let increment = if let Some(step) = self.mapping.step { - step - } else { - (self.mapping.max - self.mapping.min) / 10.0 - }; - - if mouse_delta < 0.0 { - increment - } else { - -increment - } - } } impl Widget for Slider { @@ -200,7 +186,7 @@ impl Widget for Slider { } if let Event::Wheel(me) = event { if !self.knob.active { - *data = (*data + self.calculate_scroll_value(me.wheel_delta.y)) + *data = (*data + self.mapping.calculate_scroll_value(me.wheel_delta.y)) .max(self.mapping.min) .min(self.mapping.max); ctx.request_paint(); @@ -680,6 +666,20 @@ impl SliderValueMapping { value } + fn calculate_scroll_value(&self, mouse_delta: f64) -> f64 { + let increment = if let Some(step) = self.step { + step + } else { + (self.max - self.min) / 10.0 + }; + + if mouse_delta < 0.0 { + increment + } else { + -increment + } + } + fn get_point(&self, value: f64, knob_size: f64, widget_size: Size) -> Point { let knob_major = (self.axis.major(widget_size) - knob_size) * self.normalize(value) + knob_size / 2.; From 4366da111fa1834cdcca79934cb80f408a4ba40b Mon Sep 17 00:00:00 2001 From: Gordon Shieh Date: Sat, 8 Jan 2022 20:09:39 -0800 Subject: [PATCH 7/9] Handle mouse wheel on RangeSlider --- druid/src/widget/slider.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/druid/src/widget/slider.rs b/druid/src/widget/slider.rs index 69e6073910..66d66ff8a8 100644 --- a/druid/src/widget/slider.rs +++ b/druid/src/widget/slider.rs @@ -368,6 +368,26 @@ impl Widget<(f64, f64)> for RangeSlider { ctx.request_paint(); } } + if let Event::Wheel(me) = event { + if !self.left_knob.is_active() && !self.right_knob.is_active() { + let knob_size = env.get(theme::BASIC_WIDGET_HEIGHT); + let press_value = + self.mapping + .calculate_value(me.pos, knob_size, ctx.size(), 0.0); + + if press_value - data.0 < data.1 - press_value { + data.0 = (data.0 + self.mapping.calculate_scroll_value(me.wheel_delta.y)) + .min(self.mapping.max) + .max(self.mapping.min); + } else { + data.1 = (data.1 + self.mapping.calculate_scroll_value(me.wheel_delta.y)) + .min(self.mapping.max) + .max(self.mapping.min); + } + ctx.request_paint(); + ctx.set_handled(); + } + } } } From 60a7481452473273679095db95e23df5c25d6413 Mon Sep 17 00:00:00 2001 From: Gordon Shieh Date: Sat, 8 Jan 2022 21:38:44 -0800 Subject: [PATCH 8/9] Properly bound mouse wheel event ranges --- druid/src/widget/slider.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/druid/src/widget/slider.rs b/druid/src/widget/slider.rs index 66d66ff8a8..83bd49854f 100644 --- a/druid/src/widget/slider.rs +++ b/druid/src/widget/slider.rs @@ -377,12 +377,12 @@ impl Widget<(f64, f64)> for RangeSlider { if press_value - data.0 < data.1 - press_value { data.0 = (data.0 + self.mapping.calculate_scroll_value(me.wheel_delta.y)) - .min(self.mapping.max) + .min(data.1) .max(self.mapping.min); } else { data.1 = (data.1 + self.mapping.calculate_scroll_value(me.wheel_delta.y)) .min(self.mapping.max) - .max(self.mapping.min); + .max(data.0); } ctx.request_paint(); ctx.set_handled(); From e61ab09c182731c1846713b58465c0979592e501 Mon Sep 17 00:00:00 2001 From: Gordon Shieh Date: Sun, 9 Jan 2022 21:00:50 -0800 Subject: [PATCH 9/9] Don't infinite loop when the slider ranges are equal --- druid/src/widget/slider.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/druid/src/widget/slider.rs b/druid/src/widget/slider.rs index 83bd49854f..fd2b86a8cc 100644 --- a/druid/src/widget/slider.rs +++ b/druid/src/widget/slider.rs @@ -505,6 +505,9 @@ impl> Annotated { self.labels.push(layout); walk += self.labeled_steps; + if self.labeled_steps == 0.0 { + break; + } } } @@ -596,6 +599,9 @@ impl> Widget for Annotated { ctx.stroke(line, &text_color, 1.0); walk += self.unlabeled_steps; + if self.labeled_steps == 0.0 { + return; + } } let mut walk = self.mapping.min; @@ -626,6 +632,9 @@ impl> Widget for Annotated { ); walk += self.labeled_steps; + if self.labeled_steps == 0.0 { + return; + } } self.inner.paint(ctx, data, env);