mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 13:23:22 +00:00
OpenType: a menu choice at a Type tool caret reaches every character
At a caret the panel sends text.setRangeStyle with no range, which styles all of the text, but the check that skips a choice that changes nothing read only the insertion style. When the characters at the caret already had the chosen feature and others did not, the choice did nothing. The check now covers every character of the text at a caret, so the choice applies, and a choice that changes no character still adds no undo step.
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
use egui::Ui;
|
||||
use serde_json::json;
|
||||
use vectorcraft_doc::{CharStyle, NodeKind};
|
||||
use vectorcraft_text::{EXTRA_FEATURES, FontDb, OtFeatures, StylisticSet};
|
||||
|
||||
use super::character::{shared, text_editing, text_style};
|
||||
@@ -135,14 +136,22 @@ impl Change {
|
||||
}
|
||||
|
||||
/// Make `change` to the features of each character the panel acts on, from the character's own
|
||||
/// features (`featureChanges`), unless it changes none of them.
|
||||
/// features (`featureChanges`), unless it changes none of them. At a Type tool caret the
|
||||
/// command styles all the text, so every character of the text is checked.
|
||||
fn edit(app: &mut VectorcraftApp, change: Change) {
|
||||
let unchanged = shared(app, |s| {
|
||||
let same = |s: &CharStyle| {
|
||||
let before = OtFeatures::from_tags(s.features.iter().map(String::as_str));
|
||||
let mut after = before;
|
||||
change.apply(&mut after);
|
||||
after == before
|
||||
});
|
||||
};
|
||||
let unchanged = match text_editing(app) {
|
||||
Some((id, a, b)) if b <= a => match app.session.active().and_then(|st| st.doc.node(id)).map(|n| &n.kind) {
|
||||
Some(NodeKind::Text(t)) => Some(t.runs.iter().all(|r| same(&r.style))),
|
||||
_ => None,
|
||||
},
|
||||
_ => shared(app, same),
|
||||
};
|
||||
if unchanged != Some(true) {
|
||||
run_features(app, "featureChanges", OtFeatures::changes(|f| change.apply(f)));
|
||||
}
|
||||
@@ -525,4 +534,26 @@ mod tests {
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// At a caret whose insertion style is already a denominator, Denominator still reaches the
|
||||
/// characters the command styles at a caret (all of them) in one undo step; chosen again once
|
||||
/// every character has it, it adds no undo step.
|
||||
#[test]
|
||||
fn caret_with_the_same_position_still_applies_it() {
|
||||
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
|
||||
app.session.execute("file.new", &json!({"width": 100, "height": 100})).unwrap();
|
||||
app.session.select_tool("type", Default::default()).unwrap();
|
||||
let id = app.session.execute("text.create", &json!({"x": 10, "y": 40, "text": "1/23"})).unwrap()["id"].clone();
|
||||
app.session.execute("text.setRangeStyle", &json!({"id": id, "start": 0, "end": 1, "features": ["dnom"]})).unwrap();
|
||||
app.session.apply_actions(vec![vectorcraft_tools::Action::Notify("text.editNew".into())]).unwrap();
|
||||
app.session.set_tool_option("select", &json!({"start": 1, "end": 1}));
|
||||
assert_eq!(text_editing(&app).map(|(_, a, b)| (a, b)), Some((1, 1)));
|
||||
assert_eq!(shown_position(&app), Some(4));
|
||||
let undo = undo_steps(&app);
|
||||
edit(&mut app, Change::Position(4));
|
||||
assert_eq!(undo_steps(&app), undo + 1);
|
||||
assert_eq!(run_features(&mut app, &id, 4), [("1/23".to_string(), json!(["dnom"]))]);
|
||||
edit(&mut app, Change::Position(4));
|
||||
assert_eq!(undo_steps(&app), undo + 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user