mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-24 10:46:50 -06:00
Merge PR #970: Control: Go To and Select over the control channel scroll the active cell into view
This commit is contained in:
@@ -71,6 +71,16 @@ fn wrap(r: Result<Json, String>) -> Outcome {
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs a command for an agent. Commands that move the selection scroll the active cell into
|
||||
/// view, as the Go To dialog, the Name Box and the arrow keys do.
|
||||
fn run(app: &mut SheetApp, id: &str, params: Json) -> Result<Json, String> {
|
||||
let r = app.run(id, params);
|
||||
if r.is_ok() && matches!(id, "edit.goTo" | "edit.goToSpecial" | "selection.set" | "selection.move") {
|
||||
app.grid.ensure_visible = true;
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
pub fn inspect(app: &SheetApp, ctx: &egui::Context) -> Json {
|
||||
let r = ctx.content_rect();
|
||||
let v = app.view();
|
||||
@@ -171,7 +181,7 @@ pub fn handle(app: &mut SheetApp, ctx: &egui::Context, method: &str, p: &Json) -
|
||||
"engine.execute" | "command" | "ui.menu.invoke" => {
|
||||
let Some(id) = s("command").or(s("id")) else { return err("missing `command`") };
|
||||
let params = p.get("params").cloned().unwrap_or(json!({}));
|
||||
wrap(app.run(id, if params.is_null() { json!({}) } else { params }))
|
||||
wrap(run(app, id, if params.is_null() { json!({}) } else { params }))
|
||||
}
|
||||
"engine.commands" => {
|
||||
let mut v: Vec<Json> = app.session.commands().into_iter().map(|c| serde_json::to_value(c).unwrap_or_default()).collect();
|
||||
@@ -387,7 +397,7 @@ pub fn handle(app: &mut SheetApp, ctx: &egui::Context, method: &str, p: &Json) -
|
||||
ok(Json::Null)
|
||||
}
|
||||
// Anything else that names a command runs it.
|
||||
other if gridcraft_engine::find_command(other).is_some() => wrap(app.run(other, p.clone())),
|
||||
other if gridcraft_engine::find_command(other).is_some() => wrap(run(app, other, p.clone())),
|
||||
other => err(format!("unknown method `{other}`")),
|
||||
};
|
||||
ctx.request_repaint();
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
//! Extending the selection from the keyboard scrolls its moving end into view, not the anchor.
|
||||
//! Go To and Select over the control channel scroll the active cell into view.
|
||||
|
||||
use egui::{Event, Key, Modifiers};
|
||||
use gridcraft_engine::Session;
|
||||
use gridcraft_engine::core::{CellRef, RangeRef};
|
||||
use gridcraft_ui_egui::control::{Outcome, handle};
|
||||
use gridcraft_ui_egui::{SheetApp, grid::Geo};
|
||||
use serde_json::json;
|
||||
use serde_json::{Value as Json, json};
|
||||
|
||||
type Harness = egui_kittest::Harness<'static, SheetApp>;
|
||||
|
||||
@@ -104,3 +106,39 @@ fn ctrl_shift_home_and_end_scroll_the_moving_end_into_view() {
|
||||
key(&mut h, Key::Home, CTRL_SHIFT);
|
||||
assert_extended(&h, "CV200", "A1");
|
||||
}
|
||||
|
||||
fn control(h: &mut Harness, method: &str, params: Json) -> Json {
|
||||
let ctx = h.ctx.clone();
|
||||
let out = match handle(h.state_mut(), &ctx, method, ¶ms) {
|
||||
Outcome::Done(v) => v,
|
||||
Outcome::Screenshot { .. } => json!(null),
|
||||
};
|
||||
h.run_steps(2);
|
||||
out
|
||||
}
|
||||
|
||||
fn active(h: &Harness) -> CellRef {
|
||||
h.state().session.active().unwrap().selection.active
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn go_to_over_the_control_channel_scrolls_the_target_into_view() {
|
||||
let mut h = harness();
|
||||
assert!(!visible(&h, "Z300"));
|
||||
let r = control(&mut h, "engine.execute", json!({"command": "edit.goTo", "params": {"reference": "Z300"}}));
|
||||
assert_eq!(r["ok"], json!(true), "{r}");
|
||||
assert_eq!(active(&h), CellRef::parse("Z300").unwrap());
|
||||
assert!(visible(&h, "Z300"), "Go To scrolls Z300 into view");
|
||||
assert!(!visible(&h, "A1"));
|
||||
// A command named as the method runs the same way.
|
||||
control(&mut h, "edit.goTo", json!({"reference": "A1"}));
|
||||
assert!(visible(&h, "A1") && !visible(&h, "Z300"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn select_over_the_control_channel_scrolls_the_active_cell_into_view() {
|
||||
let mut h = harness();
|
||||
control(&mut h, "engine.execute", json!({"command": "selection.set", "params": {"range": "BZ150:CA160"}}));
|
||||
assert_eq!(active(&h), CellRef::parse("BZ150").unwrap());
|
||||
assert!(visible(&h, "BZ150") && !visible(&h, "A1"), "selecting a far range scrolls its active cell into view");
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ connection; nothing sent after it runs. Blank lines are skipped.
|
||||
|
||||
| Method | Params | What it does |
|
||||
|---|---|---|
|
||||
| `engine.execute` | `{command, params}` | Runs any engine command (see `engine.commands` or `gridcraft-cli commands`) |
|
||||
| `engine.execute` | `{command, params}` | Runs any engine command (see `engine.commands` or `gridcraft-cli commands`). `edit.goTo`, `edit.goToSpecial`, `selection.set` and `selection.move` scroll the active cell into view, as Go To does in the window |
|
||||
| `engine.commands` | `{search?}` | Every command: id, label, ribbon path, shortcut, params doc, enabled; `search` keeps those whose id, label or ribbon path contains it (case-insensitive) |
|
||||
| `engine.journal` | | Commands run so far (replayable). Passwords (`password`, `…Password` params) are left out, so a replayed Protect Sheet has no password |
|
||||
| `document.inspect` | | Workbook summary: sheets, used ranges, tables, charts, names, selection, undo labels |
|
||||
|
||||
Reference in New Issue
Block a user