From 5e2b3d4a51be97c77124dcd60e5ee3bed1b19826 Mon Sep 17 00:00:00 2001 From: Jonatan Pettersson Date: Wed, 20 Sep 2023 20:56:50 +0200 Subject: Enhance `Slider` and `VerticalSlider` functionality * Add optional default behavior * Add a `default` field * Add a `default()` method to set the `default` field * A double-click, ctrl-click or command-click will set the slider to the default value * Add optional fine-grained control * Add an optional `step_fine` field * Add a `step_fine()` method to set the `step_fine` field * Use `step_fine` in place of `step` while shift is pressed * Add increment/decrement via up/down keys * Update `Slider` and `VerticalSlider` examples --- widget/src/slider.rs | 164 +++++++++++++++++++++++++++++++++++++----- widget/src/vertical_slider.rs | 163 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 296 insertions(+), 31 deletions(-) (limited to 'widget/src') diff --git a/widget/src/slider.rs b/widget/src/slider.rs index 5c3b6384..3b7de8b9 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -2,8 +2,10 @@ //! //! A [`Slider`] has some local [`State`]. use crate::core::event::{self, Event}; +use crate::core::keyboard; +use crate::core::keyboard::key::{self, Key}; use crate::core::layout; -use crate::core::mouse; +use crate::core::mouse::{self, click}; use crate::core::renderer; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; @@ -49,7 +51,9 @@ where { range: RangeInclusive, step: T, + step_fine: Option, value: T, + default: Option, on_change: Box Message + 'a>, on_release: Option, width: Length, @@ -92,8 +96,10 @@ where Slider { value, + default: None, range, step: T::from(1), + step_fine: None, on_change: Box::new(on_change), on_release: None, width: Length::Fill, @@ -102,6 +108,13 @@ where } } + /// Sets the optional default value for the [`Slider`]. + /// If set, [`Slider`] will reset to this value when doubled-clicked, ctrl-clicked, or command-clicked. + pub fn default(mut self, default: impl Into) -> Self { + self.default = Some(default.into()); + self + } + /// Sets the release message of the [`Slider`]. /// This is called when the mouse is released from the slider. /// @@ -136,6 +149,13 @@ where self.step = step.into(); self } + + /// Sets the optional fine-grained step size for the [`Slider`]. + /// If set, this value is used as the step size while shift is pressed. + pub fn step_fine(mut self, step_fine: impl Into) -> Self { + self.step_fine = Some(step_fine.into()); + self + } } impl<'a, T, Message, Theme, Renderer> Widget @@ -188,8 +208,10 @@ where shell, tree.state.downcast_mut::(), &mut self.value, + self.default, &self.range, self.step, + self.step_fine, self.on_change.as_ref(), &self.on_release, ) @@ -253,8 +275,10 @@ pub fn update( shell: &mut Shell<'_, Message>, state: &mut State, value: &mut T, + default: Option, range: &RangeInclusive, step: T, + step_fine: Option, on_change: &dyn Fn(T) -> Message, on_release: &Option, ) -> event::Status @@ -264,14 +288,19 @@ where { let is_dragging = state.is_dragging; - let mut change = |cursor_position: Point| { + let change_cursor_position = |cursor_position: Point| -> Option { let bounds = layout.bounds(); let new_value = if cursor_position.x <= bounds.x { - *range.start() + Some(*range.start()) } else if cursor_position.x >= bounds.x + bounds.width { - *range.end() + Some(*range.end()) } else { - let step = step.into(); + let step = match step_fine { + Some(step_fine) if state.keyboard_modifiers.shift() => { + step_fine.into() + } + _ => step.into(), + }; let start = (*range.start()).into(); let end = (*range.end()).into(); @@ -281,17 +310,67 @@ where let steps = (percent * (end - start) / step).round(); let value = steps * step + start; - if let Some(value) = T::from_f64(value) { - value - } else { - return; + T::from_f64(value) + }; + + new_value + }; + + let increment = |value: T| -> Option { + let step = match step_fine { + Some(step_fine) if state.keyboard_modifiers.shift() => { + step_fine.into() + } + _ => step.into(), + }; + + let steps = (value.into() / step).round(); + let new_value = step * (steps + f64::from(1)); + + if new_value > (*range.end()).into() { + return Some(*range.end()); + } + + T::from_f64(new_value) + }; + + let decrement = |value: T| -> Option { + let step = match step_fine { + Some(step_fine) if state.keyboard_modifiers.shift() => { + step_fine.into() } + _ => step.into(), }; - if ((*value).into() - new_value.into()).abs() > f64::EPSILON { - shell.publish((on_change)(new_value)); + let steps = (value.into() / step).round(); + let new_value = step * (steps - f64::from(1)); + + if new_value < (*range.start()).into() { + return Some(*range.start()); + } + + T::from_f64(new_value) + }; + + enum Change { + Default, + CursorPosition(Point), + Increment, + Decrement, + } - *value = new_value; + let mut change = |change: Change| { + if let Some(new_value) = match change { + Change::Default => default, + Change::CursorPosition(point) => change_cursor_position(point), + Change::Increment => increment(*value), + Change::Decrement => decrement(*value), + } { + if ((*value).into() - new_value.into()).abs() > f64::EPSILON { + shell.publish((on_change)(new_value)); + + *value = new_value; + } } }; @@ -300,8 +379,31 @@ where | Event::Touch(touch::Event::FingerPressed { .. }) => { if let Some(cursor_position) = cursor.position_over(layout.bounds()) { - change(cursor_position); - state.is_dragging = true; + let click = + mouse::Click::new(cursor_position, state.last_click); + + match click.kind() { + click::Kind::Single => { + if state.keyboard_modifiers.control() + || state.keyboard_modifiers.command() + { + change(Change::Default); + state.is_dragging = false; + } else { + change(Change::CursorPosition(cursor_position)); + state.is_dragging = true; + } + } + click::Kind::Double => { + change(Change::Default); + state.is_dragging = false; + } + mouse::click::Kind::Triple => { + state.is_dragging = false; + } + } + + state.last_click = Some(click); return event::Status::Captured; } @@ -321,11 +423,31 @@ where Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { if is_dragging { - let _ = cursor.position().map(change); + let _ = cursor + .position() + .map(|point| change(Change::CursorPosition(point))); return event::Status::Captured; } } + Event::Keyboard(keyboard::Event::KeyPressed { key, .. }) => { + if cursor.position_over(layout.bounds()).is_some() { + match key { + Key::Named(key::Named::ArrowUp) => { + change(Change::Increment); + } + Key::Named(key::Named::ArrowDown) => { + change(Change::Decrement); + } + _ => (), + } + + return event::Status::Captured; + } + } + Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => { + state.keyboard_modifiers = modifiers; + } _ => {} } @@ -451,9 +573,11 @@ pub fn mouse_interaction( } /// The local state of a [`Slider`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +#[derive(Debug, Clone, Copy, Default)] pub struct State { is_dragging: bool, + last_click: Option, + keyboard_modifiers: keyboard::Modifiers, } impl State { @@ -462,3 +586,11 @@ impl State { State::default() } } + +impl PartialEq for State { + fn eq(&self, other: &Self) -> bool { + self.is_dragging == other.is_dragging + } +} + +impl Eq for State {} diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index d3086a81..c16727b6 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -7,8 +7,11 @@ pub use crate::style::slider::{Appearance, Handle, HandleShape, StyleSheet}; use crate::core; use crate::core::event::{self, Event}; +use crate::core::keyboard; +use crate::core::keyboard::key::{self, Key}; use crate::core::layout::{self, Layout}; use crate::core::mouse; +use crate::core::mouse::click; use crate::core::renderer; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; @@ -46,7 +49,9 @@ where { range: RangeInclusive, step: T, + step_fine: Option, value: T, + default: Option, on_change: Box Message + 'a>, on_release: Option, width: f32, @@ -89,8 +94,10 @@ where VerticalSlider { value, + default: None, range, step: T::from(1), + step_fine: None, on_change: Box::new(on_change), on_release: None, width: Self::DEFAULT_WIDTH, @@ -99,6 +106,13 @@ where } } + /// Sets the optional default value for the [`VerticalSlider`]. + /// If set, [`VerticalSlider`] will reset to this value when doubled-clicked, ctrl-clicked, or command-clicked. + pub fn default(mut self, default: impl Into) -> Self { + self.default = Some(default.into()); + self + } + /// Sets the release message of the [`VerticalSlider`]. /// This is called when the mouse is released from the slider. /// @@ -133,6 +147,13 @@ where self.step = step; self } + + /// Sets the optional fine-grained step size for the [`VerticalSlider`]. + /// If set, this value is used as the step size while shift is pressed. + pub fn step_fine(mut self, step_fine: impl Into) -> Self { + self.step_fine = Some(step_fine.into()); + self + } } impl<'a, T, Message, Theme, Renderer> Widget @@ -185,8 +206,10 @@ where shell, tree.state.downcast_mut::(), &mut self.value, + self.default, &self.range, self.step, + self.step_fine, self.on_change.as_ref(), &self.on_release, ) @@ -251,8 +274,10 @@ pub fn update( shell: &mut Shell<'_, Message>, state: &mut State, value: &mut T, + default: Option, range: &RangeInclusive, step: T, + step_fine: Option, on_change: &dyn Fn(T) -> Message, on_release: &Option, ) -> event::Status @@ -262,15 +287,20 @@ where { let is_dragging = state.is_dragging; - let mut change = |cursor_position: Point| { + let change_cursor_position = |cursor_position: Point| -> Option { let bounds = layout.bounds(); let new_value = if cursor_position.y >= bounds.y + bounds.height { - *range.start() + Some(*range.start()) } else if cursor_position.y <= bounds.y { - *range.end() + Some(*range.end()) } else { - let step = step.into(); + let step = match step_fine { + Some(step_fine) if state.keyboard_modifiers.shift() => { + step_fine.into() + } + _ => step.into(), + }; let start = (*range.start()).into(); let end = (*range.end()).into(); @@ -281,17 +311,67 @@ where let steps = (percent * (end - start) / step).round(); let value = steps * step + start; - if let Some(value) = T::from_f64(value) { - value - } else { - return; + T::from_f64(value) + }; + + new_value + }; + + let increment = |value: T| -> Option { + let step = match step_fine { + Some(step_fine) if state.keyboard_modifiers.shift() => { + step_fine.into() + } + _ => step.into(), + }; + + let steps = (value.into() / step).round(); + let new_value = step * (steps + f64::from(1)); + + if new_value > (*range.end()).into() { + return Some(*range.end()); + } + + T::from_f64(new_value) + }; + + let decrement = |value: T| -> Option { + let step = match step_fine { + Some(step_fine) if state.keyboard_modifiers.shift() => { + step_fine.into() } + _ => step.into(), }; - if ((*value).into() - new_value.into()).abs() > f64::EPSILON { - shell.publish((on_change)(new_value)); + let steps = (value.into() / step).round(); + let new_value = step * (steps - f64::from(1)); + + if new_value < (*range.start()).into() { + return Some(*range.start()); + } + + T::from_f64(new_value) + }; + + enum Change { + Default, + CursorPosition(Point), + Increment, + Decrement, + } - *value = new_value; + let mut change = |change: Change| { + if let Some(new_value) = match change { + Change::Default => default, + Change::CursorPosition(point) => change_cursor_position(point), + Change::Increment => increment(*value), + Change::Decrement => decrement(*value), + } { + if ((*value).into() - new_value.into()).abs() > f64::EPSILON { + shell.publish((on_change)(new_value)); + + *value = new_value; + } } }; @@ -300,8 +380,31 @@ where | Event::Touch(touch::Event::FingerPressed { .. }) => { if let Some(cursor_position) = cursor.position_over(layout.bounds()) { - change(cursor_position); - state.is_dragging = true; + let click = + mouse::Click::new(cursor_position, state.last_click); + + match click.kind() { + click::Kind::Single => { + if state.keyboard_modifiers.control() + || state.keyboard_modifiers.command() + { + change(Change::Default); + state.is_dragging = false; + } else { + change(Change::CursorPosition(cursor_position)); + state.is_dragging = true; + } + } + click::Kind::Double => { + change(Change::Default); + state.is_dragging = false; + } + mouse::click::Kind::Triple => { + state.is_dragging = false; + } + } + + state.last_click = Some(click); return event::Status::Captured; } @@ -321,11 +424,31 @@ where Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { if is_dragging { - let _ = cursor.position().map(change); + let _ = cursor + .position() + .map(|point| change(Change::CursorPosition(point))); return event::Status::Captured; } } + Event::Keyboard(keyboard::Event::KeyPressed { key, .. }) => { + if cursor.position_over(layout.bounds()).is_some() { + match key { + Key::Named(key::Named::ArrowUp) => { + change(Change::Increment); + } + Key::Named(key::Named::ArrowDown) => { + change(Change::Decrement); + } + _ => (), + } + + return event::Status::Captured; + } + } + Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => { + state.keyboard_modifiers = modifiers; + } _ => {} } @@ -451,9 +574,11 @@ pub fn mouse_interaction( } /// The local state of a [`VerticalSlider`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +#[derive(Debug, Clone, Copy, Default)] pub struct State { is_dragging: bool, + last_click: Option, + keyboard_modifiers: keyboard::Modifiers, } impl State { @@ -462,3 +587,11 @@ impl State { State::default() } } + +impl PartialEq for State { + fn eq(&self, other: &Self) -> bool { + self.is_dragging == other.is_dragging + } +} + +impl Eq for State {} -- cgit From 00716a159a371d070c5fb7d9ed2c660348343a33 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 31 Jan 2024 21:38:16 +0100 Subject: Simplify `Change` enum in `slider` logic and remove double-click behavior --- widget/src/slider.rs | 76 ++++++++++-------------------------------- widget/src/vertical_slider.rs | 77 ++++++++++--------------------------------- 2 files changed, 35 insertions(+), 118 deletions(-) (limited to 'widget/src') diff --git a/widget/src/slider.rs b/widget/src/slider.rs index 3b7de8b9..3d1d08ba 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -5,7 +5,7 @@ use crate::core::event::{self, Event}; use crate::core::keyboard; use crate::core::keyboard::key::{self, Key}; use crate::core::layout; -use crate::core::mouse::{self, click}; +use crate::core::mouse; use crate::core::renderer; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; @@ -287,8 +287,9 @@ where Message: Clone, { let is_dragging = state.is_dragging; + let current_value = *value; - let change_cursor_position = |cursor_position: Point| -> Option { + let locate = |cursor_position: Point| -> Option { let bounds = layout.bounds(); let new_value = if cursor_position.x <= bounds.x { Some(*range.start()) @@ -352,25 +353,11 @@ where T::from_f64(new_value) }; - enum Change { - Default, - CursorPosition(Point), - Increment, - Decrement, - } + let change = |new_value: T| { + if ((*value).into() - new_value.into()).abs() > f64::EPSILON { + shell.publish((on_change)(new_value)); - let mut change = |change: Change| { - if let Some(new_value) = match change { - Change::Default => default, - Change::CursorPosition(point) => change_cursor_position(point), - Change::Increment => increment(*value), - Change::Decrement => decrement(*value), - } { - if ((*value).into() - new_value.into()).abs() > f64::EPSILON { - shell.publish((on_change)(new_value)); - - *value = new_value; - } + *value = new_value; } }; @@ -379,32 +366,14 @@ where | Event::Touch(touch::Event::FingerPressed { .. }) => { if let Some(cursor_position) = cursor.position_over(layout.bounds()) { - let click = - mouse::Click::new(cursor_position, state.last_click); - - match click.kind() { - click::Kind::Single => { - if state.keyboard_modifiers.control() - || state.keyboard_modifiers.command() - { - change(Change::Default); - state.is_dragging = false; - } else { - change(Change::CursorPosition(cursor_position)); - state.is_dragging = true; - } - } - click::Kind::Double => { - change(Change::Default); - state.is_dragging = false; - } - mouse::click::Kind::Triple => { - state.is_dragging = false; - } + if state.keyboard_modifiers.command() { + let _ = default.map(change); + state.is_dragging = false; + } else { + let _ = locate(cursor_position).map(change); + state.is_dragging = true; } - state.last_click = Some(click); - return event::Status::Captured; } } @@ -423,9 +392,7 @@ where Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { if is_dragging { - let _ = cursor - .position() - .map(|point| change(Change::CursorPosition(point))); + let _ = cursor.position().and_then(locate).map(change); return event::Status::Captured; } @@ -434,10 +401,10 @@ where if cursor.position_over(layout.bounds()).is_some() { match key { Key::Named(key::Named::ArrowUp) => { - change(Change::Increment); + let _ = increment(current_value).map(change); } Key::Named(key::Named::ArrowDown) => { - change(Change::Decrement); + let _ = decrement(current_value).map(change); } _ => (), } @@ -573,10 +540,9 @@ pub fn mouse_interaction( } /// The local state of a [`Slider`]. -#[derive(Debug, Clone, Copy, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub struct State { is_dragging: bool, - last_click: Option, keyboard_modifiers: keyboard::Modifiers, } @@ -586,11 +552,3 @@ impl State { State::default() } } - -impl PartialEq for State { - fn eq(&self, other: &Self) -> bool { - self.is_dragging == other.is_dragging - } -} - -impl Eq for State {} diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index c16727b6..168d7848 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -11,7 +11,6 @@ use crate::core::keyboard; use crate::core::keyboard::key::{self, Key}; use crate::core::layout::{self, Layout}; use crate::core::mouse; -use crate::core::mouse::click; use crate::core::renderer; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; @@ -286,8 +285,9 @@ where Message: Clone, { let is_dragging = state.is_dragging; + let current_value = *value; - let change_cursor_position = |cursor_position: Point| -> Option { + let locate = |cursor_position: Point| -> Option { let bounds = layout.bounds(); let new_value = if cursor_position.y >= bounds.y + bounds.height { @@ -353,25 +353,11 @@ where T::from_f64(new_value) }; - enum Change { - Default, - CursorPosition(Point), - Increment, - Decrement, - } + let change = |new_value: T| { + if ((*value).into() - new_value.into()).abs() > f64::EPSILON { + shell.publish((on_change)(new_value)); - let mut change = |change: Change| { - if let Some(new_value) = match change { - Change::Default => default, - Change::CursorPosition(point) => change_cursor_position(point), - Change::Increment => increment(*value), - Change::Decrement => decrement(*value), - } { - if ((*value).into() - new_value.into()).abs() > f64::EPSILON { - shell.publish((on_change)(new_value)); - - *value = new_value; - } + *value = new_value; } }; @@ -380,32 +366,16 @@ where | Event::Touch(touch::Event::FingerPressed { .. }) => { if let Some(cursor_position) = cursor.position_over(layout.bounds()) { - let click = - mouse::Click::new(cursor_position, state.last_click); - - match click.kind() { - click::Kind::Single => { - if state.keyboard_modifiers.control() - || state.keyboard_modifiers.command() - { - change(Change::Default); - state.is_dragging = false; - } else { - change(Change::CursorPosition(cursor_position)); - state.is_dragging = true; - } - } - click::Kind::Double => { - change(Change::Default); - state.is_dragging = false; - } - mouse::click::Kind::Triple => { - state.is_dragging = false; - } + if state.keyboard_modifiers.control() + || state.keyboard_modifiers.command() + { + let _ = default.map(change); + state.is_dragging = false; + } else { + let _ = locate(cursor_position).map(change); + state.is_dragging = true; } - state.last_click = Some(click); - return event::Status::Captured; } } @@ -424,9 +394,7 @@ where Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { if is_dragging { - let _ = cursor - .position() - .map(|point| change(Change::CursorPosition(point))); + let _ = cursor.position().and_then(locate).map(change); return event::Status::Captured; } @@ -435,10 +403,10 @@ where if cursor.position_over(layout.bounds()).is_some() { match key { Key::Named(key::Named::ArrowUp) => { - change(Change::Increment); + let _ = increment(current_value).map(change); } Key::Named(key::Named::ArrowDown) => { - change(Change::Decrement); + let _ = decrement(current_value).map(change); } _ => (), } @@ -574,10 +542,9 @@ pub fn mouse_interaction( } /// The local state of a [`VerticalSlider`]. -#[derive(Debug, Clone, Copy, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub struct State { is_dragging: bool, - last_click: Option, keyboard_modifiers: keyboard::Modifiers, } @@ -587,11 +554,3 @@ impl State { State::default() } } - -impl PartialEq for State { - fn eq(&self, other: &Self) -> bool { - self.is_dragging == other.is_dragging - } -} - -impl Eq for State {} -- cgit From 66f8cf8215c1bcdf8bf7e5b698b901b49fd87c78 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 31 Jan 2024 21:48:34 +0100 Subject: Simplify `slider` logic further --- widget/src/slider.rs | 41 +++++++++++++++++++++-------------------- widget/src/vertical_slider.rs | 41 +++++++++++++++++++++-------------------- 2 files changed, 42 insertions(+), 40 deletions(-) (limited to 'widget/src') diff --git a/widget/src/slider.rs b/widget/src/slider.rs index 3d1d08ba..ef451d43 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -296,12 +296,13 @@ where } else if cursor_position.x >= bounds.x + bounds.width { Some(*range.end()) } else { - let step = match step_fine { - Some(step_fine) if state.keyboard_modifiers.shift() => { - step_fine.into() - } - _ => step.into(), - }; + let step = if state.keyboard_modifiers.shift() { + step_fine.unwrap_or(step) + } else { + step + } + .into(); + let start = (*range.start()).into(); let end = (*range.end()).into(); @@ -318,15 +319,15 @@ where }; let increment = |value: T| -> Option { - let step = match step_fine { - Some(step_fine) if state.keyboard_modifiers.shift() => { - step_fine.into() - } - _ => step.into(), - }; + let step = if state.keyboard_modifiers.shift() { + step_fine.unwrap_or(step) + } else { + step + } + .into(); let steps = (value.into() / step).round(); - let new_value = step * (steps + f64::from(1)); + let new_value = step * (steps + 1.0); if new_value > (*range.end()).into() { return Some(*range.end()); @@ -336,15 +337,15 @@ where }; let decrement = |value: T| -> Option { - let step = match step_fine { - Some(step_fine) if state.keyboard_modifiers.shift() => { - step_fine.into() - } - _ => step.into(), - }; + let step = if state.keyboard_modifiers.shift() { + step_fine.unwrap_or(step) + } else { + step + } + .into(); let steps = (value.into() / step).round(); - let new_value = step * (steps - f64::from(1)); + let new_value = step * (steps - 1.0); if new_value < (*range.start()).into() { return Some(*range.start()); diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index 168d7848..9c49d8f5 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -295,12 +295,13 @@ where } else if cursor_position.y <= bounds.y { Some(*range.end()) } else { - let step = match step_fine { - Some(step_fine) if state.keyboard_modifiers.shift() => { - step_fine.into() - } - _ => step.into(), - }; + let step = if state.keyboard_modifiers.shift() { + step_fine.unwrap_or(step) + } else { + step + } + .into(); + let start = (*range.start()).into(); let end = (*range.end()).into(); @@ -318,15 +319,15 @@ where }; let increment = |value: T| -> Option { - let step = match step_fine { - Some(step_fine) if state.keyboard_modifiers.shift() => { - step_fine.into() - } - _ => step.into(), - }; + let step = if state.keyboard_modifiers.shift() { + step_fine.unwrap_or(step) + } else { + step + } + .into(); let steps = (value.into() / step).round(); - let new_value = step * (steps + f64::from(1)); + let new_value = step * (steps + 1.0); if new_value > (*range.end()).into() { return Some(*range.end()); @@ -336,15 +337,15 @@ where }; let decrement = |value: T| -> Option { - let step = match step_fine { - Some(step_fine) if state.keyboard_modifiers.shift() => { - step_fine.into() - } - _ => step.into(), - }; + let step = if state.keyboard_modifiers.shift() { + step_fine.unwrap_or(step) + } else { + step + } + .into(); let steps = (value.into() / step).round(); - let new_value = step * (steps - f64::from(1)); + let new_value = step * (steps - 1.0); if new_value < (*range.start()).into() { return Some(*range.start()); -- cgit From cd03a0dd24e300a8a39006e99ee647045e370591 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 31 Jan 2024 21:53:29 +0100 Subject: Rename `step_fine` in `slider` to `shift_step` --- widget/src/slider.rs | 25 +++++++++++++------------ widget/src/vertical_slider.rs | 23 ++++++++++++----------- 2 files changed, 25 insertions(+), 23 deletions(-) (limited to 'widget/src') diff --git a/widget/src/slider.rs b/widget/src/slider.rs index ef451d43..a372f8e7 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -51,7 +51,7 @@ where { range: RangeInclusive, step: T, - step_fine: Option, + shift_step: Option, value: T, default: Option, on_change: Box Message + 'a>, @@ -63,7 +63,7 @@ where impl<'a, T, Message, Theme> Slider<'a, T, Message, Theme> where - T: Copy + From + std::cmp::PartialOrd, + T: Copy + From + PartialOrd, Message: Clone, Theme: StyleSheet, { @@ -99,7 +99,7 @@ where default: None, range, step: T::from(1), - step_fine: None, + shift_step: None, on_change: Box::new(on_change), on_release: None, width: Length::Fill, @@ -150,10 +150,11 @@ where self } - /// Sets the optional fine-grained step size for the [`Slider`]. - /// If set, this value is used as the step size while shift is pressed. - pub fn step_fine(mut self, step_fine: impl Into) -> Self { - self.step_fine = Some(step_fine.into()); + /// Sets the optional "shift" step for the [`Slider`]. + /// + /// If set, this value is used as the step while the shift key is pressed. + pub fn shift_step(mut self, shift_step: impl Into) -> Self { + self.shift_step = Some(shift_step.into()); self } } @@ -211,7 +212,7 @@ where self.default, &self.range, self.step, - self.step_fine, + self.shift_step, self.on_change.as_ref(), &self.on_release, ) @@ -278,7 +279,7 @@ pub fn update( default: Option, range: &RangeInclusive, step: T, - step_fine: Option, + shift_step: Option, on_change: &dyn Fn(T) -> Message, on_release: &Option, ) -> event::Status @@ -297,7 +298,7 @@ where Some(*range.end()) } else { let step = if state.keyboard_modifiers.shift() { - step_fine.unwrap_or(step) + shift_step.unwrap_or(step) } else { step } @@ -320,7 +321,7 @@ where let increment = |value: T| -> Option { let step = if state.keyboard_modifiers.shift() { - step_fine.unwrap_or(step) + shift_step.unwrap_or(step) } else { step } @@ -338,7 +339,7 @@ where let decrement = |value: T| -> Option { let step = if state.keyboard_modifiers.shift() { - step_fine.unwrap_or(step) + shift_step.unwrap_or(step) } else { step } diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index 9c49d8f5..06c27752 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -48,7 +48,7 @@ where { range: RangeInclusive, step: T, - step_fine: Option, + shift_step: Option, value: T, default: Option, on_change: Box Message + 'a>, @@ -96,7 +96,7 @@ where default: None, range, step: T::from(1), - step_fine: None, + shift_step: None, on_change: Box::new(on_change), on_release: None, width: Self::DEFAULT_WIDTH, @@ -147,10 +147,11 @@ where self } - /// Sets the optional fine-grained step size for the [`VerticalSlider`]. - /// If set, this value is used as the step size while shift is pressed. - pub fn step_fine(mut self, step_fine: impl Into) -> Self { - self.step_fine = Some(step_fine.into()); + /// Sets the optional "shift" step for the [`VerticalSlider`]. + /// + /// If set, this value is used as the step while the shift key is pressed. + pub fn shift_step(mut self, shift_step: impl Into) -> Self { + self.shift_step = Some(shift_step.into()); self } } @@ -208,7 +209,7 @@ where self.default, &self.range, self.step, - self.step_fine, + self.shift_step, self.on_change.as_ref(), &self.on_release, ) @@ -276,7 +277,7 @@ pub fn update( default: Option, range: &RangeInclusive, step: T, - step_fine: Option, + shift_step: Option, on_change: &dyn Fn(T) -> Message, on_release: &Option, ) -> event::Status @@ -296,7 +297,7 @@ where Some(*range.end()) } else { let step = if state.keyboard_modifiers.shift() { - step_fine.unwrap_or(step) + shift_step.unwrap_or(step) } else { step } @@ -320,7 +321,7 @@ where let increment = |value: T| -> Option { let step = if state.keyboard_modifiers.shift() { - step_fine.unwrap_or(step) + shift_step.unwrap_or(step) } else { step } @@ -338,7 +339,7 @@ where let decrement = |value: T| -> Option { let step = if state.keyboard_modifiers.shift() { - step_fine.unwrap_or(step) + shift_step.unwrap_or(step) } else { step } -- cgit From 55791e45ebac908c59609641649e0f596b698303 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 31 Jan 2024 21:58:21 +0100 Subject: Fix documentation of `default` method for `slider` --- widget/src/slider.rs | 3 ++- widget/src/vertical_slider.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'widget/src') diff --git a/widget/src/slider.rs b/widget/src/slider.rs index a372f8e7..65bc1772 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -109,7 +109,8 @@ where } /// Sets the optional default value for the [`Slider`]. - /// If set, [`Slider`] will reset to this value when doubled-clicked, ctrl-clicked, or command-clicked. + /// + /// If set, the [`Slider`] will reset to this value when ctrl-clicked or command-clicked. pub fn default(mut self, default: impl Into) -> Self { self.default = Some(default.into()); self diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index 06c27752..8f7c88da 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -106,7 +106,8 @@ where } /// Sets the optional default value for the [`VerticalSlider`]. - /// If set, [`VerticalSlider`] will reset to this value when doubled-clicked, ctrl-clicked, or command-clicked. + /// + /// If set, the [`VerticalSlider`] will reset to this value when ctrl-clicked or command-clicked. pub fn default(mut self, default: impl Into) -> Self { self.default = Some(default.into()); self -- cgit