graphic design tool
git clone https://git.lucas.co/cce-designer.git
fix: graph edge-panning waits for a real drag gesture
A press on a node arms the graph drag immediately, so tick_frame's
drag edge-panning (5px/frame inside the 30px pane-edge margin) engaged
on a bare CLICK of an edge-adjacent node: a few frames of pan slid the
grid origin under the armed drag, and commit_drag re-derived the node's
cell against the moved origin — the node teleported instead of just
selecting. The pan now waits until the pointer strays >= 8px from the
press point (drag_press_cursor latch); dragging past the edge still
auto-pans as before.
Co-Authored-By: Claude Fable 5 <[email protected]>
src/app.rs | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/src/app.rs b/src/app.rs
index f20741a..ce64fa7 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -853,6 +853,12 @@ pub struct State {
pub cloud_popups: cce_ui::process::CloudPopupTracker,
pub drag_widget: Option<usize>,
+ /// Where the pointer pressed when `drag_widget` armed — the drag
+ /// edge-panning gate: a bare click (press ~ release with jitter) must not
+ /// slide the graph under the armed node drag, or the commit re-derives the
+ /// node's cell against the panned origin and it teleports. Cleared (latch
+ /// open) once the pointer strays a real-drag distance from the press.
+ drag_press_cursor: Option<(f32, f32)>,
pub focused_widget: Option<usize>,
pub cursor_x: f32,
@@ -2502,6 +2508,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
splitter_layout,
cloud_popups: cce_ui::process::CloudPopupTracker::new(),
drag_widget: None,
+ drag_press_cursor: None,
focused_widget: None,
cursor_x: 0.0,
cursor_y: 0.0,
@@ -4175,6 +4182,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
unsafe { (*ptr).handle_event(&ev, &mut self.ui_context); }
}
self.drag_widget = Some(i);
+ self.drag_press_cursor = Some((self.cursor_x, self.cursor_y));
}
if i != PARAM_IDX {
self.slots.get_dyn_mut(i).focus();
@@ -4277,6 +4285,7 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
}
}
self.drag_widget = None;
+ self.drag_press_cursor = None;
changed = true;
}
let mut sync_params = false;
@@ -4800,9 +4809,18 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
if tick_changed {
}
+ // Edge-panning waits for a real drag gesture: the pointer must stray
+ // from the press point first (see `drag_press_cursor`).
+ if let Some((sx, sy)) = self.drag_press_cursor {
+ let dx = self.cursor_x - sx;
+ let dy = self.cursor_y - sy;
+ if dx * dx + dy * dy >= 64.0 {
+ self.drag_press_cursor = None;
+ }
+ }
let mut panned = false;
if let Some(idx) = self.drag_widget {
- if idx == CONTENT_IDX {
+ if idx == CONTENT_IDX && self.drag_press_cursor.is_none() {
let (px, py, pw, ph) = self.positions[CONTENT_IDX];
let margin = 30.0_f32;
let pan_speed = 5.0_f32;