Slider: Add step parameter (#1225)
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
parent
c4528beb72
commit
62504fface
3 changed files with 62 additions and 11 deletions
|
@ -24,6 +24,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w
|
||||||
* Added linked axis support for plots via `plot::LinkedAxisGroup` ([#1184](https://github.com/emilk/egui/pull/1184)).
|
* Added linked axis support for plots via `plot::LinkedAxisGroup` ([#1184](https://github.com/emilk/egui/pull/1184)).
|
||||||
* Added `Response::on_hover_text_at_pointer` as a convenience akin to `Response::on_hover_text` ([1179](https://github.com/emilk/egui/pull/1179)).
|
* Added `Response::on_hover_text_at_pointer` as a convenience akin to `Response::on_hover_text` ([1179](https://github.com/emilk/egui/pull/1179)).
|
||||||
* Added `ui.weak(text)`.
|
* Added `ui.weak(text)`.
|
||||||
|
* Added `Slider::step_by` ([1255](https://github.com/emilk/egui/pull/1225)).
|
||||||
|
|
||||||
### Changed 🔧
|
### Changed 🔧
|
||||||
* ⚠️ `Context::input` and `Ui::input` now locks a mutex. This can lead to a dead-lock is used in an `if let` binding!
|
* ⚠️ `Context::input` and `Ui::input` now locks a mutex. This can lead to a dead-lock is used in an `if let` binding!
|
||||||
|
|
|
@ -71,6 +71,8 @@ pub struct Slider<'a> {
|
||||||
suffix: String,
|
suffix: String,
|
||||||
text: String,
|
text: String,
|
||||||
text_color: Option<Color32>,
|
text_color: Option<Color32>,
|
||||||
|
/// Sets the minimal step of the widget value
|
||||||
|
step: Option<f64>,
|
||||||
min_decimals: usize,
|
min_decimals: usize,
|
||||||
max_decimals: Option<usize>,
|
max_decimals: Option<usize>,
|
||||||
}
|
}
|
||||||
|
@ -113,6 +115,7 @@ impl<'a> Slider<'a> {
|
||||||
suffix: Default::default(),
|
suffix: Default::default(),
|
||||||
text: Default::default(),
|
text: Default::default(),
|
||||||
text_color: None,
|
text_color: None,
|
||||||
|
step: None,
|
||||||
min_decimals: 0,
|
min_decimals: 0,
|
||||||
max_decimals: None,
|
max_decimals: None,
|
||||||
}
|
}
|
||||||
|
@ -199,6 +202,16 @@ impl<'a> Slider<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the minimal change of the value.
|
||||||
|
/// Value `0.0` effectively disables the feature. If the new value is out of range
|
||||||
|
/// and `clamp_to_range` is enabled, you would not have the ability to change the value.
|
||||||
|
///
|
||||||
|
/// Default: `0.0` (disabled).
|
||||||
|
pub fn step_by(mut self, step: f64) -> Self {
|
||||||
|
self.step = if step != 0.0 { Some(step) } else { None };
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: we should also have a "min precision".
|
// TODO: we should also have a "min precision".
|
||||||
/// Set a minimum number of decimals to display.
|
/// Set a minimum number of decimals to display.
|
||||||
/// Normally you don't need to pick a precision, as the slider will intelligently pick a precision for you.
|
/// Normally you don't need to pick a precision, as the slider will intelligently pick a precision for you.
|
||||||
|
@ -255,6 +268,9 @@ impl<'a> Slider<'a> {
|
||||||
if let Some(max_decimals) = self.max_decimals {
|
if let Some(max_decimals) = self.max_decimals {
|
||||||
value = emath::round_to_decimals(value, max_decimals);
|
value = emath::round_to_decimals(value, max_decimals);
|
||||||
}
|
}
|
||||||
|
if let Some(step) = self.step {
|
||||||
|
value = (value / step).round() * step;
|
||||||
|
}
|
||||||
set(&mut self.get_set_value, value);
|
set(&mut self.get_set_value, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,14 +346,22 @@ impl<'a> Slider<'a> {
|
||||||
let prev_value = self.get_value();
|
let prev_value = self.get_value();
|
||||||
let prev_position = self.position_from_value(prev_value, position_range.clone());
|
let prev_position = self.position_from_value(prev_value, position_range.clone());
|
||||||
let new_position = prev_position + kb_step;
|
let new_position = prev_position + kb_step;
|
||||||
let new_value = if self.smart_aim {
|
let new_value = match self.step {
|
||||||
let aim_radius = ui.input().aim_radius();
|
Some(step) => prev_value + (kb_step as f64 * step),
|
||||||
emath::smart_aim::best_in_range_f64(
|
None if self.smart_aim => {
|
||||||
self.value_from_position(new_position - aim_radius, position_range.clone()),
|
let aim_radius = ui.input().aim_radius();
|
||||||
self.value_from_position(new_position + aim_radius, position_range.clone()),
|
emath::smart_aim::best_in_range_f64(
|
||||||
)
|
self.value_from_position(
|
||||||
} else {
|
new_position - aim_radius,
|
||||||
self.value_from_position(new_position, position_range.clone())
|
position_range.clone(),
|
||||||
|
),
|
||||||
|
self.value_from_position(
|
||||||
|
new_position + aim_radius,
|
||||||
|
position_range.clone(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => self.value_from_position(new_position, position_range.clone()),
|
||||||
};
|
};
|
||||||
self.set_value(new_value);
|
self.set_value(new_value);
|
||||||
}
|
}
|
||||||
|
@ -438,10 +462,19 @@ impl<'a> Slider<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn value_ui(&mut self, ui: &mut Ui, position_range: RangeInclusive<f32>) {
|
fn value_ui(&mut self, ui: &mut Ui, position_range: RangeInclusive<f32>) {
|
||||||
|
// If `DragValue` is controlled from the keyboard and `step` is defined, set speed to `step`
|
||||||
|
let change = ui.input().num_presses(Key::ArrowUp) as i32
|
||||||
|
+ ui.input().num_presses(Key::ArrowRight) as i32
|
||||||
|
- ui.input().num_presses(Key::ArrowDown) as i32
|
||||||
|
- ui.input().num_presses(Key::ArrowLeft) as i32;
|
||||||
|
let speed = match self.step {
|
||||||
|
Some(step) if change != 0 => step,
|
||||||
|
_ => self.current_gradient(&position_range),
|
||||||
|
};
|
||||||
let mut value = self.get_value();
|
let mut value = self.get_value();
|
||||||
ui.add(
|
ui.add(
|
||||||
DragValue::new(&mut value)
|
DragValue::new(&mut value)
|
||||||
.speed(self.current_gradient(&position_range))
|
.speed(speed)
|
||||||
.clamp_range(self.clamp_range())
|
.clamp_range(self.clamp_range())
|
||||||
.min_decimals(self.min_decimals)
|
.min_decimals(self.min_decimals)
|
||||||
.max_decimals_opt(self.max_decimals)
|
.max_decimals_opt(self.max_decimals)
|
||||||
|
|
|
@ -11,6 +11,8 @@ pub struct Sliders {
|
||||||
pub logarithmic: bool,
|
pub logarithmic: bool,
|
||||||
pub clamp_to_range: bool,
|
pub clamp_to_range: bool,
|
||||||
pub smart_aim: bool,
|
pub smart_aim: bool,
|
||||||
|
pub step: f64,
|
||||||
|
pub use_steps: bool,
|
||||||
pub integer: bool,
|
pub integer: bool,
|
||||||
pub vertical: bool,
|
pub vertical: bool,
|
||||||
pub value: f64,
|
pub value: f64,
|
||||||
|
@ -24,6 +26,8 @@ impl Default for Sliders {
|
||||||
logarithmic: true,
|
logarithmic: true,
|
||||||
clamp_to_range: false,
|
clamp_to_range: false,
|
||||||
smart_aim: true,
|
smart_aim: true,
|
||||||
|
step: 10.0,
|
||||||
|
use_steps: false,
|
||||||
integer: false,
|
integer: false,
|
||||||
vertical: false,
|
vertical: false,
|
||||||
value: 10.0,
|
value: 10.0,
|
||||||
|
@ -55,6 +59,8 @@ impl super::View for Sliders {
|
||||||
logarithmic,
|
logarithmic,
|
||||||
clamp_to_range,
|
clamp_to_range,
|
||||||
smart_aim,
|
smart_aim,
|
||||||
|
step,
|
||||||
|
use_steps,
|
||||||
integer,
|
integer,
|
||||||
vertical,
|
vertical,
|
||||||
value,
|
value,
|
||||||
|
@ -79,6 +85,7 @@ impl super::View for Sliders {
|
||||||
SliderOrientation::Horizontal
|
SliderOrientation::Horizontal
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let istep = if *use_steps { *step } else { 0.0 };
|
||||||
if *integer {
|
if *integer {
|
||||||
let mut value_i32 = *value as i32;
|
let mut value_i32 = *value as i32;
|
||||||
ui.add(
|
ui.add(
|
||||||
|
@ -87,7 +94,8 @@ impl super::View for Sliders {
|
||||||
.clamp_to_range(*clamp_to_range)
|
.clamp_to_range(*clamp_to_range)
|
||||||
.smart_aim(*smart_aim)
|
.smart_aim(*smart_aim)
|
||||||
.orientation(orientation)
|
.orientation(orientation)
|
||||||
.text("i32 demo slider"),
|
.text("i32 demo slider")
|
||||||
|
.step_by(istep),
|
||||||
);
|
);
|
||||||
*value = value_i32 as f64;
|
*value = value_i32 as f64;
|
||||||
} else {
|
} else {
|
||||||
|
@ -97,7 +105,8 @@ impl super::View for Sliders {
|
||||||
.clamp_to_range(*clamp_to_range)
|
.clamp_to_range(*clamp_to_range)
|
||||||
.smart_aim(*smart_aim)
|
.smart_aim(*smart_aim)
|
||||||
.orientation(orientation)
|
.orientation(orientation)
|
||||||
.text("f64 demo slider"),
|
.text("f64 demo slider")
|
||||||
|
.step_by(istep),
|
||||||
);
|
);
|
||||||
|
|
||||||
ui.label(
|
ui.label(
|
||||||
|
@ -128,6 +137,14 @@ impl super::View for Sliders {
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
|
ui.checkbox(use_steps, "Use steps");
|
||||||
|
ui.label("When enabled, the minimal value change would be restricted to a given step.");
|
||||||
|
if *use_steps {
|
||||||
|
ui.add(egui::DragValue::new(step).speed(1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label("Slider type:");
|
ui.label("Slider type:");
|
||||||
ui.radio_value(integer, true, "i32");
|
ui.radio_value(integer, true, "i32");
|
||||||
|
|
Loading…
Reference in a new issue