Skip to content

feat(dialogs): redesign the state and transition editors, and merge dense edge labels - #139

Merged
thethinkmachine merged 1 commit into
mainfrom
feat/edit-dialogs
Oct 8, 2026
Merged

thethinkmachine merged 1 commit into
mainfrom
feat/edit-dialogs

Conversation

@thethinkmachine

Copy link
Copy Markdown
Owner

The state and transition dialogs become one vocabulary, end in a live preview drawn by the canvas's own code, and an edge carrying many rules stops drawing as a tower of single characters.

Transition dialog

  • From → To is one row at the top — the edge itself. To used to sit at the far end of the dialog with every field between.
  • Spaced by gaps, fixing Move sitting flush against To (.modal-row:last-of-type zeroed the last row of each section).
  • Reserved symbols say what they mean in the Read menu (Σ — any symbol, ⊔ — blank cell).
  • Move is a strip of arrows (← • →), keyboard-navigable.
  • Multi-tape rules are a table, one row per tape, instead of three stacked rows per tape (a four-tape rule was twelve rows tall).
  • Headings name what follows: a two-way head's Move is under Head; Output gets its own heading after a Stack/Head section. The rule picker says Copy from when adding. Focus starts on Read.

State dialog

  • Edit State, matching Edit Transition — as the title and as the first item of the state context menu (it said Rename, or Configure on Moore/Mealy).
  • Start / Accepting are toggle chips; hiding Accepting no longer leaves the word behind.
  • A Mealy state's outgoing outputs are a table.

Previews

Both dialogs draw what they will make with geometry.js's shapes, render.js's label writers and canvas.css's classes (new js/edit-preview.js), so theme, label style, name wrapping, bends, accepting rings, Moore outputs and parity badges follow the diagram. The transition preview shows every rule on the edge, marks the one being edited, and draws the reverse edge that bends it.

Dense edges

edgeLabelLines() decides what a label draws, per edge, at any machine size: rules differing only in the symbol read share a row (b, f, j → q3, braced when a comma follows), long lists wrap evenly, and past four lines the label ends in +k more. Four states over a 36-symbol alphabet (144 rules) never trips the large-machine profile, and drew every edge as a column of characters. The canvas, the layout's label sizes, the preview and the label editor all read it; double-clicking a merged line or +k more opens the dialog with exactly those rules.

Fixes

  • 2DFA / 2NFA / 2DFT: saving a rule unchanged added a write field these heads don't have (dialog and label editor alike).
  • Moore / Mealy: an output missing from the menu was replaced by the first option on an untouched save.
  • mtm-classic.json: one rule carried a stray symbol: "ε".

Verification

  • npm test: 2890 pass. New tests/edit-dialogs.test.js saves every rule and state of every example through the dialogs unchanged and requires them back identical; tests/dense-edges.test.js pins merge, wrap, cap and that every reader agrees.
  • Browser sweep over all machine types: both dialogs in edit and add mode, desktop and 390px — fields match each machine's declared fields, preview label rows match the canvas's, no overflow, no console errors. Checked under dark and Dracula themes.
  • npm run bench: no change beyond this machine's run-to-run noise (the untouched code showed the same spread).

…ense edge labels

The two editors become one vocabulary, drawn with the canvas's own code.

Transition dialog
- From → To is one row at the top, the edge itself; To used to sit at the
  far end of the dialog with every field between them.
- Spaced by gaps: `.modal-row:last-of-type` zeroed the last row of each
  section, so Move sat flush against To.
- Reserved symbols say what they mean in the Read menu (Σ — any symbol,
  ⊔ — blank cell); the value stays the bare symbol.
- Move is a strip of arrows (← • →) with arrow-key navigation; the select
  stays the field the form reads.
- A multi-tape rule is a table, one row per tape (read, write, move), with
  a key for the reserved symbols, instead of three stacked rows per tape.
- A two-way head's Move sits under "Head"; Output gets its own heading after
  a Stack or Head section. The rule picker says "Copy from" when adding.
- Focus starts on Read.

State dialog
- Titled Edit State, matching Edit Transition; the canvas context menu
  leads with Edit State (it said Rename, Configure on Moore/Mealy).
- Start and Accepting are toggle chips; hiding Accepting no longer leaves
  the word "Accept" behind.
- A Mealy state's outgoing outputs are a table (read, to, output).

Previews (js/edit-preview.js)
- Both dialogs end in a live drawing of what they will make, built from
  geometry.js's shapes, render.js's label writers and canvas.css's classes,
  so theme, label style, name wrapping, bends, badges and loops follow the
  diagram. The transition preview shows every rule on the edge with the one
  being edited marked, and the reverse edge that bends it.
- labelRestPoint() shares placeLabel's first candidate rather than copying it.

Dense edges
- A label line is no longer one rule. edgeLabelLines() merges rules that
  differ only in the symbol read (`b, f, j → q3`; braced when a comma
  follows), wraps long lists evenly, and caps a label at four lines with
  `+k more`. Decided per edge at any machine size: four states over a
  36-symbol alphabet drew every edge as a tower of characters, and the
  large-machine profile (a whole-machine performance line) never fires.
- The canvas, the layout's label sizes, the preview and the label editor
  all read it. Double-click on a one-rule line edits in place; on a merged
  line or `+k more` it opens the dialog with exactly those rules.

Fixes
- 2DFA/2NFA/2DFT: saving a rule unchanged (dialog or label editor) added a
  `write` the machine does not have.
- Moore and Mealy: an output missing from the menu was replaced by the first
  option on an untouched save.
- mtm-classic.json: one rule carried a stray `symbol: "ε"`.

Tests: tests/edit-dialogs.test.js saves every rule and state of every example
through the dialogs unchanged and requires them back identical;
tests/dense-edges.test.js pins the merge, wrap, cap and the readers' agreement.
Copilot AI balanced review requested due to automatic review settings October 8, 2026 08:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-08T09:06:14.162913Z 23980ae PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@thethinkmachine
thethinkmachine merged commit 6b202ea into main Oct 8, 2026
18 checks passed
@thethinkmachine
thethinkmachine deleted the feat/edit-dialogs branch October 8, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants