Support per-view connection boundary attachments in ordinary and state diagrams
This commit is contained in:
+49
-2
@@ -1167,8 +1167,9 @@ its authored sides and fractions. Frozen schema-1/schema-2 readers do not accept
|
||||
``port_anchors``; their explicit migration supplies an empty list.
|
||||
|
||||
Each ``routes`` entry is an EdgeRoute record with a required ``edge`` reference
|
||||
to an existing Relation or Trace, ``waypoints`` (default ``[]``), and ``label``
|
||||
(default ``none``). Route records have no separate UUID or alias. An edge occurs
|
||||
to an existing Relation or Trace, ``waypoints`` (default ``[]``), ``label``
|
||||
(default ``none``), and ``source_attachment`` / ``target_attachment`` (each
|
||||
default ``none``). Route records have no separate UUID or alias. An edge occurs
|
||||
at most once in a diagram's route list; different diagrams MAY store independent
|
||||
routes for the same edge. List order and explicit empty entries are retained by
|
||||
source and JSON round trips, although list order has no routing meaning. Edges
|
||||
@@ -1178,6 +1179,7 @@ need not currently be visible in their diagram.
|
||||
|
||||
routes [
|
||||
{ edge @report_exchange;
|
||||
source_attachment { side Bottom; offset 0.25; };
|
||||
waypoints [{ x 420; y 260; }, { x 690; y 260; }];
|
||||
label { fraction 0.55; offset { x 0; y -16; }; };
|
||||
}
|
||||
@@ -1196,6 +1198,51 @@ geometric routing difficulty is reported separately from structural validity.
|
||||
Each EdgeRoute counts as one record against ``ParseLimits.max_records``; pinned
|
||||
points are bounded by the per-route limit and aggregate input byte limits.
|
||||
|
||||
An attachment is an EdgeAttachment record with required ``side`` (Left, Right,
|
||||
Top, Bottom) and required finite binary32 ``offset`` from zero through one.
|
||||
Unknown fields, omitted nested fields and out-of-range offsets are structural
|
||||
errors (``invalid_attachment_offset`` for the latter). Attachments are bounded
|
||||
inline values, at most two per route, not additional graph objects or records.
|
||||
JSON uses the same field names, enum strings and number values. Omitted or null
|
||||
attachments mean automatic positioning; canonical compact source and JSON omit
|
||||
absent attachments. Earlier schema-3 input hydrates both fields as absent.
|
||||
|
||||
The end names designate stored source/target slots, even for undirected edges.
|
||||
These values MUST NOT change semantic endpoints, ports, ownership, type,
|
||||
orientation or identity. Each preference belongs to that edge end in that view:
|
||||
another view remains independent. It follows the current endpoint's projected
|
||||
boundary under movement, resize or semantic reconnect; reconnect preserves the
|
||||
preference, as it preserves authored bends. The fraction does not identify the
|
||||
previous semantic endpoint. Deletion/reidentification of the edge follows the
|
||||
existing whole-route rules; moving, hiding or replacing its placement retains
|
||||
the preference. Removing one attachment restores that end's automatic position
|
||||
without changing bends, labels or the opposite attachment.
|
||||
|
||||
For Left/Right, offset gives the Y fraction of the complete projected bounding
|
||||
box; for Top/Bottom it gives the X fraction. The attachment intersects the painted
|
||||
shape along that cardinal scan line. Rounded cards use radius 10, limited by half
|
||||
their width/height; Regions and fork/join bars are rectangles. State circles use
|
||||
their ellipse boundary and Choice uses its diamond boundary. More precisely, let
|
||||
``t = 2 * offset - 1`` and ``D`` be width for Left/Right or height for Top/Bottom.
|
||||
The inset from the selected bounding side is ``D/2 * (1 - sqrt(1-t*t))`` for an
|
||||
ellipse and ``D/2 * abs(t)`` for a diamond. A Terminate X uses the outermost
|
||||
painted-stroke intersection, inset ``D * min(offset, 1-offset)``. Zero and one
|
||||
are valid; different side/fraction pairs can describe the same painted point.
|
||||
Routing leads extend in the selected cardinal direction beyond the bounding box
|
||||
before turning. Source/API fractions retain their precision; pointer editing
|
||||
snaps fractions to hundredths without changing the stored semantic record.
|
||||
|
||||
An actual semantic Port remains authoritative, including when projection hides
|
||||
its port marker. An edge attachment on that end is retained but dormant; use
|
||||
the port's own placement anchor to move a port. When folding promotes an endpoint
|
||||
to an ancestor, all authored route data is suspended and resumes on expansion.
|
||||
Geometric difficulty MUST NOT discard preferences. Coincident authored self-loop
|
||||
tips retain their positions with an external loop and a routing warning; the
|
||||
editor must offer an explicit way to choose either end even when handles overlap.
|
||||
Internal state transitions have no external connection. Process's generated
|
||||
topology and Scenario's lifeline/activation/time-derived tips are not consumers
|
||||
of these diagram route fields; this feature does not redefine their semantics.
|
||||
|
||||
``SetEdgeRoute { diagram, route }`` upserts an entry by edge identity, retaining
|
||||
the order and contents of unrelated entries. ``RemoveEdgeRoute { diagram, edge }``
|
||||
removes it; removing an absent entry is a no-op for an existing diagram and edge.
|
||||
|
||||
Reference in New Issue
Block a user