diff --git a/Doc/UserManual/Architecture.tex b/Doc/UserManual/Architecture.tex new file mode 100644 index 0000000000000000000000000000000000000000..e96412d0be19444dce97eb0bdcf994ef71a68300 --- /dev/null +++ b/Doc/UserManual/Architecture.tex @@ -0,0 +1,94 @@ + + +\section{Data classes for simulations and fits} +This section will give an overview of the classes that are used to describe all the data needed to perform a single simulation. The prime elements of this data are formed by the sample, the experimental conditions (beam and detector parameters) and simulation parameters. + +These classes constitute the main interface to the software's users, since they will mostly be interacting with the program by creating samples and running simulations with specific parameters. Since it is not the intent to explain internals of classes in this document, the text and figures will only mention the most important methods and fields of the classes discussed. Furthermore, getters and setters of private member fields will not be indicated, although these do belong to the public interface. For more detailed information about the project's classes, their methods and fields, the reader is referred to the source code documentation. REF? + +\subsection{The Experiment object} +The Experiment class holds all references to data objects that are needed to perform a simulation. These consist of a sample description, possibly implemented by a builder object, detector and beam parameters and finally, a simulation parameter class that defines the different approximations that can be used during a simulation. Besides getters and setters for these fields, the class also contains a runSimulation() method that will generate an ISimulation object that will perform the actual computations. The class diagram for Experiment is shown in \reffig{exp}. + +\vspace{8mm} +\begin{figure}[H] +%the makebox macro ensures centering of the resulting figure +\makebox[\textwidth][c]{ +\begin{tikzpicture} +\begin{umlpackage}{Simulation Data} +\umlclass{Experiment}{ + -- mp\_sample : ISample* \\ + -- mp\_sample\_builder : ISampleBuilder* \\ + -- m\_detector : Detector \\ + -- m\_beam : Beam \\ + -- m\_intensity\_map : OutputData<double> \\ + -- m\_sim\_params : SimulationParameters +}{ + \umlvirt{+ clone() : Experiment*} \\ + \umlvirt{+ runSimulation() : void} \\ + \umlvirt{+ normalize() : void} +} +\umlemptyclass[x=7, y=0]{ISample} +\umlemptyclass[x=7, y=-2]{Detector} +\umlemptyclass[x=7, y=-4]{Beam} +\umlemptyclass[x=7, y=-6]{SimulationParameters} +\umlemptyclass[y=-4]{GISASExperiment} +\umluniassoc[geometry=|-, anchor1=0]{Experiment}{ISample} +\umluniassoc[geometry=|-, anchor1=0]{Experiment}{Detector} +\umluniassoc[geometry=|-, anchor1=0]{Experiment}{Beam} +\umluniassoc[geometry=|-, anchor1=0]{Experiment}{SimulationParameters} +\umlinherit[geometry=--]{GISASExperiment}{Experiment} + +\umlnote[y=-6.5, width=6cm]{GISASExperiment}{ + The ``runSimulation()'' method retrieves an ISimulation object + from the topmost ISample object and calls its ``run()'' method + to perform the actual computations. +} +\end{umlpackage} +\end{tikzpicture} +} %end makebox +\caption{The Experiment class as a container for sample, beam, detector and simulation parameters.} +\label{fig:exp} +\end{figure} + +\subsection{The ISample class hi\"erarchy} + +Samples are described by a hi\"erarchy tree of objects which all adhere to the ISample interface. The composite pattern is used to achieve a common interface for all objects in the sample tree. The sample description is maximally decoupled from all computational classes, with the exception of the ``createDWBASimulation()'' method. This method will create a new object of type ``DWBASimulation'' that is capable of calculating the scattering contributions originating from the sample in question. The coupling is however not very tight, since the ISample subclasses only need to know about which class to instantiate and return. + +This interface and two of its subclasses are sketched in \reffig{isample}. + +\vspace{8mm} + +\begin{figure}[H] +\makebox[\textwidth][c]{ +\begin{tikzpicture} +\begin{umlpackage}{Sample description} +% Code from official documentation goes here... +\umlinterface{ISample}{ +}{ + \umlvirt{+ clone() : ISample*} \\ + \umlvirt{+ createDWBASimulation() : DWBASimulation*} +} +\umlclass[y=-4]{MultiLayer}{ + -- m\_layers : std::vector<Layer *> \\ + -- m\_interfaces : std::vector<LayerInterface *> +}{ + + getNumberOfLayers() : size\_t \\ + + getNumberOfInterfaces() : size\_t \\ + + addLayer(const Layer \&layer) : void +} +\umlclass[x=8,y=-4]{Layer}{ + -- mp\_material : IMaterial* \\ + -- m\_thickness : double +}{ + + getThickness() : double \\ + + setThickness(double thickness) : void +} +\umlinherit[geometry=-|]{MultiLayer}{ISample} +\umlinherit[geometry=|-]{Layer}{ISample} +\umluniassoc[geometry=--, mult2=n]{MultiLayer}{Layer} +\end{umlpackage} +\end{tikzpicture} +} +\caption{The ISample interface} +\label{fig:isample} +\end{figure} + diff --git a/Doc/UserManual/Examples.tex b/Doc/UserManual/Examples.tex new file mode 100644 index 0000000000000000000000000000000000000000..f245783153cf4d207a23f2aa70450ab782b475fb --- /dev/null +++ b/Doc/UserManual/Examples.tex @@ -0,0 +1,73 @@ +\newpage +\section{Examples} + + +\subsection{Hello listing} + +\begin{lstlisting}[language=python, style=eclipse] +mAmbience = MaterialManager.getHomogeneousMaterial("Air", 1.0, 0.0 ) +mSubstrate = MaterialManager.getHomogeneousMaterial("Substrate", 1.0-6e-6, 2e-8 ) +n_particle = complex(1.0-6e-4, 2e-8) +cylinder_ff = FormFactorCylinder(5*nanometer, 5*nanometer) +cylinder = Particle(n_particle, cylinder_ff) +prism_ff = FormFactorPrism3(5*nanometer, 5*nanometer) +prism = Particle(n_particle, prism_ff) +particle_decoration = ParticleDecoration() +particle_decoration.addParticle(cylinder, 0.0, 0.5) +particle_decoration.addParticle(prism, 0.0, 0.5) +interference = InterferenceFunctionNone() +particle_decoration.addInterferenceFunction(interference) +# air layer with particles and substrate form multi layer +air_layer = Layer(mAmbience) +air_layer_decorator = LayerDecorator(air_layer, particle_decoration) +substrate_layer = Layer(mSubstrate, 0) +multi_layer = MultiLayer() +multi_layer.addLayer(air_layer_decorator) +multi_layer.addLayer(substrate_layer) + +# build and run experiment +simulation = Simulation() +simulation.setDetectorParameters(100,-1.0*degree, 1.0*degree, 100, 0.0*degree 2.0*degree, True) +simulation.setBeamParameters(1.0*angstrom, -0.2*degree, 0.0*degree) +simulation.setSample(multi_layer) +simulation.runSimulation() +\end{lstlisting} + +% \newpage +% \subsection{Hello, minted} +% +% \begin{minted}[linenos=true, frame=single]{python} +% mAmbience = MaterialManager.getHomogeneousMaterial("Air", 1.0, 0.0 ) +% mSubstrate = MaterialManager.getHomogeneousMaterial("Substrate", 1.0-6e-6, 2e-8 ) +% n_particle = complex(1.0-6e-4, 2e-8) +% cylinder_ff = FormFactorCylinder(5*nanometer, 5*nanometer) +% cylinder = Particle(n_particle, cylinder_ff) +% prism_ff = FormFactorPrism3(5*nanometer, 5*nanometer) +% prism = Particle(n_particle, prism_ff) +% particle_decoration = ParticleDecoration() +% particle_decoration.addParticle(cylinder, 0.0, 0.5) +% particle_decoration.addParticle(prism, 0.0, 0.5) +% interference = InterferenceFunctionNone() +% particle_decoration.addInterferenceFunction(interference) +% # air layer with particles and substrate form multi layer +% air_layer = Layer(mAmbience) +% air_layer_decorator = LayerDecorator(air_layer, particle_decoration) +% substrate_layer = Layer(mSubstrate, 0) +% multi_layer = MultiLayer() +% multi_layer.addLayer(air_layer_decorator) +% multi_layer.addLayer(substrate_layer) +% +% # build and run experiment +% simulation = Simulation() +% simulation.setDetectorParameters(100,-1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree, True) +% simulation.setBeamParameters(1.0*angstrom, -0.2*degree, 0.0*degree) +% simulation.setSample(multi_layer) +% simulation.runSimulation() +% \end{minted} + + +\end{document} + + + + diff --git a/Doc/UserManual/Fitting.tex b/Doc/UserManual/Fitting.tex new file mode 100644 index 0000000000000000000000000000000000000000..ff3be097c4e38092780fd2e8e091094ac13c540d --- /dev/null +++ b/Doc/UserManual/Fitting.tex @@ -0,0 +1,24 @@ +\newpage +\section{Fitting} + +% Minuit Library: +% Migrad Algorithm ("Minuit", "Migrad"), +% Simplex Algorithm ("Minuit", "Simplex") +% Minimize Algorithm ("Minuit", "Minimize") +% Scan Algorithm ("Minuit", "Scan") +% Seek Algorithm ("Minuit", "Seek") +% Fumili Library: +% Fumili Algorithm +% Minuit2 Library: +% Migrad Algorithm ("Minuit2", "Migrad") +% Simplex Algorithm ("Minuit2", "Simplex") +% Minimize Algorithm ("Minuit2", "Minimize") +% Scan Algorithm ("Minuit2", "Scan") +% Fumili2 Algorithm ("Minuit2", "Fumili2") +% GSL Library: (Only available if GSL and MathMore are avaiable too) +% Fletcher-Reeves Conjugate Gradient Algorithm ("GSLMultiMin", "conjugatefr") +% Polak-Ribiere Conjugate Gradient Algorithm ("GSLMultiMin", "conjugatepr") +% BFGS Conjugate Gradient Algorithm ("GSLMultiMin", "bfgs2") +% Levenberg-Marquardt Algorithm ("GSLMultiFit", "") +% Simulated Annealing Algorithm ("GSLSimAn", "") +% diff --git a/Doc/UserManual/Installation.tex b/Doc/UserManual/Installation.tex new file mode 100644 index 0000000000000000000000000000000000000000..f6cabb0177c82bd88511c0642162dcd7a0aeb112 --- /dev/null +++ b/Doc/UserManual/Installation.tex @@ -0,0 +1,3 @@ +\section{Installation} + +This is how to install diff --git a/Doc/UserManual/Introduction.tex b/Doc/UserManual/Introduction.tex new file mode 100644 index 0000000000000000000000000000000000000000..f96114af7c362a138fc814c5af581f1b4d803437 --- /dev/null +++ b/Doc/UserManual/Introduction.tex @@ -0,0 +1,2 @@ +\section{Introduction} + diff --git a/Doc/UserManual/UserManual.tex b/Doc/UserManual/UserManual.tex new file mode 100644 index 0000000000000000000000000000000000000000..022121cee13f4a7d9692d9382da8b9d3cc9afd60 --- /dev/null +++ b/Doc/UserManual/UserManual.tex @@ -0,0 +1,48 @@ +\documentclass[a4paper,10pt]{article} + +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{float} +\usepackage{tikz} +\usepackage{tikz-uml} +\usepackage{amsmath} + + +% custom listing settings +\usepackage{listings} +\usepackage{lstcustom} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[scaled=0.8]{beramono} % beramono or luximono give very nice ttfamily fonts +\renewcommand{\lstfontfamily}{\ttfamily} + +\newcommand{\reffig}[1]{figure \ref{fig:#1}} + +%\usepackage{minted} + + +%\maketitle + +%\begin{abstract} +%This document describes the general architecture of the BornAgain project. +%\end{abstract} + + +\title{BornAgain. } +\author{} + + + +\begin{document} +A software to simulate and fit neutron and x-ray scattering at grazing incidence +Some software + + +\input{Introduction} +\input{Installation} +\input{Architecture} +\input{Fitting} +\input{Examples} + +\end{document} + diff --git a/Doc/UserManual/lstcustom.sty b/Doc/UserManual/lstcustom.sty new file mode 100644 index 0000000000000000000000000000000000000000..744154d0782faa981a096e94905372a486fe54f6 --- /dev/null +++ b/Doc/UserManual/lstcustom.sty @@ -0,0 +1,327 @@ + +% this is customisation of 'listings' package +% TODO: cleanup + + + +\usepackage{color} + +\lstdefinelanguage{pseudo}{ + keywords={procedure,end,return,integer,real,foreach,for,each, + do,if,then,else,while,until,true,false,algorithm}, + comment=[l]{//} +} + +\lstdefinelanguage{oaw}{ + morekeywords={import, this, create, let, then, Void, extension, JAVA, + IMPORT, DEFINE, ENDDEFINE, LET, ENDLET, FOR, FILE, ENDFILE, ITERATOR, FOREACH, + AS, IF, ENDFOREACH, ENDIF, EXPAND, INSTANCEOF, USING, SEPARATOR, CSTART, CEND, + PROTECT, ENDPROTECT, ID, EXTENSION, + context, ERROR, WARNING, INFO, enum}, + morecomment=[l]{//}, + morecomment=[s]{/*}{*/}, + % FIXME: listings does not see guillemots, so any regions with them wont work + morecomment=[s]{«REM»}{«ENDREM»}, + morecomment=[s]{«REM}{»}, + morestring=[s]{'}{'}, + morestring=[s]{"}{"}, + escapechar={@}, + % required for use with UTF-8 + literate={«}{\guillemotleft}{1} + {»}{\guillemotright}{1} +} + +% extension, if, then, else, switch, Void, Boolean, Integer, Real, String, let + +\lstdefinelanguage{shell} +{alsodigit={>}, + morekeywords={linux>}, + backgroundcolor=\color{lstbackgroundshellcolor} +} + +\lstdefinelanguage{csimul} +{alsodigit={>}, + alsodigit={\%}, + morekeywords={CONDITIONER>, COUNTER>, \%}, + backgroundcolor=\color{lstbackgroundshellcolor}, + morecomment=[l]{\#} +} + +\lstdefinelanguage{Esterel} +{morekeywords={ + abort, and, assert, await, + bool, + call, case, clock, combine, constant, + data, do, doup, dodown, dopar, + each, emit, else, elseif, end, every, exec, exit, extends, + for, function, + generic, + goto, + halt, handle, + if, immediate, in, input, inputoutput, integer, interface, + loop, + map, module, multiclock, mux, + not, nothing, + or, output, + pause, positive, pre, present, procedure, + relation, repeat, return, run, + sensor, seq, signal, signed, suspend, sustain, + task, then, times, trap, type, + unsigned, + var, + weak, when, with}, + morecomment=[l]{\%} +} + +\lstdefinelanguage{Lustre} +{keywords={ + and, assert, + bool, + current, + else, + float, + if, int, + let, + node, not, + or, + pre, + returns, + tel, then, + var, + when + }, + literate={-}{{--}}2 {->}{{$\to$~}}2 , + morecomment=[l]{--}, +} + +\lstdefinelanguage{KEP} +{morekeywords={ + ABORT, ABORTI, ADD, ADDC, AWAIT, AWAITI, AWAITN, + CALL, CAWAIT, CAWAITE, CMP, CMPS, + EMIT, EMITV, EMITD, EMITR, EXIT, GOTO, HALT, INPUT, JOIN, JW, LABORT, LABORTI, + LWABORT, LWABORTI, LOAD, MUL, NOTHING, OUTPUT, PAUSE, PAR, PARE, + PRE, PRIO, PRESENT, + SETV, + SIGNAL, SIGNALV, SUSPEND, SUSPENDI, SUSTAIN, SUSTAINV, SUSTAIND, + SUSTAINR, TABORT, TABORTI, TWABORT, TWABORTI, WABORT, WABORTI, + %chkabort, jmp, ldaaddr + }, + morecomment=[l]{//}, + morecomment=[s]{/*}{*/}, + morecomment=[l]{\%}, + morestring=[b]" +} + +\lstdefinelanguage{KLP} +{morekeywords={ + ADD, ADDI, AND, + DIV, DIVI, DONE, + EQ, + GOTO, + IADD, IAND, IDIV, IEQ, IGE, IGT, ILE, ILT, INITC, INITV, INPUT, + ICMOV, IRMOV, ISUB, IVMOV, IOR, IXOR, + IMUL, + JF, JMP, JNZ, JT, JZ, + LOCAL, + MUL, MULI, + NEQ, + OUTPUT, + PRIO, + RRMOV, + SETCLK, SETPC, + SUB, SUBI, + VVMOV, + XOR + }, + morecomment=[l]{//}, + morecomment=[l]{\#}, + morecomment=[s]{/*}{*/}, + morecomment=[l]{\%}, + morestring=[b]", +} + +\lstdefinelanguage{Kit} +{morekeywords={% +statechart, model, version, input, output, var, label, type, history, hi, +deephistory, dh, initial, in, fork, fk, join, jn, junction, jc, sync, sy, +choice, ch, dynamicchoice, dc, suspend, sd, final, doActivity, do, +entryActivity, entry, exitActivity, exit, bindActivity, bind, localEvent, +localVariable, priority, weakAbortion, wa, strongAbortion, sa, +normalTermination, nt, suspension, sp, conditional, co, internalTransition, +it, integer, float, double, boolean, combine, with, pos, pp, lp, width, +height, collapsed, true, false% +}, + morecomment=[l]{\#}, +} + +\lstdefinelanguage{Repic}{ + morekeywords={ + abort, await, chkabort, emit, fork, goto, jmp, join, + ldaaddr, present, sync}, + morecomment=[l]{\%} +} + + +\newcommand{\lstfontfamily}{\ttfamily} +%\newcommand{\lstfontfamily}{\sffamily} % Adapt to schneider +\newcommand{\textlst}[1]{\texttt{#1}} +\newcommand{\mathlst}[1]{\mathtt{#1}} +\lstdefinestyle{tiny}{basicstyle=\tiny\lstfontfamily} +\lstdefinestyle{scriptsize}{basicstyle=\scriptsize\lstfontfamily} +\lstdefinestyle{footnotesize}{basicstyle=\footnotesize\lstfontfamily} +\lstdefinestyle{small}{basicstyle=\small\lstfontfamily} +\lstdefinestyle{normalsize}{basicstyle=\normalsize\lstfontfamily} +\lstdefinestyle{large}{basicstyle=\lstfontfamily} + +\lstdefinestyle{monitor}{morekeywords={monitor, export}} +\lstdefinestyle{ConcPascal}{language=Pascal,style=monitor} + +% To make this accessible to Emacs/AUCTeX (C-c C-f C-o), +% add something like this to TeX-mode-hook: +% (setq LaTeX-font-list +% (append '((?{\^O} "\\codefont{" "}")) +% LaTeX-font-list)) +%\newcommand{\codefont}[1]{{\renewcommand{\textnormal}[1]{\textlst{#1}}\lstfontfamily #1}} +\newcommand{\mathcodefont}[1]{\mathtt{#1}} +\newcommand{\codefont}[1]{{\lstfontfamily #1}} +\newlength{\lstframexleftmargin} +\setlength{\lstframexleftmargin}{1mm} + +% rulesepcolor and backgroundcolor are set in beamercustom{presentation|handout}.sty +\lstdefinestyle{mydefault}{ + style=scriptsize, + emphstyle=\color{red}, + framexleftmargin=\lstframexleftmargin, + frame=shadowbox, + keywordstyle=\structure, + commentstyle=\itshape, + columns=flexible, % Columns not rigid - gives nicer spacing + gobble=4, % Gobble first 4 characters of each line + escapeinside=`', + escapechar=@, + lineskip=+0.2ex, + rulesepcolor=\color{lstrulesepcolor}, + % WARNING: For some reason, the settin of backgroundcolor must take + % place at the very end!!! + backgroundcolor=\color{lstbackgroundprogcolor} +} + +\definecolor{darkviolet}{rgb}{0.5,0,0.4} +\definecolor{darkgreen}{rgb}{0,0.4,0.2} +\definecolor{darkblue}{rgb}{0.1,0.1,0.9} +\definecolor{darkgrey}{rgb}{0.5,0.5,0.5} +\definecolor{lightblue}{rgb}{0.4,0.4,1} + +\lstdefinestyle{eclipse}{ + basicstyle=\small\lstfontfamily, + emphstyle=\color{red}\bfseries, + keywordstyle=\color{darkviolet}\bfseries, + commentstyle=\color{darkgreen}, + stringstyle=\color{darkblue}, + numberstyle=\color{darkgrey}\lstfontfamily, + emphstyle=\color{red}, + % get also javadoc style comments + morecomment=[s][\color{lightblue}]{/**}{*/}, + %columns=fullflexible, %spaceflexible, %flexible, fullflexible +% escapeinside=`', +% escapechar=@, + showstringspaces=false, + numbers=left +} + +\lstdefinestyle{black}{ + basicstyle=\small\lstfontfamily, + numbers=left, + columns=fullflexible, + breaklines=true, + mathescape=true, + escapechar=\#, + tabsize=4, + frame=lines, + showstringspaces=false +} + +% use proper tt font that supports bold printing, e.g. by +% \usepackage{courier} +\lstdefinestyle{seminar}{ + basicstyle=\small\ttfamily, + numbers=left, + breaklines=true, + mathescape=true, + escapechar=\#, + tabsize=4, + showstringspaces=false +} + + + +% +% Another example of customisation (to Study) +% + +% \documentclass[a4paper,12pt]{article} +% \usepackage[utf8]{inputenc} +% +% % Default fixed font does not support bold face +% \DeclareFixedFont{\ttb}{T1}{txtt}{bx}{n}{12} % for bold +% \DeclareFixedFont{\ttm}{T1}{txtt}{m}{n}{12} % for normal +% +% % Custom colors +% \usepackage{color} +% \definecolor{deepblue}{rgb}{0,0,0.5} +% \definecolor{deepred}{rgb}{0.6,0,0} +% \definecolor{deepgreen}{rgb}{0,0.5,0} +% +% \usepackage{listings} +% +% % Python style for highlighting +% \newcommand\pythonstyle{\lstset{ +% language=Python, +% basicstyle=\ttm, +% otherkeywords={self}, % Add keywords here +% keywordstyle=\ttb\color{deepblue}, +% emph={MyClass,__init__}, % Custom highlighting +% emphstyle=\ttb\color{deepred}, % Custom highlighting style +% stringstyle=\color{deepgreen}, +% frame=tb, % Any extra options here +% showstringspaces=false % +% }} +% +% +% % Python environment +% \lstnewenvironment{python}[1][] +% { +% \pythonstyle +% \lstset{#1} +% } +% {} +% +% % Python for external files +% \newcommand\pythonexternal[1]{{ +% \pythonstyle +% \lstinputlisting{#1}}} +% +% % Python for inline +% \newcommand\pythoninline[1]{{\pythonstyle\lstinline!#1!}} +% +% \begin{document} +% +% \section{``In-text'' listing highlighting} +% +% \begin{python} +% class MyClass(Yourclass): +% def __init__(self, my, yours): +% bla = '5 1 2 3 4' +% print bla +% \end{python} +% +% \section{External listing highlighting} +% +% \pythonexternal{demo.py} +% +% \section{Inline highlighting} +% +% Definition \pythoninline{class MyClass} means \dots +% +% \end{document} +% diff --git a/Doc/UserManual/minted.sty b/Doc/UserManual/minted.sty new file mode 100644 index 0000000000000000000000000000000000000000..0e0585cfdd294c0855b396b9deebafac6ca7bb8c --- /dev/null +++ b/Doc/UserManual/minted.sty @@ -0,0 +1,239 @@ +%% +%% This is file `minted.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% minted.dtx (with options: `package') +%% Copyright 2010--2011 Konrad Rudolph +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% Additionally, the project may be distributed under the terms of the new BSD +%% license. +%% +%% This work has the LPPL maintenance status `maintained'. +%% +%% The Current Maintainer of this work is Konrad Rudolph. +%% +%% This work consists of the files minted.dtx and minted.ins +%% and the derived file minted.sty. +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{minted}[2011/09/17 v1.7 Yet another Pygments shim for LaTeX] +\RequirePackage{keyval} +\RequirePackage{fancyvrb} +\RequirePackage{xcolor} +\RequirePackage{float} +\RequirePackage{ifthen} +\RequirePackage{calc} +\RequirePackage{ifplatform} +\DeclareOption{chapter}{\def\minted@float@within{chapter}} +\DeclareOption{section}{\def\minted@float@within{section}} +\ProcessOptions\relax +\ifwindows + \providecommand\DeleteFile[1]{\immediate\write18{del #1}} +\else + \providecommand\DeleteFile[1]{\immediate\write18{rm #1}} +\fi +\newboolean{AppExists} +\newcommand\TestAppExists[1]{ + \ifwindows + \DeleteFile{\jobname.aex} + \immediate\write18{for \string^\@percentchar i in (#1.exe #1.bat #1.cmd) + do set >\jobname.aex <nul: /p x=\string^\@percentchar \string~$PATH:i>>\jobname.aex} %$ + \newread\@appexistsfile + \immediate\openin\@appexistsfile\jobname.aex + \expandafter\def\expandafter\@tmp@cr\expandafter{\the\endlinechar} + \endlinechar=-1\relax + \readline\@appexistsfile to \@apppathifexists + \endlinechar=\@tmp@cr + \ifthenelse{\equal{\@apppathifexists}{}} + {\AppExistsfalse} + {\AppExiststrue} + \immediate\closein\@appexistsfile + \DeleteFile{\jobname.aex} +\immediate\typeout{file deleted} + \else + \immediate\write18{which #1 && touch \jobname.aex} + \IfFileExists{\jobname.aex} + {\AppExiststrue + \DeleteFile{\jobname.aex}} + {\AppExistsfalse} + \fi} +\newcommand\minted@resetoptions{} +\newcommand\minted@defopt[1]{ + \expandafter\def\expandafter\minted@resetoptions\expandafter{% + \minted@resetoptions + \@namedef{minted@opt@#1}{}}} +\newcommand\minted@opt[1]{ + \expandafter\detokenize% + \expandafter\expandafter\expandafter{\csname minted@opt@#1\endcsname}} +\newcommand\minted@define@opt[3][]{ + \minted@defopt{#2} + \ifthenelse{\equal{#1}{}}{ + \define@key{minted@opt}{#2}{\@namedef{minted@opt@#2}{#3}}} + {\define@key{minted@opt}{#2}[#1]{\@namedef{minted@opt@#2}{#3}}}} +\newcommand\minted@define@switch[3][]{ + \minted@defopt{#2} + \define@booleankey{minted@opt}{#2} + {\@namedef{minted@opt@#2}{#3}} + {\@namedef{minted@opt@#2}{#1}}} +\minted@defopt{extra} +\newcommand\minted@define@extra[1]{ + \define@key{minted@opt}{#1}{ + \expandafter\def\expandafter\minted@opt@extra\expandafter{% + \minted@opt@extra,#1=##1}}} +\newcommand\minted@define@extra@switch[1]{ + \define@booleankey{minted@opt}{#1} + {\expandafter\def\expandafter\minted@opt@extra\expandafter{% + \minted@opt@extra,#1}} + {\expandafter\def\expandafter\minted@opt@extra\expandafter{% + \minted@opt@extra,#1=false}}} +\minted@define@switch{texcl}{-P texcomments} +\minted@define@switch{mathescape}{-P mathescape} +\minted@define@switch{linenos}{-P linenos} +\minted@define@switch{startinline}{-P startinline} +\minted@define@switch[-P funcnamehighlighting=False]% + {funcnamehighlighting}{-P funcnamehighlighting} +\minted@define@opt{gobble}{-F gobble:n=#1} +\minted@define@opt{bgcolor}{#1} +\minted@define@extra{frame} +\minted@define@extra{framesep} +\minted@define@extra{framerule} +\minted@define@extra{rulecolor} +\minted@define@extra{numbersep} +\minted@define@extra{firstnumber} +\minted@define@extra{stepnumber} +\minted@define@extra{firstline} +\minted@define@extra{lastline} +\minted@define@extra{baselinestretch} +\minted@define@extra{xleftmargin} +\minted@define@extra{xrightmargin} +\minted@define@extra{fillcolor} +\minted@define@extra{tabsize} +\minted@define@extra{fontfamily} +\minted@define@extra{fontsize} +\minted@define@extra{fontshape} +\minted@define@extra{fontseries} +\minted@define@extra{formatcom} +\minted@define@extra{label} +\minted@define@extra@switch{numberblanklines} +\minted@define@extra@switch{showspaces} +\minted@define@extra@switch{resetmargins} +\minted@define@extra@switch{samepage} +\minted@define@extra@switch{showtabs} +\minted@define@extra@switch{obeytabs} +\newsavebox{\minted@bgbox} +\newenvironment{minted@colorbg}[1]{ + \def\minted@bgcol{#1} + \noindent + \begin{lrbox}{\minted@bgbox} + \begin{minipage}{\linewidth-2\fboxsep}} + {\end{minipage} + \end{lrbox}% + \colorbox{\minted@bgcol}{\usebox{\minted@bgbox}}} +\newwrite\minted@code +\newcommand\minted@savecode[1]{ + \immediate\openout\minted@code\jobname.pyg + \immediate\write\minted@code{#1} + \immediate\closeout\minted@code} +\newcommand\minted@pygmentize[2][\jobname.pyg]{ + \def\minted@cmd{pygmentize -l #2 -f latex -F tokenmerge + \minted@opt{gobble} \minted@opt{texcl} \minted@opt{mathescape} + \minted@opt{startinline} \minted@opt{funcnamehighlighting} + \minted@opt{linenos} -P "verboptions=\minted@opt{extra}" + -o \jobname.out.pyg #1} + \immediate\write18{\minted@cmd} + % For debugging, uncomment: + %\immediate\typeout{\minted@cmd} + \ifthenelse{\equal{\minted@opt@bgcolor}{}} + {} + {\begin{minted@colorbg}{\minted@opt@bgcolor}} + \input{\jobname.out.pyg} + \ifthenelse{\equal{\minted@opt@bgcolor}{}} + {} + {\end{minted@colorbg}} + \DeleteFile{\jobname.out.pyg}} +\newcommand\minted@usedefaultstyle{\usemintedstyle{default}} +\newcommand\usemintedstyle[1]{ + \renewcommand\minted@usedefaultstyle{} + \immediate\write18{pygmentize -S #1 -f latex > \jobname.pyg} + \input{\jobname.pyg}} +\newcommand\mint[3][]{ + \DefineShortVerb{#3} + \minted@resetoptions + \setkeys{minted@opt}{#1} + \SaveVerb[aftersave={ + \UndefineShortVerb{#3} + \minted@savecode{\FV@SV@minted@verb} + \minted@pygmentize{#2} + \DeleteFile{\jobname.pyg}}]{minted@verb}#3} +\newcommand\minted@proglang[1]{} +\newenvironment{minted}[2][] + {\VerbatimEnvironment + \renewcommand{\minted@proglang}[1]{#2} + \minted@resetoptions + \setkeys{minted@opt}{#1} + \begin{VerbatimOut}[codes={\catcode`\^^I=12}]{\jobname.pyg}}% + {\end{VerbatimOut} + \minted@pygmentize{\minted@proglang{}} + \DeleteFile{\jobname.pyg}} +\newcommand\inputminted[3][]{ + \minted@resetoptions + \setkeys{minted@opt}{#1} + \minted@pygmentize[#3]{#2}} +\newcommand\newminted[3][]{ + \ifthenelse{\equal{#1}{}} + {\def\minted@envname{#2code}} + {\def\minted@envname{#1}} + \newenvironment{\minted@envname} + {\VerbatimEnvironment\begin{minted}[#3]{#2}} + {\end{minted}} + \newenvironment{\minted@envname *}[1] + {\VerbatimEnvironment\begin{minted}[#3,##1]{#2}} + {\end{minted}}} +\newcommand\newmint[3][]{ + \ifthenelse{\equal{#1}{}} + {\def\minted@shortname{#2}} + {\def\minted@shortname{#1}} + \expandafter\newcommand\csname\minted@shortname\endcsname[2][]{ + \mint[#3,##1]{#2}##2}} +\newcommand\newmintedfile[3][]{ + \ifthenelse{\equal{#1}{}} + {\def\minted@shortname{#2file}} + {\def\minted@shortname{#1}} + \expandafter\newcommand\csname\minted@shortname\endcsname[2][]{ + \inputminted[#3,##1]{#2}{##2}}} +\@ifundefined{minted@float@within} + {\newfloat{listing}{h}{lol}} + {\newfloat{listing}{h}{lol}[\minted@float@within]} +\newcommand\listingscaption{Listing} +\floatname{listing}{\listingscaption} +\newcommand\listoflistingscaption{List of listings} +\providecommand\listoflistings{\listof{listing}{\listoflistingscaption}} +\AtBeginDocument{ + \minted@usedefaultstyle} +\AtEndOfPackage{ + \ifnum\pdf@shellescape=1\relax\else + \PackageError{minted} + {You must invoke LaTeX with the + -shell-escape flag} + {Pass the -shell-escape flag to LaTeX. Refer to the minted.sty + documentation for more information.}\fi + \TestAppExists{pygmentize} + \ifAppExists\else + \PackageError{minted} + {You must have `pygmentize' installed + to use this package} + {Refer to the installation instructions in the minted + documentation for more information.} + \fi} +\endinput +%% +%% End of file `minted.sty'. diff --git a/Doc/UserManual/tikz-uml.sty b/Doc/UserManual/tikz-uml.sty new file mode 100644 index 0000000000000000000000000000000000000000..2ea87dfdc3871ae8a3ad208b210333c18cc4e961 --- /dev/null +++ b/Doc/UserManual/tikz-uml.sty @@ -0,0 +1,4429 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Start of tikz-uml.sty +% +% Some macros for UML Diagrams. +% Home page of project : +% Author: Nicolas Kielbasiewicz +% Style from : +% Fixed by Nicolas Kielbasiewicz (nicolas.kielbasiewicz@ensta-paristech.fr) in dec 2010 to compile with pgf 2.00 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\NeedsTeXFormat{LaTeX2e}[1995/12/01]% +\ProvidesPackage{tikz-uml}[2011/01/26]% + +\RequirePackage{ifthen}% +\RequirePackage{tikz}% +\RequirePackage{xstring}% +\RequirePackage{calc}% +\RequirePackage{pgfopts}% +\usetikzlibrary{backgrounds,arrows,shapes,fit,shadows,decorations.markings}% + +\def\tikzumlPackageLayersNum{3}% +\pgfkeys{/tikzuml/options/.cd, packageLayers/.initial=3}% +\pgfkeys{/tikzuml/options/.cd, packageLayers/.store in=\tikzumlPackageLayersNum}% +\def\tikzumlStateLayersNum{3}% +\pgfkeys{/tikzuml/options/.cd, stateLayers/.initial=3}% +\pgfkeys{/tikzuml/options/.cd, stateLayers/.store in=\tikzumlStateLayersNum}% +\def\tikzumlFragmentLayersNum{3}% +\pgfkeys{/tikzuml/options/.cd, fragmentLayers/.initial=3}% +\pgfkeys{/tikzuml/options/.cd, fragmentLayers/.store in=\tikzumlFragmentLayersNum}% +\def\tikzumlComponentLayersNum{3}% +\pgfkeys{/tikzuml/options/.cd, componentLayers/.initial=3}% +\pgfkeys{/tikzuml/options/.cd, componentLayers/.store in=\tikzumlComponentLayersNum}% + +\ProcessPgfOptions{/tikzuml/options}% + +\def\pgfsetlayersArg{background}% +\pgfdeclarelayer{background}% +\newcounter{tikzumlPackageLayers}% +\loop \pgfdeclarelayer{package\thetikzumlPackageLayers}% + \xdef\pgfsetlayersArg{\pgfsetlayersArg,package\thetikzumlPackageLayers}% + \ifnum\tikzumlPackageLayersNum>\thetikzumlPackageLayers% + \stepcounter{tikzumlPackageLayers}% +\repeat% +% +\newcounter{tikzumlFragmentLayers}% +\loop \pgfdeclarelayer{fragment\thetikzumlFragmentLayers}% + \xdef\pgfsetlayersArg{\pgfsetlayersArg,fragment\thetikzumlFragmentLayers}% + \ifnum\tikzumlFragmentLayersNum>\thetikzumlFragmentLayers% + \stepcounter{tikzumlFragmentLayers}% +\repeat% +% +\newcounter{tikzumlStateLayers}% +\loop \pgfdeclarelayer{state\thetikzumlStateLayers}% + \xdef\pgfsetlayersArg{\pgfsetlayersArg,state\thetikzumlStateLayers}% + \ifnum\tikzumlStateLayersNum>\thetikzumlStateLayers% + \stepcounter{tikzumlStateLayers}% +\repeat% +% +\newcounter{tikzumlComponentLayers}% +\loop \pgfdeclarelayer{component\thetikzumlComponentLayers}% + \xdef\pgfsetlayersArg{\pgfsetlayersArg,component\thetikzumlComponentLayers}% + \ifnum\tikzumlComponentLayersNum>\thetikzumlComponentLayers% + \stepcounter{tikzumlComponentLayers}% +\repeat% +% +\pgfdeclarelayer{lifelines}% +\pgfdeclarelayer{activity}% +\pgfdeclarelayer{connections}% +\xdef\pgfsetlayersArg{\pgfsetlayersArg,lifelines,activity,connections,main}% +\pgfsetlayers{\pgfsetlayersArg}% + +\pgfkeys{/tikzuml/.cd,% + text/.initial=black, draw/.initial=black, font/.initial=\small,% + fill class/.initial=yellow!20, fill template/.initial=yellow!2,% + fill package/.initial=blue!20, fill note/.initial=green!20,% + fill usecase/.initial=blue!20, fill system/.initial=white,% + fill state/.initial=yellow!20, fill object/.initial=yellow!20,% + fill call/.initial=white, fill fragment/.initial= none,% + fill component/.initial= yellow!20, fill port/.initial= yellow!20,% + fill assembly connector/.initial= white,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in tikzuml global, invalid option \keyname}% + }}% +\pgfkeys{/tikzuml/.cd,% + text/.get=\tikzumltextcolor, draw/.get=\tikzumldrawcolor, font/.get=\tikzumlfont,% + fill class/.get=\tikzumlfillclasscolor,% + fill template/.get=\tikzumlfilltemplatecolor,% + fill package/.get=\tikzumlfillpackagecolor, fill note/.get=\tikzumlfillnotecolor,% + fill usecase/.get=\tikzumlfillusecasecolor,% + fill system/.get=\tikzumlfillsystemcolor,% + fill state/.get=\tikzumlfillstatecolor, fill object/.get=\tikzumlfillobjectcolor,% + fill call/.get=\tikzumlfillcallcolor,% + fill fragment/.get=\tikzumlfillfragmentcolor,% + fill component/.get=\tikzumlfillcomponentcolor,% + fill port/.get=\tikzumlfillportcolor,% + fill assembly connector/.get=\tikzumlfillassemblyconnectorcolor}% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% class diagrams % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\pgfkeys{/tikzuml/relation/.cd,% + attr1/.style args={#1|#2}{arg1=#1, mult1=#2},% + attr2/.style args={#1|#2}{arg2=#1, mult2=#2},% + attr/.style args={#1|#2}{arg=#1, mult=#2},% + recursive/.style args={#1|#2|#3}{angle1=#1, angle2=#2, loopsize=#3},% + anchors/.style args={#1 and #2}{anchor1=#1, anchor2=#2},% + recursive direction/.style args={#1 to #2}{recursive direction start=#1, recursive direction end=#2}}% +\pgfkeys{/tikzuml/note/.cd,% + anchors/.style args={#1 and #2}{anchor1=#1, anchor2=#2}}% + +\tikzstyle{tikzuml simpleclass style}=[rectangle, minimum height=2em, node distance=2em]% +\tikzstyle{tikzuml class style}=[rectangle split, rectangle split parts=3, rectangle split part align={center, left, left}, minimum height=2em, node distance=2em]% +\tikzstyle{tikzuml narynode style}=[diamond]% +\tikzstyle{tikzuml template style}=[dashed, inner ysep=0.5em, inner xsep=1ex]% +\tikzstyle{tikzuml control nodes style}=[fill=black, inner sep=1.5pt, circle]% +% +\tikzstyle{tikzuml association style}=[color=\tikzumldrawcolor, -]% +\tikzstyle{tikzuml bidirectional association style}=[color=\tikzumldrawcolor, angle45-angle45]% +\tikzstyle{tikzuml unidirectional association style}=[color=\tikzumldrawcolor, -angle 45]% +\tikzstyle{tikzuml aggregation style}=[color=\tikzumldrawcolor, open diamond-]% +\tikzstyle{tikzuml unidirectional aggregation style}=[color=\tikzumldrawcolor, open diamond-angle 45]% +\tikzstyle{tikzuml composition style}=[color=\tikzumldrawcolor, diamond-]% +\tikzstyle{tikzuml unidirectional composition style}=[color=\tikzumldrawcolor, diamond-angle 45]% +\tikzstyle{tikzuml dependency style}=[color=\tikzumldrawcolor, -angle 45, dashed]% +\tikzstyle{tikzuml import style}=[color=\tikzumldrawcolor, -angle 45, dashed]% +\tikzstyle{tikzuml inherit style}=[color=\tikzumldrawcolor, -open triangle 45]% +\tikzstyle{tikzuml implements style}=[color=\tikzumldrawcolor, -open triangle 45, dashed]% + +\pgfkeys{/tikzuml/assemblyconnectorrelation/.cd, anchors/.style args={#1 and #2}{anchor1=#1, anchor2=#2}}% + +\newcounter{tikzumlPackageClassNum}% +\newcounter{tikzumlPackageSubPackageNum}% +\newcounter{tikzumlRelationNum}% +\setcounter{tikzumlRelationNum}{1}% +\newcounter{tikzumlNoteNum}% +\setcounter{tikzumlNoteNum}{1}% + +\newcounter{pos}% +\newcounter{posT}% +\newcounter{posStereo}% + +\newcounter{tikzumlPackageLevel}% +\setcounter{tikzumlPackageLevel}{0}% + +\newif\ifumlclassSimpleStyle% + +% utility : change default colors +\newcommand{\tikzumlset}[1]{% + \pgfkeys{/tikzuml/.cd,#1}% + \pgfkeys{/tikzuml/.cd,% + text/.get=\tikzumltextcolor, draw/.get=\tikzumldrawcolor,% + font/.get=\tikzumlfont,% + fill class/.get=\tikzumlfillclasscolor,% + fill template/.get=\tikzumlfilltemplatecolor,% + fill package/.get=\tikzumlfillpackagecolor,% + fill note/.get=\tikzumlfillnotecolor,% + fill usecase/.get=\tikzumlfillusecasecolor,% + fill system/.get=\tikzumlfillsystemcolor,% + fill state/.get=\tikzumlfillstatecolor,% + fill object/.get=\tikzumlfillobjectcolor,% + fill call/.get=\tikzumlfillcallcolor,% + fill fragment/.get=\tikzumlfillfragmentcolor,% + fill component/.get=\tikzumlfillcomponentcolor,% + fill port/.get=\tikzumlfillportcolor,% + fill assembly connector/.get=\tikzumlfillassemblyconnectorcolor}% +}% + +% define a point +% arg : node/coordinates of the point +\newcommand{\umlpoint}[1]{% + \begin{pgfonlayer}{connections}% + \node[tikzuml control nodes style] at (#1) {};% + \end{pgfonlayer}% +}% + +\newcommand{\tikzumlskipescape}[3][_]{% +\begingroup% + \def\_{#1}\edef\x{\endgroup% + \def\noexpand\csname #3\endcsname{#2}}\x% +}% + +% define a uml package +% arg : package name +% optional : x, y coordinates of the package +% draw, fill, text colors +\newenvironment{umlpackage}[2][]{% + \pgfkeys{/tikzuml/package/.cd,% + x/.initial=0, y/.initial=0,% + name/.initial=tikzumlEmpty, draw/.initial=\tikzumldrawcolor,% + fill/.initial=\tikzumlfillpackagecolor, text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlpackage, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/package/.cd, #1}% + \pgfkeys{/tikzuml/package/.cd,% + x/.get=\xshift, y/.get=\yshift, name/.get=\tikzumlpackagename,% + draw/.get=\tikzumlpackagedraw, fill/.get=\tikzumlpackagefill,% + text/.get=\tikzumlpackagetext}% + % + \ifnum\thetikzumlPackageLevel>0% + \let\tikzumlPackage@nameold\tikzumlPackage@fitname% + \def\tikzumlPackage@name{#2}% + \begingroup% + \def\_{@}\edef\x{\endgroup% + \def\noexpand\tikzumlPackage@fitname{\tikzumlPackage@name}}\x% + \let\tikzumlPackage@parentold\tikzumlPackage@parent% + \edef\tikzumlPackage@parent{\tikzumlPackage@parentold @@\tikzumlPackage@nameold}% + \else% + \def\tikzumlPackage@parent{}% + \def\tikzumlPackage@name{#2}% + \begingroup% + \def\_{@}\edef\x{\endgroup% + \def\noexpand\tikzumlPackage@fitname{\tikzumlPackage@name}}\x% + \fi% + % + \let\tikzumlPackage@nodeNameold\tikzumlPackage@nodeName% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlPackage@nodeName{\tikzumlPackage@name}}\x% + % + \ifthenelse{\equal{\tikzumlpackagename}{tikzumlEmpty}}{}{% + \def\tikzumlPackage@nodeName{\tikzumlpackagename}% + }% + % + \StrSubstitute{\tikzumlPackage@nodeName}{.}{@POINT@}{\tikzumlPackage@nodeName}% + % + \expandafter\gdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{}% + % + \setcounter{tikzumlPackageClassNum}{0}% + \setcounter{tikzumlPackageSubPackageNum}{0}% + \stepcounter{tikzumlPackageLevel}% + % + \begin{scope}[xshift=\xshift cm, yshift=\yshift cm]% +}{% + \addtocounter{tikzumlPackageLevel}{-1}% + \begin{pgfonlayer}{package\thetikzumlPackageLevel}% + % + % if contains no class, one define a fictive node to enable the fit option + \ifnum\c@tikzumlPackageClassNum=0% + \ifnum\c@tikzumlPackageSubPackageNum=0% + \node[inner sep=1.5ex] (\tikzumlPackage@nodeName-root) at (0,0) {\phantom{\tikzumlPackage@nodeName}};% + \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{(\tikzumlPackage@nodeName-root)}% + % + \fi% + \fi% + % + \ifnum\c@tikzumlPackageLevel>0% + \def\tikzumlPackageFitTmp{\csname tikzumlPackageFit\tikzumlPackage@parent\endcsname}% + \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent\endcsname{\tikzumlPackageFitTmp (\tikzumlPackage@nodeName) (\tikzumlPackage@nodeName-caption)}% + \stepcounter{tikzumlPackageSubPackageNum}% + \fi% + % + \node[draw=\tikzumlpackagedraw, fill=\tikzumlpackagefill, text=\tikzumlpackagetext, font=\tikzumlfont, inner sep=1.5ex, fit = \csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname] (\tikzumlPackage@nodeName) {};% + \node[draw=\tikzumlpackagedraw, fill=\tikzumlpackagefill, text=\tikzumlpackagetext, font=\tikzumlfont, minimum height=1.5em, outer ysep=-0.3, anchor=south west] (\tikzumlPackage@nodeName-caption) at (\tikzumlPackage@nodeName.north west) {\tikzumlPackage@name};% + \end{pgfonlayer}% + \end{scope}% +}% + +% shortcut to define an empty package +\newcommand{\umlemptypackage}[2][]{\begin{umlpackage}[#1]{#2} \end{umlpackage}}% + +% define a uml class +% args : name of the class +% attributes of the class +% operations of the class +% optional : x,y coordinates of the class +% width of the class node +% type of class (class, interface, typedef, enum) +% template parameters +% draw, fill, text colors +\newcommand{\umlclass}[4][]{% + \pgfkeys{/tikzuml/class/.cd,% + x/.initial=0, y/.initial=0, width/.initial=10ex, type/.initial=class,% + tags/.initial={}, simple/.is if=umlclassSimpleStyle,% + template/.initial={}, name/.initial={tikzumlEmpty},% + draw/.initial=\tikzumldrawcolor,% + fill template/.initial=\tikzumlfilltemplatecolor,% + fill/.initial=\tikzumlfillclasscolor,% + text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlclass, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/class/.cd,#1}% + \pgfkeys{/tikzuml/class/.cd,% + x/.get=\umlclassX, y/.get=\umlclassY, width/.get=\umlclassMinimumWidth,% + type/.get=\umlclassType, tags/.get=\umlclasstags, template/.get=\umlclassTemplateParam,% + name/.get=\umlclassName,% + draw/.get=\tikzumlclassdraw, fill/.get=\tikzumlclassfill,% + text/.get=\tikzumlclasstext, fill template/.get=\tikzumlclasstemplate}% + % + \ifthenelse{\equal{\umlclassType}{class}\OR\equal{\umlclassType}{abstract}}{% + \def\tikzumlClassType{}% + }{% + \def\tikzumlClassType{\guillemotleft\umlclassType\guillemotright \\}% + }% + % + \ifthenelse{\equal{\umlclasstags}{}}{% + \def\tikzumlClassTags{}% + }{% + \def\tikzumlClassTags{\\ \{\umlclasstags\}}% + }% + % + \ifthenelse{\equal{\umlclassTemplateParam}{}}{% + \def\tikzumlClassVPadding{}% + \def\tikzumlClassHPadding{}% + }{% + \def\tikzumlClassVPadding{\vspace{0.1em} \\}% + \def\tikzumlClassHPadding{\hspace{0.5ex} $ $}% + }% + % + \def\tikzumlClassName{#2}% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlClassNodeName{\tikzumlClassName}}\x% + % + \ifthenelse{\equal{\umlclassName}{tikzumlEmpty}}{}{% + \def\tikzumlClassNodeName{\umlclassName}% + }% + % + \StrSubstitute{\tikzumlClassNodeName}{:}{@COLON@}[\tikzumlClassNodeName] + % + \ifthenelse{\equal{\umlclassType}{abstract}}{% + \let\tikzumlClassNameOld\tikzumlClassName% + \def\tikzumlClassName{{\it \tikzumlClassNameOld}}% + }{}% + % + \def\tikzumlClassPos{\umlclassX,\umlclassY}% + \def\tikzumlClassAttributes{#3}% + \def\tikzumlClassOperations{#4}% + % + \ifumlclassSimpleStyle% + \node[tikzuml simpleclass style, draw=\tikzumlclassdraw, fill=\tikzumlclassfill, text=\tikzumlclasstext, font=\tikzumlfont, minimum width=\umlclassMinimumWidth] (\tikzumlClassNodeName) at (\tikzumlClassPos) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}% + };% + \else% + \node[tikzuml class style, draw=\tikzumlclassdraw, fill=\tikzumlclassfill, text=\tikzumlclasstext, font=\tikzumlfont, minimum width=\umlclassMinimumWidth] (\tikzumlClassNodeName) at (\tikzumlClassPos) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular}% + \nodepart{second}% + \begin{tabular}{l}% + \tikzumlClassAttributes% + \end{tabular}% + \nodepart{third}% + \begin{tabular}{l}% + \tikzumlClassOperations% + \end{tabular}% + };% + \fi% + % + \ifthenelse{\equal{\umlclassTemplateParam}{}}{}{% + \draw (\tikzumlClassNodeName.north east) node[tikzuml template style, name=\tikzumlClassNodeName-template, draw=\tikzumlclassdraw, fill=\tikzumlclasstemplate, text=\tikzumlclasstext, font=\tikzumlfont] {\umlclassTemplateParam};% + }% + % + % add to fit + \ifnum\c@tikzumlPackageLevel>0% + \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}% + \ifthenelse{\equal{\umlclassTemplateParam}{}}{% + \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlClassNodeName)}% + }{% + \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlClassNodeName) (\tikzumlClassNodeName-template)}% + }% + \stepcounter{tikzumlPackageClassNum}% + \fi% + \ifnum\c@tikzumlComponentLevel>0% + \message{class \tikzumlComponent@parent{} @@@@ \tikzumlComponent@fitname} + \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname}% + \ifthenelse{\equal{\umlclassTemplateParam}{}}{% + \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlClassNodeName)}% + }{% + \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlClassNodeName) (\tikzumlClassNodeName-template)}% + }% + \stepcounter{tikzumlComponentSubComponentNum}% + \fi% +}% + +% shortcuts for interface, enum and typedef environments +\newcommand{\umlabstract}[4][]{\umlclass[type=abstract,#1]{#2}{#3}{#4}}% +\newcommand{\umlinterface}[4][]{\umlclass[type=interface,#1]{#2}{#3}{#4}}% +\newcommand{\umltypedef}[4][]{\umlclass[type=typedef,#1]{#2}{#3}{#4}}% +\newcommand{\umlenum}[4][]{\umlclass[type=enum,#1]{#2}{#3}{#4}}% + +% shortcut to define an empty class +\newcommand{\umlemptyclass}[2][]{\umlclass[#1]{#2}{}{}}% +\newcommand{\umlsimpleclass}[2][]{% + \pgfkeys{/tikzuml/friendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlCNfriend, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/friendrelation/.cd, #1}% + \umlemptyclass[simple, #1]{#2}% +}% + +% underline the text for static arg +\newcommand{\umlstatic}[1]{\underline{#1}}% +\newcommand{\umlvirt}[1]{\textit{#1}}% + +% define node for n-ary association +\newcommand{\umlNarynode}[2][]{% + \def\tikzumlNaryNodeAnchor{.north} + \def\tikzumlNaryNodeLabelPos{above} + \pgfkeys{/tikzuml/narynode/.cd,% + x/.initial=0, y/.initial=0, width/.initial=6ex, name/.initial={tikzumlEmpty},% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillclasscolor,% + text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{above}}{% + \def\tikzumlNaryNodeAnchor{.north}% + \def\tikzumlNaryNodeLabelPos{above}% + }{% + \ifthenelse{\equal{\keyname}{above left}}{% + \def\tikzumlNaryNodeAnchor{.north west}% + \def\tikzumlNaryNodeLabelPos{above left}% + }{% + \ifthenelse{\equal{\keyname}{left}}{% + \def\tikzumlNaryNodeAnchor{.west}% + \def\tikzumlNaryNodeLabelPos{left}% + }{% + \ifthenelse{\equal{\keyname}{below left}}{% + \def\tikzumlNaryNodeAnchor{.south west}% + \def\tikzumlNaryNodeLabelPos{below left}% + }{% + \ifthenelse{\equal{\keyname}{below}}{% + \def\tikzumlNaryNodeAnchor{.south}% + \def\tikzumlNaryNodeLabelPos{below}% + }{% + \ifthenelse{\equal{\keyname}{below right}}{% + \def\tikzumlNaryNodeAnchor{.south east}% + \def\tikzumlNaryNodeLabelPos{below right}% + }{% + \ifthenelse{\equal{\keyname}{right}}{% + \def\tikzumlNaryNodeAnchor{.east}% + \def\tikzumlNaryNodeLabelPos{right}% + }{% + \ifthenelse{\equal{\keyname}{above right}}{% + \def\tikzumlNaryNodeAnchor{.north east}% + \def\tikzumlNaryNodeLabelPos{above right}% + }{% + \errmessage{TIKZUML ERROR : in umlNarynode, invalid option \keyname}% + }% + }% + }% + }% + }% + }% + }% + }% + }}% + \pgfkeys{/tikzuml/narynode/.cd,#1}% + \pgfkeys{/tikzuml/narynode/.cd,% + x/.get=\umlnarynodeX, y/.get=\umlnarynodeY, width/.get=\umlnarynodeMinimumWidth,% + name/.get=\umlnaryName,% + draw/.get=\tikzumlnarynodedraw, fill/.get=\tikzumlnarynodefill,% + text/.get=\tikzumlnarynodetext}% + % + \def\tikzumlNaryName{#2}% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlNaryNodeName{\tikzumlNaryName}}\x% + % + \ifthenelse{\equal{\umlnaryName}{tikzumlEmpty}}{}{% + \def\tikzumlNaryNodeName{\umlnaryName}% + }% + % + \StrSubstitute{\tikzumlNaryNodeName}{:}{@COLON@}[\tikzumlNaryNodeName] + % + \def\tikzumlNarynodePos{\umlnarynodeX,\umlnarynodeY}% + % + \node[tikzuml narynode style, draw=\tikzumlnarynodedraw, fill=\tikzumlnarynodefill, text=\tikzumlnarynodetext, font=\tikzumlfont, minimum width=\umlnarynodeMinimumWidth, minimum height=\umlnarynodeMinimumWidth] (\tikzumlNaryNodeName) at (\tikzumlNarynodePos) {};% + \draw (\tikzumlNaryNodeName\tikzumlNaryNodeAnchor) node[\tikzumlNaryNodeLabelPos] {\tikzumlNaryName}; + % + % add to fit + \ifnum\c@tikzumlPackageLevel>0% + \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}% + \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlNaryNodeName)}% + \stepcounter{tikzumlPackageClassNum}% + \fi% +}% + +% main command to define a relation between two classes +% args : src class +% dest class +% optional : geometry of the line +% barycentric weight +% name of the src class type attribute defined by the relation +% multiplicity of the src class type attribute defined by the relation +% position on the relation +% text justification on the relation +% name of the dest class type attribute defined by the relation +% multiplicity of the dest class type attribute defined by the relation +% position on the relation +% anchors on linked classes +% text justification on the relation +% start angle, end angle and size of the relation (only if recursive) +% stereotype of the relation +% style of the relation (association, aggregation, composition, inherit, ...) +\newcommand{\umlrelation}[3][]{% + \pgfkeys{/tikzuml/relation/.cd,% + geometry/.initial=--, weight/.initial=0.5,% + arm1/.initial={auto}, arm2/.initial={auto},% + arg1/.initial={}, arg2/.initial={}, arg/.initial={},% + mult1/.initial={}, mult2/.initial={}, mult/.initial={},% + pos1/.initial=0.2, pos2/.initial=0.8, pos/.initial={tikzumlEmpty},% + align1/.initial={}, align2/.initial={}, align/.initial={},% + anchor1/.initial={tikzumlEmpty}, anchor2/.initial={tikzumlEmpty},% + angle1/.initial=-30, angle2/.initial=30, loopsize/.initial=3em,% + stereo/.initial={}, pos stereo/.initial=0.5,% + style/.initial=->, name/.initial=relation-\thetikzumlRelationNum,% + recursive mode/.initial=default, recursive direction start/.initial=right,% + recursive direction end/.initial=bottom,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{with port}% + \OR\equal{\keyname}{interface}% + \OR\equal{\keyname}{padding}% + \OR\equal{\keyname}{width}% + \OR\equal{\keyname}{first arm}% + \OR\equal{\keyname}{second arm}% + \OR\equal{\keyname}{middle arm}% + \OR\equal{\keyname}{last arm}% + \OR\equal{\keyname}{distance}}{}{% + \errmessage{TIKZUML ERROR : in umlrelation, invalid option \keyname}% + }% + }}% + \pgfkeys{/tikzuml/relation/.cd,#1}% + \pgfkeys{/tikzuml/relation/.cd,% + geometry/.get=\geometry, weight/.get=\weight, arm1/.get=\armO, arm2/.get=\armT,% + arg1/.get=\attrName, arg2/.get=\attrNameTO, arg/.get=\attrNameTT,% + mult1/.get=\multiplicity, mult2/.get=\multiplicityTO, mult/.get=\multiplicityTT,% + pos1/.get=\position, pos2/.get=\positionTO, pos/.get=\positionTT,% + align1/.get=\align, align2/.get=\alignTO, align/.get=\alignTT,% + anchor1/.get=\tikzumlSrcAnchor, anchor2/.get=\tikzumlDestAnchor,% + angle1/.get=\startangle, angle2/.get=\endangle, loopsize/.get=\loopsize,% + stereo/.get=\stereo, pos stereo/.get=\positionStereotype,% + style/.get=\style, name/.get=\relationName,% + recursive mode/.get=\tikzumlrecmode,% + recursive direction start/.get=\tikzumlrecdirstart,% + recursive direction end/.get=\tikzumlrecdirend}% + % + \def\tikzumlSrcClassName{#2}% + % + % managing \_ in class names for node names + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlSrcClassNodeName{\tikzumlSrcClassName}}\x% + % + \StrSubstitute{\tikzumlSrcClassNodeName}{:}{@COLON@}[\tikzumlSrcClassNodeName] + % + \def\tikzumlDestClassName{#3}% + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlDestClassNodeName{\tikzumlDestClassName}}\x% + % + \StrSubstitute{\tikzumlDestClassNodeName}{:}{@COLON@}[\tikzumlDestClassNodeName] + % + % managing alias keys + \def\attrNameT{\attrNameTO\attrNameTT}% + \def\multiplicityT{\multiplicityTO\multiplicityTT}% + \def\alignT{\alignTO\alignTT}% + \def\posAttrName{}% + \def\posMultiplicity{}% + \def\posAttrNameT{}% + \def\posMultiplicityT{}% + % + \ifthenelse{\equal{\positionTT}{tikzumlEmpty}}{% + \def\positionT{\positionTO}% + }{% + \def\positionT{\positionTT}% + }% + % + \def\attrAlign{}% + \def\multAlign{}% + \def\attrAlignT{}% + \def\multAlignT{}% + % + \ifthenelse{\equal{\align}{left}}{% + \def\attrAlign{above right}% + \def\multAlign{below right}% + }{% + \ifthenelse{\equal{\align}{right}}{% + \def\attrAlign{above left}% + \def\multAlign{below left}% + }{}% + }% + % + \ifthenelse{\equal{\alignT}{left}}{% + \def\attrAlignT{above right}% + \def\multAlignT{below right}% + }{% + \ifthenelse{\equal{\alignT}{right}}{% + \def\attrAlignT{above left}% + \def\multAlignT{below left}% + }{}% + }% + % + % def stereotype + \ifthenelse{\equal{\stereo}{}}{% + \def\stereotype{}% + }{% + \def\stereotype{\guillemotleft\stereo\guillemotright}% + }% + + % def anchors macros + \ifthenelse{\equal{\tikzumlSrcAnchor}{tikzumlEmpty}}{% + \def\tikzumlSrcAnchor{}% + }{% + \let\tikzumlSrcAnchorold\tikzumlSrcAnchor% + \def\tikzumlSrcAnchor{.\tikzumlSrcAnchorold}% + }% + % + \ifthenelse{\equal{\tikzumlDestAnchor}{tikzumlEmpty}}{% + \def\tikzumlDestAnchor{}% + }{% + \let\tikzumlDestAnchorold\tikzumlDestAnchor% + \def\tikzumlDestAnchor{.\tikzumlDestAnchorold}% + }% + % + \setcounter{pos}{100*\real{\position}}% + \setcounter{posT}{100*\real{\positionT}}% + \setcounter{posStereo}{100*\real{\positionStereotype}}% + % + \pgfmathsetmacro{\weightT}{1-\real{\weight}}% + % + \def\tikzumlControlNodesNum{0}% + % + \def\pos{\position}% + \def\posT{\positionT}% + \def\posStereo{\positionStereotype}% + % + \node[inner sep=0] (\relationName-middle) at (barycentric cs:\tikzumlSrcClassNodeName=\weightT,\tikzumlDestClassNodeName=\weight) {};% + % + % straight line + \ifthenelse{\equal{\geometry}{--}}{% + \ifthenelse{\equal{\tikzumlSrcClassNodeName}{\tikzumlDestClassNodeName}}{% + \def\arcNum{1}% + \def\arcNumT{1}% + % + \ifthenelse{\equal{\tikzumlrecmode}{default}}{% + \xdef\tikzumlLastArc{node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}% + node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}% + node[pos=\positionStereotype, anchor=center] {\stereotype} }% + \xdef\tikzumlPath{(\tikzumlSrcClassNodeName) edge[in=\endangle, out=\startangle, distance=\loopsize] \tikzumlLastArc% + node[midway, inner sep=0, name=\relationName-1, anchor=center] {} (\tikzumlDestClassNodeName) }% + }{% + \ifthenelse{\equal{\tikzumlrecmode}{transition}}{% + \xdef\tikzumlFirstArc{node[midway, inner sep=0, name=\relationName-1, anchor=center] {}}% + \xdef\tikzumlMidOneArc{node[midway, inner sep=0, name=\relationName-3, anchor=center] {}}% + % + \ifthenelse{\equal{\tikzumlrecdirstart}{\tikzumlrecdirend}}{% + \def\numArcs{3}% + \xdef\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-5, anchor=center] {}}% + % + \begin{pgfonlayer}{connections}% + \draw (\tikzumlSrcClassNodeName) edge[in=\endangle, out=\startangle, distance=\loopsize, draw=none] % + node[midway, inner sep=0, name=\relationName-tmp, anchor=center] {} (\tikzumlDestClassNodeName);% + \ifthenelse{\equal{\tikzumlrecdirstart}{right}\OR\equal{\tikzumlrecdirstart}{left}}{% + \node[inner sep=0, name=\relationName-2] at (\tikzumlSrcClassNodeName.\startangle -| \relationName-tmp) {};% + \node[inner sep=0, name=\relationName-4] at (\tikzumlDestClassNodeName.\endangle -| \relationName-tmp) {};% + }{% + \node[inner sep=0, name=\relationName-2] at (\tikzumlSrcClassNodeName.\startangle |- \relationName-tmp) {};% + \node[inner sep=0, name=\relationName-4] at (\tikzumlDestClassNodeName.\endangle |- \relationName-tmp) {};% + }% + \end{pgfonlayer}% + }{% + \def\numArcs{4}% + \xdef\tikzumlMidTwoArc{node[midway, inner sep=0, name=\relationName-5, anchor=center] {}}% + \xdef\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-7, anchor=center] {}}% + % + \begin{pgfonlayer}{connections}% + \draw (\tikzumlSrcClassNodeName) edge[in=\endangle, out=\startangle, distance=\loopsize, draw=none] % + node[midway, name=\relationName-4, anchor=center] {} (\tikzumlDestClassNodeName);% + \ifthenelse{\equal{\tikzumlrecdirstart}{right}\OR\equal{\tikzumlrecdirstart}{left}}{% + \node[inner sep=0, name=\relationName-2] at (\tikzumlSrcClassNodeName.\startangle -| \relationName-4) {};% + \node[inner sep=0, name=\relationName-6] at (\tikzumlDestClassNodeName.\endangle |- \relationName-4) {};% + }{% + \node[inner sep=0, name=\relationName-2] at (\tikzumlSrcClassNodeName.\startangle |- \relationName-4) {};% + \node[inner sep=0, name=\relationName-6] at (\tikzumlDestClassNodeName.\endangle -| \relationName-4) {};% + }% + \end{pgfonlayer}% + }% + % + \ifnum\numArcs=4% + \ifnum\theposStereo>300% + \pgfmathsetmacro{\posStereo}{(\theposStereo-300)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype}}% + \else% + \ifnum\theposStereo<100% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype}}% + \else% + \ifnum\theposStereo>200% + \pgfmathsetmacro{\posStereo}{(\theposStereo-200)/100}% + \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\posStereo, anchor=center] {\stereotype}}% + \else% + \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posStereo, anchor=center] {\stereotype}}% + \fi% + \fi% + \fi% + % + \ifthenelse{\thepos=300\OR\thepos=100}{% + \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{left}}{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirend}{left}}{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }% + }% + }% + }% + }{}% + % + \ifthenelse{\thepos=200}{% + \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{left}}{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirend}{left}}{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }% + }% + }% + }% + }{}% + % + \ifnum\thepos>300% + \pgfmathsetmacro{\pos}{(\thepos-300)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}% + }% + \else% + \ifnum\thepos<100% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}% + }% + \else% + \ifnum\thepos>200% + \pgfmathsetmacro{\pos}{(\thepos-200)/100}% + \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}% + }% + \else% + \pgfmathsetmacro{\pos}{(\thepos-100)/100}% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}% + }% + \fi% + \fi% + \fi% + % + \ifthenelse{\theposT=300\OR\theposT=100}{% + \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{left}}{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirend}{left}}{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }% + }% + }% + }% + }{}% + \ifthenelse{\theposT=200}{% + \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{% + \def\posAttrNameT{above left}% + \def\posMultiplicity{below right}% + }{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{bottom}}{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{% + \ifthenelse{\equal{\tikzumlrecdirend}{left}}{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirend}{left}}{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }% + }% + }% + }% + }{}% + % + \ifnum\theposT>300% + \pgfmathsetmacro{\posT}{(\theposT-300)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}% + }% + \else% + \ifnum\theposT<100% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}% + }% + \else% + \ifnum\theposT>200% + \pgfmathsetmacro{\posT}{(\theposT-200)/100}% + \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}% + }% + \else% + \pgfmathsetmacro{\posT}{(\theposT-100)/100}% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}% + }% + \fi% + \fi% + \fi% + \else% + \ifnum\theposStereo>200% + \pgfmathsetmacro{\posStereo}{(\theposStereo-200)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \else% + \ifnum\theposStereo<100% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \else% + \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \fi% + \fi% + % + \ifthenelse{\thepos=100}{% + \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }% + }{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }% + }% + }% + }% + }{}% + % + \ifthenelse{\thepos=200}{% + \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }% + }{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrName{above right}% + \def\posMultiplicity{below left}% + }{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }% + }% + }% + }% + }{}% + % + \ifnum\thepos>200% + \pgfmathsetmacro{\pos}{(\thepos-200)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}% + }% + \else% + \ifnum\thepos<100% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}% + }% + \else% + \pgfmathsetmacro{\pos}{(\thepos-100)/100}% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}% + }% + \fi% + \fi% + % + \ifthenelse{\theposT=100}{% + \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }% + }{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }% + }% + }% + }% + }{}% + % + \ifthenelse{\theposT=200}{% + \ifthenelse{\equal{\tikzumlrecdirstart}{right}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{left}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }% + }{% + \ifthenelse{\equal{\tikzumlrecdirstart}{top}}{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }% + }{% + \ifthenelse{\endangle<\startangle}{% + \def\posAttrNameT{above right}% + \def\posMultiplicityT{below left}% + }{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }% + }% + }% + }% + }{}% + % + \ifnum\theposT>200% + \pgfmathsetmacro{\posT}{(\theposT-200)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}% + }% + \else% + \ifnum\theposT<100% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}% + }% + \else% + \pgfmathsetmacro{\posT}{(\theposT-100)/100}% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}% + }% + \fi% + \fi% + \fi% + % + \ifthenelse{\equal{\tikzumlrecdirstart}{\tikzumlrecdirend}}{% + \xdef\tikzumlPath{(\tikzumlSrcClassNodeName.\startangle) -- \tikzumlFirstArc (\relationName-2.center) -- \tikzumlMidOneArc (\relationName-4.center) -- \tikzumlLastArc (\tikzumlDestClassNodeName.\endangle) }% + \ifnum\thetikzumlStateLevel>0% + \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) (\relationName-4) (\relationName-5)}% + \fi% + }{% + \xdef\tikzumlPath{(\tikzumlSrcClassNodeName.\startangle) -- \tikzumlFirstArc (\relationName-2.center) -- \tikzumlMidOneArc (\relationName-4.center) -- \tikzumlMidTwoArc (\relationName-6.center) -- \tikzumlLastArc (\tikzumlDestClassNodeName.\endangle) }% + \ifnum\thetikzumlStateLevel>0% + \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) (\relationName-4) (\relationName-5) (\relationName-6) (\relationName-7)}% + \fi% + }% + }{}% + }% + }{% + \def\arcNum{1}% + \def\arcNumT{1}% + % + \node[inner sep=0] (\relationName-1) at (\relationName-middle) {};% + \xdef\tikzumlLastArc{node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity}% + node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT}% + node[pos=\positionStereotype, anchor=center] {\stereotype} }% + \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }% + \ifnum\thetikzumlStateLevel>0% + \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) }% + \fi% + }% + }{% + % first vertical then horizontal line + \ifthenelse{\equal{\geometry}{|-}}% + {% + \def\tikzumlControlNodesNum{1}% + % + \def\tikzumlFirstArc{node[midway, inner sep=0, name=\relationName-1, anchor=center] {} }% + \def\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-3, anchor=center]{} }% + % + \begin{pgfonlayer}{connections}% + \node[inner sep=0] (\relationName-2) at (\tikzumlSrcClassNodeName\tikzumlSrcAnchor |- \tikzumlDestClassNodeName\tikzumlDestAnchor) {};% + \end{pgfonlayer}% + % + \ifnum\theposStereo>100% + \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \else% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \fi% + % + \ifnum\thepos>100% + \pgfmathsetmacro{\pos}{(\thepos-100)/100}% + \def\arcNum{2}% + \else% + \def\arcNum{1}% + \ifnum\thepos=100% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + \fi% + \fi% + % + \ifnum\arcNum=1% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + \ifnum\arcNum=2% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + % + \ifnum\theposT>100% + \pgfmathsetmacro{\posT}{(\theposT-100)/100}% + \def\arcNumT{2}% + \else% + \def\arcNumT{1}% + \ifnum\theposT=100% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + \fi% + \fi% + % + \ifnum\arcNumT=1% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + \ifnum\arcNumT=2% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + % + \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlFirstArc (\relationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }% + \ifnum\thetikzumlStateLevel>0% + \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) }% + \fi% + }{% + % first horizontal then vertical line + \ifthenelse{\equal{\geometry}{-|}}{% + \def\tikzumlControlNodesNum{1}% + % + \def\tikzumlFirstArc{node[midway, inner sep=0, name=\relationName-1, anchor=center]{} }% + \def\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-3, anchor=center] {} }% + % + \begin{pgfonlayer}{connections}% + \node[inner sep=0] (\relationName-2) at (\tikzumlSrcClassNodeName\tikzumlSrcAnchor -| \tikzumlDestClassNodeName\tikzumlDestAnchor) {};% + \end{pgfonlayer}% + % + \ifnum\theposStereo>100% + \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \else% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \fi% + % + \ifnum\thepos>100% + \pgfmathsetmacro{\pos}{(\thepos-100)/100}% + \def\arcNum{2}% + \else% + \def\arcNum{1}% + \ifnum\thepos=100% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + \fi% + \fi% + % + \ifnum\arcNum=1% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + \ifnum\arcNum=2% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + % + \ifnum\theposT>100% + \pgfmathsetmacro{\posT}{(\theposT-100)/100}% + \def\arcNumT{2}% + \else% + \def\arcNumT{1}% + \ifnum\theposT=100% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + \fi% + \fi% + % + \ifnum\arcNumT=1% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + \ifnum\arcNumT=2% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + % + \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlFirstArc (\relationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }% + \ifnum\thetikzumlStateLevel>0% + \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) }% + \fi% + }{% + % first vertical, then horizontal, finally vertical line + \ifthenelse{\equal{\geometry}{|-|}}{% + \def\tikzumlControlNodesNum{2}% + % + \def\tikzumlFirstArc{node[midway, inner sep=0, name=\relationName-1, anchor=center] {} }% + \def\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-5, anchor=center] {} }% + \def\tikzumlMidOneArc{ }% + % + \begin{pgfonlayer}{connections}% + % + \ifthenelse{\equal{\armO}{auto}}{% + \ifthenelse{\equal{\armT}{auto}}{% + \node[inner sep=0] (\relationName-3) at (\relationName-middle) {};% + \node[inner sep=0] (\relationName-2) at (\tikzumlSrcClassNodeName\tikzumlSrcAnchor |- \relationName-3) {};% + \node[inner sep=0] (\relationName-4) at (\relationName-3 -| \tikzumlDestClassNodeName\tikzumlDestAnchor) {};% + }{% + \draw (\tikzumlDestClassNodeName\tikzumlDestAnchor)+(0,\armT) node[inner sep=0, name=\relationName-4] {};% + \node[inner sep=0] (\relationName-2) at (\relationName-4 -| \tikzumlSrcClassNodeName\tikzumlSrcAnchor) {};% + \node[inner sep=0] (\relationName-3) at (barycentric cs:\relationName-2=0.5,\relationName-4=0.5) {};% + }% + }{% + \draw (\tikzumlSrcClassNodeName\tikzumlSrcAnchor)+(0,\armO) node[inner sep=0, name=\relationName-2] {};% + \node[inner sep=0] (\relationName-4) at (\relationName-2 -| \tikzumlDestClassNodeName\tikzumlDestAnchor) {};% + \node[inner sep=0] (\relationName-3) at (barycentric cs:\relationName-2=0.5,\relationName-4=0.5) {};% + }% + \end{pgfonlayer}% + % + \ifnum\theposStereo>200% + \pgfmathsetmacro{\posStereo}{(\theposStereo-200)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \else% + \ifnum\theposStereo<100% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \else% + \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \fi% + \fi% + % + \ifthenelse{\thepos=200\OR\thepos=100}{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }{}% + % + \ifthenelse{\thepos>200}{% + \pgfmathsetmacro{\pos}{(\thepos-200)/100}% + \def\arcNum{3}% + }{% + \ifthenelse{\thepos<100}{% + \def\arcNum{1}% + }{% + \pgfmathsetmacro{\pos}{(\thepos-100)/100}% + \def\arcNum{2}% + }% + }% + % + \ifnum\arcNum=1% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + \ifnum\arcNum=2% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + \ifnum\arcNum=3% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + % + \ifthenelse{\theposT=200\OR\theposT=100}{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }{}% + % + \ifthenelse{\theposT>200}{% + \pgfmathsetmacro{\posT}{(\theposT-200)/100}% + \def\arcNumT{3}% + }{% + \ifthenelse{\theposT<100}{% + \def\arcNumT{1}% + }{% + \pgfmathsetmacro{\posT}{(\theposT-100)/100}% + \def\arcNumT{2}% + }% + }% + % + \ifnum\arcNumT=1% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + \ifnum\arcNumT=2% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + \ifnum\arcNumT=3% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + % + \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlFirstArc (\relationName-2.base) -- \tikzumlMidOneArc (\relationName-4.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }% + \ifnum\thetikzumlStateLevel>0% + \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) (\relationName-4) (\relationName-5) }% + \fi% + }{% + % first horizontal, then vertical, finally horizontal line + \ifthenelse{\equal{\geometry}{-|-}}{% + \def\tikzumlControlNodesNum{2}% + % + \def\tikzumlFirstArc{node[midway, inner sep=0, name=\relationName-1, anchor=center] {} }% + \def\tikzumlLastArc{node[midway, inner sep=0, name=\relationName-5, anchor=center] {} }% + \def\tikzumlMidOneArc{}% + % + \begin{pgfonlayer}{connections}% + % + \ifthenelse{\equal{\armO}{auto}}{% + \ifthenelse{\equal{\armT}{auto}}{% + \node[inner sep=0] (\relationName-3) at (\relationName-middle) {};% + \node[inner sep=0] (\relationName-2) at (\tikzumlSrcClassNodeName\tikzumlSrcAnchor -| \relationName-3) {};% + \node[inner sep=0] (\relationName-4) at (\relationName-3 |- \tikzumlDestClassNodeName\tikzumlDestAnchor) {};% + }{% + \draw (\tikzumlDestClassNodeName\tikzumlDestAnchor)+(\armT,0) node[inner sep=0, name=\relationName-4] {};% + \node[inner sep=0] (\relationName-2) at (\relationName-4 |- \tikzumlSrcClassNodeName\tikzumlSrcAnchor) {};% + \node[inner sep=0] (\relationName-3) at (barycentric cs:\relationName-2=0.5,\relationName-4=0.5) {};% + }% + }{% + \draw (\tikzumlSrcClassNodeName\tikzumlSrcAnchor)+(\armO,0) node[inner sep=0, name=\relationName-2] {};% + \node[inner sep=0] (\relationName-4) at (\relationName-2 |- \tikzumlDestClassNodeName\tikzumlDestAnchor) {};% + \node[inner sep=0] (\relationName-3) at (barycentric cs:\relationName-2=0.5,\relationName-4=0.5) {};% + }% + \end{pgfonlayer}% + % + % + \ifnum\theposStereo>200% + \pgfmathsetmacro{\posStereo}{(\theposStereo-200)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \else% + \ifnum\theposStereo<100% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \else% + \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \fi% + \fi% + % + \ifthenelse{\thepos=200\OR\thepos=100}{% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + }{}% + % + \ifthenelse{\thepos>200}{% + \pgfmathsetmacro{\pos}{(\thepos-200)/100}% + \def\arcNum{3}% + }{% + \ifthenelse{\thepos<100}{% + \def\arcNum{1}% + }{% + \pgfmathsetmacro{\pos}{(\thepos-100)/100}% + \def\arcNum{2}% + }% + }% + % + \ifnum\arcNum=1% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + \ifnum\arcNum=2% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + \ifnum\arcNum=3% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + % + \ifthenelse{\theposT=200\OR\theposT=100}{% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + }{}% + % + \ifthenelse{\theposT>200}{% + \pgfmathsetmacro{\posT}{(\theposT-200)/100}% + \def\arcNumT{3}% + }{% + \ifthenelse{\theposT<100}{% + \def\arcNumT{1}% + }{% + \pgfmathsetmacro{\posT}{(\theposT-100)/100}% + \def\arcNumT{2}% + }% + }% + % + \ifnum\arcNumT=1% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + \ifnum\arcNumT=2% + \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + \ifnum\arcNumT=3% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + % + \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlFirstArc (\relationName-2.base) -- \tikzumlMidOneArc (\relationName-4.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }% + \ifnum\thetikzumlStateLevel>0% + \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\relationName-1) (\relationName-2) (\relationName-3) (\relationName-4) (\relationName-5) }% + \fi% + }{% + \errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-}% + }% + }% + }% + }% + }% + % + \begin{pgfonlayer}{connections}% + \draw[auto, \style, font=\tikzumlfont] \tikzumlPath ;% + \end{pgfonlayer}% + % + \stepcounter{tikzumlRelationNum}% +}% + +% shortcuts of \umlrelation +\newcommand{\umlHVrelation}[3][]{% + \pgfkeys{/tikzuml/HVrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVrelation, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/HVrelation/.cd, #1}% + \umlrelation[geometry=-|, #1]{#2}{#3}% +}% + +\newcommand{\umlVHrelation}[3][]{% + \pgfkeys{/tikzuml/VHrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHrelation, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/VHrelation/.cd, #1}% + \umlrelation[geometry=|-, #1]{#2}{#3}% +}% + +\newcommand{\umlHVHrelation}[3][]{% + \pgfkeys{/tikzuml/HVHrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVHrelation, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/HVHrelation/.cd, #1}% + \umlrelation[geometry=-|-, #1]{#2}{#3}% +}% + +\newcommand{\umlVHVrelation}[3][]{% + \pgfkeys{/tikzuml/VHVrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHVrelation, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/VHVrelation/.cd, #1}% + \umlrelation[geometry=|-|, #1]{#2}{#3}% +}% + +% shortcuts for relations +\newcommand{\umlinherit}[3][]{\umlrelation[style={tikzuml inherit style}, #1]{#2}{#3}}% +\newcommand{\umlimpl}[3][]{\umlrelation[style={tikzuml implements style}, #1]{#2}{#3}}% +\newcommand{\umlreal}[3][]{\umlrelation[style={tikzuml implements style}, #1]{#2}{#3}}% +\newcommand{\umlassoc}[3][]{\umlrelation[style={tikzuml association style}, #1]{#2}{#3}}% +\newcommand{\umlbiassoc}[3][]{\umlrelation[style={tikzuml bidirectional association style}, #1]{#2}{#3}}% +\newcommand{\umluniassoc}[3][]{\umlrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}% +\newcommand{\umlaggreg}[3][]{\umlrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}% +\newcommand{\umluniaggreg}[3][]{\umlrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}% +\newcommand{\umlcompo}[3][]{\umlrelation[style={tikzuml composition style}, #1]{#2}{#3}}% +\newcommand{\umlunicompo}[3][]{\umlrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}% +\newcommand{\umlimport}[3][]{\umlrelation[style={tikzuml import style}, #1]{#2}{#3}}% +\newcommand{\umldep}[3][]{\umlrelation[style={tikzuml dependency style}, #1]{#2}{#3}}% +\newcommand{\umlfriend}[3][]{% + \pgfkeys{/tikzuml/friendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlfriend, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/friendrelation/.cd, #1}% + \umlrelation[stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}% +}% + +\newcommand{\umlHVinherit}[3][]{\umlHVrelation[style={tikzuml inherit style}, #1]{#2}{#3}}% +\newcommand{\umlHVimpl}[3][]{\umlHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}% +\newcommand{\umlHVreal}[3][]{\umlHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}% +\newcommand{\umlHVassoc}[3][]{\umlHVrelation[style={tikzuml association style}, #1]{#2}{#3}}% +\newcommand{\umlHVuniassoc}[3][]{\umlHVrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}% +\newcommand{\umlHVaggreg}[3][]{\umlHVrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}% +\newcommand{\umlHVuniaggreg}[3][]{\umlHVrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}% +\newcommand{\umlHVcompo}[3][]{\umlHVrelation[style={tikzuml composition style}, #1]{#2}{#3}}% +\newcommand{\umlHVunicompo}[3][]{\umlHVrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}% +\newcommand{\umlHVimport}[3][]{\umlHVrelation[style={tikzuml import style}, #1]{#2}{#3}}% +\newcommand{\umlHVdep}[3][]{\umlHVrelation[style={tikzuml dependency style}, #1]{#2}{#3}}% +\newcommand{\umlHVfriend}[3][]{% + \pgfkeys{/tikzuml/friendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlHVfriend, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVfriend, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/friendrelation/.cd, #1}% + \umlrelation[geometry=-|, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}% +}% + +\newcommand{\umlVHinherit}[3][]{\umlVHrelation[style={tikzuml inherit style}, #1]{#2}{#3}}% +\newcommand{\umlVHimpl}[3][]{\umlVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}% +\newcommand{\umlVHreal}[3][]{\umlVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}% +\newcommand{\umlVHassoc}[3][]{\umlVHrelation[style={tikzuml association style}, #1]{#2}{#3}}% +\newcommand{\umlVHuniassoc}[3][]{\umlVHrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}% +\newcommand{\umlVHaggreg}[3][]{\umlVHrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}% +\newcommand{\umlVHuniaggreg}[3][]{\umlVHrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}% +\newcommand{\umlVHcompo}[3][]{\umlVHrelation[style={tikzuml composition style}, #1]{#2}{#3}}% +\newcommand{\umlVHunicompo}[3][]{\umlVHrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}% +\newcommand{\umlVHimport}[3][]{\umlVHrelation[style={tikzuml import style}, #1]{#2}{#3}}% +\newcommand{\umlVHdep}[3][]{\umlVHrelation[style={tikzuml dependency style}, #1]{#2}{#3}}% +\newcommand{\umlVHfriend}[3][]{% + \pgfkeys{/tikzuml/friendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlVHfriend, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHfriend, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/friendrelation/.cd, #1}% + \umlrelation[geometry=|-, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}% +}% + +\newcommand{\umlHVHinherit}[3][]{\umlHVHrelation[style={tikzuml inherit style}, #1]{#2}{#3}}% +\newcommand{\umlHVHimpl}[3][]{\umlHVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}% +\newcommand{\umlHVHreal}[3][]{\umlHVHrelation[style={tikzuml implements style}, #1]{#2}{#3}}% +\newcommand{\umlHVHassoc}[3][]{\umlHVHrelation[style={tikzuml association style}, #1]{#2}{#3}}% +\newcommand{\umlHVHuniassoc}[3][]{\umlHVHrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}% +\newcommand{\umlHVHaggreg}[3][]{\umlHVHrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}% +\newcommand{\umlHVHuniaggreg}[3][]{\umlHVHrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}% +\newcommand{\umlHVHcompo}[3][]{\umlHVHrelation[style={tikzuml composition style}, #1]{#2}{#3}}% +\newcommand{\umlHVHunicompo}[3][]{\umlHVHrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}% +\newcommand{\umlHVHimport}[3][]{\umlHVHrelation[style={tikzuml import style}, #1]{#2}{#3}}% +\newcommand{\umlHVHdep}[3][]{\umlHVHrelation[style={tikzuml dependency style}, #1]{#2}{#3}}% +\newcommand{\umlHVHfriend}[3][]{% + \pgfkeys{/tikzuml/friendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlHVHfriend, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVHfriend, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/friendrelation/.cd, #1}% + \umlrelation[geometry=-|-, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}% +}% + +\newcommand{\umlVHVinherit}[3][]{\umlVHVrelation[style={tikzuml inherit style}, #1]{#2}{#3}}% +\newcommand{\umlVHVimpl}[3][]{\umlVHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}% +\newcommand{\umlVHVreal}[3][]{\umlVHVrelation[style={tikzuml implements style}, #1]{#2}{#3}}% +\newcommand{\umlVHVassoc}[3][]{\umlVHVrelation[style={tikzuml association style}, #1]{#2}{#3}}% +\newcommand{\umlVHVuniassoc}[3][]{\umlVHVrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}}% +\newcommand{\umlVHVaggreg}[3][]{\umlVHVrelation[style={tikzuml aggregation style}, #1]{#2}{#3}}% +\newcommand{\umlVHVuniaggreg}[3][]{\umlVHVrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}}% +\newcommand{\umlVHVcompo}[3][]{\umlVHVrelation[style={tikzuml composition style}, #1]{#2}{#3}}% +\newcommand{\umlVHVunicompo}[3][]{\umlVHVrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}}% +\newcommand{\umlVHVimport}[3][]{\umlVHVrelation[style={tikzuml import style}, #1]{#2}{#3}}% +\newcommand{\umlVHVdep}[3][]{\umlVHVrelation[style={tikzuml dependency style}, #1]{#2}{#3}}% +\newcommand{\umlVHVfriend}[3][]{% + \pgfkeys{/tikzuml/friendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlVHVfriend, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHVfriend, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/friendrelation/.cd, #1}% + \umlrelation[geometry=|-|, stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}% +}% + +% define a node +\newcommand{\umlnode}[2]{% + \node (#2) at (#1) {};% +}% + +% main command to define a relation between two classes through a control node +% args : src class +% control node +% dest class +% optional : geometry of the line +% barycentric weight +% name of the src class type attribute defined by the relation +% multiplicity of the src class type attribute defined by the relation +% position on the relation +% text justification on the relation +% name of the dest class type attribute defined by the relation +% multiplicity of the dest class type attribute defined by the relation +% position on the relation +% border anchors +% text justification on the relation +% start angle, end angle and size of the relation (only if recursive) +% stereotype of the relation +% style of the relation (association, aggregation, composition, inherit, ...) +\newcommand{\umlCNrelation}[4][]% +{% + \pgfkeys{/tikzuml/relation/.cd,% + arg1/.initial={}, arg2/.initial={}, arg/.initial={},% + mult1/.initial={}, mult2/.initial={}, mult/.initial={},% + pos1/.initial=0.2, pos2/.initial=0.8, pos/.initial={tikzumlEmpty},% + align1/.initial={}, align2/.initial={}, align/.initial={},% + anchor1/.initial={tikzumlEmpty}, anchor2/.initial={tikzumlEmpty},% + stereo/.initial={}, pos stereo/.initial=1,% + style/.initial=->, name/.initial=relation-\thetikzumlRelationNum,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlCNrelation, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/relation/.cd,#1}% + \pgfkeys{/tikzuml/relation/.cd,% + arg1/.get=\attrName, arg2/.get=\attrNameTO, arg/.get=\attrNameTT,% + mult1/.get=\multiplicity, mult2/.get=\multiplicityTO, mult/.get=\multiplicityTT,% + pos1/.get=\position, pos2/.get=\positionTO, pos/.get=\positionTT,% + align1/.get=\align, align2/.get=\alignTO, align/.get=\alignTT,% + anchor1/.get=\tikzumlSrcAnchor, anchor2/.get=\tikzumlDestAnchor,% + stereo/.get=\stereo, pos stereo/.get=\positionStereotype,% + style/.get=\style, name/.get=\relationName}% + % + % managing \_ in class names for node names + \def\tikzumlSrcClassName{#2}% + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlSrcClassNodeName{\tikzumlSrcClassName}}\x% + % + \StrSubstitute{\tikzumlSrcClassNodeName}{:}{@COLON@}[\tikzumlSrcClassNodeName] + % + \def\tikzumlDestClassName{#4}% + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlDestClassNodeName{\tikzumlDestClassName}}\x% + % + \StrSubstitute{\tikzumlDestClassNodeName}{:}{@COLON@}[\tikzumlDestClassNodeName] + % + % managing alias keys + \def\attrNameT{\attrNameTO\attrNameTT}% + \def\multiplicityT{\multiplicityTO\multiplicityTT}% + \def\alignT{\alignTO\alignTT}% + \def\orientationT{\orientationTO\orientationTT}% + % + \ifthenelse{\equal{\positionTT}{tikzumlEmpty}}{% + \def\positionT{\positionTO}% + }{% + \def\positionT{\positionTT}% + }% + % + \def\attrAlign{}% + \def\multAlign{}% + \def\attrAlignT{}% + \def\multAlignT{}% + % + \ifthenelse{\equal{\align}{left}}{% + \def\attrAlign{above right}% + \def\multAlign{below right}% + }{% + \ifthenelse{\equal{\align}{right}}{% + \def\attrAlign{above left}% + \def\multAlign{below left}% + }{}% + }% + % + \ifthenelse{\equal{\alignT}{left}}{% + \def\attrAlignT{above right}% + \def\multAlignT{below right}% + }{% + \ifthenelse{\equal{\alignT}{right}}{% + \def\attrAlignT{above left}% + \def\multAlignT{below left}% + }{}% + }% + % + % def stereotype + \ifthenelse{\equal{\stereo}{}}{% + \def\stereotype{}% + }{% + \def\stereotype{\guillemotleft\stereo\guillemotright}% + }% + % + % def anchors macros + \ifthenelse{\equal{\tikzumlSrcAnchor}{tikzumlEmpty}}{% + \def\tikzumlSrcAnchor{}% + }{% + \let\tikzumlSrcAnchorold\tikzumlSrcAnchor% + \def\tikzumlSrcAnchor{.\tikzumlSrcAnchorold}% + }% + % + \ifthenelse{\equal{\tikzumlDestAnchor}{tikzumlEmpty}}{% + \def\tikzumlDestAnchor{}% + }{% + \let\tikzumlDestAnchorold\tikzumlDestAnchor% + \def\tikzumlDestAnchor{.\tikzumlDestAnchorold}% + }% + % + \setcounter{pos}{100*\real{\position}}% + \setcounter{posT}{100*\real{\positionT}}% + \setcounter{posStereo}{100*\real{\positionStereotype}}% + % + \def\pos{\position}% + \def\posT{\positionT}% + \def\posStereo{\positionStereotype}% + % + % straight line + \def\tikzumlControlNodesNum{1}% + % + \def\tikzumlFirstArc{node[midway, name=\relationName-1, anchor=center] {} }% + \def\tikzumlLastArc{node[midway, name=\relationName-3, anchor=center]{} }% + \def\posAttrName{}% + \def\posMultiplicity{}% + \def\posAttrNameT{}% + \def\posMultiplicityT{}% + % + \begin{pgfonlayer}{connections}% + \node (\relationName-2) at (#3) {};% + \end{pgfonlayer}% + % + \ifnum\theposStereo>100% + \pgfmathsetmacro{\posStereo}{(\theposStereo-100)/100}% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \else% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posStereo, anchor=center] {\stereotype} }% + \fi% + % + \ifnum\thepos>100% + \pgfmathsetmacro{\pos}{(\thepos-100)/100}% + \def\arcNum{2}% + \else% + \def\arcNum{1}% + \ifnum\thepos=100% + \def\posAttrName{above left}% + \def\posMultiplicity{below right}% + \fi% + \fi% + % + \ifnum\arcNum=1% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + \ifnum\arcNum=2% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\pos, \posAttrName, \attrAlign] {\attrName}% + node[pos=\pos, swap, \posMultiplicity, \multAlign] {\multiplicity} }% + \fi% + % + \ifnum\theposT>100% + \pgfmathsetmacro{\posT}{(\theposT-100)/100}% + \def\arcNumT{2}% + \else% + \def\arcNumT{1}% + \ifnum\theposT=100% + \def\posAttrNameT{above left}% + \def\posMultiplicityT{below right}% + \fi% + \fi% + % + \ifnum\arcNumT=1% + \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + \ifnum\arcNumT=2% + \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\posT, \posAttrNameT, \attrAlignT] {\attrNameT}% + node[pos=\posT, swap, \posMultiplicityT, \multAlignT] {\multiplicityT} }% + \fi% + % + \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlSrcAnchor) -- \tikzumlFirstArc (\relationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlDestAnchor) }% + + \begin{pgfonlayer}{connections}% + \draw[auto, \style, font=\tikzumlfont] \tikzumlPath ;% + \end{pgfonlayer}% + % + \stepcounter{tikzumlRelationNum}% +}% + +% shortcuts for cnrelations +\newcommand{\umlCNinherit}[4][]{\umlCNrelation[style={tikzuml inherit style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNimpl}[4][]{\umlCNrelation[style={tikzuml implements style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNreal}[4][]{\umlCNrelation[style={tikzuml implements style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNassoc}[4][]{\umlCNrelation[style={tikzuml association style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNuniassoc}[4][]{\umlCNrelation[style={tikzuml unidirectional association style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNaggreg}[4][]{\umlCNrelation[style={tikzuml aggregation style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNuniaggreg}[4][]{\umlCNrelation[style={tikzuml unidirectional aggregation style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNcompo}[4][]{\umlCNrelation[style={tikzuml composition style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNunicompo}[4][]{\umlCNrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNimport}[4][]{\umlCNrelation[style={tikzuml import style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNdep}[4][]{\umlCNrelation[style={tikzuml dependency style}, #1]{#2}{#3}{#4}}% +\newcommand{\umlCNfriend}[4][]{% + \pgfkeys{/tikzuml/friendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlCNfriend, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/friendrelation/.cd, #1}% + \umlCNrelation[stereo=friend, style={tikzuml dependency style}, #1]{#2}{#3}{#4}% +}% + +% define a note +% arg : attached class +% label of the note +% optional : x,y coordinates of the note +% width of the note +% draw, fill, text colors +\newcommand{\umlnote}[3][]{ + \pgfkeys{/tikzuml/note/.cd,% + x/.initial=0, y/.initial=0, width/.initial=3cm, geometry/.initial=--,% + weight/.initial=0.5, arm/.initial={auto},% + anchor1/.initial={tikzumlEmpty}, anchor2/.initial={tikzumlEmpty},% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillnotecolor,% + text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlnote, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/note/.cd, #1}% + \pgfkeys{/tikzuml/note/.cd,% + x/.get=\tikzumlnoteX, y/.get=\tikzumlnoteY, width/.get=\notetextwidth,% + geometry/.get=\tikzumlnotegeometry,% + weight/.get=\tikzumlnoteweight, arm/.get=\tikzumlnotearm,% + anchor1/.get=\tikzumlnoteSrcAnchor, anchor2/.get=\tikzumlnoteDestAnchor,% + draw/.get=\tikzumlnotedraw, fill/.get=\tikzumlnotefill,% + text/.get=\tikzumlnotetext}% + % + \def\tikzumlClassName{#2}% + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlClassNodeName{\tikzumlClassName}}\x% + % + % def anchors macros + \ifthenelse{\equal{\tikzumlnoteSrcAnchor}{tikzumlEmpty}}{% + \def\tikzumlnoteSrcAnchor{}% + }{% + \let\tikzumlnoteSrcAnchorold\tikzumlnoteSrcAnchor% + \def\tikzumlnoteSrcAnchor{.\tikzumlnoteSrcAnchorold}% + }% + % + \ifthenelse{\equal{\tikzumlnoteDestAnchor}{tikzumlEmpty}}{% + \def\tikzumlnoteDestAnchor{}% + }{% + \let\tikzumlnoteDestAnchorold\tikzumlnoteDestAnchor% + \def\tikzumlnoteDestAnchor{.\tikzumlnoteDestAnchorold}% + }% + % + \node[text=\tikzumlnotetext, text width=\notetextwidth, font=\tikzumlfont, outer sep=0, inner xsep=1ex, inner ysep=3ex] (note-\thetikzumlNoteNum-coord) at (\tikzumlnoteX, \tikzumlnoteY) {#3};% + \draw (note-\thetikzumlNoteNum-coord.north east) node[name=note-\thetikzumlNoteNum-right-top, below=2ex, coordinate] {};% + \draw (note-\thetikzumlNoteNum-coord.north east) node[name=note-\thetikzumlNoteNum-top-right, left=2ex, coordinate] {};% + \draw[draw=\tikzumlnotedraw, fill=\tikzumlnotefill] (note-\thetikzumlNoteNum-coord.south west) -- (note-\thetikzumlNoteNum-coord.south east) -- (note-\thetikzumlNoteNum-right-top.base) -- (note-\thetikzumlNoteNum-top-right.base) -- (note-\thetikzumlNoteNum-coord.north west) -- cycle;% + \node[text=\tikzumlnotetext, text width=\notetextwidth, outer sep=0, inner xsep=1ex, inner ysep=3ex, font=\tikzumlfont] (note-\thetikzumlNoteNum) at (note-\thetikzumlNoteNum-coord) {#3};% + \draw[draw=\tikzumlnotedraw] (note-\thetikzumlNoteNum-right-top) -| (note-\thetikzumlNoteNum-top-right);% + % + \pgfmathsetmacro{\tikzumlnoteweightT}{1-\tikzumlnoteweight}% + \node (note-\thetikzumlNoteNum-middle) at (barycentric cs:note-\thetikzumlNoteNum-coord=\tikzumlnoteweight,\tikzumlClassNodeName=\tikzumlnoteweightT) {};% + % + \ifthenelse{\equal{\tikzumlnotegeometry}{--}% + \OR\equal{\tikzumlnotegeometry}{-|}% + \OR\equal{\tikzumlnotegeometry}{|-}}{% + \edef\tikzumlnotepath{\tikzumlnotegeometry} + }{% + \ifthenelse{\equal{\tikzumlnotegeometry}{-|-}}{% + \ifthenelse{\equal{\tikzumlnotearm}{auto}}{% + \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-coord\tikzumlnoteSrcAnchor -| note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center |- \tikzumlClassNodeName\tikzumlnoteDestAnchor) --}% + }{% + \draw (note-\thetikzumlNoteNum-coord\tikzumlnoteSrcAnchor)+(\tikzumlnotearm,0) node[name=note-\thetikzumlNoteNum-tmp] {}; + \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-tmp.center) |-}% + }% + }{% + \ifthenelse{\equal{\tikzumlnotegeometry}{|-|}}{% + \ifthenelse{\equal{\tikzumlnotearm}{auto}}{% + \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-coord\tikzumlnoteSrcAnchor |- note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center) -- (note-\thetikzumlNoteNum-middle.center -| \tikzumlClassNodeName\tikzumlnoteDestAnchor) --}% + }{% + \draw (note-\thetikzumlNoteNum-coord\tikzumlnoteSrcAnchor)+(0,\tikzumlnotearm) node[name=note-\thetikzumlNoteNum-tmp] {}; + \edef\tikzumlnotepath{-- (note-\thetikzumlNoteNum-tmp.center) -|}% + }% + + }{% + \errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-}% + }% + }% + }% + % + \begin{pgfonlayer}{connections}% + \draw[dashed] (note-\thetikzumlNoteNum-coord\tikzumlnoteSrcAnchor) \tikzumlnotepath (\tikzumlClassNodeName\tikzumlnoteDestAnchor);% + \end{pgfonlayer}% + % + \stepcounter{tikzumlNoteNum}% +}% + +% shortcuts for note with geometry +\newcommand{\umlHVnote}[3][]{% + \pgfkeys{/tikzuml/note/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVnote, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/note/.cd, #1}% + \umlnote[geometry=-|, #1]{#2}{#3}% +}% +\newcommand{\umlVHnote}[3][]{% + \pgfkeys{/tikzuml/note/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHnote, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/note/.cd, #1}% + \umlnote[geometry=|-, #1]{#2}{#3}% +}% +\newcommand{\umlVHVnote}[3][]{% + \pgfkeys{/tikzuml/note/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHVnote, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/note/.cd, #1}% + \umlnote[geometry=|-|, #1]{#2}{#3}% +}% +\newcommand{\umlHVHnote}[3][]{% + \pgfkeys{/tikzuml/note/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVHnote, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/note/.cd, #1}% + \umlnote[geometry=-|-, #1]{#2}{#3}% +}% + +% define a uml association class (command) +% args : name of the class +% attributes of the class +% operations of the class +% optional : x,y coordinates of the class +% width of the class node +% type of class (class, interface, typedef, enum) +% template parameters +% draw, fill, text colors +\newcommand{\umlassocclass}[5][]{% + \pgfkeys{/tikzuml/assocclass/.cd,% + x/.initial=0, y/.initial=0, width/.initial=10ex, type/.initial=class,% + template/.initial={}, name/.initial={tikzumlEmpty}, geometry/.initial=--,% + weight/.initial=0.5, arm/.initial={auto},% + anchor1/.initial={tikzumlEmpty}, anchor2/.initial={tikzumlEmpty},% + draw/.initial=\tikzumldrawcolor,% + fill template/.initial=\tikzumlfilltemplatecolor,% + fill/.initial=\tikzumlfillclasscolor,% + text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlassocclass, invalid option \keyname}% + }}% + % + \pgfkeys{/tikzuml/assocclass/.cd,#1}% + \pgfkeys{/tikzuml/assocclass/.cd,% + x/.get=\umlassocclassX, y/.get=\umlassocclassY,% + width/.get=\umlassocclassMinimumWidth, type/.get=\umlassocclassType,% + template/.get=\umlassocclassTemplateParam,% + name/.get=\umlassocclassName, geometry/.get=\tikzumlassocclassgeometry,% + weight/.get=\tikzumlassocclassweight, arm/.get=\tikzumlassocclassarm,% + anchor1/.get=\tikzumlassocclassSrcAnchor,% + anchor2/.get=\tikzumlassocclassDestAnchor,% + draw/.get=\tikzumlassocclassdraw, fill/.get=\tikzumlassocclassfill,% + text/.get=\tikzumlassocclasstext, fill template/.get=\tikzumlassocclasstemplate}% + % + \ifthenelse{\equal{\umlassocclassType}{class}\OR\equal{\umlassocclassType}{abstract}}{% + \def\tikzumlAssocClassType{}% + }{% + \def\tikzumlAssocClassType{\guillemotleft\umlassocclassType\guillemotright \\}% + }% + % + \ifthenelse{\equal{\umlassocclassTemplateParam}{}}{% + \def\tikzumlAssocClassVPadding{}% + \def\tikzumlAssocClassHPadding{}% + }{% + \def\tikzumlAssocClassVPadding{\vspace{0.1em} \\}% + \def\tikzumlAssocClassHPadding{\hspace{0.5ex} $ $}% + }% + % + \def\tikzumlAssocClassName{#2}% + \def\tikzumlAssocClassRelationName{#3}% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlAssocClassNodeName{\tikzumlAssocClassName}}\x% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlAssocClassRelationNodeName{\tikzumlAssocClassRelationName}}\x% + % + \ifthenelse{\equal{\umlassocclassName}{tikzumlEmpty}}{}{% + \def\tikzumlAssocClassNodeName{\umlassocclassName}% + }% + % + \StrSubstitute{\tikzumlAssocClassNodeName}{:}{@COLON@}[\tikzumlAssocClassNodeName] + % + \ifthenelse{\equal{\umlassocclassType}{abstract}}{% + \let\tikzumlAssocClassNameOld\tikzumlAssocClassName% + \def\tikzumlAssocClassName{{\it \tikzumlAssocClassNameOld}}% + }{}% + % + \def\tikzumlAssocClassPos{\umlassocclassX,\umlassocclassY}% + \def\tikzumlAssocClassAttributes{#4}% + \def\tikzumlAssocClassOperations{#5}% + % + % def anchors macros + \ifthenelse{\equal{\tikzumlassocclassSrcAnchor}{tikzumlEmpty}}{% + \def\tikzumlassocclassSrcAnchor{}% + }{% + \let\tikzumlassocclassSrcAnchorold\tikzumlassocclassSrcAnchor% + \def\tikzumlassocclassSrcAnchor{.\tikzumlassocclassSrcAnchorold}% + }% + % + \ifthenelse{\equal{\tikzumlassocclassDestAnchor}{tikzumlEmpty}}{% + \def\tikzumlassocclassDestAnchor{}% + }{% + \let\tikzumlassocclassDestAnchorold\tikzumlassocclassDestAnchor% + \def\tikzumlassocclassDestAnchor{.\tikzumlassocclassDestAnchorold}% + }% + % + \node[tikzuml class style, draw=\tikzumlassocclassdraw, fill=\tikzumlassocclassfill, text=\tikzumlassocclasstext, font=\tikzumlfont, minimum width=\umlassocclassMinimumWidth] (\tikzumlAssocClassNodeName) at (\tikzumlAssocClassPos) {\begin{tabular}{c}\tikzumlAssocClassVPadding \tikzumlAssocClassType \tikzumlAssocClassHPadding \textbf{\tikzumlAssocClassName} \tikzumlAssocClassHPadding \end{tabular}% + \nodepart{second}% + \begin{tabular}{l}% + \tikzumlAssocClassAttributes% + \end{tabular}% + \nodepart{third}% + \begin{tabular}{l}% + \tikzumlAssocClassOperations% + \end{tabular}% + };% + % + \ifthenelse{\equal{\umlassocclassTemplateParam}{}}{}{% + \draw (\tikzumlAssocClassNodeName.north east) node[tikzuml template style, name=\tikzumlAssocClassNodeName-template, draw=\tikzumlassocclassdraw, fill=\tikzumlassocclasstemplate, text=\tikzumlassocclasstext, font=\tikzumlfont] {\umlassocclassTemplateParam};% + }% + % + \pgfmathsetmacro{\tikzumlassocclassweightT}{1-\tikzumlassocclassweight} + \node (\tikzumlAssocClassNodeName-middle) at (barycentric cs:\tikzumlAssocClassNodeName=\tikzumlassocclassweight,\tikzumlAssocClassRelationNodeName=\tikzumlassocclassweightT) {};% + % + \ifthenelse{\equal{\tikzumlassocclassgeometry}{--}\OR\equal{\tikzumlassocclassgeometry}{-|}\OR\equal{\tikzumlassocclassgeometry}{|-}}{% + \edef\tikzumlassocclasspath{\tikzumlassocclassgeometry} + }{% + \ifthenelse{\equal{\tikzumlassocclassgeometry}{-|-}}{% + \ifthenelse{\equal{\tikzumlassocclassarm}{auto}}{% + \edef\tikzumlassocclasspath{-- (\tikzumlAssocClassNodeName\tikzumlassocclassSrcAnchor -| \tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center |- \tikzumlAssocClassRelationNodeName\tikzumlassocclassDestAnchor) --}% + }{% + \draw (\tikzumlAssocClassNodeName\tikzumlassocclassSrcAnchor)+(\tikzumlassocclassarm,0) node[name=\tikzumlAssocClassNodeName-tmp] {}; + \edef\tikzumlnotepath{-- (\tikzumlAssocClassNodeName-tmp.center) |-}% + }% + }{% + \ifthenelse{\equal{\tikzumlassocclassgeometry}{|-|}}{% + \ifthenelse{\equal{\tikzumlassocclassarm}{auto}}{% + \edef\tikzumlassocclasspath{-- (\tikzumlAssocClassNodeName\tikzumlassocclassSrcAnchor |- \tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center) -- (\tikzumlAssocClassNodeName-middle.center -| \tikzumlAssocClassRelationNodeName\tikzumlassocclassDestAnchor) --}% + }{% + \draw (\tikzumlAssocClassNodeName\tikzumlassocclassSrcAnchor)+(0,\tikzumlassocclassarm) node[name=\tikzumlAssocClassNodeName-tmp] {}; + \edef\tikzumlassocclasspath{-- (\thetikzumlAssocClassNodeName-tmp.center) -|}% + }% + + }{% + \errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-}% + }% + }% + }% + % + \begin{pgfonlayer}{connections}% + \draw[dashed] (\tikzumlAssocClassNodeName\tikzumlassocclassSrcAnchor) \tikzumlassocclasspath (\tikzumlAssocClassRelationNodeName\tikzumlassocclassDestAnchor);% + \end{pgfonlayer}% + % + + + % + % add to fit + \ifnum\c@tikzumlPackageLevel>0% + \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}% + \ifthenelse{\equal{\umlassocclassTemplateParam}{}}{% + \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlAssocClassNodeName)(\tikzumlAssocClassNodeName-middle)}% + }{% + \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlAssocClassNodeName) (\tikzumlAssocClassNodeName-template)(\tikzumlAssocClassNodeName-middle)}% + }% + \stepcounter{tikzumlPackageClassNum}% + \fi% +}% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% use case diagrams % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\tikzstyle{tikzuml usecase style}=[ellipse, text centered]% +\tikzstyle{tikzuml actor style}=[ellipse, inner sep=0, outer sep=0]% + +\newcounter{tikzumlSystemUseCaseNum}% +\newcounter{tikzumlSystemLevel}% +\newcounter{tikzumlUseCaseNum}% +\newcounter{tikzumlActorNum}% + +% define a system +% arg : name +% optional : x, y coordinates of the system +% draw, fill, text colors +\newenvironment{umlsystem}[2][]{% + \gdef\tikzumlSystemFit{}% + \def\tikzumlSystemName{#2}% + \setcounter{tikzumlSystemUseCaseNum}{0}% + % + \pgfkeys{/tikzuml/system/.cd,% + x/.initial=0, y/.initial=0, x/.default=0, y/.default=0,% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillsystemcolor,% + text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlsystem, invalid option \keyname}% + }}% + % + \pgfkeys{/tikzuml/system/.cd, #1}% + \pgfkeys{/tikzuml/system/.cd,% + x/.get=\xshift, y/.get=\yshift,% + draw/.get=\tikzumlsystemdraw, fill/.get=\tikzumlsystemfill,% + text/.get=\tikzumlsystemtext}% + % + \stepcounter{tikzumlSystemLevel}% + % + \begin{scope}[xshift=\xshift cm, yshift=\yshift cm]% +}{% + \addtocounter{tikzumlSystemLevel}{-1}% + % if contains no usecase, one define a fictive node to enable the fit option + \ifnum\c@tikzumlSystemUseCaseNum=0% + \node[inner xsep=10ex, inner ysep=1em] (\tikzumlSystemName-root) at (0,0) {};% + \xdef\tikzumlSystemFit{(\tikzumlSystemName-root)}% + \fi% + % + \begin{pgfonlayer}{background}% + \node[inner ysep=1em, inner xsep=2ex, fit = \tikzumlSystemFit] (\tikzumlSystemName-tmp) {};% + \node[text=\tikzumlsystemtext, font=\tikzumlfont] (\tikzumlSystemName-caption-tmp) at (\tikzumlSystemName-tmp.north) {\tikzumlSystemName};% + \node[draw=\tikzumlsystemdraw, fill=\tikzumlsystemfill, text=\tikzumlsystemtext, font=\tikzumlfont, inner ysep=1em, inner xsep=2ex, fit = (\tikzumlSystemName-tmp) (\tikzumlSystemName-caption-tmp)] (\tikzumlSystemName) {};% + \node[text=\tikzumlsystemtext, font=\tikzumlfont] (\tikzumlSystemName-caption) at (\tikzumlSystemName-caption-tmp.north) {\tikzumlSystemName};% + \end{pgfonlayer}% + \end{scope}% + % +}% + +% define a use case +% arg : label of the use case +% optional : x, y coordinates of the use case +% name of the node +% draw, fill, text colors +\newcommand{\umlusecase}[2][]{% + \stepcounter{tikzumlUseCaseNum}% + \pgfkeys{/tikzuml/usecase/.cd,% + x/.initial=0, y/.initial=0, width/.initial=auto,% + name/.initial=usecase-\thetikzumlUseCaseNum,% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillusecasecolor,% + text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlusecase, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/usecase/.cd, #1}% + \pgfkeys{/tikzuml/usecase/.cd,% + x/.get=\posx, y/.get=\posy, width/.get=\tikzumlusecasetextwidth,% + name/.get=\usecaseName,% + draw/.get=\tikzumlusecasedraw, fill/.get=\tikzumlusecasefill,% + text/.get=\tikzumlusecasetext}% + % + \def\tikzumlUseCaseText{#2}% + % + \def\tikzumlUseCasePos{\posx,\posy}% + % + \ifthenelse{\equal{\tikzumlusecasetextwidth}{auto}}{% + \node[tikzuml usecase style, draw=\tikzumlusecasedraw, fill=\tikzumlusecasefill, text=\tikzumlusecasetext, font=\tikzumlfont] (\usecaseName) at (\tikzumlUseCasePos) {\tikzumlUseCaseText};% + }{% + \node[tikzuml usecase style, draw=\tikzumlusecasedraw, fill=\tikzumlusecasefill, text=\tikzumlusecasetext, font=\tikzumlfont, text width=\tikzumlusecasetextwidth] (\usecaseName) at (\tikzumlUseCasePos) {\tikzumlUseCaseText};% + }% + % + % add to fit + \ifnum\c@tikzumlSystemLevel>0% + \let\tikzumlSystemFitOld\tikzumlSystemFit% + \xdef\tikzumlSystemFit{\tikzumlSystemFitOld (\usecaseName)}% + \stepcounter{tikzumlSystemUseCaseNum}% + \fi% +}% + +% define the actor symbol +% optional : global tikzpicture styles +\newcommand{\picturedactor}[1]{% + \pgfkeys{/tikzuml/picactor/.cd, scale/.initial=1, .unknown/.code={}}% + \pgfkeys{/tikzuml/picactor/.cd,#1}% + \pgfkeys{/tikzuml/picactor/.cd, scale/.get=\tikzumlpicactorscale}% + % + \begin{tikzpicture}[#1] + \coordinate (head) at (0,4ex); + \coordinate (left-hand) at (-2ex,2ex); + \coordinate (right-hand) at (2ex,2ex); + \coordinate (left-foot) at (-2ex,-2ex); + \coordinate (right-foot) at (2ex,-2ex); + \coordinate (empty) at (0,-3ex); + \draw (empty) (0,0) -- (head); + \draw (left-hand) -- (right-hand); + \draw (0,0) -- (left-foot) (0,0) -- (right-foot); + \node[fill, draw, circle, inner sep=\tikzumlpicactorscale*0.3333ex, minimum size=\tikzumlpicactorscale*2ex] at (head) {}; + \end{tikzpicture} +}% + +% define an actor +% arg : var name +% optional : x, y coordinates of the actor +% name of the node +% draw, text colors +\newcommand{\umlactor}[2][]{% + \stepcounter{tikzumlActorNum}% + \pgfkeys{/tikzuml/actor/.cd,% + x/.initial=0, y/.initial=0, scale/.initial=1, below/.initial=0.5cm,% + draw/.initial=\tikzumldrawcolor, text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlactor, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/actor/.cd, #1}% + \pgfkeys{/tikzuml/actor/.cd,% + x/.get=\posx, y/.get=\posy, scale/.get=\tikzumlactorscale,% + below/.get=\tikzumlactorbelow,% + draw/.get=\tikzumlactordraw, text/.get=\tikzumlactortext}% + % + \def\tikzumlActorName{#2}% + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlActorNodeName{\tikzumlActorName}}\x% + % + \def\tikzumlActorPos{\posx,\posy}% + % + \ifthenelse{\equal{}{tikzumlEmpty}}{}{} + \node[tikzuml actor style, text=\tikzumlactortext, font=\tikzumlfont] (\tikzumlActorNodeName) at (\tikzumlActorPos) {\picturedactor{scale=\tikzumlactorscale, fill=white, draw=\tikzumlactordraw, thick}};% + \node[text=\tikzumlactortext, font=\tikzumlfont, below=\tikzumlactorscale*\tikzumlactorbelow] at (\tikzumlActorNodeName) {\tikzumlActorName};% + % +}% + +% shortcuts for include and extend relation +\newcommand{\umlinclude}[3][]{% + \pgfkeys{/tikzuml/includerelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlinclude, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlinclude, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/includerelation/.cd, #1}% + \umlrelation[stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}% +}% +\newcommand{\umlextend}[3][]{% + \pgfkeys{/tikzuml/extendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlextend, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlextend, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/extendrelation/.cd, #1}% + \umlrelation[stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}% +}% + +\newcommand{\umlHVinclude}[3][]{% + \pgfkeys{/tikzuml/includerelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlHVinclude, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVinclude, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/includerelation/.cd, #1}% + \umlrelation[geometry=-|, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}% +}% +\newcommand{\umlHVextend}[3][]{% + \pgfkeys{/tikzuml/extendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlHVextend, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVextend, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/extendrelation/.cd, #1}% + \umlrelation[geometry=-|, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}% +}% + +\newcommand{\umlVHinclude}[3][]{% + \pgfkeys{/tikzuml/includerelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlVHinclude, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHinclude, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/includerelation/.cd, #1}% + \umlrelation[geometry=|-, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}% +}% +\newcommand{\umlVHextend}[3][]{% + \pgfkeys{/tikzuml/extendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR :in umlVHextend, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHextend, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/extendrelation/.cd, #1}% + \umlrelation[geometry=|-, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}% +}% + +\newcommand{\umlHVHinclude}[3][]{% + \pgfkeys{/tikzuml/includerelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlHVHinclude, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVHinclude, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/includerelation/.cd, #1}% + \umlrelation[geometry=-|-, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}% +}% +\newcommand{\umlHVHextend}[3][]{% + \pgfkeys{/tikzuml/extendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlHVHextend, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVHextend, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/extendrelation/.cd, #1}% + \umlrelation[geometry=-|-, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}% +}% + +\newcommand{\umlVHVinclude}[3][]{% + \pgfkeys{/tikzuml/includerelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlVHVinclude, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHVinclude, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/includerelation/.cd, #1}% + \umlrelation[geometry=|-|, stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}% +}% +\newcommand{\umlVHVextend}[3][]{% + \pgfkeys{/tikzuml/extendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlVHVextend, forbidden option stereo}% + }{% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHVextend, forbidden option geometry}% + }{}% + }% + }}% + \pgfkeys{/tikzuml/extendrelation/.cd, #1}% + \umlrelation[geometry=|-|, stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}% +}% + +\newcommand{\umlCNinclude}[4][]{% + \pgfkeys{/tikzuml/includerelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlCNinclude, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/includerelation/.cd, #1}% + \umlCNrelation[stereo=include, style={tikzuml dependency style}, #1]{#2}{#3}{#4}% +}% + +\newcommand{\umlCNextend}[4][]{% + \pgfkeys{/tikzuml/extendrelation/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlCNextend, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/extendrelation/.cd, #1}% + \umlCNrelation[stereo=extend, style={tikzuml dependency style}, #1]{#2}{#3}{#4}% +}% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% state diagrams % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\tikzstyle{tikzuml state style}=[rectangle split, rectangle split parts=2, rounded corners, inner xsep=1.5ex]% +\tikzstyle{tikzuml transition style}=[color=\tikzumldrawcolor, rounded corners, -angle 45]% + +\newcounter{tikzumlStateJoinNum}% +\newcounter{tikzumlStateDecisionNum}% +\newcounter{tikzumlStateInitialNum}% +\newcounter{tikzumlStateFinalNum}% +\newcounter{tikzumlStateEnterNum}% +\newcounter{tikzumlStateExitNum}% +\newcounter{tikzumlStateEndNum}% +\newcounter{tikzumlStateHistoryNum}% +\newcounter{tikzumlStateDeepHistoryNum}% +\newcounter{tikzumlStateLevel}% +\newcounter{tikzumlStateSubStateNum}% +\newcounter{tikzumlStateText}% + +\newcommand{\umlstatejoin}[1][]{% + \pgfkeys{/tikzuml/statejoin/.cd,% + x/.initial=0, y/.initial=0, width/.initial=3ex,% + name/.initial=statejoin-\thetikzumlStateJoinNum,% + color/.initial=\tikzumldrawcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlstatejoin, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/statejoin/.cd, #1}% + \pgfkeys{/tikzuml/statejoin/.cd,% + x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstatejoinwidth,% + name/.get=\tikzumlstatejoinname, color/.get=\tikzumlstatejoincolor}% + % + \def\tikzumlStateJoinPos{\posx,\posy}% + % + \node[circle, minimum size=\tikzumlstatejoinwidth, draw=\tikzumlstatejoincolor, fill=\tikzumlstatejoincolor] (\tikzumlstatejoinname) at (\tikzumlStateJoinPos) {};% + % + % add to fit + \ifnum\c@tikzumlStateLevel>0% + \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstatejoinname)}% + \stepcounter{tikzumlStateSubStateNum}% + \fi% + \stepcounter{tikzumlStateJoinNum}% +}% + +\newcommand{\umlstatedecision}[1][]{% + \pgfkeys{/tikzuml/statedecision/.cd,% + x/.initial=0, y/.initial=0, width/.initial=3ex,% + name/.initial=statedecision-\thetikzumlStateDecisionNum,% + color/.initial=\tikzumldrawcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlstatedecision, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/statedecision/.cd, #1}% + \pgfkeys{/tikzuml/statedecision/.cd,% + x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstatedecisionwidth,% + name/.get=\tikzumlstatedecisionname, color/.get=\tikzumlstatedecisioncolor}% + % + \def\tikzumlStateDecisionPos{\posx,\posy}% + % + \node[rectangle, rotate=45, minimum size=\tikzumlstatedecisionwidth, draw=\tikzumlstatedecisioncolor] (\tikzumlstatedecisionname) at (\tikzumlStateDecisionPos) {};% + % + % add to fit + \ifnum\c@tikzumlStateLevel>0% + \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstatedecisionname)}% + \stepcounter{tikzumlStateSubStateNum}% + \fi% + \stepcounter{tikzumlStateDecisionNum}% +}% + +\newcommand{\umlstateinitial}[1][]{% + \pgfkeys{/tikzuml/stateinitial/.cd,% + x/.initial=0, y/.initial=0, width/.initial=5ex,% + name/.initial=stateinitial-\thetikzumlStateInitialNum,% + color/.initial=\tikzumldrawcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlstateinitial, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/stateinitial/.cd, #1}% + \pgfkeys{/tikzuml/stateinitial/.cd,% + x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstateinitialwidth,% + name/.get=\tikzumlstateinitialname, color/.get=\tikzumlstateinitialcolor}% + % + \def\tikzumlStateInitialPos{\posx,\posy}% + % + \node[circle, minimum size=\tikzumlstateinitialwidth, fill=\tikzumlstateinitialcolor] (\tikzumlstateinitialname) at (\tikzumlStateInitialPos) {};% + % + % add to fit + \ifnum\c@tikzumlStateLevel>0% + \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstateinitialname)}% + \stepcounter{tikzumlStateSubStateNum}% + \fi% + \stepcounter{tikzumlStateInitialNum}% +}% + +\newcommand{\umlstatefinal}[1][]{% + \pgfkeys{/tikzuml/statefinal/.cd,% + x/.initial=0, y/.initial=0, width/.initial=5.5ex,% + name/.initial=statefinal-\thetikzumlStateFinalNum,% + color/.initial=\tikzumldrawcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlstatefinal, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/statefinal/.cd, #1}% + \pgfkeys{/tikzuml/statefinal/.cd, x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstatefinalwidth,% + name/.get=\tikzumlstatefinalname, color/.get=\tikzumlstatefinalcolor}% + % + \def\tikzumlStateFinalPos{\posx,\posy}% + % + \node[circle, minimum size=\tikzumlstatefinalwidth, draw=\tikzumlstatefinalcolor, fill=\tikzumlstatefinalcolor, double, double distance=0.1cm] (\tikzumlstatefinalname) at (\tikzumlStateFinalPos) {};% + % + % add to fit + \ifnum\c@tikzumlStateLevel>0% + \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstatefinalname)}% + \stepcounter{tikzumlStateSubStateNum}% + \fi% + \stepcounter{tikzumlStateFinalNum}% +}% + +\newcommand{\umlstateenter}[1][]{% + \pgfkeys{/tikzuml/stateenter/.cd,% + x/.initial=0, y/.initial=0, width/.initial=5ex,% + name/.initial=stateenter-\thetikzumlStateEnterNum,% + color/.initial=\tikzumldrawcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlstateenter, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/stateenter/.cd, #1}% + \pgfkeys{/tikzuml/stateenter/.cd,% + x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstateenterwidth,% + name/.get=\tikzumlstateentername, color/.get=\tikzumlstateentercolor}% + % + \def\tikzumlStateEnterPos{\posx,\posy}% + % + \node[circle, minimum size=\tikzumlstateenterwidth, draw=\tikzumlstateentercolor] (\tikzumlstateentername) at (\tikzumlStateEnterPos) {};% + % + % add to fit + \ifnum\c@tikzumlStateLevel>0% + \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstateentername)}% + \stepcounter{tikzumlStateSubStateNum}% + \fi% + \stepcounter{tikzumlStateEnterNum}% +}% + +\newcommand{\umlstateexit}[1][]{% + \pgfkeys{/tikzuml/stateexit/.cd,% + x/.initial=0, y/.initial=0, width/.initial=5ex,% + name/.initial=stateexit-\thetikzumlStateExitNum,% + color/.initial=\tikzumldrawcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlstateexit, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/stateexit/.cd, #1}% + \pgfkeys{/tikzuml/stateexit/.cd,% + x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstateexitwidth,% + name/.get=\tikzumlstateexitname, color/.get=\tikzumlstateexitcolor}% + % + \def\tikzumlStateExitPos{\posx,\posy}% + % + \node[circle, minimum size=\tikzumlstateexitwidth, draw=\tikzumlstateexitcolor] (\tikzumlstateexitname) at (\tikzumlStateExitPos) {};% + \draw[draw=\tikzumlstateexitcolor] (\tikzumlstateexitname.north east) -- (\tikzumlstateexitname.south west) (\tikzumlstateexitname.north west) -- (\tikzumlstateexitname.south east); + % + % add to fit + \ifnum\c@tikzumlStateLevel>0% + \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstateexitname)}% + \stepcounter{tikzumlStateSubStateNum}% + \fi% + \stepcounter{tikzumlStateExitNum}% +}% + +\newcommand{\umlstateend}[1][]{% + \pgfkeys{/tikzuml/stateend/.cd,% + x/.initial=0, y/.initial=0, width/.initial=5ex,% + name/.initial=stateend-\thetikzumlStateEndNum, color/.initial=\tikzumldrawcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlstateend, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/stateend/.cd, #1}% + \pgfkeys{/tikzuml/stateend/.cd, x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstateendwidth,% + name/.get=\tikzumlstateendname, color/.get=\tikzumlstateendcolor}% + % + \def\tikzumlStateEndPos{\posx,\posy}% + % + \node[circle, minimum size=\tikzumlstateendwidth] (\tikzumlstateendname) at (\tikzumlStateEndPos) {};% + \draw[draw=\tikzumlstateendcolor] (\tikzumlstateendname.north east) -- (\tikzumlstateendname.south west) (\tikzumlstateendname.north west) -- (\tikzumlstateendname.south east); + % + % add to fit + \ifnum\c@tikzumlStateLevel>0% + \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstateendname)}% + \stepcounter{tikzumlStateSubStateNum}% + \fi% + \stepcounter{tikzumlStateEndNum}% +}% + +\newcommand{\picturedhistory}[1]{% + \begin{tikzpicture}[#1] + \draw[thick] (-0.1cm,-0.15cm) -- (-0.1cm,0.15cm) + (-0.1cm,0) -- (0.1cm,0) + (0.1cm,-0.15cm) -- (0.1cm,0.15cm); + \end{tikzpicture} +}% + +\newcommand{\umlstatehistory}[1][]{% + \pgfkeys{/tikzuml/statehistory/.cd,% + x/.initial=0, y/.initial=0, width/.initial=5ex,% + name/.initial=statehistory-\thetikzumlStateHistoryNum,% + color/.initial=\tikzumldrawcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlstatehistory, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/statehistory/.cd, #1}% + \pgfkeys{/tikzuml/statehistory/.cd, x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstatehistorywidth,% + name/.get=\tikzumlstatehistoryname, color/.get=\tikzumlstatehistorycolor}% + % + \def\tikzumlStateHistoryPos{\posx,\posy}% + % + \node[circle, minimum size=\tikzumlstatehistorywidth, draw=\tikzumlstatehistorycolor] (\tikzumlstatehistoryname) at (\tikzumlStateHistoryPos) {\picturedhistory{draw=\tikzumlstatehistorycolor}};% + % + % add to fit + \ifnum\c@tikzumlStateLevel>0% + \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstatehistoryname)}% + \stepcounter{tikzumlStateSubStateNum}% + \fi% + \stepcounter{tikzumlStateHistoryNum}% +}% + +\newcommand{\pictureddeephistory}[1]{% + \begin{tikzpicture}[#1] + \draw[thick] (-0.1cm,-0.15cm) -- (-0.1cm,0.15cm) + (-0.1cm,0) -- (0.1cm,0) + (0.1cm,-0.15cm) -- (0.1cm,0.15cm) + (0.23cm,0.19cm) -- (0.23cm,0.11cm) + (0.20cm,0.17cm) -- (0.26cm,0.13cm) + (0.20cm,0.13cm) -- (0.26cm,0.17cm); + \end{tikzpicture} +}% + +\newcommand{\umlstatedeephistory}[1][]{% + \pgfkeys{/tikzuml/statedeephistory/.cd,% + x/.initial=0, y/.initial=0, width/.initial=5ex,% + name/.initial=statedeephistory-\thetikzumlStateDeepHistoryNum,% + color/.initial=\tikzumldrawcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlstatedeephistory, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/statedeephistory/.cd, #1}% + \pgfkeys{/tikzuml/statedeephistory/.cd, x/.get=\posx, y/.get=\posy, width/.get=\tikzumlstatedeephistorywidth,% + name/.get=\tikzumlstatedeephistoryname, color/.get=\tikzumlstatedeephistorycolor}% + % + \def\tikzumlStateDeepHistoryPos{\posx,\posy}% + % + \node[circle, minimum size=\tikzumlstatedeephistorywidth, draw=\tikzumlstatedeephistorycolor] (\tikzumlstatedeephistoryname) at (\tikzumlStateDeepHistoryPos) {\pictureddeephistory{draw=\tikzumlstatedeephistorycolor}};% + % + % add to fit + \ifnum\c@tikzumlStateLevel>0% + \edef\tikzumlStateFitOld{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitOld (\tikzumlstatedeephistoryname)}% + \stepcounter{tikzumlStateSubStateNum}% + \fi% + \stepcounter{tikzumlStateDeepHistoryNum}% +}% + +% define a uml state +% args : name of the state +% content of the state +% optional args : x,y coordinates of the state +% width of the state node +\newenvironment{umlstate}[2][]{% + \ifnum\thetikzumlStateLevel>0% + \let\tikzumlState@nameold\tikzumlState@fitname% + \let\tikzumlState@parentold\tikzumlState@parent% + \edef\tikzumlState@parent{\tikzumlState@parentold @@\tikzumlState@nameold}% + \else% + \def\tikzumlState@parent{}% + \fi% + + \stepcounter{tikzumlStateLevel}% + + \pgfkeys{/tikzuml/state/.cd,% + x/.initial=0, y/.initial=0, width/.initial=8ex, type/.initial=class,% + name/.initial={},% + entry/.initial={}, do/.initial={}, exit/.initial={},% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillstatecolor,% + text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlstate, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/state/.cd, #1}% + \pgfkeys{/tikzuml/state/.cd,% + x/.get=\tikzumlstateX, y/.get=\tikzumlstateY, width/.get=\umlstateMinimumWidth,% + type/.get=\umlstateType, name/.get=\umlstateName,% + entry/.get=\umlstateentry, do/.get=\umlstatedo, exit/.get=\umlstateexit,% + draw/.get=\tikzumlstatedraw, fill/.get=\tikzumlstatefill,% + text/.get=\tikzumlstatetext}% + % + \ifthenelse{\equal{\umlstateName}{}}{% + \edef\tikzumlState@name{#2}% + }{% + \edef\tikzumlState@name{\umlstateName}% + }% + % + \begingroup% + \def\_{@}\edef\x{\endgroup% + \def\noexpand\tikzumlState@fitname{\tikzumlState@name}}\x% + % + \let\tikzumlState@nodeNameold\tikzumlState@nodeName% + \def\tikzumlState@caption{#2}% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlState@nodeName{\tikzumlState@name}}\x% + % + \expandafter\gdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{}% + % + \setcounter{tikzumlStateSubStateNum}{0}% + \setcounter{tikzumlStateText}{0}% + % + \def\tikzumlStateText{tikzumlEmpty}% + \begin{scope}[xshift=\tikzumlstateX cm, yshift=\tikzumlstateY cm]% +}{% + % + \def\tikzumlstaterootlabel{\phantom{\tikzumlState@nodeName}}% + % + \def\tikzumlstaterootinnerysep{0.5ex}% + \def\tikzumlstatebodyinnerysep{2ex}% + % + \ifthenelse{\equal{\umlstateentry}{}}{}{% + \def\tikzumlStateText{entry/\umlstateentry}% + \setcounter{tikzumlStateText}{1}% + \ifnum\c@tikzumlStateSubStateNum=0% + \def\tikzumlstatebodyinnerysep{0}% + \def\tikzumlstaterootinnerysep{0}% + \fi% + }% + \ifthenelse{\equal{\umlstatedo}{}}{}{% + \ifnum\c@tikzumlStateText=0% + \def\tikzumlStateText{do/\umlstatedo}% + \else% + \let\tikzumlStateTextOld\tikzumlStateText% + \def\tikzumlStateText{\tikzumlStateTextOld \\ do/\umlstatedo}% + \fi% + \setcounter{tikzumlStateText}{1}% + \ifnum\c@tikzumlStateSubStateNum=0% + \def\tikzumlstatebodyinnerysep{0}% + \def\tikzumlstaterootinnerysep{0}% + \fi% + }% + \ifthenelse{\equal{\umlstateexit}{}}{}{% + \ifnum\c@tikzumlStateText=0% + \def\tikzumlStateText{exit/\umlstateexit}% + \else% + \let\tikzumlStateTextOld\tikzumlStateText% + \def\tikzumlStateText{\tikzumlStateTextOld \\ exit/\umlstateexit}% + \fi% + \setcounter{tikzumlStateText}{1}% + \ifnum\c@tikzumlStateSubStateNum=0% + \def\tikzumlstatebodyinnerysep{0}% + \def\tikzumlstaterootinnerysep{0}% + \fi% + }% + % + \addtocounter{tikzumlStateLevel}{-1}% + \begin{pgfonlayer}{state\thetikzumlStateLevel}% + % + % if contains nothing, one define a fictive node to enable the fit option + \ifnum\c@tikzumlStateSubStateNum=0% + \node[inner ysep=\tikzumlstaterootinnerysep, minimum width=\umlstateMinimumWidth] (\tikzumlState@nodeName-root) at (0,0) {\tikzumlstaterootlabel};% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{(\tikzumlState@nodeName-root)}% + \fi% + % + \ifnum\c@tikzumlStateLevel>0% + \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent\endcsname}% + \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent\endcsname{\tikzumlStateFitTmp (\tikzumlState@nodeName-body) (\tikzumlState@nodeName-caption)}% + \stepcounter{tikzumlStateSubStateNum}% + \fi% + % + \node[inner xsep=2ex, inner ysep=\tikzumlstatebodyinnerysep, fit = \csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname] (\tikzumlState@nodeName-body) {};% + \def\tikzumlState@orig{body}% + \ifnum\c@tikzumlStateText=1% + \node[above=0] (\tikzumlState@nodeName-texttmp) at (\tikzumlState@nodeName-\tikzumlState@orig.north) {\begin{tabular}{l}\tikzumlStateText \end{tabular}};% + \def\tikzumlState@orig{texttmp}% + \fi% + \node[above] (\tikzumlState@nodeName-captiontmp) at (\tikzumlState@nodeName-\tikzumlState@orig.north) {\tikzumlState@caption};% + \node[rounded corners, draw=\tikzumlstatedraw, fill=\tikzumlstatefill, name=\tikzumlState@nodeName, fit=(\tikzumlState@nodeName-body) (\tikzumlState@nodeName-captiontmp)] {};% + \ifnum\c@tikzumlStateText=1% + \node (\tikzumlState@nodeName-text) at (\tikzumlState@nodeName-texttmp) {\begin{tabular}{l}\tikzumlStateText \end{tabular}};% + \fi% + \node (\tikzumlState@nodeName-caption) at (\tikzumlState@nodeName-captiontmp) {\tikzumlState@caption};% + \draw (\tikzumlState@nodeName-caption.south -| \tikzumlState@nodeName.north west) -- (\tikzumlState@nodeName-caption.south -| \tikzumlState@nodeName.north east);% + \end{pgfonlayer}% + \end{scope}% +}% + +% shortcut for empty state +\newcommand{\umlbasicstate}[2][]{\begin{umlstate}[#1]{#2} \end{umlstate}}% + +% command to add text in a state +\newcommand{\umlstatetext}[1]{% + \def\tikzumlStateText{#1}% + \setcounter{tikzumlStateText}{1}% +}% + +% shortcuts for state transitions macros +\newcommand{\umltrans}[3][]{% + \ifthenelse{\equal{#2}{#3}}{% + \umlrelation[style={tikzuml transition style}, recursive mode=transition, #1]{#2}{#3}% + }{% + \umlrelation[style={tikzuml transition style}, #1]{#2}{#3}% + }% +}% +\newcommand{\umlHVtrans}[3][]{\umlHVrelation[style={tikzuml transition style}, #1]{#2}{#3}}% +\newcommand{\umlVHtrans}[3][]{\umlVHrelation[style={tikzuml transition style}, #1]{#2}{#3}}% +\newcommand{\umlVHVtrans}[3][]{\umlVHVrelation[style={tikzuml transition style}, #1]{#2}{#3}}% +\newcommand{\umlHVHtrans}[3][]{\umlHVHrelation[style={tikzuml transition style}, #1]{#2}{#3}}% +\newcommand{\umlCNtrans}[4][]{\umlCNrelation[style={tikzuml transition style}, #1]{#2}{#3}{#4}}% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% sequence diagrams % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\tikzstyle{tikzuml synchron-msg style}=[color=\tikzumldrawcolor, -triangle 45]% +\tikzstyle{tikzuml asynchron-msg style}=[color=\tikzumldrawcolor, -angle 45]% +\tikzstyle{tikzuml return-msg style}=[color=\tikzumldrawcolor, dashed, -angle 45]% +\tikzstyle{tikzuml call return style}=[color=\tikzumldrawcolor, dashed, -angle 45]% +\tikzstyle{tikzuml activity style}=[inner xsep=1ex, inner ysep=1ex]% + +\newcounter{tikzumlObjectNum} +\newcounter{tikzumlCallLevel} +\newcounter{tikzumlCallNum} +\newcounter{tikzumlFragmentLevel} +\newcounter{tikzumlFragmentLevelNum} +\newcounter{tikzumlFragmentNum} +\newcounter{tikzumlFragmentPartNum} +\newcounter{tikzumlCallStartFragmentNum} +\newcounter{tikzumlCallEndFragmentNum} + +% define a sequence diagram +% +\newenvironment{umlseqdiag}{% + \gdef\tikzumlInCreateCall{0}% + \setcounter{tikzumlObjectNum}{0}% + \setcounter{tikzumlCallLevel}{0}% + \setcounter{tikzumlCallNum}{0}% + \setcounter{tikzumlFragmentLevel}{0}% + \setcounter{tikzumlFragmentLevelNum}{0}% + \setcounter{tikzumlFragmentNum}{0}% + \setcounter{tikzumlFragmentPartNum}{0}% + \setcounter{tikzumlCallStartFragmentNum}{0}% + \setcounter{tikzumlCallEndFragmentNum}{0}% + % + \ifx \@umlactor \@empty + \newcommand{\umlactor}[2][]{% + \pgfkeys{/tikzuml/actorobj/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlactor, forbidden option stereo}% + }{}% + }}% + % + \pgfkeys{/tikzuml/actorobj/.cd, ##1}% + \umlobject[stereo=actor, ##1]{##2}% + }% + \else% + \renewcommand{\umlactor}[2][]{ + \pgfkeys{/tikzuml/actorobj/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlactor, forbidden option stereo}% + }{}% + }}% + % + \pgfkeys{/tikzuml/actorobj/.cd, ##1}% + \umlobject[stereo=actor, ##1]{##2}% + }% + \fi% + \begin{scope}[font=\tikzumlfont]% +}{% + % draw lifelines of each object + \begin{pgfonlayer}{lifelines}% + \foreach \id in \tikzumlIdList {% + \draw (\csname tikzumlLastChild@\id \endcsname)+(0,-2.5ex) node[inner sep=0, name=end-\id] {};% + \draw[dotted] (\id) -- (end-\id);% + }% + \end{pgfonlayer}% + \end{scope}% +}% + +% define the actor symbol +% optional : global tikzpicture styles +\newcommand{\pictureddatabase}[1]{% + \pgfkeys{/tikzuml/database/.cd, scale/.initial=1, .unknown/.code={}}% + \pgfkeys{/tikzuml/database/.cd,#1}% + \pgfkeys{/tikzuml/database/.cd, scale/.get=\tikzumldatabasescale}% + % + \begin{tikzpicture}[#1] + \node[fill, draw, ellipse, minimum width=\tikzumldatabasescale*4ex, minimum height=\tikzumldatabasescale*2ex, inner sep=0] (bottom) at (0,-2ex) {}; + \node[fill, draw, ellipse, minimum width=\tikzumldatabasescale*4ex, minimum height=\tikzumldatabasescale*2ex, inner sep=0] (top) at (0,4ex) {}; + \fill (bottom.west) rectangle (top.east); + \begin{scope} + \clip (-3.5ex,-0.5ex) rectangle (3.5ex,2.5ex); + \node[draw, dashed, ellipse, minimum width=\tikzumldatabasescale*4ex, minimum height=\tikzumldatabasescale*2ex, inner sep=0] (bottom2) at (0,-2ex) {}; + \end{scope} + \node[draw, ellipse, minimum width=\tikzumldatabasescale*4ex, minimum height=\tikzumldatabasescale*2ex, inner sep=0] (top2) at (0,4ex) {}; + \draw (bottom.west) -- (top.west) (bottom.east) -- (top.east); + \end{tikzpicture} +}% + +% define the actor symbol +% optional : global tikzpicture styles +\newcommand{\picturedentity}[1]{% + \pgfkeys{/tikzuml/entity/.cd, scale/.initial=1, .unknown/.code={}}% + \pgfkeys{/tikzuml/entity/.cd,#1}% + \pgfkeys{/tikzuml/entity/.cd, scale/.get=\tikzumlentityscale}% + % + \begin{tikzpicture}[#1]% + \node[fill, draw, circle, inner sep=0, minimum size=\tikzumlentityscale*5ex] (center) at (0,0) {};% + \draw (center.south) node[coordinate, name=bottom] {};% + \draw (bottom)+(-2ex,0) node[coordinate, name=bottom-left] {};% + \draw (bottom)+(2ex,0) node[coordinate, name=bottom-right] {};% + \draw (center) -- (bottom);% + \draw (bottom-left) -- (bottom-right);% + \end{tikzpicture}% +}% + +% define the actor symbol +% optional : global tikzpicture styles +\newcommand{\picturedboundary}[1]{% + \pgfkeys{/tikzuml/boundary/.cd, scale/.initial=1, .unknown/.code={}}% + \pgfkeys{/tikzuml/boundary/.cd,#1}% + \pgfkeys{/tikzuml/boundary/.cd, scale/.get=\tikzumlboundaryscale}% + % + \begin{tikzpicture}[#1] + \node[fill, draw, circle, inner sep=0, minimum size=\tikzumlboundaryscale*5ex] (center) at (0,0) {}; + \draw (center.west)+(-0.8ex,0) node[coordinate, name=left] {}; + \draw (left)+(0,0.2ex) node[coordinate, name=left-top] {}; + \draw (left)+(0,-0.2ex) node[coordinate, name=left-bottom] {}; + \draw (center) -- (left); + \draw (left-top) -- (left-bottom); + \end{tikzpicture} +}% + +% define the actor symbol +% optional : global tikzpicture styles +\newcommand{\picturedcontrol}[1]{% + \pgfkeys{/tikzuml/control/.cd, scale/.initial=1, .unknown/.code={}}% + \pgfkeys{/tikzuml/control/.cd,#1}% + \pgfkeys{/tikzuml/control/.cd, scale/.get=\tikzumlcontrolscale}% + % + \begin{tikzpicture}[#1, decoration={markings, mark=at position 0.25 with {\arrow{>}}}] + \node[fill, draw, circle, inner sep=0, minimum size=\tikzumlcontrolscale*5ex, postaction={decorate}] (center) at (0,0) {}; + \end{tikzpicture} +}% + +% define a uml object for a sequence diagram +% args : name of the object +% optional : x, y coordinates of the object +% stereotype of the object (object, actor, database, boundary, control, entity, multiobject) +% class of the object +% draw, fill, text colors +\newcommand{\umlobject}[2][]{ + \stepcounter{tikzumlObjectNum}% + % + \edef\tikzumlobject@ddot{:}% + \pgfkeys{/tikzuml/obj/.cd,% + x/.initial={tikzumlEmpty}, y/.initial=0, stereo/.initial=object,% + class/.initial={}, scale/.initial=1,% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillobjectcolor,% + text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{no ddots}}{% + \edef\tikzumlobject@ddot{}% + }{% + \errmessage{TIKZUML ERROR : in umlobj, invalid option \keyname}% + }% + }}% + \pgfkeys{/tikzuml/obj/.cd, #1}% + \pgfkeys{/tikzuml/obj/.cd,% + x/.get=\tikzumlobjectX, y/.get=\tikzumlobjectY,% + stereo/.get=\tikzumlobjectstereo, class/.get=\tikzumlobjectclass,% + scale/.get=\tikzumlobjectscale,% + draw/.get=\tikzumlobjectdraw, fill/.get=\tikzumlobjectfill,% + text/.get=\tikzumlobjecttext}% + % + \ifthenelse{\equal{\tikzumlobjectX}{tikzumlEmpty}}{% + \pgfmathsetmacro{\tikzumlobjectX}{4*(\thetikzumlObjectNum-1)}% + }{}% + % + \def\tikzumlObjectName{#2}% + \expandafter\xdef\csname tikzumlLastChild@\tikzumlObjectName \endcsname{\tikzumlObjectName}% + % + \ifnum\thetikzumlObjectNum=1% + \xdef\tikzumlIdList{\tikzumlObjectName}% + \else% + \let\tikzumlIdListOld\tikzumlIdList% + \xdef\tikzumlIdList{\tikzumlIdListOld,\tikzumlObjectName}% + \fi% + % + \tikzstyle{tikzuml object box style}=[rectangle, text=\tikzumlobjecttext, font=\tikzumlfont]% + % + \ifthenelse{\equal{\tikzumlobjectstereo}{object}}{% + \tikzstyle{tikzuml object box style}+=[draw=\tikzumlobjectdraw, fill=\tikzumlobjectfill]% + }{% + \ifthenelse{\equal{\tikzumlobjectstereo}{multi}}{% + \tikzstyle{tikzuml object box style}+=[fill=\tikzumlobjectfill]% + }{}% + }% + % + \ifnum\tikzumlInCreateCall=1% + \draw (\tikzumlCreateCallObjectSrc -| \tikzumlobjectX,0) node[tikzuml object box style] (\tikzumlObjectName) {\tikzumlObjectName\tikzumlobject@ddot\tikzumlobjectclass};% + \else% + \node[tikzuml object box style] (\tikzumlObjectName) at (\tikzumlobjectX,\tikzumlobjectY) {\tikzumlObjectName\tikzumlobject@ddot\tikzumlobjectclass};% + \fi% + % + \ifthenelse{\equal{\tikzumlobjectstereo}{multi}}{% + \draw (\tikzumlObjectName.north east)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-tr, coordinate] {}; + \draw (\tikzumlObjectName.north west)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-tl, coordinate] {}; + \draw (\tikzumlObjectName.south east)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-br, coordinate] {}; + \draw (\tikzumlObjectName-tr)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-ttr, coordinate] {}; + \draw (\tikzumlObjectName-tl)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-ttl, coordinate] {}; + \draw (\tikzumlObjectName-br)+(0.4ex,0.4ex) node[name=\tikzumlObjectName-tbr, coordinate] {}; + \fill[fill=\tikzumlobjectfill] (\tikzumlObjectName-ttl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-ttl) -- (\tikzumlObjectName-ttr) -- (\tikzumlObjectName-tbr) -- (\tikzumlObjectName-tbr -| \tikzumlObjectName.east) -- (\tikzumlObjectName.north east) -- (\tikzumlObjectName-ttl |- \tikzumlObjectName.north); + \draw[draw=\tikzumlobjectdraw] (\tikzumlObjectName-ttl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-ttl) -- (\tikzumlObjectName-ttr) -- (\tikzumlObjectName-tbr) -- (\tikzumlObjectName-tbr -| \tikzumlObjectName.east); + \fill[fill=\tikzumlobjectfill] (\tikzumlObjectName-tl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-tl) -- (\tikzumlObjectName-tr) -- (\tikzumlObjectName-br) -- (\tikzumlObjectName-br -| \tikzumlObjectName.east) -- (\tikzumlObjectName.north east) -- (\tikzumlObjectName-tl |- \tikzumlObjectName.north); + \draw[draw=\tikzumlobjectdraw] (\tikzumlObjectName-tl |- \tikzumlObjectName.north) -- (\tikzumlObjectName-tl) -- (\tikzumlObjectName-tr) -- (\tikzumlObjectName-br) -- (\tikzumlObjectName-br -| \tikzumlObjectName.east); + \draw[draw=\tikzumlobjectdraw] (\tikzumlObjectName.north west) rectangle (\tikzumlObjectName.south east); + }{% + \ifthenelse{\equal{\tikzumlobjectstereo}{object}}{}{% + \node[above=1ex, name=\tikzumlObjectName-picture] at (\tikzumlObjectName) {\csname pictured\tikzumlobjectstereo \endcsname{draw=\tikzumlobjectdraw, fill=\tikzumlobjectfill, scale=\tikzumlobjectscale}}; + }% + }% +} + +% shortcuts for objects +\newcommand{\umlbasicobject}[2][]{% + \pgfkeys{/tikzuml/basicobj/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{no ddots}}{% + \errmessage{TIKZUML ERROR : in umlbasicobject, forbidden option no ddots}% + }{}% + }}% + \pgfkeys{/tikzuml/basicobj/.cd, #1}% + \umlobject[no ddots, #1]{#2}% +}% + +\newcommand{\umldatabase}[2][]{% + \pgfkeys{/tikzuml/databaseobj/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umldatabase, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/databaseobj/.cd, #1}% + \umlobject[stereo=database, #1]{#2}% +}% +\newcommand{\umlentity}[2][]{% + \pgfkeys{/tikzuml/entityobj/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlentity, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/entityobj/.cd, #1}% + \umlobject[stereo=entity, #1]{#2}% +}% +\newcommand{\umlcontrol}[2][]{% + \pgfkeys{/tikzuml/controlobj/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlcontrol, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/controlobj/.cd, #1}% + \umlobject[stereo=control, #1]{#2}% +}% +\newcommand{\umlboundary}[2][]{% + \pgfkeys{/tikzuml/boundaryobj/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlboundary, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/boundaryobj/.cd, #1}% + \umlobject[stereo=boundary, #1]{#2}% +}% +\newcommand{\umlmulti}[2][]{% + \pgfkeys{/tikzuml/multiobj/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlmulti, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/multiobj/.cd, #1}% + \umlobject[stereo=multi, #1]{#2}% +}% + +\newlength{\tikzumlCall@xa}% +\newlength{\tikzumlCall@xb}% + +% define a uml operation call for sequence diagrams +% args : call sender +% call receiver +% optional : dt, time delay from precedent event end +% name of the call +% operation name and input args +% return value +% type of the call (synchron, asynchron) +% draw, fill, text colors +% time padding from call start and to call end +\newenvironment{umlcall}[3][]{% + \stepcounter{tikzumlCallNum}% + \def\tikzumlCallWithReturn{tikzumlFalse}% + \edef\tikzumlCall@lastchildNum{\thetikzumlCallNum}% for testing presence of sub-calls + \gdef\tikzumlCallBottom{0}% + % + \pgfkeys{/tikzuml/call/.cd,% + dt/.initial={tikzumlEmpty}, name/.initial={call-\thetikzumlCallNum},% + op/.initial={}, return/.initial={}, type/.initial=synchron,% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillcallcolor,% + text/.initial=\tikzumltextcolor,% + padding/.initial=2,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{with return}}{% + \def\tikzumlCallWithReturn{tikzumlTrue}% + }{% + \errmessage{TIKZUML ERROR : in umlcall, invalid option \keyname}% + }% + }}% + \pgfkeys{/tikzuml/call/.cd, #1}% + \pgfkeys{/tikzuml/call/.cd,% + dt/.get=\tikzumlcallDT, name/.get=\tikzumlcallname, op/.get=\tikzumlcallop,% + return/.get=\tikzumlcallreturn, type/.get=\tikzumlcalltype,% + padding/.get=\tikzumlcallpadding,% + draw/.get=\tikzumlcalldraw, fill/.get=\tikzumlcallfill,% + text/.get=\tikzumlcalltext}% + % + \edef\tikzumlfillcall{\tikzumlcallfill}% + \edef\tikzumldrawcall{\tikzumlcalldraw}% + \edef\tikzumltextcall{\tikzumlcalltext}% + \edef\tikzumltypecall{\tikzumlcalltype}% + % + \ifthenelse{\equal{\tikzumlcallDT}{tikzumlEmpty}}{% + \ifnum\thetikzumlCallNum=1% + \def\tikzumlcallDT{2}% + \def\tikzumlcallSrc{2}% + \else% + \def\tikzumlcallDT{2}% + \def\tikzumlcallSrc{1}% + \fi% + }{ + \def\tikzumlcallSrc{0}% + }% + % + \let\tikzumlCallStartNodeNameold\tikzumlCallStartNodeName% + \def\tikzumlCallStartNodeName{#2}% + \let\tikzumlCallEndNodeNameold\tikzumlCallEndNodeName% + \def\tikzumlCallEndNodeName{#3}% + \def\tikzumlcallheight{\tikzumlcallpadding}% + % + % managing time delays from previous/parent fragments + \ifnum\thetikzumlCallStartFragmentNum>0% + \let\tikzumlcallDTold\tikzumlcallDT% + \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}% + \edef\tikzumlcallDT{\pgfmathresult}% + \addtocounter{tikzumlCallStartFragmentNum}{-1} + \fi% + \ifnum\thetikzumlCallEndFragmentNum>0% + \let\tikzumlcallDTold\tikzumlcallDT% + \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}% + \edef\tikzumlcallDT{\pgfmathresult}% + \addtocounter{tikzumlCallEndFragmentNum}{-1} + \fi% + \ifnum\thetikzumlFragmentPartNum>0% + \let\tikzumlcallDTold\tikzumlcallDT% + \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}% + \edef\tikzumlcallDT{\pgfmathresult}% + \fi% + % + % managing parent-child structure + \ifnum\thetikzumlCallLevel>0% + \let\tikzumlCall@nameold\tikzumlCall@name% + \edef\tikzumlCall@name{\tikzumlcallname}% + \let\tikzumlCall@parentold\tikzumlCall@parent% + \edef\tikzumlCall@parent{\tikzumlCall@parentold @@\tikzumlCall@nameold}% + \else% + \edef\tikzumlCall@parent{}% + \edef\tikzumlCall@parentold{}% + \edef\tikzumlCall@nameold{} + \edef\tikzumlCall@name{\tikzumlcallname}% + \fi% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlCall@nodeName{\tikzumlCall@name}}\x% + % + \let\tikzumlCall@nodeNameold\tikzumlCall@nodeName% + % + \def\tikzumlcallstyle{tikzuml \tikzumlcalltype-msg style}% + % + % top node of activity period of call sender + \begin{pgfonlayer}{connections}% + \pgfmathparse{\tikzumlcallDT+\tikzumlcallSrc}% + \draw (\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname)+(0,-\pgfmathresult ex) node[coordinate, name=tikzumlTmpNode] {};% + \node[tikzuml activity style] (st-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};% + % + % update last node drawn on sender lifeline + \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname{st-\tikzumlCall@nodeName}% + % + % top node of activity period of call receiver + \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{% + \draw (st-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlcallpadding ex) node[coordinate, name=tikzumlTmpNode] {};% + \node[tikzuml activity style] (et-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};% + }{% + \node[tikzuml activity style] (et-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- st-\tikzumlCall@nodeName) {};% + }% + % + % update last node drawn on receiver lifeline + \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallEndNodeName \endcsname{et-\tikzumlCall@nodeName}% + \xdef\tikzumlCallBottomSrc{et-\tikzumlCall@nodeName}% + \end{pgfonlayer}% + % + \stepcounter{tikzumlCallLevel}% +}{% + \addtocounter{tikzumlCallLevel}{-1}% + % + % bottom nodes of activity periods of call sender and receiver + \begin{pgfonlayer}{connections}% + \ifnum\tikzumlCall@lastchildNum=\thetikzumlCallNum% + % + % this test occurs a bug with latex package preview + \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{% + \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlcallpadding ex) node[coordinate, name=tikzumlTmpNode] {};% + \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};% + \draw (eb-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlcallpadding ex) node[coordinate, name=tikzumlTmpNode] {};% + \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};% + }{% + \ifthenelse{\equal{\tikzumlcallreturn}{tikzumlEmpty}}{% + \pgfmathsetmacro{\tikzumlcallpaddingd}{0.5*\tikzumlcallpadding}% + }{% + \pgfmathsetmacro{\tikzumlcallpaddingd}{1.2*\tikzumlcallpadding}% + }% + \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlcallpaddingd ex) node[coordinate, name=tikzumlTmpNode] {};% + \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};% + \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- eb-\tikzumlCall@nodeName) {};% + }% + \xdef\tikzumlCallBottomSrc{sb-\tikzumlCall@nodeName}% + \else% + % + % managing time delays from previous/parent fragments + \ifnum\thetikzumlCallStartFragmentNum>0% + \let\tikzumlcallheightold\tikzumlcallpadding + \pgfmathparse{\tikzumlcallheightold+0.5*\tikzumlFragment@paddingy} + \edef\tikzumlcallheight{\pgfmathresult} + \addtocounter{tikzumlCallStartFragmentNum}{-1} + \fi% + \ifnum\thetikzumlCallEndFragmentNum>0% + \let\tikzumlcallheightold\tikzumlcallpadding + \pgfmathparse{\tikzumlcallheightold+0.5*\tikzumlFragment@paddingy} + \edef\tikzumlcallheight{\pgfmathresult} + \addtocounter{tikzumlCallEndFragmentNum}{-1} + \fi% + % + \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{% + \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlcallheight ex) node[coordinate, name=tikzumlTmpNode] {};% + \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};% + \draw (eb-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlcallpadding ex) node[coordinate, name=tikzumlTmpNode] {};% + \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};% + }{% + \draw (\tikzumlCallBottomSrc)+(0,-\tikzumlcallheight ex) node[coordinate, name=tikzumlTmpNode] {};% + \node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};% + \node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- eb-\tikzumlCall@nodeName) {};% + }% + % + \xdef\tikzumlCallBottomSrc{sb-\tikzumlCall@nodeName}% + \fi% + \end{pgfonlayer}% + % + % draw activity periods + \begin{pgfonlayer}{activity}% + \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{% + % draw root activity period only + \ifnum\thetikzumlCallLevel=0% + \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);% + \else% + % draw root activity from inner call + \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeNameold}}{}{% + \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);% + }% + \fi% + }{% + % draw root activity period + \ifnum\thetikzumlCallLevel=0% + \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);% + \else% + % draw root activity from inner call + \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeNameold}}{}{% + \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);% + }% + \fi% + % draw receiver activity period + \draw[draw=\tikzumldrawcall, fill=\tikzumlfillcall] (et-\tikzumlCall@nodeName.north west) rectangle (eb-\tikzumlCall@nodeName.south east);% + }% + \end{pgfonlayer}% + \ifthenelse{\equal{\tikzumlfillcallcolor}{\tikzumlcallfill}}{}{% + \fill[\tikzumlfillcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south east);% + \draw[\tikzumldrawcall] (st-\tikzumlCall@nodeName.north west) rectangle (sb-\tikzumlCall@nodeName.south west) (st-\tikzumlCall@nodeName.north east) rectangle (sb-\tikzumlCall@nodeName.south east); + }% + % + % update last nodes drawn on sender and receiver lifelines + \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallEndNodeName \endcsname{eb-\tikzumlCall@nodeName}% + \expandafter\xdef\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname{sb-\tikzumlCall@nodeName}% + % + % draw call arrows + \begin{pgfonlayer}{connections}% + \ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{% + \draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.east) -- ++(2.5*\tikzumlcallpadding ex,0) % + -- ++(0,-0.75*\tikzumlcallpadding ex) % + node[font=\tikzumlfont, text=\tikzumltextcall, midway, right, name=\tikzumlCall@nodeName-op] {\tikzumlcallop} % + -- (et-\tikzumlCall@nodeName.east);% + % + % draw return arrow and update fit for parent fragment + \ifthenelse{\equal{\tikzumltypecall}{synchron}}{% + \ifthenelse{\NOT\equal{\tikzumlcallreturn}{}\OR\equal{\tikzumlCallWithReturn}{tikzumlTrue}}{% + \ifnum\c@tikzumlFragmentLevel>0% + \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}% + \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op) (\tikzumlCall@nodeName-return)}% + \fi% + % + \draw[tikzuml call return style, \tikzumldrawcall] (eb-\tikzumlCall@nodeName.east) -- ++(2.5*\tikzumlcallpadding ex,0) -- ++(0,-0.75*\tikzumlcallpadding ex) % + node[font=\tikzumlfont, text=\tikzumltextcall, midway, right, name=\tikzumlCall@nodeName-return] {\tikzumlcallreturn} % + -- (sb-\tikzumlCall@nodeName.east);% + }{% + \ifnum\c@tikzumlFragmentLevel>0% + \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}% + \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}% + \fi% +}% + }{% + \ifnum\c@tikzumlFragmentLevel>0% + \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}% + \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}% + \fi% + % + }% + }{% + % draw call arrows + \pgfextractx{\tikzumlCall@xa}{\pgfpointanchor{\tikzumlCallStartNodeName}{center}}% + \pgfextractx{\tikzumlCall@xb}{\pgfpointanchor{\tikzumlCallEndNodeName}{center}}% + % + \ifthenelse{\tikzumlCall@xb>\tikzumlCall@xa}{% + \draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.east) -- (et-\tikzumlCall@nodeName.west) % + node[font=\tikzumlfont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-op] {\tikzumlcallop};% + }{% + \draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.west) -- (et-\tikzumlCall@nodeName.east) % + node[font=\tikzumlfont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-op] {\tikzumlcallop};% + }% + % + % draw return arrow and update fit for parent fragment + \ifthenelse{\equal{\tikzumltypecall}{synchron}}{% + \ifthenelse{\NOT\equal{\tikzumlcallreturn}{}\OR\equal{\tikzumlCallWithReturn}{tikzumlTrue}}{% + \ifnum\c@tikzumlFragmentLevel>0% + \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}% + \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op) (\tikzumlCall@nodeName-return)}% + \fi% + % + \ifthenelse{\tikzumlCall@xb>\tikzumlCall@xa}{% + \draw[tikzuml call return style, \tikzumldrawcall] (eb-\tikzumlCall@nodeName.west) -- (sb-\tikzumlCall@nodeName.east) % + node[font=\tikzumlfont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-return] {\tikzumlcallreturn};% + }{% + \draw[tikzuml call return style, \tikzumldrawcall] (eb-\tikzumlCall@nodeName.east) -- (sb-\tikzumlCall@nodeName.west) % + node[font=\tikzumlfont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-return] {\tikzumlcallreturn};% + }% + }{% + \ifnum\c@tikzumlFragmentLevel>0% + \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}% + \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}% + \fi% + }% + }{% + \ifnum\c@tikzumlFragmentLevel>0% + \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}% + \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCall@nodeName) (et-\tikzumlCall@nodeName) (eb-\tikzumlCall@nodeName) (sb-\tikzumlCall@nodeName) (\tikzumlCall@nodeName-op)}% + \fi% + }% + }% + \end{pgfonlayer}% +}% + +% alias for function self call +\newenvironment{umlcallself}[2][]{\begin{umlcall}[#1]{#2}{#2} }{\end{umlcall}}% + +% define a combined fragment +% optional : name of fragment +% type of fragment (opt, alt, break, loop, par, critical, ignore, consider, assert, neg, weak, strict, ref) +% label of fragment (ex : condition for opt, iterator for loop, ...) +% inner xsep and ysep (padding of the fragment box) +% draw, fill, text colors +\newenvironment{umlfragment}[1][]{% + + % define a fragment separator + % optional : label of the fragment part (ex : else for alt) + \providecommand{\umlfpart}[1][]{% + \stepcounter{tikzumlFragmentPartNum}% + % + \node[outer sep=0, inner xsep=\tikzumlfragmentxsep ex, inner ysep=\tikzumlfragmentysep ex, fit=\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname, name=\tikzumlFragment@name-Part-tmp] {};% + \node[anchor=east, name=\tikzumlFragment@name-PartType-\thetikzumlFragmentPartNum] at (\tikzumlFragment@name-Part-tmp.north west |- \tikzumlCallBottomSrc) {\phantom{\tikzumlfragmenttype}}; + \draw (\tikzumlFragment@name-PartType-\thetikzumlFragmentPartNum.north west |- \tikzumlCallBottomSrc)+(0,-0.4*\tikzumlFragment@paddingy ex) node[name=\tikzumlFragment@name-PartWest-\thetikzumlFragmentPartNum] {}; + \draw (\tikzumlFragment@name-Part-tmp.north east |- \tikzumlCallBottomSrc)+(0,-0.4*\tikzumlFragment@paddingy ex) node[name=\tikzumlFragment@name-PartEast-\thetikzumlFragmentPartNum] {}; + \draw[dashed] (\tikzumlFragment@name-PartWest-\thetikzumlFragmentPartNum) -- (\tikzumlFragment@name-PartEast-\thetikzumlFragmentPartNum); + \draw (\tikzumlFragment@name-PartType-\thetikzumlFragmentPartNum)+(0,-0.4*\tikzumlFragment@paddingy ex) node[name=tikzumlTmpNode] {\phantom{\tikzumlfragmenttype}}; + \node[anchor=north west] at (tikzumlTmpNode.south west) {[##1]};% + }% + + \stepcounter{tikzumlFragmentNum}% + % + \pgfkeys{/tikzuml/fragment/.cd,% + name/.initial={fragment@\alph{tikzumlFragmentNum}}, type/.initial=opt,% + label/.initial={tikzumlEmpty},% + inner xsep/.initial=1, inner ysep/.initial=1,% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillfragmentcolor,% + text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlfragment, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/fragment/.cd, #1}% + \pgfkeys{/tikzuml/fragment/.cd,% + name/.get=\tikzumlfragmentname, type/.get=\tikzumlfragmenttype,% + label/.get=\tikzumlfragmentlabel,% + inner xsep/.get=\tikzumlfragmentxsep, inner ysep/.get=\tikzumlfragmentysep,% + draw/.get=\tikzumlfragmentdraw, fill/.get=\tikzumlfragmentfill,% + text/.get=\tikzumlfragmenttext}% + % + \ifthenelse{\equal{\tikzumlfragmentlabel}{tikzumlEmpty}}{% + \def\tikzumlfragmentlabel{}% + }{% + \let\tikzumlfragmentlabelold\tikzumlfragmentlabel% + \def\tikzumlfragmentlabel{[\tikzumlfragmentlabelold]}% + }% + + % + \ifnum\thetikzumlFragmentLevel>0% + \let\tikzumlFragment@parentold\tikzumlFragment@parent% + \let\tikzumlFragment@nameold\tikzumlFragment@name% + \edef\tikzumlFragment@parent{\tikzumlFragment@nameold}% + \else% + \setcounter{tikzumlFragmentPartNum}{0}% + \edef\tikzumlFragment@parent{}% + \edef\tikzumlFragment@parentold{}% + \edef\tikzumlFragment@nameold{}% + \fi% + % + \edef\tikzumlFragment@name{\tikzumlfragmentname}% + \expandafter\gdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{}% + % + \stepcounter{tikzumlFragmentLevel}% + % + \ifnum\thetikzumlCallLevel>0% + \stepcounter{tikzumlCallStartFragmentNum}% + \fi% + % + \pgfmathparse{6*\tikzumlfragmentysep}% + \xdef\tikzumlFragment@paddingy{\pgfmathresult}% + \if\c@tikzumlFragmentLevelNum=0% + \setcounter{tikzumlFragmentLevelNum}{\thetikzumlFragmentLevel}% + \fi% + % + % time delay adjustment for two consecutive fragments + \ifnum\thetikzumlCallEndFragmentNum>0% + \addtocounter{tikzumlCallEndFragmentNum}{-1} + \fi% +}{% + % + \addtocounter{tikzumlFragmentLevel}{-1}% + % + \ifnum\thetikzumlFragmentLevel>0% + \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@parent \endcsname}% + \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@parent \endcsname{\tikzumlFragmentFitOld (\tikzumlFragment@name)}% + \fi% + % + % draw working fragment box + \begin{pgfonlayer}{fragment\thetikzumlFragmentLevel}% + \node[outer sep=0, inner xsep=\tikzumlfragmentxsep ex, inner ysep=\tikzumlfragmentysep ex, fit=\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname, name=\tikzumlFragment@name-back] {};% + \end{pgfonlayer}% + % + % draw type and label + \node[text=\tikzumlfragmenttext, font=\tikzumlfont, anchor=north east, name=\tikzumlFragment@name-type] % + at (\tikzumlFragment@name-back.north west) {\tikzumlfragmenttype};% + \node[text=\tikzumlfragmenttext, font=\tikzumlfont, anchor=north west, name=\tikzumlFragment@name-label] % + at (\tikzumlFragment@name-type.south west) {\tikzumlfragmentlabel};% + % + % draw final fragment box + \begin{pgfonlayer}{fragment\thetikzumlFragmentLevel}% + \node[draw=\tikzumlfragmentdraw, fill=\tikzumlfragmentfill, outer sep=0, inner sep=0, font=\tikzumlfont, fit=(\tikzumlFragment@name-back) (\tikzumlFragment@name-type) (\tikzumlFragment@name-label), name=\tikzumlFragment@name] {};% + \end{pgfonlayer}% + % + \draw[draw=\tikzumlfragmentdraw] (\tikzumlFragment@name.north west) rectangle (\tikzumlFragment@name.south east);% + \draw (\tikzumlFragment@name-type.south east)+(0,1ex) node[name=\tikzumlFragment@name-typetop, inner sep=0] {};% + \draw (\tikzumlFragment@name-type.south east)+(-1ex,0) node[name=\tikzumlFragment@name-typeleft, inner sep=0] {};% + \draw (\tikzumlFragment@name.north west) -| (\tikzumlFragment@name-typetop.center) -- (\tikzumlFragment@name-typeleft.center) -| (\tikzumlFragment@name.north west);% + % + \ifnum\thetikzumlCallLevel>0% + \stepcounter{tikzumlCallEndFragmentNum}% + \fi% +}% + +% define a constructor call +% arg : call sender +% name of constructed object +% optional : x coordinate of the new object +% stereotype of the new object +% class type of the new object +% time delay from last event +% name of the call +% draw, fill, text colors +\newcommand{\umlcreatecall}[3][]{% + \stepcounter{tikzumlCallNum}% + \edef\tikzumlCall@lastchildNum{\thetikzumlCallNum}% for testing presence of sub-calls + \gdef\tikzumlInCreateCall{1}% + \pgfkeys{/tikzuml/createcall/.cd,% + x/.initial={tikzumlEmpty}, stereo/.initial=object, class/.initial={},% + dt/.initial=4, name/.initial={call-\thetikzumlCallNum},% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillcallcolor,% + text/.initial=\tikzumltextcolor,% + draw obj/.initial=\tikzumldrawcolor, fill obj/.initial=\tikzumlfillobjectcolor,% + text obj/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlcreatecall, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/createcall/.cd, #1}% + \pgfkeys{/tikzuml/createcall/.cd,% + x/.get=\tikzumlcallX, stereo/.get=\tikzumlcallstereo,% + class/.get=\tikzumlcallclass,% + dt/.get=\tikzumlcallDT, name/.get=\tikzumlcallname,% + draw/.get=\tikzumlcalldraw, fill/.get=\tikzumlcallfill,% + text/.get=\tikzumlcalltext,% + draw obj/.get=\tikzumlcallobjdraw, fill obj/.get=\tikzumlcallobjfill,% + text obj/.get=\tikzumlcallobjtext}% + % + \def\tikzumlCreateCallSrc@name{#2}% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlCreateCallSrc@nodeName{\tikzumlCreateCallSrc@name}}\x% + % + % managing time delays from previous/parent fragments + \ifnum\thetikzumlCallStartFragmentNum>0% + \let\tikzumlcallDTold\tikzumlcallDT% + \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}% + \edef\tikzumlcallDT{\pgfmathresult}% + \addtocounter{tikzumlCallStartFragmentNum}{-1} + \fi% + \ifnum\thetikzumlCallEndFragmentNum>0% + \let\tikzumlcallDTold\tikzumlcallDT% + \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}% + \edef\tikzumlcallDT{\pgfmathresult}% + \addtocounter{tikzumlCallEndFragmentNum}{-1} + \fi% + \ifnum\thetikzumlFragmentPartNum>0% + \let\tikzumlcallDTold\tikzumlcallDT% + \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlcallDTold}% + \edef\tikzumlcallDT{\pgfmathresult}% + \fi% + % + % managing parent-child structure + \ifnum\thetikzumlCallLevel>0% + \let\tikzumlCall@nameold\tikzumlCall@name% + \def\tikzumlCall@name{\tikzumlcallname}% + \let\tikzumlCall@parentold\tikzumlCall@parent% + \edef\tikzumlCall@parent{\tikzumlCall@parentold @@\tikzumlCall@nameold}% + \else% + \edef\tikzumlCall@parent{}% + \edef\tikzumlCall@parentold{}% + \edef\tikzumlCall@nameold{} + \edef\tikzumlCall@name{\tikzumlcallname}% + \fi% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlCreateCall@nodeName{\tikzumlCall@name}}\x% + % + \draw (\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname)+(0,-\tikzumlcallDT ex) node[name=st-\tikzumlCreateCall@nodeName, tikzuml activity style] {};% + % + \xdef\tikzumlCreateCallObjectSrc{st-\tikzumlCreateCall@nodeName}% + % + \umlobject[x=\tikzumlcallX, stereo=\tikzumlcallstereo, class=\tikzumlcallclass, draw=\tikzumlcallobjdraw, fill=\tikzumlcallobjfill, text=\tikzumlcallobjtext]{#3}% + % + \draw (\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname |- #3)+(0,-0.5*\tikzumlcallDT ex) node[name=sb-\tikzumlCreateCall@nodeName, tikzuml activity style] {};% + % + \expandafter\xdef\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname{sb-\tikzumlCreateCall@nodeName}% + \xdef\tikzumlCallBottomSrc{sb-\tikzumlCreateCall@nodeName}% + % + \begin{pgfonlayer}{connections}% + \draw[tikzuml synchron-msg style, \tikzumlcalldraw] (st-\tikzumlCreateCall@nodeName) -- (#3) node[midway, above, font=\tikzumlfont, text=\tikzumlcalltext, name=\tikzumlCreateCall@nodeName-op] {create};% + \end{pgfonlayer}% + % + \ifnum\thetikzumlCallLevel=0% + \begin{pgfonlayer}{activity}% + \draw[draw=\tikzumlcalldraw, fill=\tikzumlcallfill] (st-\tikzumlCreateCall@nodeName.north west) rectangle (sb-\tikzumlCreateCall@nodeName.south east);% + \end{pgfonlayer}% + \fi% + % add to fit fragment + \ifnum\c@tikzumlFragmentLevel>0% + \edef\tikzumlFragmentFitOld{\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname}% + \expandafter\xdef\csname tikzumlFragmentFit\tikzumlFragment@name \endcsname{\tikzumlFragmentFitOld (st-\tikzumlCreateCall@nodeName) (sb-\tikzumlCreateCall@nodeName) (\tikzumlCreateCall@nodeName-op) (#3) }% + \fi% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% component diagrams % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\tikzstyle{tikzuml connector style}=[color=\tikzumldrawcolor, -]% + +\newcounter{tikzumlComponentLevel}% +\newcounter{tikzumlComponentSubComponentNum}% +\newcounter{tikzumlConnectorNum}% +\setcounter{tikzumlConnectorNum}{1}% + +\newcommand{\picturedcomponent}[1]{% + \pgfkeys{/tikzuml/component/picture/.cd, scale/.initial=1, .unknown/.code={}}% + \pgfkeys{/tikzuml/component/picture/.cd,#1}% + \pgfkeys{/tikzuml/component/picture/.cd, scale/.get=\tikzumlcomponentscale}% + \begin{tikzpicture}[#1]% + \filldraw (0,0) rectangle (1ex,1.5ex);% + \filldraw (-0.2ex,0.4ex) rectangle (0.2ex,0.6ex);% + \filldraw (-0.2ex,0.9ex) rectangle (0.2ex,1.1ex);% + \end{tikzpicture}% +}% + +% define a uml component +% args : name of the component +% content of the component +% optional args : x,y coordinates of the component +% width of the component node +\newenvironment{umlcomponent}[2][]{% + \ifnum\thetikzumlComponentLevel>0% + \let\tikzumlComponent@nameold\tikzumlComponent@fitname% + \let\tikzumlComponent@parentold\tikzumlComponent@parent% + \edef\tikzumlComponent@parent{\tikzumlComponent@parentold @@\tikzumlComponent@nameold}% + \else% + \def\tikzumlComponent@parent{}% + \fi% + % + \stepcounter{tikzumlComponentLevel}% + % + \pgfkeys{/tikzuml/component/.cd,% + x/.initial=0, y/.initial=0, width/.initial=8ex, name/.initial={},% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillcomponentcolor,% + text/.initial=\tikzumltextcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlcomponent, invalid option \keyname}% + }}% + \pgfkeys{/tikzuml/component/.cd, #1}% + \pgfkeys{/tikzuml/component/.cd,% + x/.get=\tikzumlcomponentX, y/.get=\tikzumlcomponentY,% + width/.get=\umlcomponentMinimumWidth, name/.get=\umlcomponentName,% + draw/.get=\tikzumlcomponentdraw, fill/.get=\tikzumlcomponentfill,% + text/.get=\tikzumlcomponenttext}% + % + \ifthenelse{\equal{\umlcomponentName}{}}{% + \edef\tikzumlComponent@name{#2}% + }{% + \edef\tikzumlComponent@name{\umlcomponentName}% + }% + % + \begingroup% + \def\_{@}\edef\x{\endgroup% + \def\noexpand\tikzumlComponent@fitname{\tikzumlComponent@name}}\x% + % + \let\tikzumlComponent@nodeNameold\tikzumlComponent@nodeName% + \def\tikzumlComponent@caption{#2}% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlComponent@nodeName{\tikzumlComponent@name}}\x% + % + \expandafter\gdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{}% + % + \setcounter{tikzumlComponentSubComponentNum}{0}% + % + \begin{scope}[xshift=\tikzumlcomponentX cm, yshift=\tikzumlcomponentY cm]% +}{% + \addtocounter{tikzumlComponentLevel}{-1}% + \begin{pgfonlayer}{component\thetikzumlComponentLevel}% + % + % if contains nothing, one define a fictive node to enable the fit option + \ifnum\c@tikzumlComponentSubComponentNum=0% + \node[inner ysep=0.5ex, minimum width=\umlcomponentMinimumWidth, font=\tikzumlfont] (\tikzumlComponent@nodeName-root) at (0,0) {\phantom{\tikzumlComponent@nodeName}};% + \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{(\tikzumlComponent@nodeName-root)}% + \fi% + % + \ifnum\c@tikzumlComponentLevel>0% + \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent\endcsname}% + \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent\endcsname{\tikzumlComponentFitTmp (\tikzumlComponent@nodeName-body) (\tikzumlComponent@nodeName-caption)}% + \stepcounter{tikzumlComponentSubComponentNum}% + \fi% + % + \node[inner sep=2ex, font=\tikzumlfont, fit = \csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname] (\tikzumlComponent@nodeName-body) {};% + \node[above, font=\tikzumlfont] (\tikzumlComponent@nodeName-captiontmp) at (\tikzumlComponent@nodeName-body.north) {\tikzumlComponent@caption};% + \node (\tikzumlComponent@nodeName-logotmp) at (\tikzumlComponent@nodeName-captiontmp.north -| \tikzumlComponent@nodeName-body.east) {\picturedcomponent{draw=\tikzumlcomponentdraw, fill=\tikzumlcomponentfill, font=\tikzumlfont} };% + \node[draw=\tikzumlcomponentdraw, fill=\tikzumlcomponentfill, name=\tikzumlComponent@nodeName, fit=(\tikzumlComponent@nodeName-body) (\tikzumlComponent@nodeName-captiontmp)] {};% + \node[font=\tikzumlfont] (\tikzumlComponent@nodeName-caption) at (\tikzumlComponent@nodeName-captiontmp) {\tikzumlComponent@caption};% + \draw (\tikzumlComponent@nodeName-caption.north -| \tikzumlComponent@nodeName.east) node[font=\tikzumlfont, xshift=-1ex, below=-1ex, name=\tikzumlComponent@nodeName-logo] {\picturedcomponent{draw=\tikzumlcomponentdraw, fill=\tikzumlcomponentfill, font=\tikzumlfont} };% + \draw (\tikzumlComponent@nodeName-caption.south -| \tikzumlComponent@nodeName.north west) -- (\tikzumlComponent@nodeName-caption.south -| \tikzumlComponent@nodeName.north east);% + \coordinate (\tikzumlComponent@nodeName-west-port) at (\tikzumlComponent@nodeName.west); + \coordinate (\tikzumlComponent@nodeName-east-port) at (\tikzumlComponent@nodeName.east); + \coordinate (\tikzumlComponent@nodeName-south-port) at (\tikzumlComponent@nodeName.south); + \coordinate (\tikzumlComponent@nodeName-north-port) at (\tikzumlComponent@nodeName.north); + + \end{pgfonlayer}% + \end{scope}% + % + % add to fit + \ifnum\c@tikzumlPackageLevel>0% + \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname}% + \expandafter\xdef\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname{\tikzumlPackageFitOld (\tikzumlComponent@nodeName)}% + \stepcounter{tikzumlPackageClassNum}% + \fi% +}% + +% shortcut for empty state +\newcommand{\umlbasiccomponent}[2][]{\begin{umlcomponent}[#1]{#2} \end{umlcomponent}}% + +\newcommand{\umlrequiredinterface}[2][]{% + \def\tikzumlInterfaceWithPort{tikzumlFalse}% + \pgfkeys{/tikzuml/requiredinterfacerelation/.cd,% + interface/.initial={}, distance/.initial=2.5cm,% + width/.initial=1em, padding/.initial=1cm,% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillcomponentcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{with port}}{% + \def\tikzumlInterfaceWithPort{tikzumlTrue}% + }{}% + }}% + \pgfkeys{/tikzuml/requiredinterfacerelation/.cd, #1}% + \pgfkeys{/tikzuml/requiredinterfacerelation/.cd,% + interface/.get=\tikzumlRequiredInterfaceLabel,% + distance/.get=\tikzumlRequiredInterfaceDistance,% + width/.get=\tikzumlRequiredInterfaceWidth,% + padding/.get=\tikzumlRequiredInterfacePadding,% + draw/.get=\tikzumlrequiredinterfacedraw,% + fill/.get=\tikzumlrequiredinterfacefill,}% + % + \edef\tikzumlRequiredInterface@name{#2}% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlRequiredInterface@nodeName{\tikzumlRequiredInterface@name}}\x% + % + \ifthenelse{\equal{\tikzumlInterfaceWithPort}{tikzumlTrue}}{% + \node[inner sep=0.5*\tikzumlRequiredInterfaceWidth, rectangle, draw=\tikzumlrequiredinterfacedraw, fill=\tikzumlrequiredinterfacefill] (\tikzumlRequiredInterface@nodeName-east-port) at (\tikzumlRequiredInterface@nodeName.east) {};% + }{% + \node[inner sep=0] (\tikzumlRequiredInterface@nodeName-east-port) at (\tikzumlRequiredInterface@nodeName.east) {};% + }% + \begin{scope}% + \draw (\tikzumlRequiredInterface@nodeName)+(\tikzumlRequiredInterfaceDistance,0) node[inner sep=0, text width=\tikzumlRequiredInterfaceWidth, circle, name=\tikzumlRequiredInterface@nodeName-east-interface-tmp] {};% + \clip (\tikzumlRequiredInterface@nodeName-east-interface-tmp.north) rectangle (\tikzumlRequiredInterface@nodeName-east-interface-tmp.south -| \tikzumlRequiredInterface@nodeName-east-interface-tmp.west);% + \node[inner sep=0, text width=\tikzumlRequiredInterfaceWidth, circle, draw=\tikzumlrequiredinterfacedraw] (\tikzumlRequiredInterface@nodeName-east-interface) at (\tikzumlRequiredInterface@nodeName-east-interface-tmp) {};% + \end{scope}% + \node[above] at (\tikzumlRequiredInterface@nodeName-east-interface.north) {\tikzumlRequiredInterfaceLabel};% + % + \umlrelation[style={tikzuml connector style}, #1]{\tikzumlRequiredInterface@nodeName-east-port}{\tikzumlRequiredInterface@nodeName-east-interface}% + + \draw (\tikzumlRequiredInterface@nodeName-east-interface)+(\tikzumlRequiredInterfacePadding,0) node[name=\tikzumlRequiredInterface@nodeName-east-padding] {};% + + % add to fit + \ifnum\c@tikzumlComponentLevel>0% + \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname}% + \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlRequiredInterface@nodeName-east-padding) (\tikzumlRequiredInterface@nodeName-east-port) }% + \fi% +}% + +\newcommand{\umlprovidedinterface}[2][]{% + \def\tikzumlInterfaceWithPort{tikzumlFalse}% + \pgfkeys{/tikzuml/providedinterfacerelation/.cd,% + interface/.initial={}, distance/.initial=3cm,% + width/.initial=1em, padding/.initial=1cm,% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillcomponentcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{with port}}{% + \def\tikzumlInterfaceWithPort{tikzumlTrue}% + }{}% + }}% + \pgfkeys{/tikzuml/providedinterfacerelation/.cd, #1}% + \pgfkeys{/tikzuml/providedinterfacerelation/.cd,% + interface/.get=\tikzumlProvidedInterfaceLabel,% + distance/.get=\tikzumlProvidedInterfaceDistance,% + padding/.get=\tikzumlProvidedInterfacePadding,% + width/.get=\tikzumlProvidedInterfaceWidth,% + draw/.get=\tikzumlprovidedinterfacedraw,% + fill/.get=\tikzumlprovidedinterfacefill}% + % + \edef\tikzumlProvidedInterface@name{#2}% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlProvidedInterface@nodeName{\tikzumlProvidedInterface@name}}\x% + % + \ifthenelse{\equal{\tikzumlInterfaceWithPort}{tikzumlTrue}}{% + \node[inner sep=0.5*\tikzumlProvidedInterfaceWidth, rectangle, draw=\tikzumlprovidedinterfacedraw, fill=\tikzumlprovidedinterfacefill] (\tikzumlProvidedInterface@nodeName-west-port) at (\tikzumlProvidedInterface@nodeName.west) {};% + }{% + \node[inner sep=0] (\tikzumlProvidedInterface@nodeName-west-port) at (\tikzumlProvidedInterface@nodeName.west) {};% + }% + \draw (\tikzumlProvidedInterface@nodeName)+(-\tikzumlProvidedInterfaceDistance,0) node[inner sep=0, text width=\tikzumlProvidedInterfaceWidth, circle, draw=\tikzumlprovidedinterfacedraw, fill=\tikzumlprovidedinterfacefill, name=\tikzumlProvidedInterface@nodeName-west-interface] {};% + \node[above] at (\tikzumlProvidedInterface@nodeName-west-interface.north) + {\tikzumlProvidedInterfaceLabel};% + % + \umlrelation[style={tikzuml connector style}, #1]{\tikzumlProvidedInterface@nodeName-west-port}{\tikzumlProvidedInterface@nodeName-west-interface}% + + \draw (\tikzumlProvidedInterface@nodeName-west-interface)+(-\tikzumlProvidedInterfacePadding,0) node[name=\tikzumlProvidedInterface@nodeName-west-padding] {};% + % add to fit + \ifnum\thetikzumlComponentLevel>0% + \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname}% + \expandafter\xdef\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname{\tikzumlComponentFitTmp (\tikzumlProvidedInterface@nodeName-west-padding) (\tikzumlProvidedInterface@nodeName-west-port) }% + \fi% +}% + +\newlength{\tikzuml@AC@xa}% +\newlength{\tikzuml@AC@ya}% +\newlength{\tikzuml@AC@xb}% +\newlength{\tikzuml@AC@yb}% +\newlength{\tikzuml@AC@xi}% +\newlength{\tikzuml@AC@yi}% +\newlength{\tikzuml@AC@xic}% +\newlength{\tikzuml@AC@yic}% +\newlength{\tikzuml@AC@xio}% +\newlength{\tikzuml@AC@yio}% +\newlength{\tikzuml@AC@AB}% +\newlength{\tikzuml@AC@lambda}% +\newlength{\tikzuml@AC@xtrc}% +\newlength{\tikzuml@AC@ytrc}% +\newlength{\tikzuml@AC@xtlc}% +\newlength{\tikzuml@AC@ytlc}% +\newlength{\tikzuml@AC@xblc}% +\newlength{\tikzuml@AC@yblc}% +\newlength{\tikzuml@AC@xbrc}% +\newlength{\tikzuml@AC@ybrc}% +\newlength{\tikzuml@AC@middleArm}% + +\newcommand{\umlassemblyconnectorsymbol}[2]{% + \ifthenelse{\NOT\equal{\tikzumlAssemblyConnectorLabel}{}}{% + \edef\tikzuml@ACStart@name{#1}% + \edef\tikzuml@ACEnd@name{#2}% + \edef\tikzuml@AC@width{\tikzumlAssemblyConnectorWidth}% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzuml@ACStart@nodeName{\tikzuml@ACStart@name}}\x% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzuml@ACEnd@nodeName{\tikzuml@ACEnd@name}}\x% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzuml@ACInterface@nodeName{\tikzumlAssemblyConnectorSymbolName}}\x% + % + \pgfextractx{\tikzuml@AC@xa}{\pgfpointanchor{\tikzuml@ACStart@nodeName}{\tikzumlAssemblyConnectorStartAnchor}}% + \pgfextracty{\tikzuml@AC@ya}{\pgfpointanchor{\tikzuml@ACStart@nodeName}{\tikzumlAssemblyConnectorStartAnchor}}% + \pgfextractx{\tikzuml@AC@xb}{\pgfpointanchor{\tikzuml@ACEnd@nodeName}{\tikzumlAssemblyConnectorEndAnchor}}% + \pgfextracty{\tikzuml@AC@yb}{\pgfpointanchor{\tikzuml@ACEnd@nodeName}{\tikzumlAssemblyConnectorEndAnchor}}% + \pgfmathsetlength{\tikzuml@AC@xi}{0.5*\tikzuml@AC@xa+0.5*\tikzuml@AC@xb}% + \pgfmathsetlength{\tikzuml@AC@yi}{0.5*\tikzuml@AC@ya+0.5*\tikzuml@AC@yb}% + \pgfmathsetlength{\tikzuml@AC@AB}{veclen(\tikzuml@AC@xa-\tikzuml@AC@xb,\tikzuml@AC@ya-\tikzuml@AC@yb)}% + \pgfmathsetlength{\tikzuml@AC@lambda}{0.25*\tikzuml@AC@width/\tikzuml@AC@AB}% + \pgfmathsetlength{\tikzuml@AC@xic}{\tikzuml@AC@xi-\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}% + \pgfmathsetlength{\tikzuml@AC@yic}{\tikzuml@AC@yi-\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}% + \pgfmathsetlength{\tikzuml@AC@xio}{\tikzuml@AC@xi+\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}% + \pgfmathsetlength{\tikzuml@AC@yio}{\tikzuml@AC@yi+\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}% + \node[inner sep=0.5*\tikzuml@AC@width] (\tikzuml@ACInterface@nodeName-interface) at (\tikzuml@AC@xi,\tikzuml@AC@yi) {};% + \node[inner sep=0, text width=\tikzuml@AC@width, circle, draw=\tikzumlassemblyconnectordraw, fill=\tikzumlassemblyconnectorfill] (\tikzuml@ACInterface@nodeName-io) at (\tikzuml@AC@xio,\tikzuml@AC@yio) {};% + \begin{scope}% + \pgfmathsetlength{\tikzuml@AC@xtrc}{\tikzuml@AC@xic-2*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}% + \pgfmathsetlength{\tikzuml@AC@ytrc}{\tikzuml@AC@yic+2*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}% + \pgfmathsetlength{\tikzuml@AC@xbrc}{\tikzuml@AC@xic+2*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya)}% + \pgfmathsetlength{\tikzuml@AC@ybrc}{\tikzuml@AC@yic-2*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa)}% + \pgfmathsetlength{\tikzuml@AC@xtlc}{\tikzuml@AC@xic-3*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya+\tikzuml@AC@xb-\tikzuml@AC@xa)}% + \pgfmathsetlength{\tikzuml@AC@ytlc}{\tikzuml@AC@yic+3*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa+\tikzuml@AC@ya-\tikzuml@AC@yb)}% + \pgfmathsetlength{\tikzuml@AC@xblc}{\tikzuml@AC@xic+3*\tikzuml@AC@lambda*(\tikzuml@AC@yb-\tikzuml@AC@ya+\tikzuml@AC@xa-\tikzuml@AC@xb)}% + \pgfmathsetlength{\tikzuml@AC@yblc}{\tikzuml@AC@yic-3*\tikzuml@AC@lambda*(\tikzuml@AC@xb-\tikzuml@AC@xa+\tikzuml@AC@yb-\tikzuml@AC@ya)}% + \coordinate (\tikzuml@ACInterface@nodeName-trc) at (\tikzuml@AC@xtrc,\tikzuml@AC@ytrc);% + \coordinate (\tikzuml@ACInterface@nodeName-brc) at (\tikzuml@AC@xbrc,\tikzuml@AC@ybrc);% + \coordinate (\tikzuml@ACInterface@nodeName-tlc) at (\tikzuml@AC@xtlc,\tikzuml@AC@ytlc);% + \coordinate (\tikzuml@ACInterface@nodeName-blc) at (\tikzuml@AC@xblc,\tikzuml@AC@yblc);% + \clip (\tikzuml@ACInterface@nodeName-trc) -- (\tikzuml@ACInterface@nodeName-tlc) -- (\tikzuml@ACInterface@nodeName-blc) -- (\tikzuml@ACInterface@nodeName-brc) -- cycle;% + \node[inner sep=0, text width=\tikzuml@AC@width, circle, draw=\tikzumlassemblyconnectordraw, fill=\tikzumlassemblyconnectorfill] (\tikzuml@ACInterface@nodeName-ic) at (\tikzuml@AC@xic,\tikzuml@AC@yic) {};% + \end{scope}% + \node[above, font=\tikzumlfont] at (\tikzuml@ACInterface@nodeName-interface.north) + {\tikzumlAssemblyConnectorLabel};% + }{}% +}% + +\newcommand{\umlassemblyconnector}[3][]{% + \def\tikzumlAssemblyConnectorWithPort{tikzumlFalse}% + \def\tikzumlAssemblyConnectorFirstArm{tikzumlFalse}% + \def\tikzumlAssemblyConnectorSecondArm{tikzumlFalse}% + \def\tikzumlAssemblyConnectorMiddleArm{tikzumlFalse}% + \def\tikzumlAssemblyConnectorLastArm{tikzumlFalse}% + \pgfkeys{/tikzuml/assemblyconnectorrelation/.cd,% + geometry/.initial=--, interface/.initial={},% + arm1/.initial={auto}, arm2/.initial={auto},% + name/.initial=connector-\thetikzumlConnectorNum, width/.initial=1em,% + anchor1/.initial={}, anchor2/.initial={},% + draw/.initial=\tikzumldrawcolor,% + fill assembly connector/.initial=\tikzumlfillassemblyconnectorcolor,% + fill port/.initial=\tikzumlfillportcolor,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{with port}}{% + \def\tikzumlAssemblyConnectorWithPort{tikzumlTrue}% + }{% + \ifthenelse{\equal{\keyname}{first arm}}{% + \def\tikzumlAssemblyConnectorFirstArm{tikzumlTrue}% + }{% + \ifthenelse{\equal{\keyname}{second arm}}{% + \def\tikzumlAssemblyConnectorSecondArm{tikzumlTrue}% + }{% + \ifthenelse{\equal{\keyname}{middle arm}}{% + \def\tikzumlAssemblyConnectorMiddleArm{tikzumlTrue}% + }{% + \ifthenelse{\equal{\keyname}{last arm}}{% + \def\tikzumlAssemblyConnectorLastArm{tikzumlTrue}% + }{% + }% + }% + }% + }% + }% + }}% + \pgfkeys{/tikzuml/assemblyconnectorrelation/.cd, #1}% + \pgfkeys{/tikzuml/assemblyconnectorrelation/.cd,% + geometry/.get=\tikzumlAssemblyConnectorGeometry,% + name/.get=\tikzumlAssemblyConnectorName,% + interface/.get=\tikzumlAssemblyConnectorLabel,% + width/.get=\tikzumlAssemblyConnectorWidth,% + arm1/.get=\tikzumlAssemblyConnectorStartArm,% + arm2/.get=\tikzumlAssemblyConnectorEndArm,% + anchor1/.get=\umlAssemblyConnectorStartAnchor,% + anchor2/.get=\umlAssemblyConnectorEndAnchor,% + draw/.get=\tikzumlassemblyconnectordraw,% + fill assembly connector/.get=\tikzumlassemblyconnectorfill,% + fill port/.get=\tikzumlassemblyconnectorportfill}% + % + \edef\tikzumlAssemblyConnectorStart@name{#2}% + \edef\tikzumlAssemblyConnectorEnd@name{#3}% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlAssemblyConnectorStart@nodeName{\tikzumlAssemblyConnectorStart@name}}\x% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlAssemblyConnectorEnd@nodeName{\tikzumlAssemblyConnectorEnd@name}}\x% + % + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlAssemblyConnectorLabel@nodeName{\tikzumlAssemblyConnectorLabel}}\x% + % + \pgfextractx{\tikzuml@AC@xa}{\pgfpointanchor{\tikzumlAssemblyConnectorStart@nodeName}{center}}% + \pgfextracty{\tikzuml@AC@ya}{\pgfpointanchor{\tikzumlAssemblyConnectorStart@nodeName}{center}}% + \pgfextractx{\tikzuml@AC@xb}{\pgfpointanchor{\tikzumlAssemblyConnectorEnd@nodeName}{center}}% + \pgfextracty{\tikzuml@AC@yb}{\pgfpointanchor{\tikzumlAssemblyConnectorEnd@nodeName}{center}}% + % + \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{--}}{% + \ifthenelse{\tikzuml@AC@xb>\tikzuml@AC@xa}{% + \def\tikzumlAssemblyConnectorStartAnchor{east}% + \def\tikzumlAssemblyConnectorEndAnchor{west}% + }{% + \def\tikzumlAssemblyConnectorStartAnchor{west}% + \def\tikzumlAssemblyConnectorEndAnchor{east}% + } + }{}% + % + \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|}}{% + \ifthenelse{\tikzuml@AC@xb>\tikzuml@AC@xa}{% + \def\tikzumlAssemblyConnectorStartAnchor{east}% + }{% + \def\tikzumlAssemblyConnectorStartAnchor{west}% + } + \ifthenelse{\tikzuml@AC@yb>\tikzuml@AC@ya}{% + \def\tikzumlAssemblyConnectorEndAnchor{south}% + }{% + \def\tikzumlAssemblyConnectorEndAnchor{north}% + } + }{}% + % + \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-}}{% + \ifthenelse{\tikzuml@AC@xb>\tikzuml@AC@xa}{% + \def\tikzumlAssemblyConnectorEndAnchor{west}% + }{% + \def\tikzumlAssemblyConnectorEndAnchor{east}% + } + \ifthenelse{\tikzuml@AC@yb>\tikzuml@AC@ya}{% + \def\tikzumlAssemblyConnectorStartAnchor{north}% + }{% + \def\tikzumlAssemblyConnectorStartAnchor{south}% + } + }{}% + % + \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|-}}{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorStartArm}{auto}}{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorEndArm}{auto}}{% + \pgfmathsetlength{\tikzuml@AC@middleArm}{0.5 * \tikzuml@AC@xa + 0.5 * \tikzuml@AC@xb}% + }{% + \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@xb+\tikzumlAssemblyConnectorEndArm}% + }% + }{% + \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@xa+\tikzumlAssemblyConnectorStartArm}% + }% + \pgfmathparse{\tikzuml@AC@middleArm>\tikzuml@AC@xa} + \pgfmathparse{\tikzuml@AC@middleArm>\tikzuml@AC@xb} + \ifthenelse{\lengthtest{\tikzuml@AC@middleArm>\tikzuml@AC@xa}}{% + \def\tikzumlAssemblyConnectorStartAnchor{east}% + }{% + \def\tikzumlAssemblyConnectorStartAnchor{west}% + } + \ifthenelse{\lengthtest{\tikzuml@AC@middleArm>\tikzuml@AC@xb}}{% + \def\tikzumlAssemblyConnectorEndAnchor{east}% + }{% + \def\tikzumlAssemblyConnectorEndAnchor{west}% + } + }{}% + % + \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-|}}{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorStartArm}{auto}}{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorEndArm}{auto}}{% + \pgfmathsetlength{\tikzuml@AC@middleArm}{0.5 * \tikzuml@AC@ya + 0.5 * \tikzuml@AC@yb}% + }{% + \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@yb+\tikzumlAssemblyConnectorEndArm}% + }% + }{% + \pgfmathsetlength{\tikzuml@AC@middleArm}{\tikzuml@AC@ya+\tikzumlAssemblyConnectorStartArm}% + }% + \ifthenelse{\tikzuml@AC@middleArm>\tikzuml@AC@ya}{% + \def\tikzumlAssemblyConnectorStartAnchor{north}% + }{% + \def\tikzumlAssemblyConnectorStartAnchor{south}% + } + \ifthenelse{\tikzuml@AC@middleArm>\tikzuml@AC@yb}{% + \def\tikzumlAssemblyConnectorEndAnchor{north}% + }{% + \def\tikzumlAssemblyConnectorEndAnchor{south}% + } + }{}% + % + \ifthenelse{\equal{\umlAssemblyConnectorStartAnchor}{}}{% + }{% + \def\tikzumlAssemblyConnectorStartAnchor{\umlAssemblyConnectorStartAnchor}% + }% + \ifthenelse{\equal{\umlAssemblyConnectorEndAnchor}{}}{% + }{% + \def\tikzumlAssemblyConnectorEndAnchor{\umlAssemblyConnectorEndAnchor}% + }% + % + \node[inner sep=0] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) at (\tikzumlAssemblyConnectorStart@nodeName.\tikzumlAssemblyConnectorStartAnchor) {};% + \node[inner sep=0] (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) at (\tikzumlAssemblyConnectorEnd@nodeName.\tikzumlAssemblyConnectorEndAnchor) {};% + % + \umlrelation[style={tikzuml connector style}, #1]{\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp}{\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp}% + % + \ifthenelse{\equal{\tikzumlAssemblyConnectorWithPort}{tikzumlTrue}}{% + \node[inner sep=0.5*\tikzumlAssemblyConnectorWidth, rectangle, draw=\tikzumlassemblyconnectordraw, fill=\tikzumlassemblyconnectorportfill] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) {};% + \node[inner sep=0.5*\tikzumlAssemblyConnectorWidth, rectangle, draw=\tikzumlassemblyconnectordraw, fill=\tikzumlassemblyconnectorportfill] (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) {};% + }{% + \node[inner sep=0] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorStart@nodeName.\tikzumlAssemblyConnectorStartAnchor) {};% + \node[inner sep=0] (\tikzumlAssemblyConnectorEnd@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorEnd@nodeName.\tikzumlAssemblyConnectorEndAnchor) {};% + }% + % + \addtocounter{tikzumlRelationNum}{-1}% + \ifthenelse{\equal{\tikzumlAssemblyConnectorName}{connector-\thetikzumlConnectorNum}}{% + \edef\tikzumlAssemblyConnectorName{relation-\thetikzumlRelationNum}% + \edef\tikzumlAssemblyConnectorSymbolName{\tikzumlAssemblyConnectorLabel@nodeName}% + }{% + \edef\tikzumlAssemblyConnectorSymbolName{\tikzumlAssemblyConnectorName}% + }% + % + \stepcounter{tikzumlRelationNum}% + % + \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{--}}{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorEnd@nodeName}% + }{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|}}{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}% + }{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorEnd@nodeName}% + }% + }{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-}}{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}% + }{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorEnd@nodeName}% + }% + }{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{-|-}}{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}% + }{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorLastArm}{tikzumlTrue}}{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-4}{\tikzumlAssemblyConnectorEnd@nodeName}% + }{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorName-4}% + }% + }% + }{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorGeometry}{|-|}}{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorFirstArm}{tikzumlTrue}}{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorStart@nodeName}{\tikzumlAssemblyConnectorName-2}% + }{% + \ifthenelse{\equal{\tikzumlAssemblyConnectorLastArm}{tikzumlTrue}}{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-4}{\tikzumlAssemblyConnectorEnd@nodeName}% + }{% + \umlassemblyconnectorsymbol{\tikzumlAssemblyConnectorName-2}{\tikzumlAssemblyConnectorName-4}% + }% + }% + }{}% + }% + }% + }% + }% + \stepcounter{tikzumlConnectorNum}% +}% + +% shortcuts of \umlassemblyconnector +\newcommand{\umlHVassemblyconnector}[3][]{% + \pgfkeys{/tikzuml/HVassemblyconnector/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVassemblyconnector, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/HVassemblyconnector/.cd, #1}% + \umlassemblyconnector[geometry=-|, #1]{#2}{#3}% +}% + +\newcommand{\umlVHassemblyconnector}[3][]{% + \pgfkeys{/tikzuml/VHassemblyconnector/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHassemblyconnector, forbidden option geometry}% + }{}% + }% + }% + \pgfkeys{/tikzuml/VHassemblyconnector/.cd, #1}% + \umlassemblyconnector[geometry=|-, #1]{#2}{#3}% +}% + +\newcommand{\umlHVHassemblyconnector}[3][]{% + \pgfkeys{/tikzuml/HVHassemblyconnector/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlHVHassemblyconnector, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/HVHassemblyconnector/.cd, #1}% + \umlassemblyconnector[geometry=-|-, #1]{#2}{#3}% +}% + +\newcommand{\umlVHVassemblyconnector}[3][]{% + \pgfkeys{/tikzuml/VHVassemblyconnector/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}}{% + \errmessage{TIKZUML ERROR : in umlVHVassemblyconnector, forbidden option geometry}% + }{}% + }}% + \pgfkeys{/tikzuml/VHVassemblyconnector/.cd, #1}% + \umlassemblyconnector[geometry=|-|, #1]{#2}{#3}% +}% + +\newcommand{\umlport}[3][]{% + \pgfkeys{/tikzuml/port/.cd,% + draw/.initial=\tikzumldrawcolor, fill/.initial=\tikzumlfillportcolor,% + width/.initial=1em,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \errmessage{TIKZUML ERROR : in umlport forbidden option \keyname}% + }}% + \pgfkeys{/tikzuml/port/.cd, #1}% + \pgfkeys{/tikzuml/port/.cd,% + width/.get=\tikzumlPortWidth,% + draw/.get=\tikzumlportdraw, fill/.get=\tikzumlportfill}% + \edef\tikzumlPort@name{#2}% + \edef\tikzumlPort@anchor{#3}% + \begingroup% + \def\_{_}\edef\x{\endgroup% + \def\noexpand\tikzumlPort@nodeName{\tikzumlPort@name}}\x% + % + \node[inner sep=0.5*\tikzumlPortWidth, rectangle, draw=\tikzumlportdraw, fill=\tikzumlportfill] (\tikzumlPort@nodeName-\tikzumlPort@anchor-port) at (\tikzumlPort@nodeName.\tikzumlPort@anchor) {}; +} + +\newcommand{\umldelegateconnector}[3][]{% + \def\tikzumlDelegateConnectorWithStartPort{tikzumlFalse}% + \def\tikzumlDelegateConnectorWithEndPort{tikzumlFalse}% + \pgfkeys{/tikzuml/delegateconnector/.cd, + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umldelegateconnector, forbidden option stereo}% + }{}% + }}% + \pgfkeys{/tikzuml/delegateconnector/.cd, #1}% + \umlrelation[style={tikzuml connector style}, stereo=delegate, #1]{#2}{#3}% +}% + + +% shortcuts of \umldelegateconnector +\newcommand{\umlHVdelegateconnector}[3][]{% + \pgfkeys{/tikzuml/HVdelegateconnector/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlHVdelegateconnector, forbidden option \keyname}% + }{}% + }}% + \pgfkeys{/tikzuml/HVdelegateconnector/.cd, #1}% + \umldelegateconnector[geometry=-|, #1]{#2}{#3}% +}% + +\newcommand{\umlVHdelegateconnector}[3][]{% + \pgfkeys{/tikzuml/VHdelegateconnector/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlVHdelegateconnector, forbidden option \keyname}% + }{}% + }}% + \pgfkeys{/tikzuml/VHdelegateconnector/.cd, #1}% + \umldelegateconnector[geometry=|-, #1]{#2}{#3}% +}% + +\newcommand{\umlHVHdelegateconnector}[3][]{% + \pgfkeys{/tikzuml/HVHdelegateconnector/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlHVHdelegateconnector, forbidden option \keyname}% + }{}% + }}% + \pgfkeys{/tikzuml/HVHdelegateconnector/.cd, #1}% + \umldelegateconnector[geometry=-|-, #1]{#2}{#3}% +}% + +\newcommand{\umlVHVdelegateconnector}[3][]{% + \pgfkeys{/tikzuml/VHVdelegateconnector/.cd,% + .unknown/.code={% + \let\keyname=\pgfkeyscurrentname% + \ifthenelse{\equal{\keyname}{geometry}\OR\equal{\keyname}{stereo}}{% + \errmessage{TIKZUML ERROR : in umlVHVdelegateconnector, forbidden option \keyname}% + }{}% + }}% + \pgfkeys{/tikzuml/VHVdelegateconnector/.cd, #1}% + \umldelegateconnector[geometry=|-|, #1]{#2}{#3}% +}% +%%% End of tikz-uml.sty +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ No newline at end of file