From c2b4514ee6ed434c822ac81ecc52fa53b154dac7 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Fri, 30 Oct 2026 21:25:42 -0700 Subject: [PATCH] Tables: Go to Row shows the caret in the frame that shows the row table.goToRow and table.select naming a table in another story kept the previous caret's frame, so frame commands that follow acted on the other story's frame. The caret's frame is now kept only within the same story, and Go to Row puts it in the frame that shows the row. The Table menu order test lists Go to Row after Distribute Columns Evenly. --- crates/engine/src/cmd/table/selection.rs | 22 ++++++++++++++++++++-- crates/ui-egui/src/menus/tests.rs | 2 ++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/crates/engine/src/cmd/table/selection.rs b/crates/engine/src/cmd/table/selection.rs index 833a84e22..f29b3ca58 100644 --- a/crates/engine/src/cmd/table/selection.rs +++ b/crates/engine/src/cmd/table/selection.rs @@ -24,7 +24,8 @@ pub(super) fn select(s: &mut Session, p: &Value) -> Result { _ => {} } let st = s.doc_mut()?; - let frame = st.selection.text.and_then(|t| t.frame); + // The caret's frame is kept only within the same story. + let frame = st.selection.text.filter(|t| t.story == g.story).and_then(|t| t.frame); st.selection = Selection { cells: Some(TableSel { story: g.story, table: g.table, range: r }), text: Some(TextSel { story: g.story, anchor: 0, focus: 0, frame, cell: Some(CellAddr { table: g.table, row: r.r0, col: r.c0 }) }), @@ -79,6 +80,12 @@ pub(super) fn go_to_row(s: &mut Session, p: &Value) -> Result { .then_some(ft.frame) }); let page = frame.and_then(|f| st.doc.page_of_item(f)).map(|p| p + 1); + // The caret is shown in the frame that shows the row. + if let Some(f) = frame + && let Some(t) = s.doc_mut()?.selection.text.as_mut() + { + t.frame = Some(f); + } Ok(json!({"story": r["story"], "table": r["table"], "range": r["range"], "page": page})) } @@ -251,10 +258,19 @@ mod go_to_row_tests { let mut s = session(); let t = s.execute("table.get", &json!({})).unwrap(); let other = s.execute("frame.create", &json!({"rect": [72, 720, 500, 760], "content": "text", "text": "Notes"})).unwrap(); - s.execute("text.select", &json!({"story": other["story"], "anchor": 0, "focus": 0})).unwrap(); + // A click in the other frame: the caret is shown in that frame. + s.execute("text.placeCaret", &json!({"frame": other["id"], "point": [80, 730]})).unwrap(); + assert_eq!(s.doc().unwrap().selection.text.and_then(|t| t.frame).map(|f| f.0), other["id"].as_u64()); assert!(s.execute("table.goToRow", &json!({"row": 2})).is_err(), "no table named and none selected"); s.execute("table.goToRow", &json!({"story": t["story"], "table": t["table"], "row": 2})).unwrap(); assert_eq!(selected(&s), CellRange { r0: 2, c0: 0, r1: 2, c1: 1 }); + let frame = s.doc().unwrap().selection.text.and_then(|t| t.frame).map(|f| f.0); + assert_ne!(frame, other["id"].as_u64(), "the caret is not left in the other story's frame"); + // table.select naming the table from another story does not keep that story's frame either. + s.execute("text.placeCaret", &json!({"frame": other["id"], "point": [80, 730]})).unwrap(); + s.execute("table.select", &json!({"story": t["story"], "table": t["table"], "what": "table"})).unwrap(); + let frame = s.doc().unwrap().selection.text.and_then(|t| t.frame).map(|f| f.0); + assert_ne!(frame, other["id"].as_u64()); } #[test] @@ -271,6 +287,8 @@ mod go_to_row_tests { } assert_eq!(s.execute("table.goToRow", &json!({"row": 1})).unwrap()["page"], 1); assert_eq!(s.execute("table.goToRow", &json!({"row": 20})).unwrap()["page"], 2); + let frame = s.doc().unwrap().selection.text.and_then(|t| t.frame).map(|f| f.0); + assert_eq!(frame, b["id"].as_u64(), "the caret is in the frame that shows the row"); // The header row repeats on page 2; the row itself is the one on page 1. assert_eq!(s.execute("table.goToRow", &json!({"row": 1, "section": "header"})).unwrap()["page"], 1); } diff --git a/crates/ui-egui/src/menus/tests.rs b/crates/ui-egui/src/menus/tests.rs index e4a111a8b..352eb3a58 100644 --- a/crates/ui-egui/src/menus/tests.rs +++ b/crates/ui-egui/src/menus/tests.rs @@ -2255,6 +2255,8 @@ fn the_table_menu_follows_indesigns_order() { "-", "Distribute Rows Evenly", "Distribute Columns Evenly", + "-", + "Go to Row…", ]; assert_eq!(labels, expected); // Cmd+Alt+Shift+T opens the dialog, as InDesign's; the engine command has no shortcut of