mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-29 20:27:05 -06:00
Type: Cmd/Ctrl+Shift+X resets horizontal scale to 100%
The reference app resets the horizontal scale of type to 100% with Cmd/Ctrl+Shift+X. VectorCraft had no command for it, and the chord cut the selection: egui reports it as a Cut with Shift held. type.resetHorizontalScale (Reset Horizontal Scale, default Cmd+Shift+X) sets the horizontal scale to 100% in the text the Type tool has selected, or else in all the text of every selected type object, in one undo step. The value is the one the Character panel shows, so a type object stretched to twice its width keeps 50% stored. The vertical scale does not change. At a caret the command leaves the text as it is. Type objects given in ids are reset in full, as type.resetTracking does. Docs: docs/mcp.md, docs/target-app-parity.md.
This commit is contained in:
@@ -112,6 +112,15 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_selection,
|
||||
reset_tracking
|
||||
),
|
||||
cmd!(
|
||||
"type.resetHorizontalScale",
|
||||
"Reset Horizontal Scale",
|
||||
[],
|
||||
Some("Cmd+Shift+X"),
|
||||
"{ids?: [id…]} set the horizontal scale to 100% (as the Character panel shows it, the object's own transform included) in all the text of the type objects in `ids`, else in the text the Type tool has selected (nothing at a caret), else in every selected type object, as one undo step → {ids}",
|
||||
has_selection,
|
||||
reset_horizontal_scale
|
||||
),
|
||||
cmd!(
|
||||
"text.discardEmpty",
|
||||
"Discard Empty Type",
|
||||
@@ -752,6 +761,26 @@ fn reset_tracking(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
Ok(json!({ "ids": ranges.iter().map(|(id, ..)| id.0).collect::<Vec<_>>() }))
|
||||
}
|
||||
|
||||
/// Cmd/Ctrl+Shift+X: horizontal scale 100% (the Character panel's value, which includes the
|
||||
/// object's own transform) in the type objects in `ids`, else in the Type tool's selected text,
|
||||
/// else in every selected type object. At a caret the command leaves the text as it is.
|
||||
fn reset_horizontal_scale(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "type.resetHorizontalScale";
|
||||
let ranges = type_ranges(s, p, C, |_, _| None)?;
|
||||
if !ranges.is_empty() {
|
||||
s.edit("Reset Horizontal Scale", |d, _| {
|
||||
for &(id, a, b, _) in &ranges {
|
||||
let t = text_mut(d, id).ok_or(EngineError::NoNode(id))?;
|
||||
let h_scale = super::typecmd::local_type_value(t, 100.0, (1.0, 10000.0), true, C)?;
|
||||
edit::style_range(&mut t.runs, a, b, |st| st.h_scale = h_scale);
|
||||
refresh_bounds(t);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
Ok(json!({ "ids": ranges.iter().map(|(id, ..)| id.0).collect::<Vec<_>>() }))
|
||||
}
|
||||
|
||||
/// Tracking (1/1000 em) that makes the first paragraph of `t` exactly `target` wide, if it fits
|
||||
/// on one line at all.
|
||||
fn headline_tracking(t: &TextObject, target: f64) -> Option<f64> {
|
||||
|
||||
@@ -1096,6 +1096,50 @@ fn reset_tracking_sets_tracking_and_kerning_to_zero() {
|
||||
assert_eq!(style_at(&s, other, 0).tracking, 0.0, "the reset stays");
|
||||
}
|
||||
|
||||
/// Cmd/Ctrl+Shift+X resets the horizontal scale to 100% in every selected type object and in the
|
||||
/// Type tool's selected text, as one undo step, and leaves the vertical scale as it is. At a caret
|
||||
/// it leaves the text as it is. On a stretched object the scale the Character panel shows, which includes the
|
||||
/// object's own stretch, goes to 100%. Type objects given in `ids` are reset in full while the
|
||||
/// Type tool edits.
|
||||
#[test]
|
||||
fn reset_horizontal_scale_sets_it_to_100_percent() {
|
||||
use vectorcraft_tools::PointerKind::{Down, Up};
|
||||
let mut s = new_doc();
|
||||
let id = NodeId(s.execute("text.create", &json!({"x": 100, "y": 100, "text": "Hello world", "size": 20})).unwrap()["id"].as_u64().unwrap());
|
||||
let scales = |s: &Session, byte| {
|
||||
let st = style_at(s, id, byte);
|
||||
(st.h_scale, st.v_scale)
|
||||
};
|
||||
s.execute("text.setRangeStyle", &json!({"id": id.0, "hScale": 150, "vScale": 80})).unwrap();
|
||||
s.execute("select.set", &json!({"ids": [id.0]})).unwrap();
|
||||
assert_eq!(find_command("type.resetHorizontalScale").unwrap().shortcut, Some("Cmd+Shift+X"));
|
||||
assert_eq!(s.execute("type.resetHorizontalScale", &json!({})).unwrap()["ids"], json!([id.0]));
|
||||
assert_eq!((scales(&s, 0), scales(&s, 10)), ((100.0, 80.0), (100.0, 80.0)));
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(scales(&s, 0), (150.0, 80.0), "one undo step");
|
||||
// A type object stretched to twice its width shows 200% and keeps half of it stored.
|
||||
let wide = NodeId(s.execute("text.create", &json!({"x": 100, "y": 300, "text": "Wide", "size": 20})).unwrap()["id"].as_u64().unwrap());
|
||||
s.execute("select.set", &json!({"ids": [wide.0]})).unwrap();
|
||||
s.execute("object.scale", &json!({"sx": 200, "sy": 100})).unwrap();
|
||||
s.execute("type.resetHorizontalScale", &json!({})).unwrap();
|
||||
assert_eq!(style_at(&s, wide, 0).h_scale, 50.0);
|
||||
// With the Type tool, it resets only the selected text.
|
||||
let v = ViewInfo::default();
|
||||
s.select_tool("type", v).unwrap();
|
||||
gesture(&mut s, v, &[(Down, 102.0, 95.0), (Up, 102.0, 95.0)]);
|
||||
assert_eq!(s.tool_options()["editing"], json!(id.0), "editing the text");
|
||||
s.set_tool_option("select", &json!({"start": 0, "end": 5}));
|
||||
s.execute("type.resetHorizontalScale", &json!({})).unwrap();
|
||||
assert_eq!((scales(&s, 4), scales(&s, 6)), ((100.0, 80.0), (150.0, 80.0)));
|
||||
// At a caret it leaves the text as it is.
|
||||
s.set_tool_option("select", &json!({"start": 8, "end": 8}));
|
||||
assert_eq!(s.execute("type.resetHorizontalScale", &json!({})).unwrap()["ids"], json!([]));
|
||||
assert_eq!((scales(&s, 7), scales(&s, 8)), ((150.0, 80.0), (150.0, 80.0)));
|
||||
// While the Type tool edits, the type objects in `ids` are reset in full.
|
||||
s.execute("type.resetHorizontalScale", &json!({"ids": [id.0]})).unwrap();
|
||||
assert_eq!((scales(&s, 6), scales(&s, 10)), ((100.0, 80.0), (100.0, 80.0)));
|
||||
}
|
||||
|
||||
/// Type › Fill New Type Objects With Placeholder Text (#394, on by default): type the Type tool
|
||||
/// places starts with placeholder text, selected, so typing replaces it; off, it starts empty.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user