Commit Graph
5 Commits
Author SHA1 Message Date
bflatasticandClaude Opus 5.5 b71d877a0a Fix #400: Scrub numeric fields by dragging their label
Dragging a numeric field's label left or right steps the field's value,
as Photoshop's scrubby labels do (beyond Illustrator): one unit every
2 points, ten with Shift, a tenth with Ctrl/Cmd (counts stay whole), in
the field's unit and precision. The panels apply each value as they
apply a typed one, so the art follows live and the caller's limits
hold (dragging back from a limit changes the value at once).

- scrub.rs: the label zone over the label noted just before a field
  (dim_label, label_row, widgets::field_label, the Character and
  Paragraph panels' icons, the Transform and Properties rotate/shear
  icons), the ↔ cursor on hover, a click on the label focuses the
  field. The text box itself never scrubs; a field without a label
  doesn't. num_field, plain_field, mixed_field (and the spin fields)
  and opt_field take part.
- Engine: undo groups (Session::begin_undo_group / end_undo_group). The
  edits made in a group, commands and committed live drags alike, are
  one undo step, journaled one by one; a cancelled group is undone and
  dropped from the journal. The app opens one while a label is dragged,
  so a scrub is one undo step whichever path the panel applies values
  by (app.run, session.execute, live_run), and Escape cancels it
  (shortcuts leave Escape to the drag, so it doesn't close a dialog or
  deselect).
- Preferences > General > Scrub Numeric Fields by Dragging
  (`scrubNumericFields`, on by default), translated in ja, es, zh-hans,
  zh-hant and pt-br.
- Tests: label drags with Shift/Ctrl, limits, counts and units, Escape,
  the preference, the cursor, click-to-focus, no scrub on the box or
  without a label, and in the app one undo step for a W drag.
- ROADMAP and docs/mcp.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 11:33:57 +07:00
bflatasticandClaude Opus 5.5 1d04ee0e84 Engine: a failed batch gives back the highlighted Layers panel rows
`command.batch` rolls a failed batch back through each document's interaction, which restored the
art, the selection, the current layer and isolation but not the highlighted Layers panel rows. A
batch whose `layer.setCurrent` step ran before a later step failed left that layer's row
highlighted, so a following Collect in New Layer collected the layer instead of the selected art.
The failed batch isn't journaled, so replaying the journal gave a different document: the
`journal_replay_reproduces_document` property test failed whenever it drew that sequence.

The interaction now keeps the highlighted rows too, which also puts them back when a drag is
cancelled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 06:55:39 +07:00
bflatasticandClaude Opus 5.5 3d87b71ed4 M14.4: a batch that opens a new document is journaled
command.batch kept its steps in one interaction of the document active
when it began and journaled itself by committing that interaction. A
step that opened, closed or reverted a document broke both: the switch
cancelled the interaction (throwing away the steps so far), and the
commit then ran in the new document, which had none, so the batch was
never journaled and a replay was missing the new document. An error
after the switch rolled back only the active document.

- Each step runs inside an interaction of the document active when it
  starts; a switch leaves it open while a batch runs, so every document
  the batch edits gets one undo step when it succeeds.
- The batch journals itself, whichever document it ends in.
- On error everything rolls back: documents the batch opened close, the
  ones it closed or reverted come back (Session::batch_stash), each
  one's interaction is undone, and the active document and the
  Untitled-N count go back too.
- DocState::keep_interaction / undo_interaction share the undo-step and
  rollback code with commit_interaction / cancel_interaction.
- Tests: a batch that opens a new document is journaled, replays to the
  same documents and keeps one undo step in each; a failed batch closes
  the document it opened and restores the one it closed; a failed batch
  brings back a document it reverted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 14:22:36 +07:00
bflatasticandClaude Opus 5.5 766b612070 M14.4: a batch journals the dates and preferences its steps used
Session::note_journal only kept values noted by the top-level command, so
a command run as a step of command.batch lost them: a save in a batch
stamped File Info's modified date from the clock without recording it,
and object.scale's strokes/corners came from the preferences again on
replay. Replaying such a journal a second later (or with other
preferences) gave a different document.

- Session::execute_step runs a batch step with its own journal notes
  (note_depth) and returns its params with what it noted; command.batch
  writes those params into its step of the batch's journal entry (steps
  that note nothing stay as given).
- journal_for_action strips the replay-only dates from a batch's steps
  too, so an action recorded with one still dates the document when it
  plays.
- Tests: a save in a batch records its date and a replay with the
  recorded date moved lands on it, while an action leaves it out; a scale
  in a batch records Scale Strokes & Effects and replays alike with the
  preference off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 14:05:09 +07:00
bflatasticandClaude Opus 5.5 851ed15104 M4.55: a journal replay reproduces File Info's dates
File Info's dates come from the clock, so documents made or saved a second
apart differed: journal_replay_reproduces_document and
rich_fixture_satisfies_invariants_and_undoes_to_blank failed at random.
One approach for every clock-derived date: it is a command input that
defaults to now, and the journal records the value used.

- file.new takes created? and document.save / file.saveAs take modified?
  (Unix seconds, or null for none; default now), through date_param /
  clock_date on the one save path (save_with), so Save, Save As and the
  UI's save stamp alike; Save a Copy still leaves the dates.
- Their journal entries always record the date used, so replaying the
  journal makes the same document whenever it runs. Actions recorded from
  the journal (Session::journal_for_action) leave those dates out, so
  playing an action later dates the document then.
- Test fixtures date their documents fixtures::CREATED, and the MCP
  property test dates its local document as the headless one, so
  documents built at different moments compare equal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 11:41:26 +07:00