mirror of
https://github.com/storytold/gridcraft.git
synced 2026-11-07 02:51:33 +00:00
Objects: only the selected object's handles resize; a press elsewhere on an object moves it
A primary drag looked for a handle under the press on whatever object it grabbed, so pressing near the edge or corner of an object that was not selected started a resize, while the pointer over that spot showed the Move cursor (handles are only shown, and only offered by the cursor, on the selected object). The press now takes its handle from `chartview::selected_handle`, the same lookup the cursor uses; a press on any other object selects and moves it. Test: dragging an unselected shape by its bottom-right corner shows the Move cursor, then selects and moves the shape without resizing it.
This commit is contained in:
1 parent
f3fbaa5568
commit
548e5345ee
2 files changed
+23
-3
No files matched your search
@@ -124,16 +124,18 @@ pub(super) fn interact(app: &mut SheetApp, ui: &mut egui::Ui, resp: &egui::Respo
|
||||
// A drag is recognised only after the pointer has moved, so grab the object where the press began.
|
||||
let at = if primary_drag { pointer.press_origin().map(|p| geo.mirror_pos(p)).or(pos) } else { pos };
|
||||
// The selected object's handles reach a little outside it, so they win over hit-testing.
|
||||
let on_handle = at.and_then(|p| crate::chartview::selected_handle(app, geo, sh, p)).map(|(o, r, _)| (o, r));
|
||||
// Only they resize: a press anywhere on another object selects and moves it, as the
|
||||
// hover cursor shows.
|
||||
let on_handle = at.and_then(|p| crate::chartview::selected_handle(app, geo, sh, p));
|
||||
let handle = on_handle.map(|(.., h)| h);
|
||||
if let Some(p) = at
|
||||
&& let Some((obj, rect)) = on_handle.or_else(|| crate::chartview::hit(app, geo, sh, p))
|
||||
&& let Some((obj, _)) = on_handle.map(|(o, r, _)| (o, r)).or_else(|| crate::chartview::hit(app, geo, sh, p))
|
||||
{
|
||||
app.selected_object = Some(obj);
|
||||
if resp.double_clicked() && app.open_object(obj) != crate::objects::OpenAction::Select {
|
||||
return;
|
||||
}
|
||||
if primary_drag && let Some(a) = sh.object_anchor(obj) {
|
||||
let handle = crate::objects::handle_at(rect, p);
|
||||
app.grid.drag = Drag::Object { obj, start: p, orig: (a.cell, a.dx, a.dy, a.width, a.height), handle, stepped: false };
|
||||
// The first recognised drag frame already holds movement away from the press.
|
||||
if let Some(now) = pos {
|
||||
|
||||
@@ -344,3 +344,21 @@ fn each_drag_of_an_object_is_its_own_undo_step() {
|
||||
h.run_steps(2);
|
||||
assert_eq!(rect(&h, o.image), start, "a second undo takes back the move");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dragging_an_unselected_object_by_its_edge_moves_it() {
|
||||
let (mut h, o) = fixture();
|
||||
assert_eq!(h.state().selected_object, None);
|
||||
let before = rect(&h, o.shape);
|
||||
// On the bottom-right corner, where the handle would be if the shape were selected; the
|
||||
// pointer shows Move there, and the press selects and moves the shape.
|
||||
let grab = Handle::BottomRight.pos(before) - vec2(2.0, 2.0);
|
||||
h.input_mut().events.push(Event::PointerMoved(grab));
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.output().platform_output.cursor_icon, egui::CursorIcon::Move);
|
||||
drag(&mut h, grab, grab + vec2(30.0, 20.0));
|
||||
let after = rect(&h, o.shape);
|
||||
assert_eq!(h.state().selected_object, Some(o.shape));
|
||||
assert!((after.size() - before.size()).length() < 0.5, "not resized: {before:?} {after:?}");
|
||||
assert!((after.min - before.min - vec2(30.0, 20.0)).length() < 1.0, "moved with the pointer: {before:?} {after:?}");
|
||||
}
|
||||
Reference in new issue
Block a user