refactor: move DragValue state

This commit is contained in:
Emil Ernerfeldt 2021-02-21 10:28:11 +01:00
parent 24a1c3136c
commit 67623919d7
3 changed files with 43 additions and 19 deletions

View file

@ -35,13 +35,8 @@ 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 `DragValue` value.
/// 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) drag_value: crate::widgets::drag_value::MonoState,
/// Value of the `DragValue` being dragged (if any).
pub(crate) drag_value: Option<(Id, f64)>,
pub(crate) areas: Areas, pub(crate) areas: Areas,
@ -203,9 +198,7 @@ impl Memory {
} }
} }
if input.pointer.any_pressed() || input.pointer.any_released() { self.drag_value.end_frame(input);
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> {

View file

@ -4,6 +4,29 @@ use std::ops::RangeInclusive;
use crate::*; use crate::*;
// ----------------------------------------------------------------------------
/// Same state for all [`DragValue`]s.
#[derive(Clone, Debug, Default)]
pub(crate) struct MonoState {
last_dragged_id: Option<Id>,
last_dragged_value: Option<f64>,
/// For temporary edit of a `DragValue` value.
/// Couples with [`Interaction::kb_focus_id`].
edit_string: Option<String>,
}
impl MonoState {
pub(crate) fn end_frame(&mut self, input: &InputState) {
if input.pointer.any_pressed() || input.pointer.any_released() {
self.last_dragged_id = None;
self.last_dragged_value = None;
}
}
}
// ----------------------------------------------------------------------------
/// Combined into one function (rather than two) to make it easier /// Combined into one function (rather than two) to make it easier
/// for the borrow checker. /// for the borrow checker.
type GetSetValue<'a> = Box<dyn 'a + FnMut(Option<f64>) -> f64>; type GetSetValue<'a> = Box<dyn 'a + FnMut(Option<f64>) -> f64>;
@ -177,7 +200,12 @@ impl<'a> Widget for DragValue<'a> {
if is_kb_editing { if is_kb_editing {
let button_width = ui.spacing().interact_size.x; let button_width = ui.spacing().interact_size.x;
let mut value_text = ui.memory().temp_edit_string.take().unwrap_or(value_text); let mut value_text = ui
.memory()
.drag_value
.edit_string
.take()
.unwrap_or(value_text);
let response = ui.add( let response = ui.add(
TextEdit::singleline(&mut value_text) TextEdit::singleline(&mut value_text)
.id(kb_edit_id) .id(kb_edit_id)
@ -190,8 +218,9 @@ impl<'a> Widget for DragValue<'a> {
} }
if ui.input().key_pressed(Key::Enter) { if ui.input().key_pressed(Key::Enter) {
ui.memory().surrender_kb_focus(kb_edit_id); ui.memory().surrender_kb_focus(kb_edit_id);
ui.memory().drag_value.edit_string = None;
} else { } else {
ui.memory().temp_edit_string = Some(value_text); ui.memory().drag_value.edit_string = Some(value_text);
} }
response response
} else { } else {
@ -208,18 +237,18 @@ impl<'a> Widget for DragValue<'a> {
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().drag_value.edit_string = None; // Filled in next frame
} else if response.dragged() { } else if response.dragged() {
let mdelta = ui.input().pointer.delta(); let mdelta = ui.input().pointer.delta();
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 = delta_points as f64 * speed; let delta_value = delta_points as f64 * speed;
if delta_value != 0.0 { if delta_value != 0.0 {
let mut drag_state = std::mem::take(&mut ui.memory().drag_value);
// Since we round the value being dragged, we need to store the full precision value in memory: // Since we round the value being dragged, we need to store the full precision value in memory:
let stored_value = ui let stored_value = (drag_state.last_dragged_id == Some(response.id))
.memory() .then(|| drag_state.last_dragged_value)
.drag_value .flatten();
.filter(|(id, _)| *id == response.id)
.map(|(_, value)| value);
let stored_value = stored_value.unwrap_or(value); let stored_value = stored_value.unwrap_or(value);
let stored_value = stored_value + delta_value as f64; let stored_value = stored_value + delta_value as f64;
let stored_value = clamp(stored_value, clamp_range.clone()); let stored_value = clamp(stored_value, clamp_range.clone());
@ -236,7 +265,9 @@ impl<'a> Widget for DragValue<'a> {
let rounded_new_value = clamp(rounded_new_value, clamp_range); let rounded_new_value = clamp(rounded_new_value, clamp_range);
set(&mut get_set_value, rounded_new_value); set(&mut get_set_value, rounded_new_value);
ui.memory().drag_value = Some((response.id, stored_value)); drag_state.last_dragged_id = Some(response.id);
drag_state.last_dragged_value = Some(stored_value);
ui.memory().drag_value = drag_state;
} }
} }
response response

View file

@ -10,7 +10,7 @@ use crate::*;
mod button; mod button;
pub mod color_picker; pub mod color_picker;
mod drag_value; pub(crate) mod drag_value;
mod hyperlink; mod hyperlink;
mod image; mod image;
mod label; mod label;