From acdc2b004fc3f65b3dfdbb0e28caf196a9f16b47 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 10 Jun 2020 16:23:49 +0200 Subject: [PATCH] [widgets] new widget: DragValue --- egui/src/examples/app.rs | 16 +++++++++++---- egui/src/widgets.rs | 44 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/egui/src/examples/app.rs b/egui/src/examples/app.rs index 68a84fc9..25faf89c 100644 --- a/egui/src/examples/app.rs +++ b/egui/src/examples/app.rs @@ -277,7 +277,7 @@ struct Widgets { checked: bool, count: usize, radio: usize, - slider_value: usize, + slider_value: f32, single_line_text_input: String, multiline_text_input: String, } @@ -288,7 +288,7 @@ impl Default for Widgets { checked: true, radio: 0, count: 0, - slider_value: 100, + slider_value: 3.14, single_line_text_input: "Hello World!".to_owned(), multiline_text_input: "Text can both be so wide that it needs a linebreak, but you can also add manual linebreak by pressing enter, creating new paragraphs.\nThis is the start of the next paragraph.\n\nClick me to edit me!".to_owned(), } @@ -330,10 +330,18 @@ impl Widgets { ui.add(label!("The button has been clicked {} times", self.count)); }); - ui.add(Slider::usize(&mut self.slider_value, 1..=1000).text("value")); + ui.add( + Slider::f32(&mut self.slider_value, -10.0..=10.0) + .text("value") + .precision(2), + ); if ui.add(Button::new("Double it")).clicked { - self.slider_value *= 2; + self.slider_value *= 2.0; } + ui.horizontal(|ui| { + ui.label("drag this number:"); + ui.add(DragValue::f32(&mut self.slider_value).speed(0.01)); + }); ui.horizontal(|ui| { ui.add(label!("Single line text input:")); diff --git a/egui/src/widgets.rs b/egui/src/widgets.rs index 68c38fe3..1a8c9d37 100644 --- a/egui/src/widgets.rs +++ b/egui/src/widgets.rs @@ -231,7 +231,7 @@ impl Button { pub fn sense(mut self, sense: Sense) -> Self { self.sense = sense; self -} + } } impl Widget for Button { @@ -506,3 +506,45 @@ impl Widget for Separator { ui.interact_hover(rect) } } + +// ---------------------------------------------------------------------------- + +pub struct DragValue<'a> { + value: &'a mut f32, + speed: f32, +} + +impl<'a> DragValue<'a> { + pub fn f32(value: &'a mut f32) -> Self { + DragValue { value, speed: 1.0 } + } + + /// How much the value changes when dragged one point (logical pixel). + pub fn speed(mut self, speed: f32) -> Self { + self.speed = speed; + self + } +} + +impl<'a> Widget for DragValue<'a> { + fn ui(self, ui: &mut Ui) -> InteractInfo { + let Self { value, speed } = self; + let speed_in_physical_pixels = speed / ui.input().pixels_per_point; + let precision = (1.0 / speed_in_physical_pixels.abs()) + .log10() + .ceil() + .max(0.0) as usize; + let button = Button::new(format!("{:.*}", precision, *value)).sense(Sense::drag()); + let interact = ui.add(button); + if interact.active { + let mdelta = ui.input().mouse.delta; + let delta_points = mdelta.x - mdelta.y; // Increase to the right and up + let delta_value = speed * delta_points; + if delta_value != 0.0 { + *value += delta_value; + *value = round_to_precision(*value, precision); + } + } + interact.into() + } +}