final
[bsc-thesis1415.git] / thesis / pgf-umlsd.sty
1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 % Start of pgf-umlsd.sty
3 %
4 % Some macros for UML Sequence Diagrams.
5 % Home page of project: http://pgf-umlsd.googlecode.com/
6 % Author: Xu Yuan <xuyuan.cn@gmail.com>, Southeast University, China
7 % Contributor: Nobel Huang <nobel1984@gmail.com>, Southeast University, China
8 %
9 % History:
10 % v0.7 2012/03/05
11 % - unify interface of call and callself
12 % - non-instantaneous message
13 % - bugfix: conflits with tikz library backgrounds
14 % v0.6 2011/07/27
15 % - Fix Issue 6 reported by frankmorgner@gmail.com
16 % - diagram without a thread
17 % - allows empty diagram
18 % - New manual
19 % v0.5 2009/09/30 Fix Issue 2 reported by vlado.handziski
20 % - Nested callself is supported
21 % - Rename sdloop and sdframe to sdblock
22 % v0.4 2008/12/08 Fix Issue 1 reported by MathStuf:
23 % Nested sdloop environment hides outer loop
24 % v0.3 2008/11/10 in Berlin, fix for the PGF cvs version:
25 % - the list items in \foreach are not evaluated by default now,
26 % the `evaluate' opinion should be used
27 % v0.2 2008/03/20 create project at http://pgf-umlsd.googlecode.com/
28 % - use `shadows' library
29 % Thanks for Dr. Ludger Humbert's <humbert@uni-wuppertal.de> feedback!
30 % - reduce the parameter numbers, the user can write the content
31 % of instance (such as no colon)
32 % - the user can redefine the `inststyle'
33 % - new option: switch underlining of the instance text
34 % - new option: switch rounded corners
35 % v0.1 2008/01/25 first release at http://www.fauskes.net/pgftikzexamples/
36 %
37
38 \NeedsTeXFormat{LaTeX2e}[1999/12/01]
39 \ProvidesPackage{pgf-umlsd}[2011/07/27 v0.6 Some LaTeX macros for UML
40 Sequence Diagrams.]
41
42 \RequirePackage{tikz}
43 \usetikzlibrary{arrows,shadows}
44
45 \RequirePackage{ifthen}
46
47 % Options
48 % ? the instance name under line ?
49 \newif\ifpgfumlsdunderline\pgfumlsdunderlinetrue
50 \DeclareOption{underline}{\pgfumlsdunderlinetrue}
51 \DeclareOption{underline=true}{\pgfumlsdunderlinetrue}
52 \DeclareOption{underline=false}{\pgfumlsdunderlinefalse}
53 % ? the instance box with rounded corners ?
54 \newif\ifpgfumlsdroundedcorners\pgfumlsdroundedcornersfalse
55 \DeclareOption{roundedcorners}{\pgfumlsdroundedcornerstrue}
56 \DeclareOption{roundedcorners=true}{\pgfumlsdroundedcornerstrue}
57 \DeclareOption{roundedcorners=false}{\pgfumlsdroundedcornersfalse}
58 \ProcessOptions
59
60 % new counters
61 \newcounter{preinst}
62 \newcounter{instnum}
63 \newcounter{threadnum}
64 \newcounter{seqlevel} % level
65 \newcounter{callevel}
66 \newcounter{callselflevel}
67 \newcounter{blocklevel}
68
69 % new an instance
70 % Example:
71 % \newinst[edge distance]{var}{name:class}
72 \newcommand{\newinst}[3][0.2]{
73 \stepcounter{instnum}
74 \path (inst\thepreinst.east)+(#1,0) node[inststyle] (inst\theinstnum)
75 {\ifpgfumlsdunderline
76 \underline{#3}
77 \else
78 #3
79 \fi};
80 \path (inst\theinstnum)+(0,-0.5*\unitfactor) node (#2) {};
81 \tikzstyle{instcolor#2}=[]
82 \stepcounter{preinst}
83 }
84
85 % new an instance thread
86 % Example:
87 % \newinst[color]{var}{name}{class}
88 \newcommand{\newthread}[3][gray!30]{
89 \newinst{#2}{#3}
90 \stepcounter{threadnum}
91 \node[below of=inst\theinstnum,node distance=0.8cm] (thread\thethreadnum) {};
92 \tikzstyle{threadcolor\thethreadnum}=[fill=#1]
93 \tikzstyle{instcolor#2}=[fill=#1]
94 }
95
96 % draw running (thick) line, should not call directly
97 \newcommand*{\drawthread}[2]{
98 \begin{pgfonlayer}{umlsd@threadlayer}
99 \draw[threadstyle] (#1.west) -- (#1.east) -- (#2.east) -- (#2.west) -- cycle;
100 \end{pgfonlayer}
101 }
102
103 % a function call
104 % Example:
105 % \begin{call}[height]{caller}{function}{callee}{return}
106 % \end{call}
107 \newenvironment{call}[5][1]{
108 \ifthenelse{\equal{#2}{#4}}
109 {
110 \begin{callself}[#1]{#2}{#3}{#5}
111 }
112 {
113 \begin{callanother}[#1]{#2}{#3}{#4}{#5}
114 }
115 }
116 {
117 \ifthenelse{\equal{\f\thecallevel}{\t\thecallevel}}
118 {
119 \end{callself}
120 }
121 {
122 \end{callanother}
123 }
124 }
125
126 % function call to another instance
127 % interal use only
128 \newenvironment*{callanother}[5][1]{
129 \stepcounter{seqlevel}
130 \stepcounter{callevel} % push
131 \path
132 (#2)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (cf\thecallevel) {}
133 (#4.\threadbias)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (ct\thecallevel) {};
134
135 \draw[->,>=triangle 60] ({cf\thecallevel}) -- (ct\thecallevel)
136 node[midway, above] {#3};
137 \def\l\thecallevel{#1}
138 \def\f\thecallevel{#2}
139 \def\t\thecallevel{#4}
140 \def\returnvalue{#5}
141 \tikzstyle{threadstyle}+=[instcolor#2]
142 }
143 {
144 \addtocounter{seqlevel}{\l\thecallevel}
145 \path
146 (\f\thecallevel)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (rf\thecallevel) {}
147 (\t\thecallevel.\threadbias)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (rt\thecallevel) {};
148 \draw[dashed,->,>=angle 60] ({rt\thecallevel}) -- (rf\thecallevel)
149 node[midway, above]{\returnvalue};
150 \drawthread{ct\thecallevel}{rt\thecallevel}
151 \addtocounter{callevel}{-1} % pop
152 }
153
154 % a function do not need call others
155 % interal use only
156 % Example:
157 % \begin{callself}[height]{caller}{function}{return}
158 % \end{callself}
159 \newenvironment*{callself}[4][1]{
160 \stepcounter{seqlevel}
161 \stepcounter{callevel} % push
162 \stepcounter{callselflevel}
163
164 \path
165 (#2)+(\thecallselflevel*0.1-0.1,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (sc\thecallevel) {}
166 ({sc\thecallevel}.east)+(0,-0.33*\unitfactor) node (scb\thecallevel) {};
167
168 \draw[->,>=triangle 60] ({sc\thecallevel}.east) -- ++(0.8,0)
169 node[near start, above right] {#3} -- ++(0,-0.33*\unitfactor)
170 -- (scb\thecallevel);
171 \def\l\thecallevel{#1}
172 \def\f\thecallevel{#2}
173 \def\t\thecallevel{#2}
174 \def\returnvalue{#4}
175 \tikzstyle{threadstyle}+=[instcolor#2]
176 }{
177 \addtocounter{seqlevel}{\l\thecallevel}
178 \path (\f\thecallevel)+(\thecallselflevel*0.1-0.1,-\theseqlevel*\unitfactor-0.33*\unitfactor) node
179 (sct\thecallevel) {};
180
181 \draw[dashed,->,>=angle 60] ({sct\thecallevel}.east) node
182 (sce\thecallevel) {} -- ++(0.8,0) -- node[midway, right]{\returnvalue} ++(0,-0.33*\unitfactor) -- ++(-0.8,0);
183 \drawthread{scb\thecallevel}{sce\thecallevel}
184 \addtocounter{callevel}{-1} % pop
185 \addtocounter{callselflevel}{-1}
186 }
187
188 % message between threads
189 % Example:
190 % \mess[delay]{sender}{message content}{receiver}
191 \newcommand{\mess}[4][0]{
192 \stepcounter{seqlevel}
193 \path
194 (#2)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (mess from) {};
195 \addtocounter{seqlevel}{#1}
196 \path
197 (#4)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (mess to) {};
198 \draw[->,>=angle 60] (mess from) -- (mess to) node[midway, above]
199 {#3};
200
201 \node (#3 from) at (mess from) {};
202 \node (#3 to) at (mess to) {};
203 }
204
205 \newenvironment{messcall}[4][1]{
206 \stepcounter{seqlevel}
207 \stepcounter{callevel} % push
208 \path
209 (#2)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (cf\thecallevel) {}
210 (#4.\threadbias)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (ct\thecallevel) {};
211
212 \draw[->,>=angle 60] ({cf\thecallevel}) -- (ct\thecallevel)
213 node[midway, above] {#3};
214 \def\l\thecallevel{#1}
215 \def\f\thecallevel{#2}
216 \def\t\thecallevel{#4}
217 \tikzstyle{threadstyle}+=[instcolor#2]
218 }
219 {
220 \addtocounter{seqlevel}{\l\thecallevel}
221 \path
222 (\f\thecallevel)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (rf\thecallevel) {}
223 (\t\thecallevel.\threadbias)+(0,-\theseqlevel*\unitfactor-0.3*\unitfactor) node (rt\thecallevel) {};
224 \drawthread{ct\thecallevel}{rt\thecallevel}
225 \addtocounter{callevel}{-1} % pop
226 }
227
228 % In the situation of multi-threads, some objects are called at the
229 % same time. Currently, we have to adjust the bias of thread line
230 % manually. Possible parameters are: center, west, east
231 \newcommand{\setthreadbias}[1]{\global\def\threadbias{#1}}
232
233 % This function makes the call earlier.
234 \newcommand{\prelevel}{\addtocounter{seqlevel}{-1}}
235
236 % This function makes the call later.
237 \newcommand{\postlevel}{\addtocounter{seqlevel}{+1}}
238
239 % a block box with caption
240 % \begin{sdblock}[caption background color]{caption}{comments}
241 % \end{sdblock}
242 \newenvironment{sdblock}[3][white]{
243 \stepcounter{seqlevel}
244 \stepcounter{blocklevel} % push
245 \coordinate (blockbeg\theblocklevel) at (0,-\theseqlevel*\unitfactor-\unitfactor);
246 \stepcounter{seqlevel}
247 \def\blockcolor\theblocklevel{#1}
248 \def\blockname\theblocklevel{#2}
249 \def\blockcomm\theblocklevel{#3}
250 \begin{pgfinterruptboundingbox}
251 }{
252 \coordinate (blockend) at (0,-\theseqlevel*\unitfactor-2*\unitfactor);
253 \path (current bounding box.east)+(0.2,0) node (boxeast) {}
254 (current bounding box.west |- {blockbeg\theblocklevel}) + (-0.2,0)
255 node (nw) {};
256 \path (boxeast |- blockend) node (se) {};
257
258 % % title
259 \node[blockstyle] (blocktitle) at (nw) {\blockname\theblocklevel};
260 \path (blocktitle.south east) + (0,0.2) node (set) {}
261 (blocktitle.south east) + (-0.2,0) node (seb) {}
262 (blocktitle.north east) + (0.2,0) node (comm) {};
263 \draw[fill=\blockcolor\theblocklevel] (blocktitle.north west) -- (blocktitle.north east) --
264 (set.center) -- (seb.center) -- (blocktitle.south west) -- cycle;
265 \node[blockstyle] (blocktitle) at (nw) {\blockname\theblocklevel};
266 \node[blockcommentstyle] (blockcomment) at (comm) {\blockcomm\theblocklevel};
267
268 \coordinate (se) at (current bounding box.south east);
269 \end{pgfinterruptboundingbox}
270
271 \draw (se) rectangle (nw);
272
273 \addtocounter{blocklevel}{-1} % pop
274 \stepcounter{seqlevel}
275 }
276
277 % the environment of sequence diagram
278 \newenvironment{sequencediagram}{
279 % declare layers
280 \pgfdeclarelayer{umlsd@background}
281 \pgfdeclarelayer{umlsd@threadlayer}
282 \pgfsetlayers{umlsd@background,umlsd@threadlayer,main}
283
284 \begin{tikzpicture}
285 \setlength{\unitlength}{1cm}
286 \tikzstyle{sequence}=[coordinate]
287 \tikzstyle{inststyle}=[rectangle, draw, anchor=west, minimum
288 height=0.8cm, minimum width=1.6cm, fill=white,
289 drop shadow={opacity=1,fill=black}]
290 \ifpgfumlsdroundedcorners
291 \tikzstyle{inststyle}+=[rounded corners=3mm]
292 \fi
293 \tikzstyle{blockstyle}=[anchor=north west]
294 \tikzstyle{blockcommentstyle}=[anchor=north west, font=\small]
295 \tikzstyle{dot}=[inner sep=0pt,fill=black,circle,minimum size=0.2pt]
296 \global\def\unitfactor{0.6}
297 \global\def\threadbias{center}
298 % reset counters
299 \setcounter{preinst}{0}
300 \setcounter{instnum}{0}
301 \setcounter{threadnum}{0}
302 \setcounter{seqlevel}{0}
303 \setcounter{callevel}{0}
304 \setcounter{callselflevel}{0}
305 \setcounter{blocklevel}{0}
306
307 % origin
308 \node[coordinate] (inst0) {};
309 }
310 {
311 \begin{pgfonlayer}{umlsd@background}
312 \ifnum\c@instnum > 0
313 \foreach \t [evaluate=\t] in {1,...,\theinstnum}{
314 \draw[dotted] (inst\t) -- ++(0,-\theseqlevel*\unitfactor-2.2*\unitfactor);
315 }
316 \fi
317 \ifnum\c@threadnum > 0
318 \foreach \t [evaluate=\t] in {1,...,\thethreadnum}{
319 \path (thread\t)+(0,-\theseqlevel*\unitfactor-0.1*\unitfactor) node (threadend) {};
320 \tikzstyle{threadstyle}+=[threadcolor\t]
321 \drawthread{thread\t}{threadend}
322 }
323 \fi
324 \end{pgfonlayer}
325 \end{tikzpicture}}
326
327
328 %%% End of pgf-umlsd.sty
329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%