mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-29 21:06:50 -06:00
fix(ui): right-click on a frame's name label picks that frame
The context menu looked only at what is under the pointer on the page, so a name label drawn over its section selected the section. Copy link to selection then gave every frame in that section the section's link. Labels now win, as they do on a press. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015wxxFg3gana4zaUKnyirTC
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
90054a89c4
commit
df6062d7fb
@@ -248,11 +248,14 @@ pub fn open_context_menu(app: &mut FigApp, pos: Pos2, deep: bool) {
|
||||
let p = app.to_page(pos);
|
||||
if let Ok(ds) = app.session.ds() {
|
||||
let (doc, page, sel, zoom) = (ds.doc.clone(), ds.page, ds.selection.clone(), ds.view.zoom.max(1e-6));
|
||||
if let Some(leaf) = app.session.hit(&doc, page, p, 2.0 / zoom) {
|
||||
let target = figcraft_doc::geometry::select_target(&doc, leaf, &sel, deep);
|
||||
if !sel.contains(&target) {
|
||||
app.session.set_selection(vec![target]);
|
||||
}
|
||||
// A frame's name label is the frame, as on a press, even where it sits over a section.
|
||||
let label = figcraft_engine::tools::label_at(&doc, page, &app.session.tool.labels, p);
|
||||
let hit = app.session.hit(&doc, page, p, 2.0 / zoom);
|
||||
let target = label.or_else(|| hit.map(|leaf| figcraft_doc::geometry::select_target(&doc, leaf, &sel, deep)));
|
||||
if let Some(target) = target
|
||||
&& !sel.contains(&target)
|
||||
{
|
||||
app.session.set_selection(vec![target]);
|
||||
}
|
||||
}
|
||||
app.ui.context_menu = Some((pos, app.session.selection()));
|
||||
|
||||
@@ -84,3 +84,46 @@ fn copying_a_link_with_nothing_selected_copies_nothing() {
|
||||
assert!(copied.lock().unwrap().is_empty(), "no link to node 0");
|
||||
assert!(u.app.ui.toast.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn copying_a_link_on_a_frame_inside_a_selected_section_links_that_frame() {
|
||||
// The section holds both frames; right-clicking each one must link that frame, not the section
|
||||
// that was selected before.
|
||||
let mut s = Session::new();
|
||||
let sec = id(&s.execute("node.create", &json!({"type": "section", "x": 0, "y": 0, "width": 800, "height": 400, "name": "Flow"})).unwrap());
|
||||
let a = id(&s.execute("frame.create", &json!({"x": 20, "y": 60, "width": 300, "height": 200, "name": "main", "parent": sec})).unwrap());
|
||||
let b = id(&s.execute("frame.create", &json!({"x": 400, "y": 60, "width": 300, "height": 200, "name": "dropdown", "parent": sec})).unwrap());
|
||||
s.set_selection(vec![sec]);
|
||||
let copied = Arc::new(Mutex::new(Vec::new()));
|
||||
let mut u = Ui::new(s);
|
||||
u.app.services = Box::new(Copied(copied.clone()));
|
||||
u.frame(vec![]);
|
||||
for (frame, x) in [(a, 170.0), (b, 550.0)] {
|
||||
let at = u.app.to_screen(x, 160.0);
|
||||
crate::canvas::open_context_menu(&mut u.app, at, false);
|
||||
crate::menus::invoke(&mut u.app, "edit.copyLink");
|
||||
let last = copied.lock().unwrap().last().cloned();
|
||||
assert_eq!(last, Some(format!("figcraft://node/{}", frame.0)), "the frame at x={x}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn copying_a_link_from_a_frames_name_label_links_that_frame() {
|
||||
// A frame inside a section has its label above it, inside the section: a right-click there
|
||||
// must pick the frame whose label it is, not the section behind the label.
|
||||
let mut s = Session::new();
|
||||
let sec = id(&s.execute("node.create", &json!({"type": "section", "x": 0, "y": 0, "width": 800, "height": 400, "name": "Flow"})).unwrap());
|
||||
let a = id(&s.execute("frame.create", &json!({"x": 20, "y": 80, "width": 300, "height": 200, "name": "main", "parent": sec})).unwrap());
|
||||
s.set_selection(vec![sec]);
|
||||
let copied = Arc::new(Mutex::new(Vec::new()));
|
||||
let mut u = Ui::new(s);
|
||||
u.app.services = Box::new(Copied(copied.clone()));
|
||||
u.frame(vec![]);
|
||||
let quad = u.app.session.tool.labels.iter().find(|(i, _)| *i == a).map(|(_, q)| *q).expect("the frame has a label");
|
||||
let (cx, cy) = (quad.iter().map(|p| p.x).sum::<f64>() / 4.0, quad.iter().map(|p| p.y).sum::<f64>() / 4.0);
|
||||
let at = u.app.to_screen(cx, cy);
|
||||
crate::canvas::open_context_menu(&mut u.app, at, false);
|
||||
assert_eq!(u.app.session.selection(), vec![a], "the label's frame is selected");
|
||||
crate::menus::invoke(&mut u.app, "edit.copyLink");
|
||||
assert_eq!(copied.lock().unwrap().last().cloned(), Some(format!("figcraft://node/{}", a.0)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user