mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-24 10:46:50 -06:00
fix(ui): commit a pointed formula on the sheet it was started on (#996)
This commit is contained in:
@@ -929,6 +929,15 @@ impl SheetApp {
|
||||
}
|
||||
self.toast = Some((msg, now_ms()));
|
||||
}
|
||||
// Point mode can leave another sheet active; the edit belongs to the sheet it started on.
|
||||
if self.session.active().is_some_and(|d| d.wb.active_sheet != ed.sheet)
|
||||
&& let Err(e) = self.session.run("sheet.activate", json!({"sheet": ed.sheet}))
|
||||
{
|
||||
self.message = Some(("GridCraft".into(), clean_error(&e)));
|
||||
self.editor = Some(ed);
|
||||
self.session.mode = gridcraft_engine::Mode::Edit;
|
||||
return false;
|
||||
}
|
||||
let r = if fill_selection {
|
||||
self.session.run("range.fill", json!({"input": text}))
|
||||
} else {
|
||||
|
||||
@@ -28,8 +28,8 @@ fn activate_sheet(app: &mut SheetApp, i: usize) {
|
||||
if app.editor.as_ref().is_some_and(|e| e.can_point()) {
|
||||
let _ = app.session.run("sheet.activate", json!({"sheet": i}));
|
||||
} else {
|
||||
if app.editor.is_some() {
|
||||
app.commit_edit(0, 0, false, false);
|
||||
if app.editor.is_some() && !app.commit_edit(0, 0, false, false) {
|
||||
return;
|
||||
}
|
||||
app.run_or_alert("sheet.activate", json!({"sheet": i}));
|
||||
}
|
||||
@@ -340,8 +340,9 @@ pub fn status_bar(app: &mut SheetApp, ui: &mut Ui) {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{navigator_items, rename_needs_focus};
|
||||
use super::{activate_sheet, navigator_items, rename_needs_focus};
|
||||
use gridcraft_engine::model::{Sheet, Visibility};
|
||||
use serde_json::json;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[test]
|
||||
@@ -360,4 +361,24 @@ mod tests {
|
||||
let sheets = [Sheet::new("Data"), hidden, very_hidden, Sheet::new("Summary")].map(Arc::new);
|
||||
assert_eq!(navigator_items(&sheets), vec![("0".to_string(), "Data".to_string()), ("3".to_string(), "Summary".to_string())]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_rejected_commit_keeps_the_sheet_and_the_edit() {
|
||||
let mut session = gridcraft_engine::Session::new();
|
||||
session.new_workbook();
|
||||
session.execute("home.insertSheet", json!({})).unwrap();
|
||||
session.execute("sheet.activate", json!({"sheet": 0})).unwrap();
|
||||
let rule = json!({"range": "A1", "type": "whole", "operator": "between", "formula1": "1", "formula2": "10"});
|
||||
session.execute("data.validation", rule).unwrap();
|
||||
let mut app = crate::SheetApp::new(session, Default::default());
|
||||
app.begin_edit(Some("99".into()), false);
|
||||
activate_sheet(&mut app, 1);
|
||||
assert_eq!(app.session.active().unwrap().wb.active_sheet, 0, "a value the validation stops must not leave its sheet");
|
||||
assert!(app.editor.is_some(), "the edit stays open to be corrected");
|
||||
app.editor.as_mut().unwrap().text = "7".into();
|
||||
activate_sheet(&mut app, 1);
|
||||
assert_eq!(app.session.active().unwrap().wb.active_sheet, 1, "the corrected value commits and the sheet changes");
|
||||
let a1 = gridcraft_engine::core::CellRef::parse("A1").unwrap();
|
||||
assert!(app.session.active().unwrap().wb.sheet(0).unwrap().cell(a1).is_some(), "the value lands on the first sheet");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//! A formula started on one sheet and pointed at another sheet lands on the sheet it started on.
|
||||
|
||||
use egui::vec2;
|
||||
use gridcraft_engine::Session;
|
||||
use gridcraft_engine::core::CellRef;
|
||||
use gridcraft_ui_egui::SheetApp;
|
||||
use serde_json::json;
|
||||
|
||||
/// Two sheets, `range` selected on the first, and `=1+2` typed there; then pointing moves to the second sheet.
|
||||
fn pointing_on_second_sheet(range: &str) -> egui_kittest::Harness<'static, SheetApp> {
|
||||
let mut session = Session::new();
|
||||
session.new_workbook();
|
||||
session.execute("home.insertSheet", json!({})).unwrap();
|
||||
session.execute("sheet.activate", json!({"sheet": 0})).unwrap();
|
||||
session.execute("selection.set", json!({"range": range})).unwrap();
|
||||
let mut h = egui_kittest::Harness::builder().with_size(vec2(1200.0, 800.0)).build_ui_state(
|
||||
|ui, app: &mut SheetApp| {
|
||||
app.logic(ui.ctx());
|
||||
app.ui(ui);
|
||||
},
|
||||
SheetApp::new(session, Default::default()),
|
||||
);
|
||||
h.run_steps(4);
|
||||
h.state_mut().begin_edit(Some("=1+2".into()), false);
|
||||
h.run_steps(2);
|
||||
// Pointing moves to the other sheet without finishing the edit.
|
||||
h.state_mut().session.execute("sheet.activate", json!({"sheet": 1})).unwrap();
|
||||
h
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn commit_after_pointing_on_another_sheet_writes_to_the_origin_sheet() {
|
||||
let mut h = pointing_on_second_sheet("F8");
|
||||
assert!(h.state_mut().commit_edit(0, 0, false, false));
|
||||
let at = CellRef::parse("F8").unwrap();
|
||||
let wb = &h.state().session.active().unwrap().wb;
|
||||
assert_eq!(wb.active_sheet, 0, "the origin sheet is shown again");
|
||||
assert!(wb.sheet(0).unwrap().cell(at).is_some_and(|c| c.formula.is_some()), "formula written on the origin sheet");
|
||||
assert!(wb.sheet(1).unwrap().cell(at).is_none(), "the pointed-at sheet is untouched");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ctrl_enter_after_pointing_on_another_sheet_fills_the_origin_selection() {
|
||||
let mut h = pointing_on_second_sheet("B2:C3");
|
||||
assert!(h.state_mut().commit_edit(0, 0, false, true));
|
||||
let wb = &h.state().session.active().unwrap().wb;
|
||||
assert_eq!(wb.active_sheet, 0, "the origin sheet is shown again");
|
||||
for a1 in ["B2", "C2", "B3", "C3"] {
|
||||
let at = CellRef::parse(a1).unwrap();
|
||||
assert!(wb.sheet(0).unwrap().cell(at).is_some_and(|c| c.formula.is_some()), "{a1} filled on the origin sheet");
|
||||
assert!(wb.sheet(1).unwrap().cell(at).is_none(), "{a1} on the pointed-at sheet is untouched");
|
||||
}
|
||||
assert!(wb.sheet(1).unwrap().cell(CellRef::parse("A1").unwrap()).is_none(), "the pointed-at sheet's selection is untouched");
|
||||
}
|
||||
Reference in New Issue
Block a user