mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 15:51:56 +00:00
Fix #5360: Type on a Path Options has a Preview checkbox
With Preview on, the selected type on a path follows Effect, Flip, Align to Path and Spacing while the dialog is open. Cancel puts it back with no history step; OK keeps the previewed values as one undo step. Preview starts off. The public pages list no Preview for this dialog, so this is a VectorCraft choice, recorded as such in the parity docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
committed by
bflatastic
co-authored by
Claude Opus 5.5
parent
9f6c7d621f
commit
f53ebdf7c0
@@ -59,11 +59,16 @@ pub(super) const SPEC: DialogSpec = DialogSpec {
|
||||
..DialogSpec::FORM
|
||||
};
|
||||
|
||||
/// Does this dialog show a Preview checkbox? Only Grid Repeat Options does: the public page for
|
||||
/// the grid options lists one, and the radial and mirror pages do not. (Cancel rolls a preview
|
||||
/// back whichever dialog started it.)
|
||||
/// Does this dialog show a Preview checkbox? Grid Repeat Options does: the public page for the
|
||||
/// grid options lists one, and the radial and mirror pages do not. Type on a Path Options does
|
||||
/// too (#5360), our choice: its public pages list none. (Cancel rolls a preview back whichever
|
||||
/// dialog started it.)
|
||||
fn previews(d: &Dialog) -> bool {
|
||||
d.str("__command") == "object.repeat.options" && d.fields.contains_key("gridType")
|
||||
match d.str("__command").as_str() {
|
||||
"object.repeat.options" => d.fields.contains_key("gridType"),
|
||||
"type.pathOptions" => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// The command the dialog runs and its parameters: the fields shown and the fixed ones.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Type → Type on a Path → Type on a Path Options… (#429): the dialog shows the selected type's
|
||||
//! options (Effect, Flip, Align to Path, Spacing) and OK leaves its brackets where they are. The
|
||||
//! Selection tool draws no brackets on a huge selection.
|
||||
//! options (Effect, Flip, Align to Path, Spacing) and OK leaves its brackets where they are; its
|
||||
//! Preview shows them on the canvas while it is open (#5360). The Selection tool draws no brackets
|
||||
//! on a huge selection.
|
||||
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_doc::{NodeId, NodeKind, TextKind};
|
||||
@@ -80,6 +81,98 @@ fn type_on_a_path_options_keep_the_type_where_it_is() {
|
||||
assert_eq!((d.fields.get("alignToPath"), d.fields.get("flip")), (Some(&json!("center")), Some(&json!(false))));
|
||||
}
|
||||
|
||||
/// The effect, alignment and spacing of type on a path `id`.
|
||||
fn options(app: &VectorcraftApp, id: NodeId) -> (&'static str, &'static str, f64) {
|
||||
match app.session.doc().unwrap().doc.node(id).map(|n| &n.kind) {
|
||||
Some(NodeKind::Text(t)) => (t.path_effect.id(), t.path_align.id(), t.path_spacing),
|
||||
k => panic!("not text: {k:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// One headless frame of the open dialog.
|
||||
fn frame(app: &mut VectorcraftApp) {
|
||||
let ctx = egui::Context::default();
|
||||
crate::theme::install_fonts(&ctx);
|
||||
let mut out = ctx.run_ui(egui::RawInput::default(), |ui| dialogs::show(app, ui.ctx()));
|
||||
out.textures_delta.clear();
|
||||
}
|
||||
|
||||
/// #5360: Type on a Path Options has a Preview checkbox, off when it opens. With it on, the type
|
||||
/// on the canvas follows Effect, Flip, Align to Path and Spacing while the dialog is open (a
|
||||
/// checked Flip turns it over once, however many frames show it); Cancel puts it back without a
|
||||
/// step of history; OK keeps what was previewed as one step, and none when nothing changed.
|
||||
#[test]
|
||||
fn type_on_a_path_options_preview_on_the_canvas() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.run("file.new", json!({"width": 600, "height": 400})).unwrap();
|
||||
let path = app.run("path.create", json!({"d": "M100 200 L500 200"})).unwrap()["id"].as_u64().unwrap();
|
||||
let r = app.run("text.createInPath", json!({"path": path, "mode": "onPath", "text": "Along", "at": [300, 210]})).unwrap();
|
||||
let id = NodeId(r["id"].as_u64().unwrap());
|
||||
app.run("select.set", json!({"ids": [id.0]})).unwrap();
|
||||
let original = (brackets(&app, id), options(&app, id));
|
||||
let state = |app: &VectorcraftApp| (brackets(app, id), options(app, id));
|
||||
let steps = |app: &VectorcraftApp| app.session.doc().unwrap().history.undo.len();
|
||||
let before = steps(&app);
|
||||
|
||||
open_options(&mut app);
|
||||
let d = app.ui.dialog.as_ref().unwrap();
|
||||
assert!(dialogs::accepts_field(d, "preview"));
|
||||
assert!(!d.bool("preview"), "Preview starts off");
|
||||
let text = crate::tests_labels::painted_text(&mut app, |app, ui| dialogs::show(app, ui.ctx()));
|
||||
assert!(text.contains("Preview"), "{text}");
|
||||
|
||||
// Off: the fields change nothing until OK.
|
||||
app.ui.dialog.as_mut().unwrap().fields.insert("effect".into(), json!("skew"));
|
||||
frame(&mut app);
|
||||
assert_eq!(state(&app), original, "no preview without the checkbox");
|
||||
// On: the type follows the fields.
|
||||
dialogs::set_field(app.ui.dialog.as_mut().unwrap(), "preview".into(), json!(true));
|
||||
frame(&mut app);
|
||||
assert_eq!(options(&app, id).0, "skew");
|
||||
let d = app.ui.dialog.as_mut().unwrap();
|
||||
d.fields.insert("alignToPath".into(), json!("center"));
|
||||
d.fields.insert("spacing".into(), json!(6.0));
|
||||
frame(&mut app);
|
||||
assert_eq!(options(&app, id), ("skew", "center", 6.0));
|
||||
// Flip turns the type over once, frame after frame, and back when unchecked.
|
||||
app.ui.dialog.as_mut().unwrap().fields.insert("flip".into(), json!(true));
|
||||
frame(&mut app);
|
||||
let flipped = brackets(&app, id);
|
||||
assert_ne!(flipped, original.0, "the preview flips the type");
|
||||
frame(&mut app);
|
||||
assert_eq!(brackets(&app, id), flipped, "and keeps it flipped once");
|
||||
app.ui.dialog.as_mut().unwrap().fields.insert("flip".into(), json!(false));
|
||||
frame(&mut app);
|
||||
assert_eq!(brackets(&app, id), original.0, "unchecked, it turns back");
|
||||
// Cancel puts the original back and leaves no history.
|
||||
dialogs::cancel(&mut app);
|
||||
assert_eq!(state(&app), original, "Cancel restores the type");
|
||||
assert_eq!(steps(&app), before, "and adds no undo step");
|
||||
assert!(!app.session.in_interaction());
|
||||
|
||||
// OK with Preview on and nothing changed: no undo step.
|
||||
open_options(&mut app);
|
||||
dialogs::set_field(app.ui.dialog.as_mut().unwrap(), "preview".into(), json!(true));
|
||||
frame(&mut app);
|
||||
dialogs::confirm(&mut app).unwrap();
|
||||
assert!(app.ui.dialog.is_none());
|
||||
assert_eq!((state(&app), steps(&app)), (original, before));
|
||||
|
||||
// OK keeps the previewed values as one undo step.
|
||||
open_options(&mut app);
|
||||
let d = app.ui.dialog.as_mut().unwrap();
|
||||
d.fields.insert("effect".into(), json!("stairStep"));
|
||||
d.fields.insert("flip".into(), json!(true));
|
||||
dialogs::set_field(d, "preview".into(), json!(true));
|
||||
frame(&mut app);
|
||||
dialogs::confirm(&mut app).unwrap();
|
||||
assert!(app.ui.dialog.is_none());
|
||||
assert_eq!((options(&app, id).0, brackets(&app, id)), ("stairStep", flipped));
|
||||
assert_eq!(steps(&app), before + 1, "one undo step");
|
||||
app.run("edit.undo", json!({})).unwrap();
|
||||
assert_eq!(state(&app), original, "one Undo takes the whole change back");
|
||||
}
|
||||
|
||||
/// The Selection tool's brackets on one selected type on a path add their lines to the frame's
|
||||
/// mesh. On 32,768 (an opened PDF can hold as many curved text lines) they add none.
|
||||
#[test]
|
||||
|
||||
+3
-2
@@ -1,6 +1,6 @@
|
||||
# Type parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-02 · **Change:** minor (font-family fields accept the mouse wheel, #5253; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-03 · **Change:** minor (Type on a Path Options has a Preview checkbox, #5360; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
|
||||
|
||||
Type is Illustrator's largest single area by use (weight 13 of 105 across "Type core" and "Type advanced" in
|
||||
[target-app-parity.md](target-app-parity.md)). This checklist lists the features one by one. Status is from the
|
||||
@@ -25,7 +25,7 @@ against Illustrator's public documentation; **estimated** unless noted.
|
||||
| Area Type Options (rows, columns, inset, first baseline, Text Flow by rows or by columns, Auto Size, Shrink Text to Fit) | done | Text Flow fills the cells down each column first (By Columns, the default, as files from before it open) or across each row first (By Rows), in the dialog and `text.areaOptions {flow}` (#4978); the commands that make or restyle type say when it does not fit its frame; MCP `add_text` takes Auto Size and Shrink Text to Fit (#1471) |
|
||||
| Threaded text, Fit Headline, Text Wrap | done | Fit Headline sees wrapping in a frame one line tall (#1444); a thread holds area type and type on a path in any mix, as Illustrator links type in an area or along a path ([help](https://helpx.adobe.com/illustrator/using/manage-text-area.html)) |
|
||||
| Threading from the ports: selected area type and type on a path show an in port and an out port, empty, with an arrow on a side where the frame is threaded, or with a red "+" in the out port when the text doesn't fit; a click on either port loads the text; a click on a closed path, area type or type on a path threads into it, a click on empty canvas makes a frame of the same kind, shape and size there, a drag draws a rectangular frame; the frame placed comes after the clicked one from its out port and before it from its in port (the story then starts there); Escape or another tool cancels; a double-click on a threaded port breaks the thread there | partial | #2572: the Selection tool, `text.thread.add {from, to?, rect?, at?, before?}`, as the reference app's help describes ports and threading ([archived help, Threading text between objects](https://web.archive.org/web/20210119051048/https://helpx.adobe.com/illustrator/using/creating-text.html), [create text threads](https://helpx.adobe.com/illustrator/desktop/design-with-text/add-manage-text/create-text-threads-between-objects.html)); area type's in port sits on the left side below the top-left corner, type on a path's just before its start bracket; Show Text Threads draws its lines between the same ports; with more than 1,000 such objects selected no ports are drawn. a double-click on a port where the frame is threaded breaks the thread there, the story flowing into the frames before the break and the frames after it left empty, still threaded with each other when two or more (`text.thread.break`, [archived help](https://web.archive.org/web/20220127090642/https://helpx.adobe.com/illustrator/using/creating-text.html)). Remaining: the ports only take clicks with the Selection tool, and the loaded cursor borrows the I-beam until it's drawn |
|
||||
| Type on a Path effects and options; brackets | done | #429 |
|
||||
| Type on a Path effects and options; brackets | done | #429; Type on a Path Options has a Preview checkbox (#5360, a VectorCraft choice: the public pages list none) |
|
||||
| Character and Paragraph panels, styles with overrides | done | Character-style Auto-leading resets, partial definitions, local leading overrides, override markers, Undo/Redo and native serialization have regression coverage; differing paragraph alignments leave the shared alignment buttons unselected (headless regressions, full integration CI and visual review pass); mixed-value display for other paragraph fields remains missing |
|
||||
| Character size and horizontal scale after object/group scaling | done | #1034: fields and setters compensate the stored affine; point size follows the transformed em-height axis, not the glyph ink bounds. Range edits, keyboard increments, leading and baseline shift use document points; rotation, reflection and shear remain editable. |
|
||||
| Preserve font sizes while scaling a group | missing | Separate enhancement; scaling still scales text with the other artwork. |
|
||||
@@ -76,6 +76,7 @@ Character Styles menu New/Redefine and footer New capture the first selected cha
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-11-03 | minor | Type on a Path Options has a Preview checkbox: the type follows the fields while it is on, Cancel restores it, OK is one undo step (#5360, a VectorCraft choice: the public pages list none); scores and estimates unchanged. |
|
||||
| 2026-11-02 | minor | The wheel over Character, Properties and Control font-family fields changes selected text, one undo step per notch (#5253); scores and estimates unchanged. |
|
||||
| 2026-11-01 | minor | The Type and Vertical Type tools make area type in a clicked closed path and type on a path along a clicked open one, with their own pointers; each type tool has its own icon; scores unchanged (estimated) |
|
||||
| 2026-10-31 | minor | Units › East Asian Type acts (#394): Q and Ha (a quarter of a millimetre each) are units that preference offers; scores unchanged |
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
# UI and interaction parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-03 · **Change:** minor (font-family fields accept the mouse wheel, #5253; Transform previews typed values and reads the Appearance target; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-03 · **Change:** minor (Type on a Path Options has a Preview checkbox, #5360; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
|
||||
|
||||
## Feature submission evidence
|
||||
|
||||
@@ -287,6 +287,7 @@ next unit in the order a right-click on a ruler lists them, from Feet back to Po
|
||||
| Pathfinder panel: a group selected alone counts its nested shapes, so an expanded stroked object keeps the Shape Modes enabled | done | #1642 (#1635) |
|
||||
| Selected Grid Repeat shows row, column and corner handles and spacing sliders; bounding-box handles take priority where they meet | done | #2691, `tools/src/repeat_grid.rs`; [public behavior reference](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/create-and-edit-patterns/set-grid-repeat-options.html); drags preview and commit `object.repeat.options` as one undo step, Escape cancels; Radial Repeat has no handles yet |
|
||||
| Grid Repeat Options (Object › Repeat › Options…) has a Preview checkbox: the repeat on the canvas follows the fields while the dialog is open, Cancel puts the original back without a history step, OK keeps the previewed values as one undo step | done | #2651; [public behavior reference](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/create-and-edit-patterns/set-grid-repeat-options.html) lists the Preview option for the grid options only, so Radial and Mirror Repeat Options have none; `dialogs/command.rs` tests |
|
||||
| Type on a Path Options (Type › Type on a Path › Type on a Path Options…, or a double-click on the Type on a Path tools) has a Preview checkbox, off when it opens: the selected type on a path follows Effect, Flip, Align to Path and Spacing while the dialog is open, Cancel puts it back without a history step, OK keeps the previewed values as one undo step | done | #5360; a VectorCraft choice: the [public page](https://helpx.adobe.com/illustrator/using/creating-type-path.html) lists the dialog's options but no Preview; `tests/pathtype.rs` |
|
||||
| Selected Mirror Repeat shows a prominent axis with move and rotation handles; bounding-box handles take priority over the axis line | done | #2877, `tools/src/mirror.rs`; [public behavior reference](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/create-and-edit-patterns/set-mirror-repeat-options.html) |
|
||||
| Object › Expand on radial, grid and mirror repeats makes groups of their instances | done | #1765 (#1756) |
|
||||
| Object › Expand… is dimmed while the selection has appearance attributes (effects, several fills or strokes, a fill or stroke with its own transparency or effects, a brush); its tooltip and the status bar say to use Object › Expand Appearance first, which leaves a stroked line with Zig Zag a stroked zig-zag line that Expand then outlines | done | #3089; [public behavior reference](https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/expand-objects.html); `dialogs/expand.rs` tests, engine `tests_objexpand`. `object.expand` (agents, scripts) still bakes effects in one step |
|
||||
@@ -407,6 +408,7 @@ separate. Scores and hours unchanged. [Behavior and command details](development
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-11-03 | minor | Type on a Path Options has a Preview checkbox (#5360, a VectorCraft choice); scores and estimates unchanged |
|
||||
| 2026-11-02 | minor | Font-family fields in Character, Properties and Control accept the wheel without opening the menu (#5253); scores and estimates unchanged. |
|
||||
| 2026-11-03 | minor | Symbol editing draws and drags 9-slice guides on the canvas (#5280). Guides outside the artwork remain unsupported. Scores and hours remain unchanged. |
|
||||
| 2026-11-01 | minor | A double-click on a Repeat with the Selection tool enters isolation mode on it, where its source art (type included: a double-click there edits the text) is edited and every copy follows (#5054); scores and estimates unchanged |
|
||||
|
||||
Reference in New Issue
Block a user