mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Merge pull request #1886 from marcoarnulfo/fix/text-edit-commit-before-transform
Type: a Transform panel edit or a dialog preview while typing keeps what was typed
This commit is contained in:
@@ -1108,6 +1108,8 @@ pub struct Session {
|
||||
/// While the active tool's actions run: their commands aren't "a command from outside the
|
||||
/// tool" ([`Session::after_command`]).
|
||||
pub(crate) in_tool_actions: bool,
|
||||
/// While [`Session::preview`] runs its command: its edits are the interaction's own.
|
||||
previewing: bool,
|
||||
/// Envelope Options with no envelope selected: the options and fidelity new envelopes get
|
||||
/// (`None`: the reference app's defaults, fidelity 50); not saved.
|
||||
pub(crate) envelope_defaults: Option<(vectorcraft_doc::live::EnvelopeOptions, f64)>,
|
||||
@@ -1183,6 +1185,7 @@ impl Session {
|
||||
batch_stash: None,
|
||||
recovery: Default::default(),
|
||||
in_tool_actions: false,
|
||||
previewing: false,
|
||||
envelope_defaults: None,
|
||||
liquify_stroke: None,
|
||||
plane_widget_press: false,
|
||||
@@ -1479,6 +1482,11 @@ impl Session {
|
||||
/// Run `f` on a mutable copy of the active document. Outside an interaction this records one
|
||||
/// undo step labelled `label`; inside one it just mutates (the interaction commits later).
|
||||
pub fn edit<T>(&mut self, label: &str, f: impl FnOnce(&mut Document, &mut Selection) -> Result<T>) -> Result<T> {
|
||||
// An edit made while typing (the Transform panel) is a step of its own: inside the typing
|
||||
// session, the next keystroke's preview would start again from before it (#1881).
|
||||
if !self.previewing && cmd::typing_in_progress(self) {
|
||||
cmd::settle_interaction(self)?;
|
||||
}
|
||||
let st = self.doc_mut()?;
|
||||
let before = st.doc.clone();
|
||||
let before_sel = st.selection.clone();
|
||||
@@ -1579,6 +1587,11 @@ impl Session {
|
||||
// ---------- interactions (live drags) ----------
|
||||
|
||||
pub fn begin_interaction(&mut self, label: &str) -> Result<()> {
|
||||
// Typing in progress is kept first: a drag or a dialog's preview would otherwise start
|
||||
// from the snapshot taken before the typing, and drop it (#1881).
|
||||
if label != "Typing" && cmd::typing_in_progress(self) {
|
||||
cmd::settle_interaction(self)?;
|
||||
}
|
||||
let st = self.doc_mut()?;
|
||||
if st.interaction.is_some() {
|
||||
return Ok(());
|
||||
@@ -1618,7 +1631,9 @@ impl Session {
|
||||
self.pending_paint = None;
|
||||
let rw = cmd::distortcmds::perspective_rewrite(self, cmd, params);
|
||||
let (cmd, params) = rw.as_ref().map_or((cmd, params), |(c, p)| (c.as_str(), p));
|
||||
let outer = std::mem::replace(&mut self.previewing, true);
|
||||
let r = self.execute(cmd, params);
|
||||
self.previewing = outer;
|
||||
let params = self.noted(params);
|
||||
let st = self.doc_mut()?;
|
||||
if let Some(it) = &mut st.interaction {
|
||||
|
||||
@@ -653,3 +653,61 @@ fn a_fill_the_selected_characters_have_records_no_undo_step() {
|
||||
s.execute("paint.setStroke", &json!({"color": "#ff0000"})).unwrap();
|
||||
assert_eq!(history(&s), before);
|
||||
}
|
||||
|
||||
fn left(s: &Session, id: NodeId) -> f64 {
|
||||
s.doc().unwrap().doc.bounds_of(&[id], false).unwrap().x0
|
||||
}
|
||||
|
||||
/// #1881: the Transform panel moving or scaling the type while it is being typed keeps both the
|
||||
/// typing and the transformation, however the editing goes on.
|
||||
#[test]
|
||||
fn a_transform_panel_edit_while_typing_keeps_the_typing_and_the_transform() {
|
||||
let mut s = session();
|
||||
let v = ViewInfo::default();
|
||||
let id = text(&mut s, "Hello");
|
||||
s.select_tool("type", v).unwrap();
|
||||
let b = s.doc().unwrap().doc.bounds_of(&[id], false).unwrap();
|
||||
click(&mut s, b.x1 - 1.0, b.center().y);
|
||||
s.tool_text(" world", v).unwrap();
|
||||
s.execute("object.setBounds", &json!({"x": 400, "reference": 0})).unwrap();
|
||||
assert!((left(&s, id) - 400.0).abs() < 1e-6);
|
||||
// Typing on.
|
||||
s.tool_text("!", v).unwrap();
|
||||
assert_eq!(obj(&s, id).plain_text(), "Hello world!");
|
||||
assert!((left(&s, id) - 400.0).abs() < 1e-6, "the move stays: {}", left(&s, id));
|
||||
s.execute("object.setBounds", &json!({"width": 300, "reference": 0, "proportional": true})).unwrap();
|
||||
let w = |s: &Session| s.doc().unwrap().doc.bounds_of(&[id], false).unwrap().width();
|
||||
assert!((w(&s) - 300.0).abs() < 1e-6);
|
||||
key(&mut s, ToolKey::Escape, Mods::default());
|
||||
assert_eq!(obj(&s, id).plain_text(), "Hello world!");
|
||||
assert!((w(&s) - 300.0).abs() < 1e-6, "the scale stays: {}", w(&s));
|
||||
assert!((left(&s, id) - 400.0).abs() < 1e-6);
|
||||
// Each its own step, the typing first.
|
||||
let labels = undo_labels(&s);
|
||||
let n = labels.len();
|
||||
assert_eq!(labels[n - 4], "Typing", "{labels:?}");
|
||||
assert_eq!(labels[n - 2], "Typing", "{labels:?}");
|
||||
}
|
||||
|
||||
/// #1881: a dialog previewing a transformation while the type is being typed (Object › Transform
|
||||
/// with Preview) starts from the typed text, and keeps it when it commits.
|
||||
#[test]
|
||||
fn a_previewed_transform_while_typing_keeps_the_typing() {
|
||||
let mut s = session();
|
||||
let v = ViewInfo::default();
|
||||
let id = text(&mut s, "Hello");
|
||||
s.select_tool("type", v).unwrap();
|
||||
let b = s.doc().unwrap().doc.bounds_of(&[id], false).unwrap();
|
||||
click(&mut s, b.x1 - 1.0, b.center().y);
|
||||
s.tool_text(" world", v).unwrap();
|
||||
s.begin_interaction("Move").unwrap();
|
||||
s.preview("object.setBounds", &json!({"x": 400, "reference": 0})).unwrap();
|
||||
assert_eq!(obj(&s, id).plain_text(), "Hello world", "the preview starts from the typed text");
|
||||
s.commit_interaction().unwrap();
|
||||
assert_eq!(obj(&s, id).plain_text(), "Hello world");
|
||||
assert!((left(&s, id) - 400.0).abs() < 1e-6);
|
||||
// Typing on starts a new session from the moved text.
|
||||
s.tool_text("!", v).unwrap();
|
||||
assert_eq!(obj(&s, id).plain_text(), "Hello world!");
|
||||
assert!((left(&s, id) - 400.0).abs() < 1e-6);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user