summaryrefslogtreecommitdiff
path: root/doc/sequence.pic
diff options
context:
space:
mode:
Diffstat (limited to 'doc/sequence.pic')
-rw-r--r--doc/sequence.pic486
1 files changed, 486 insertions, 0 deletions
diff --git a/doc/sequence.pic b/doc/sequence.pic
new file mode 100644
index 0000000..bd8764b
--- /dev/null
+++ b/doc/sequence.pic
@@ -0,0 +1,486 @@
+#/usr/bin/pic2plot -Tps
+#
+# Pic macros for drawing UML sequence diagrams
+#
+# (C) Copyright 2004-2005 Diomidis Spinellis.
+#
+# Permission to use, copy, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+# $Id: sequence.pic 1.10 2005/10/19 18:36:08 dds Exp $
+#
+
+
+# Default parameters (can be redefined)
+
+# Spacing between messages
+spacing = 0.25;
+# Active box width
+awid = .1;
+# Box height
+boxht = 0.3;
+# Commend folding
+corner_fold=awid
+# Comment distance
+define comment_default_move {up 0.25 right 0.25};
+# Comment height
+comment_default_ht=0.5;
+# Comment width
+comment_default_wid=1;
+#Default Object width
+object_default_width = 0.75
+
+# set 2 to the width of a string(text)
+define getwidth {
+ print "getwidth(" $1
+ sh X
+ for i in $1; do
+ foo=$i; bar=0;
+ if (( ${#i} > $bar)); then
+ bar=${#i};
+ fi;
+ echo "$i $bar" >> test;
+ done;
+ echo " w= ($bar * 0.75) / 6;" > .sequence.temp
+ cat .sequence.temp >> log.sh
+ X
+ copy ".sequence.temp";
+ if (w < object_default_width) then {
+ w = object_default_width;
+ }
+ print "width of " $1" is " w
+}
+
+# Create a new object with custom width (name, text)
+define object {
+ getwidth($2);
+ $1: box $2 wid w; move;
+
+ # Could also underline text with \mk\ul\ul\ul...\rt
+ {
+ line from $1.w + (.1, -.07) to $1.e + (-.1, -.07);
+ }
+ move to $1.e;
+ move right;
+ # Active is the level of activations of the object
+ # 0 : inactive : draw thin line swimlane
+ # 1 : active : draw thick swimlane
+ # > 1: nested : draw nested swimlane
+ active_$1 = 0;
+ lifestart_$1 = $1.s.y;
+}
+
+# Create a new external actor(name,text)
+define actor {
+ getwidth($2)
+ $1: [
+ XSEQC: circle rad w;
+ XSEQL: line from XSEQC.s down 2*w;
+ line from XSEQL.start - (.15,.02) to XSEQL.start + (.15,-.02);
+ XSEQL1: line from XSEQL.end left .02+w down .15;
+ XSEQL2: line from XSEQL.end right .0+w down .15;
+ line at XSEQC.n invis "" "" "" $2;
+ ]
+ move to $1.e;
+ move right;
+ active_$1 = 0;
+ lifestart_$1 = $1.s.y - .05;
+}
+
+# Create a new placeholder object(name)
+define placeholder_object {
+ $1: box invisible;
+ move;
+ move to $1.e;
+ move right;
+ active_$1 = 0;
+ lifestart_$1 = $1.s.y;
+}
+
+define pobject {
+ placeholder_object($1);
+}
+
+define extend_lifeline {
+ if (active_$1 > 0) then {
+ # draw the left edges of the boxes
+ move to ($1.x - awid/2, Here.y);
+ for level = 1 to active_$1 do {
+ line from (Here.x, lifestart_$1) to Here;
+ move right awid/2
+ }
+
+ # draw the right edge of the innermost box
+ move right awid/2;
+ line from (Here.x, lifestart_$1) to Here;
+ } else {
+ line from ($1.x, lifestart_$1) to ($1.x, Here.y) dashed;
+ }
+ lifestart_$1 = Here.y;
+}
+
+# complete(name)
+# Complete the lifeline of the object with the given name
+define complete {
+ extend_lifeline($1)
+ if (active_$1) then {
+ # draw bottom of all active boxes
+ line right ((active_$1 + 1) * awid/2) from ($1.x - awid/2, Here.y);
+ }
+}
+
+# Draw a message (from_object,to_object,label)
+define message {
+ down;
+ move spacing;
+ getwidth($3);
+ # adjust object position so text fits
+ # add buffer of awid on either side for clarity
+
+ # Adjust so that lines and arrows do not fall into the
+ # active box. Should be .5, but the arrow heads tend to
+ # overshoot.
+ if ($1.x <= $2.x) then {
+ off_from = awid * .6;
+ off_to = -awid * .6;
+ } else {
+ off_from = -awid * .6;
+ off_to = awid * .6;
+ }
+ # add half a box width for each level of nesting
+ if (active_$1 > 1) then {
+ off_from = off_from + (active_$1 - 1) * awid/2;
+ }
+
+ # add half a box width for each level of nesting
+ if (active_$2 > 1) then {
+ off_to = off_to + (active_$2 - 1) * awid/2;
+ }
+
+ if ($1.x == $2.x) then {
+ arrow from ($1.x + off_from, Here.y) right then down .25 then left $3 ljust " " " " " " ;
+ } else {
+ arrow from ($1.x + off_from, Here.y) to ($2.x + off_to, Here.y);
+ #draw the text seperatly to work around arrow bug
+ #add a small offset of awid for clarity
+ if ($1.x < $2.x) then {
+ sh X
+ rm .sequence.temp;
+ c=0
+ for i in $3; do
+ ((c++));
+ if ((c>1)); then
+ echo -n " \"$i\" below ljust " >> .sequence.temp;
+ else
+ echo -n " \"$i\" above ljust " >> .sequence.temp;
+ echo " at ($1.x + off_from + awid, Here.y)" >> .sequence.temp;
+ fi
+ done;
+ if ((c>1)); then
+ echo " at ($1.x + off_from + awid, Here.y - $((c>1?c-2:1))*8/72)" >> .sequence.temp;
+ fi
+ cat .sequence.temp >> log.sh
+ X
+ copy ".sequence.temp"
+ } else {
+ sh X
+ rm .sequence.temp;
+ c=0
+ for i in $3; do
+ ((c++));
+ if ((c>1)); then
+ echo -n " \"$i\" below rjust " >> .sequence.temp;
+ else
+ echo -n " \"$i\" above rjust " >> .sequence.temp;
+ echo " at ($1.x + off_from - awid, Here.y)" >> .sequence.temp;
+ fi
+ done;
+ if ((c>1)); then
+ echo " at ($1.x + off_from - awid, Here.y - $((c>1?c-2:1))*8/72)" >> .sequence.temp;
+ fi
+ cat .sequence.temp >> log.sh
+ X
+ copy ".sequence.temp"
+ }
+ }
+}
+
+# Display a lifeline constraint(object,label)
+define lifeline_constraint {
+ off_from = awid;
+ # add half a box width for each level of nesting
+ if (active_$1 > 1) then {
+ off_from = off_from + (active_$1 - 1) * awid/2;
+ }
+
+ box at ($1.x + off_from, Here.y) invis $2 ljust " " ;
+}
+
+define lconstraint {
+ lifeline_constraint($1,$2);
+}
+
+# Display an object constraint(label)
+# for the last object drawn
+define object_constraint {
+ { box invis with .s at last box .nw $1 ljust; }
+}
+
+define oconstraint {
+ object_constraint($1);
+}
+
+# Draw a creation message(from_object,to_object,object_label)
+define create_message {
+ down;
+ move spacing;
+ if ($1.x <= $2.x) then {
+ off_from = awid * .6;
+ off_to = -boxwid * .51;
+ } else {
+ off_from = -awid * .6;
+ off_to = boxwid * .51;
+ }
+
+ # add half a box width for each level of nesting
+ if (active_$1 > 1) then {
+ off_from = off_from + (active_$1 - 1) * awid/2;
+ }
+
+ #we shouldnt need to adjust object positioning for this message
+ #as it fits within the minimal defaults
+ # See comment in destroy_message
+ XSEQA: arrow from ($1.x + off_from, Here.y) to ($2.x + off_to, Here.y) " ";
+ #draw the text seperatly to work around arrow bug
+ #add a small offset of awid for clarity
+ if ($1.x < $2.x) then {
+ "«create»" above ljust at ($1.x + off_from + awid, Here.y) ;
+ } else {
+ "«create»" above rjust at ($1.x + off_from - awid, Here.y) ;
+ }
+
+ getwidth($3);
+ if ($1.x <= $2.x) then {
+ { XSEQB: box $3 wid w with .w at XSEQA.end; }
+ } else {
+ { XSEQB: box $3 wid w with .e at XSEQA.end; }
+ }
+ {
+ line from XSEQB.w + (.1, -.07) to XSEQB.e + (-.1, -.07);
+ }
+ lifestart_$2 = XSEQB.s.y;
+ move (spacing + boxht) / 2;
+}
+
+define cmessage {
+ create_message($1,$2,$3);
+}
+
+# Draw an X for a given object
+define drawx {
+ {
+ line from($1.x - awid, lifestart_$1 - awid) to ($1.x + awid, lifestart_$1 + awid);
+ line from($1.x - awid, lifestart_$1 + awid) to ($1.x + awid, lifestart_$1 - awid);
+ }
+}
+
+# Draw a destroy message(from_object,to_object)
+define destroy_message {
+ down;
+ move spacing;
+ # The troff code is \(Fo \(Fc
+ # The groff code is also \[Fo] \[Fc]
+ # The pic2plot code is \Fo \Fc
+ # See http://www.delorie.com/gnu/docs/plotutils/plotutils_71.html
+ # To stay compatible with all we have to hardcode the characters
+ message($1,$2,"«destroy»");
+ complete($2);
+ drawx($2);
+}
+
+define dmessage {
+ destroy_message($1,$2);
+}
+
+# An object deletes itself: delete(object)
+define delete {
+ complete($1);
+ lifestart_$1 = lifestart_$1 - awid;
+ drawx($1);
+}
+
+# Draw a message return(from_object,to_object,label)
+define return_message {
+ down;
+ move spacing;
+ # See comment in message
+ if ($1.x <= $2.x) then {
+ off_from = awid * .6;
+ off_to = -awid * .6;
+ } else {
+ off_from = -awid * .6;
+ off_to = awid * .6;
+ }
+
+ # add half a box width for each level of nesting
+ if (active_$1 > 1) then {
+ off_from = off_from + (active_$1 - 1) * awid/2;
+ }
+
+ # add half a box width for each level of nesting
+ if (active_$2 > 1) then {
+ off_to = off_to + (active_$2 - 1) * awid/2;
+ }
+
+ arrow from ($1.x + off_from, Here.y) to ($2.x + off_to, Here.y) dashed $3 " ";
+}
+
+define rmessage {
+ return_message($1,$2,$3);
+}
+
+# Object becomes active
+# Can be nested to show recursion
+define active {
+ extend_lifeline($1);
+ # draw top of new active box
+ line right awid from ($1.x + (active_$1 - 1) * awid/2, Here.y);
+ active_$1 = active_$1 + 1;
+}
+
+# Object becomes inactive
+# Can be nested to show recursion
+define inactive {
+ extend_lifeline($1);
+ active_$1 = active_$1 - 1;
+ # draw bottom of innermost active box
+ line right awid from ($1.x + (active_$1 - 1) * awid/2, Here.y);
+}
+
+# Time step
+# Useful at the beginning and the end
+# to show object states
+define step {
+ down;
+ move spacing;
+}
+
+# Switch to asynchronous messages
+define async {
+ arrowhead = 0;
+ arrowwid = arrowwid * 2;
+}
+
+# Switch to synchronous messages
+define sync {
+ arrowhead = 1;
+ arrowwid = arrowwid / 2;
+}
+
+# same as lifeline_constraint, but Text and empty string are exchanged.
+define lconstraint_below{
+ off_from = awid;
+ # add half a box width for each level of nesting
+ if (active_$1 > 1) then {
+ off_from = off_from + (active_$1 - 1) * awid/2;
+ }
+
+ box at ($1.x + off_from, Here.y) invis "" $2 ljust;
+}
+
+# begin_frame(left_object,name,label_text);
+define begin_frame {
+ # The lifeline will be cut here
+ extend_lifeline($1);
+ # draw the frame-label
+ $2: box $3 invis with .n at ($1.x, Here.y);
+ d = $2.e.y - $2.se.y;
+ line from $2.ne to $2.e then down d left d then to $2.sw;
+ # continue the lifeline below the frame-label
+ move to $2.s;
+ lifestart_$1 = Here.y;
+}
+
+# end_frame(right_object,name);
+define end_frame {
+ # dummy-box for the lower right corner:
+ box invis "" with .s at ($1.x, Here.y);
+ # draw the frame
+ frame_wid = last box.se.x - $2.nw.x
+ frame_ht = - last box.se.y + $2.nw.y
+ box with .nw at $2.nw wid frame_wid ht frame_ht;
+ # restore Here.y
+ move to last box.s;
+}
+
+# comment(object,[name],[line_movement], [box_size] text);
+define comment {
+ old_y = Here.y
+ # draw the first connecting line, at which's end the box wil be positioned
+ move to ($1.x, Here.y)
+ if "$3" == "" then {
+ line comment_default_move() dashed;
+ } else {
+ line $3 dashed;
+ }
+
+ # draw the box, use comment_default_xx if no explicit
+ # size is given together with the text in parameter 4
+ old_boxht=boxht;
+ old_boxwid=boxwid;
+ boxht=comment_default_ht;
+ boxwid=comment_default_wid;
+ if "$2" == "" then {
+ box invis $4;
+ } else {
+ $2: box invis $4;
+ }
+ boxht=old_boxht;
+ boxwid=old_boxwid;
+
+ # draw the frame of the comment
+ line from last box.nw \
+ to last box.ne - (corner_fold, 0) \
+ then to last box.ne - (0, corner_fold) \
+ then to last box.se \
+ then to last box.sw \
+ then to last box.nw ;
+ line from last box.ne - (corner_fold, 0) \
+ to last box.ne - (corner_fold, corner_fold) \
+ then to last box.ne - (0, corner_fold) ;
+
+ # restore Here.y
+ move to ($1.x, old_y)
+}
+
+# connect_to_comment(object,name);
+define connect_to_comment {
+ old_y = Here.y
+ # start at the object
+ move to ($1.x, Here.y)
+ # find the best connection-point of the comment to use as line-end
+ if $1.x < $2.w.x then {
+ line to $2.w dashed;
+ } else {
+ if $1.x > $2.e.x then {
+ line to $2.e dashed;
+ } else {
+ if Here.y < $2.s.y then {
+ line to $2.s dashed;
+ } else {
+ if Here.y > $2.n.y then {
+ line to $2.n dashed;
+ }
+ }
+ }
+ }
+ # restore Here.y
+ move to ($1.x, old_y)
+}