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.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());
|
let mut output: Output = std::mem::take(&mut self.output());
|
||||||
if self.repaint_requests.load(SeqCst) > 0 {
|
if self.repaint_requests.load(SeqCst) > 0 {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
area, collapsing_header, menu, resize, scroll_area, util::Cache, widgets::text_edit, window,
|
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};
|
use epaint::color::{Color32, Hsva};
|
||||||
|
|
||||||
|
@ -35,11 +35,14 @@ pub struct Memory {
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) window_interaction: Option<window::WindowInteraction>,
|
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`].
|
/// Couples with [`Interaction::kb_focus_id`].
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) temp_edit_string: Option<String>,
|
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,
|
pub(crate) areas: Areas,
|
||||||
|
|
||||||
/// Used by color picker
|
/// 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();
|
self.areas.end_frame();
|
||||||
|
|
||||||
if let Some(kb_focus_id) = self.interaction.kb_focus_id {
|
if let Some(kb_focus_id) = self.interaction.kb_focus_id {
|
||||||
|
@ -195,6 +202,10 @@ impl Memory {
|
||||||
self.interaction.kb_focus_id = None;
|
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> {
|
pub fn layer_id_at(&self, pos: Pos2, resize_interact_radius_side: f32) -> Option<LayerId> {
|
||||||
|
|
|
@ -160,6 +160,11 @@ impl Response {
|
||||||
self.dragged
|
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.
|
/// The widget was being dragged, but now it has been released.
|
||||||
pub fn drag_released(&self) -> bool {
|
pub fn drag_released(&self) -> bool {
|
||||||
self.drag_released
|
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
|
value as f32, // Show full precision value on-hover. TODO: figure out f64 vs f32
|
||||||
suffix
|
suffix
|
||||||
));
|
));
|
||||||
|
|
||||||
if response.clicked() {
|
if response.clicked() {
|
||||||
ui.memory().request_kb_focus(kb_edit_id);
|
ui.memory().request_kb_focus(kb_edit_id);
|
||||||
ui.memory().temp_edit_string = None; // Filled in next frame
|
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_points = mdelta.x - mdelta.y; // Increase to the right and up
|
||||||
let delta_value = speed * delta_points;
|
let delta_value = speed * delta_points;
|
||||||
if delta_value != 0.0 {
|
if delta_value != 0.0 {
|
||||||
let new_value = value + delta_value as f64;
|
// Since we round the value being dragged, we need to store the full precision value in memory:
|
||||||
let new_value = emath::round_to_decimals(new_value, auto_decimals);
|
let stored_value = ui
|
||||||
let new_value = clamp(new_value, clamp_range);
|
.memory()
|
||||||
set(&mut value_function, new_value);
|
.drag_value
|
||||||
// TODO: To make use or `smart_aim` for `DragValue` we need to store some state somewhere,
|
.filter(|(id, _)| *id == response.id)
|
||||||
// otherwise we will just keep rounding to the same value while moving the mouse.
|
.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
|
response
|
||||||
|
|
Loading…
Reference in a new issue