cpsa-2.1.2: doc/strands.mp
% Strand macros
%% John D. Ramsdell--May 2008,
%% The MITRE Corporation, Bedford, MA.
% For simple drawings, use the strand macro.
% Use these macros when drawing strand edges. The cmstrands package
% redefines these two macros.
% Draw a message edge
def drawmsg(expr p) =
drawarrow p;
enddef;
% Draw a strand succession edge. The arrow head is drawn, not filled.
% Based on "Hints and Tricks" in TUGboat, Volume 19 (1998), No. 2, by
% Jeremy Gibbons.
def drawsucc(expr p) =
draw arrowhead p;
path q;
q := fullcircle scaled (2*ahlength)
shifted (point (length p) of p);
numeric tp, tq;
(tp,tq) = p intersectiontimes q;
draw subpath (0, tp) of p;
enddef;
% Draw a message edge with a dashed line. Used sometimes for when the
% source and the distination message differ.
def drawdashedmsg(expr p) =
drawarrow p dashed evenly scaled 3;
enddef;
% Strand drawing macros
% Box the nodes of a strand. The origin of the strand is the center
% of the last strand node. The name is a picture for the first node,
% and node is a picture for the successive nodes.
vardef boxstrand@#(expr height, origin, name, node) =
boxit.@#1(name);
for i = 2 upto height:
boxit.@#[i](node);
xpart @#[i-1].s = xpart @#[i].n;
endfor;
@#[height].c = origin;
enddef;
% Space a pair of strand nodes using the given height and separation
% delta.
vardef spacestrand@#(expr pos, delta) =
ypart @#[pos].s = delta + ypart @#[pos+1].n;
enddef;
% Layout strand by making the distance been successive nodes the given
% separation delta.
vardef layoutstrand@#(expr height, delta) =
for i = 1 upto height - 1:
spacestrand@#(i, delta);
endfor;
enddef;
% Link the nodes of a strand.
vardef linkstrand@#(expr height) =
for i = 2 upto height:
drawsucc(@#[i-1].s -- @#[i].n);
endfor;
enddef;
% Draw a strand with equally spaced nodes. The origin of the strand
% is the center of the last strand node. The the distance between
% successive nodes is delta. The name is a picture for the first
% node, and node is a picture for the successive nodes.
% A strand is drawn bottom up because the size of the label in the
% first box may vary.
vardef strand@#(expr height, origin, delta, name, node) =
boxstrand@#(height, origin, name, node);
layoutstrand@#(height, delta);
for i = height downto 1:
draw pic @#[i];
endfor;
linkstrand@#(height);
enddef;
% layout a strand but don't draw it.
vardef phantomstrand@#(expr height, origin, delta, name, node) =
boxstrand@#(height, origin, name, node);
layoutstrand@#(height, delta);
for i = height downto 1:
fixsize(@#[i]);
endfor;
enddef;
% Event macros used while displaying roles.
% Draw an inbound term at a given strand position.
% The width is the length of the first arrow.
vardef inbnd@#(expr pos, width, term) =
pair d;
d = (xpart @#[1].e + width, ypart @#[pos].e);
drawmsg(d .. @#[pos].e);
label.rt(term, d);
enddef;
% Draw an outbound term at a given strand position.
% The width is the length of the first arrow.
vardef outbnd@#(expr pos, width, term) =
pair d;
d = (xpart @#[1].e + width, ypart @#[pos].e);
drawmsg(@#[pos].e .. d);
label.rt(term, d);
enddef;
% Reverse versions:
vardef rinbnd@#(expr pos, width, term) =
pair d;
d = (xpart @#[1].w - width, ypart @#[pos].w);
drawmsg(d .. @#[pos].w);
label.lft(term, d);
enddef;
vardef routbnd@#(expr pos, width, term) =
pair d;
d = (xpart @#[1].w - width, ypart @#[pos].w);
drawmsg(@#[pos].w .. d);
label.lft(term, d);
enddef;