8.5 KiB
Scenario message gesture critique — source only
Recommendation: choose A as the first candidate to evaluate: ordinary arrow/label drag changes spacing; semantic reorder is a separately identified action. This is a proposed product policy, not established user intent or runtime acceptance. Do not ship A by simply relegating the existing gesture to its current small left-hand handle. One bounded native workflow experiment is needed for discoverability and boundary feedback before acceptance; B need not be implemented in full merely to make that comparison.
Facts and correction of the initial premise
The requirements in harness/scenario-layout-design.md (Movement policy still to evaluate; Projection and editing lifecycle) require direct editing, explicit view identity, one checked transaction, no accidental operand reparenting, exact no-op/cancel behavior and graphical/text/API parity. They explicitly leave A versus B unsettled.
Current ordinary dragging already reorders: immutable695685a behavior.rs:1886–1901 captures SequencePress::Reorder for any hit whose ID has a row, falling back to the selected handle;1813 uses a three-screen-pixel threshold,1972–1998 selects on unmoved release and publishes Reorder on moved release. The current renderer readback has the same branch at1923–1938. Thus A deliberately changes an existing body/label gesture. scenario.rs:1071–1096 preserves the parent sequence and validates SetSteps with execute_batch; it is not an independent send/receive reorder command.
The existing handle is world rect x6..28, y=row−12..row+12 (behavior.rs:1660–1665), drawn inside camera translation and scale. At scale0.05 its body is only1.1×1.2 screen pixels. Panning can place x6 entirely outside the visible viewport even while an authored negative-x or far-right message is visible. Selection-only ↕ has no inherently distinct meaning from “move vertically.” These are concrete reasons that keeping the current handle alone does not establish usable explicit reorder.
Consequential comparison
| Workflow | A: spacing + explicit reorder | B: body drag switches into reorder |
|---|---|---|
| Spread two adjacent messages for readability | Directly expresses the requested presentation edit. Must show a truthful feasible boundary instead of silently clamping or moving unrelated authored anchors. | Direct while inside the interval; becomes a semantic edit at the point where the user is most likely to seek more space. |
| Accidental crossing in a dense/Fit view | Steps and operand remain invariant; preview can reject the infeasible candidate while explaining why. | A three-pixel movement can span several rows at small zoom. A visual threshold crossing cannot establish intent to change all representations of the scenario. Requires conspicuous mode feedback and stable hysteresis even for valid changes. |
| Deliberate reorder | Extra explicit action and migration from the current body gesture; must be discoverable and available near the selection or in a conventional command. | Preserves existing motor behavior and enables a continuous gesture. However, deciding whether final y means spacing or a new slot adds ambiguity; validation after release is too late to explain preview semantics. |
| Two views of one owner | A spacing drag modifies only the chosen Diagram. Explicit reorder still changes shared semantics in both views. | A drag started for one layout may change shared semantics in both views. Atomic history does not make that side effect local. |
A is preferred because “move this arrow to improve this arrangement” has an unambiguous view-local meaning, while B infers a semantic instruction from travel distance. This inference is not supported by the movement requirement. B remains a reasonable alternative if a workflow experiment demonstrates that explicit reorder is a substantial obstacle despite a visible command, and users understand its shared-model consequences. Existing implementation alone does not decide the issue.
Required semantic and interaction boundaries
- A preserves the existing steps and parents. B must preview a proposed whole-occurrence SetSteps plus active-view layout as one transaction, validate that combined project, and never infer operand reparenting. No exact minimum gap, collision policy or arbitrary independent send/receive order has been adopted. Same-scope vertical limits must account for actual receive geometry, not just sorted row/send y.
- Call/Reply and Create/Delete impose real model/lifetime constraints; self-call receive is below send and activation starts there. A spacing preview must rerun the same geometry/lifecycle/activation pipeline. B cannot silently move a partner Call/Reply, creation/deletion or child occurrence to make an invalid crossing valid. Warning-bearing models need truthful warning display; successful validation alone does not demonstrate the user intended the new chronology.
- Hit identity is not enough to define a spacing gesture. Scene::hit at1667 onward returns a call ID for an activation shoulder as well as for its arrow/label. A naive replacement of the current rows.contains_key branch would move a whole message when the user drags an activation bar. Distinguish arrow/label hit roles from activation, marker, handle and other shapes; this is a required narrow interaction seam, not a reason to redesign semantic identity.
- Existing release cancellation covers bounds, wheel, unfocus and Escape. New previews must additionally retain Diagram/derived-view identity and view-visit context. Switching A→B→A views of one owner must invalidate the old gesture. A3px return-to-origin gesture is still a final no-op and must not erase latent intent, create a view or discard redo history.
- Structurally admitted imported geometry can cross rows or exceed the current projector's supported scope. Neither gesture may normalize it merely on click/zero-motion release, or derive a semantic reorder from its already crossed appearance. Offer an explicit repair path when a nonzero candidate cannot be realized; a failed preview must leave accepted geometry/source intact.
One bounded experiment and five failure probes
Use one matched native candidate with A, an explicitly named Reorder command visible with the selection, and the existing handle only as an additional shortcut. Record actual preview, resulting source/steps/layout, both views, Undo and cancel; do not claim usability from a scripted pixel trace alone. Give an unprompted “make this diagram easier to read, then swap these two messages” task to the user or an independent workflow evaluator. If reorder cannot be found without explaining ↕, or spacing looks broken at a boundary, A fails its first acceptance attempt.
- Two asynchronous arrows near each other: drag body and long label slightly apart, then overshoot the neighbor at Fit zoom. Expect one local layout edit for an admitted release; a visibly rejected crossing preserves steps/source and offers the explicit reorder action. No unexplained jump or implicit neighboring-anchor rewrite.
- Deliberately swap two same-parent arrows, including a visible selected arrow whose world x is negative and a horizontally scrolled far-right arrow. Find and use Reorder without returning the camera to x0. Same-parent steps change once; crossing an ALT/PAR operand boundary is visibly refused.
- Self Call send610/receive634 with Reply send728, then a receiver Delete: space the Call and inspect actual receive/activation/Reply/lifetime geometry; attempt invalid explicit reorder across Reply/Delete. Reject unsupported candidates without losing valid spacing/source. Clicking or dragging an exposed activation shoulder must retain its documented selection behavior.
- Two differently arranged saved views of one owner: space one occurrence in view A; verify B's authored coordinates and semantic steps unchanged. Explicitly reorder in A and inspect shared semantics plus retained B layout. Undo once restores the complete transaction, including exact prior overrides. A stale release after A→B→A edits neither view.
- Start from a source-admitted crossed/latent coordinate and a live redo branch: click, Escape after motion, return exactly to origin, release outside, and switch views during capture. No source/revision/redo change. A real valid repair drag produces exactly one entry.
Limits: this review ran no GUI or compiler and implements no gesture. Body-or-handle behavior was checked against immutable695685a and an explicitly identified current readback; the new renderer remains in development. Candidate policy must be adopted explicitly before implementation.