DragValue: handle slowly dragging a value with limited precision
This commit is contained in:
parent
9a546ff97a
commit
7ac26b84b1
4 changed files with 37 additions and 10 deletions
|
@ -533,7 +533,8 @@ impl Context {
|
|||
self.request_repaint();
|
||||
}
|
||||
|
||||
self.memory().end_frame(&self.frame_state().used_ids);
|
||||
self.memory()
|
||||
.end_frame(&self.input, &self.frame_state().used_ids);
|
||||
|
||||
let mut output: Output = std::mem::take(&mut self.output());
|
||||
if self.repaint_requests.load(SeqCst) > 0 {
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
|
|||
|
||||
use crate::{
|
||||
area, collapsing_header, menu, resize, scroll_area, util::Cache, widgets::text_edit, window,
|
||||
Id, LayerId, Pos2, Rect, Style, Vec2,
|
||||
Id, InputState, LayerId, Pos2, Rect, Style, Vec2,
|
||||
};
|
||||
use epaint::color::{Color32, Hsva};
|
||||
|
||||
|
@ -35,11 +35,14 @@ pub struct Memory {
|
|||
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||
pub(crate) window_interaction: Option<window::WindowInteraction>,
|
||||
|
||||
/// For temporary edit of e.g. a slider value.
|
||||
/// For temporary edit of e.g. a `DragValue` value.
|
||||
/// Couples with [`Interaction::kb_focus_id`].
|
||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||
pub(crate) temp_edit_string: Option<String>,
|
||||
|
||||
/// Value of the `DragValue` being dragged (if any).
|
||||
pub(crate) drag_value: Option<(Id, f64)>,
|
||||
|
||||
pub(crate) areas: Areas,
|
||||
|
||||
/// Used by color picker
|
||||
|
@ -182,7 +185,11 @@ impl Memory {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn end_frame(&mut self, used_ids: &epaint::ahash::AHashMap<Id, Pos2>) {
|
||||
pub(crate) fn end_frame(
|
||||
&mut self,
|
||||
input: &InputState,
|
||||
used_ids: &epaint::ahash::AHashMap<Id, Pos2>,
|
||||
) {
|
||||
self.areas.end_frame();
|
||||
|
||||
if let Some(kb_focus_id) = self.interaction.kb_focus_id {
|
||||
|
@ -195,6 +202,10 @@ impl Memory {
|
|||
self.interaction.kb_focus_id = None;
|
||||
}
|
||||
}
|
||||
|
||||
if input.pointer.any_pressed() || input.pointer.any_released() {
|
||||
self.drag_value = Default::default();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn layer_id_at(&self, pos: Pos2, resize_interact_radius_side: f32) -> Option<LayerId> {
|
||||
|
|
|
@ -160,6 +160,11 @@ impl Response {
|
|||
self.dragged
|
||||
}
|
||||
|
||||
/// Did a drag on this widgets begin this frame?
|
||||
pub fn drag_started(&self) -> bool {
|
||||
self.dragged && self.ctx.input().pointer.any_pressed()
|
||||
}
|
||||
|
||||
/// The widget was being dragged, but now it has been released.
|
||||
pub fn drag_released(&self) -> bool {
|
||||
self.drag_released
|
||||
|
|
|
@ -191,6 +191,7 @@ impl<'a> Widget for DragValue<'a> {
|
|||
value as f32, // Show full precision value on-hover. TODO: figure out f64 vs f32
|
||||
suffix
|
||||
));
|
||||
|
||||
if response.clicked() {
|
||||
ui.memory().request_kb_focus(kb_edit_id);
|
||||
ui.memory().temp_edit_string = None; // Filled in next frame
|
||||
|
@ -199,12 +200,21 @@ impl<'a> Widget for DragValue<'a> {
|
|||
let delta_points = mdelta.x - mdelta.y; // Increase to the right and up
|
||||
let delta_value = speed * delta_points;
|
||||
if delta_value != 0.0 {
|
||||
let new_value = value + delta_value as f64;
|
||||
let new_value = emath::round_to_decimals(new_value, auto_decimals);
|
||||
let new_value = clamp(new_value, clamp_range);
|
||||
set(&mut value_function, new_value);
|
||||
// TODO: To make use or `smart_aim` for `DragValue` we need to store some state somewhere,
|
||||
// otherwise we will just keep rounding to the same value while moving the mouse.
|
||||
// Since we round the value being dragged, we need to store the full precision value in memory:
|
||||
let stored_value = ui
|
||||
.memory()
|
||||
.drag_value
|
||||
.filter(|(id, _)| *id == response.id)
|
||||
.map(|(_, value)| value);
|
||||
let stored_value = stored_value.unwrap_or(value);
|
||||
let stored_value = stored_value + delta_value as f64;
|
||||
let stored_value = clamp(stored_value, clamp_range.clone());
|
||||
|
||||
let rounded_new_value = emath::round_to_decimals(stored_value, auto_decimals);
|
||||
let rounded_new_value = clamp(rounded_new_value, clamp_range);
|
||||
set(&mut value_function, rounded_new_value);
|
||||
|
||||
ui.memory().drag_value = Some((response.id, stored_value));
|
||||
}
|
||||
}
|
||||
response
|
||||
|
|
Loading…
Reference in a new issue