Skip to content

Qt-removal R7.5b-2: Orthogonal Routing canvas visual#149

Merged
dovvnloading merged 1 commit into
mainfrom
qt-removal/r7-5b2-orthogonal-routing
Jul 26, 2026
Merged

Qt-removal R7.5b-2: Orthogonal Routing canvas visual#149
dovvnloading merged 1 commit into
mainfrom
qt-removal/r7-5b2-orthogonal-routing

Conversation

@dovvnloading

@dovvnloading dovvnloading commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Summary

Ports the legacy scene's orthogonal routing toggle into the new React Flow canvas — the second of R7.5's three canvas-visual parity gaps (faded connections → orthogonal routing → smart guides, shipping in that order). When enabled, eligible connections render as right-angle "step" paths instead of curves.

This adds the first custom React Flow edge component in this codebase (OrthogonalEdge.tsx) plus a node-kind eligibility classifier ported from the legacy connection-type taxonomy (confirmed via fresh recon of graphlink_connections.py, not reimplemented from memory).

The deliberate translation call

Legacy's default connections used a horizontal mid-X step (start → midX,startY → midX,endY → end) because the legacy Qt canvas laid branches out left-to-right. Every node view in this app instead uses Handle target=Top / source=Bottom — branches lay out top-to-bottom — so the geometrically correct translation is the mid-Y step (start → startX,midY → targetX,midY → end), which is the shape legacy used for exactly one connection type (GroupSummaryConnectionItem, a vertical connection) rather than its own default. This is used as the general case here.

This was flagged in design review as the highest-judgment call in the spec and was verified three independent ways:

  1. Hand-derived path-string math for two distinct geometries, cross-checked against the test suite's own expected values.
  2. An adversarial reviewer independently re-traced the same math and the actual installed @xyflow/react@12.11.2 BaseEdge/EdgeProps shapes against the type definitions in node_modules (not just the source code), including tracing into React Flow's compiled EdgeWrapper to confirm type: undefined correctly falls through to the default bezier.
  3. Live browser verification against a real running backend (see test plan below) — the rendered SVG path was captured from the actual DOM and matches the formula digit-for-digit.

What changed

  • backend/canvas.py: orthogonal_routing: bool on SceneDocument, a setOrthogonalConnections intent (name matches the legacy GridControlBridge's own Slot name 1:1) — same shape as the existing setFadeConnections.
  • graphlink_app/graphlink_scene_payload.py: matching wire field on the codegen source-of-truth dataclass.
  • web_ui/src/app/canvas/OrthogonalEdge.tsx (new): the step-path edge component described above. Forwards style so it composes correctly with faded connections when both toggles are on.
  • web_ui/src/app/canvas/SceneCanvas.tsx: a new exported isOrthogonalEligible(sourceKind, targetKind) classifier — source "note" never eligible; target in {code, document, image, thinking} never eligible; target in {chat, conversation, html} eligible; every other kind (web_research/artifact/gitlink/pycoder/code_sandbox/frame/container/chart) explicitly defaulted not eligible, documented as a deliberate call since no legacy connection-type precedent exists for them. toFlowEdges now sets type: "orthogonal" per-edge when both the toggle is on and the pair is eligible; a new edgeTypes registration wires it into React Flow.
  • web_ui/src/app/chrome/ViewPopover.tsx: a new "Orthogonal Routing" checkbox, same pattern as the existing toggles.
  • web_ui/src/app/chrome/help-data/sections.ts: Help text updated (smart guides remains the one honestly-still-unavailable item).

Test plan

  • backend/tests/test_canvas.py: new intent test
  • SceneCanvas.test.tsx: full isOrthogonalEligible truth-table coverage (every documented rule), toFlowEdges type-assignment tests, and a composition test with fade-connections both enabled
  • OrthogonalEdge.test.tsx (new): asserts the exact rendered SVG path string for two distinct geometries, plus style forwarding
  • ViewPopover.test.tsx: new checkbox coverage
  • Full verification: 866 backend / 1140 frontend tests passing, typecheck/lint/build clean, codegen confirmed in sync, Qt-free burn-down gate unchanged
  • One adversarial review (backend/frontend/integration) that independently verified the @xyflow/react API usage against actual installed type definitions and re-ran the full test suite directly — zero confirmed defects
  • Live browser verification against a real running backend, completed post-open. The initial attempt found zero edges rendering; a follow-up investigation isolated the exact cause: the browser pane was hidden, so the page never composited a frame — empirically confirmed via document.visibilityState === "hidden", requestAnimationFrame never firing, document.timeline.currentTime frozen at 0, and a ResizeObserver on a plain resized div never delivering. React Flow measures nodes via ResizeObserver and skips edges whose nodes are unmeasured, so no frames → no edges (the identity viewport transform — fitView also never ran — corroborated this). Once the pane was displayed: frames flowed, nodes measured, and the orthogonal edge rendered with path M 361,197 L 361,286 L 661,286 L 661,375 — exactly the mid-Y formula (midY = 197 + (375−197)/2 = 286), under class react-flow__edge-orthogonal, with fitView completing. Toggling fade-connections on simultaneously dimmed the same path to opacity: 0.08, confirming the composition end-to-end. Screenshot verified: a clean right-angle elbow between the two chat nodes.

Ports the legacy scene's orthogonal-routing toggle into the React Flow
canvas - the second of R7.5's 3 remaining canvas-visual parity gaps.
Adds the first custom React Flow edge component in this codebase
(OrthogonalEdge.tsx), rendering a right-angle step path for eligible
node-kind pairs, plus a documented node-kind eligibility classifier
ported from the legacy connection-type taxonomy.

Deliberate translation, not a transcription: legacy's default
connections used a horizontal mid-X step (Qt's layout ran
left-to-right), but every node view in this app uses top-to-bottom
Handle layout, so the mid-Y variant (legacy's GroupSummaryConnectionItem
shape) is used as the general case here instead.

Same bare-bool/"scene"-topic shape as fade-connections; intent name
matches the legacy GridControlBridge's own Slot name 1:1.
@dovvnloading
dovvnloading merged commit 5a0d28c into main Jul 26, 2026
2 checks passed
@dovvnloading
dovvnloading deleted the qt-removal/r7-5b2-orthogonal-routing branch July 26, 2026 18:33
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.

1 participant