Single source of truth for the PhoenixLiveGantt connector path string format.
Connector paths come in two shape families:
:forward — "M x1 y1 H mid V y2 H arrow_stop"
3 segments. Used by FS / SS / FF / SF when there's room
for a single trunk between source and target.
:detour — "M x1 y1 H stem_out V detour_y H stem_in V y2 H arrow_stop"
5 segments. Used by :fs when the forward path can't be
laid out cleanly (target before source, tight gap, or
trunk would pierce intermediate bars).Owning both the BUILDER and the PARSER here keeps PhoenixLiveGantt (which
emits paths) and PhoenixLiveGantt.Inspector (which parses them for tests
and the dump task) in sync — if a new shape family is added or the
format changes, both update at once.
All numeric inputs/outputs are integers. Decimal coords aren't emitted
by the renderer today; if that ever changes, extend parse/1.
Summary
Functions
Build the 5-segment detour path string.
Build the 3-segment forward path string.
Parse a path d-string into a structured segment map. Returns one of
All absolute {x, y} points of an M/H/V path, in order. Works for any
shape the renderer emits — the 3-segment forward, 5-segment detour, and the
consolidator's N-segment jog — not just the two canonical regex forms.
Terminal point + final-segment direction of any M/H/V path. The
direction is where the LAST segment travels (:east/:west for a horizontal
finish, :south/:north for vertical, nil for a zero-length/degenerate
finish). Used to place the arrowhead overlay on the shaft's true end.
Functions
@spec detour( integer(), integer(), integer(), integer(), integer(), integer(), integer() ) :: String.t()
Build the 5-segment detour path string.
iex> PathFormat.detour(100, 20, 130, 80, 160, 100, 180)
"M 100 20 H 130 V 80 H 160 V 100 H 180"
Build the 3-segment forward path string.
iex> PathFormat.forward(100, 20, 130, 60, 180)
"M 100 20 H 130 V 60 H 180"
Parse a path d-string into a structured segment map. Returns one of:
%{kind: :forward, x1: ..., y1: ..., mid: ..., y2: ..., arrow_stop: ...}
%{kind: :detour, x1: ..., y1: ..., stem_out: ..., detour_y: ...,
stem_in: ..., y2: ..., arrow_stop: ...}
%{kind: :unknown, raw: <input>}All coords are integers (or floats if a decimal slips into the input).
All absolute {x, y} points of an M/H/V path, in order. Works for any
shape the renderer emits — the 3-segment forward, 5-segment detour, and the
consolidator's N-segment jog — not just the two canonical regex forms.
iex> PathFormat.points("M 100 20 H 130 V 60 H 180")
[{100, 20}, {130, 20}, {130, 60}, {180, 60}]
Terminal point + final-segment direction of any M/H/V path. The
direction is where the LAST segment travels (:east/:west for a horizontal
finish, :south/:north for vertical, nil for a zero-length/degenerate
finish). Used to place the arrowhead overlay on the shaft's true end.
iex> PathFormat.terminal("M 100 20 H 130 V 60 H 180")
%{x: 180, y: 60, dir: :east}