%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Start of tikz-umld.sty % Some macros for UML Diagrams. % Repository: https://github.com/imol-ai/tikz-umld % Maintainer: David Imolai % Version: 1.0.0 (2026-10-07) % Derived from TikZ-UML 1.0 by Nicolas Kielbasiewicz. % This work may be distributed and/or modified under the terms of the % GNU Affero General Public License, version 3 or (at your option) any later % version. See LICENSE.md and NOTICE.md. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesPackage{tikz-umld}[2026/10/07 v1.0.0 TikZ UML diagrams] \RequirePackage{ifthen,tikz,xstring,calc,pgfopts,etoolbox} \usetikzlibrary{backgrounds,arrows,arrows.meta,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, x/.initial=0, y/.initial=0, package type/.initial=tikzumlEmpty, fill package/.initial=blue!15, class width/.initial=10ex, simple interface width/.initial=4ex, class type/.initial=class, fill class/.initial=cyan!30, fill template/.initial=yellow!2, narynode width/.initial=6ex, relation geometry/.initial=--, relation angle1/.initial=-30, relation angle2/.initial=30, relation loopsize/.initial=3em, relation weight/.initial=0.5, relation pos1/.initial=0.2, relation pos2/.initial=0.8, relation pos stereo/.initial=0.5, note width/.initial=3cm, fill note/.initial=yellow!30, fill system/.initial=white, fill usecase/.initial=orange!30, actor below/.initial=0.5cm, state join width/.initial=3ex, state decision width/.initial=3ex, state initial width/.initial=5ex, state final width/.initial=5.5ex, state enter width/.initial=5ex, state exit width/.initial=5ex, state end width/.initial=5ex, state history width/.initial=5ex, state deep history width/.initial=5ex, state width/.initial=8ex, fill state/.initial=orange!30, object stereo/.initial=object, fill object/.initial=orange!30, call dt/.initial=tikzumlEmpty, call padding/.initial=2, call type/.initial=synchron, fill call/.initial=yellow!30, fragment type/.initial=opt, fragment inner xsep/.initial=1, fragment inner ysep/.initial=1, fill fragment/.initial= none, create call dt/.initial=4, component width/.initial=8ex, fill component/.initial= yellow!30, required interface distance/.initial=2.5cm, required interface width/.initial=1em, required interface padding/.initial=1cm, provided interface distance/.initial=3cm, provided interface width/.initial=1em, provided interface padding/.initial=1cm, port width/.initial=1ex, fill port/.initial= yellow!30, fill assembly connector/.initial= white, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \errmessage{TIKZUML ERROR : in tikzuml global, invalid option \keyname} } } % Label-only assembly-connector options are consumed by \umlassemblyconnector. % Declare no-op TikZ counterparts because connector options are also forwarded % to the underlying relation renderer. \tikzset{ labelpos/.code={} } \pgfkeys{/tikzuml/.cd, text/.get=\tikzumlDefaultTextColor, draw/.get=\tikzumlDefaultDrawColor, font/.get=\tikzumlDefaultFont, x/.get=\tikzumlDefaultX, y/.get=\tikzumlDefaultY, package type/.get=\tikzumlPackageDefaultType, fill package/.get=\tikzumlPackageDefaultFillColor, class width/.get=\tikzumlClassDefaultWidth, simple interface width/.get=\tikzumlSimpleInterfaceDefaultWidth, class type/.get=\tikzumlClassDefaultType, fill class/.get=\tikzumlClassDefaultFillColor, fill template/.get=\tikzumlClassTemplateFillColorDefaultFillColor, narynode width/.get=\tikzumlNaryNodeDefaultWidth, relation geometry/.get=\tikzumlRelationDefaultGeometry, relation angle1/.get=\tikzumlRelationDefaultAngleO, relation angle2/.get=\tikzumlRelationDefaultAngleT, relation loopsize/.get=\tikzumlRelationDefaultLoopSize, relation weight/.get=\tikzumlRelationDefaultWeight, relation pos1/.get=\tikzumlRelationDefaultPosO, relation pos2/.get=\tikzumlRelationDefaultPosT, relation pos stereo/.get=\tikzumlRelationDefaultPosStereo, note width/.get=\tikzumlNoteDefaultWidth, fill note/.get=\tikzumlNoteDefaultFillColor, fill system/.get=\tikzumlSystemDefaultFillColor, fill usecase/.get=\tikzumlUseCaseDefaultFillColor, actor below/.get=\tikzumlActorDefaultBelow, state join width/.get=\tikzumlStateJoinDefaultWidth, state decision width/.get=\tikzumlStateDecisionDefaultWidth, state initial width/.get=\tikzumlStateInitialDefaultWidth, state final width/.get=\tikzumlStateFinalDefaultWidth, state enter width/.get=\tikzumlStateEnterDefaultWidth, state exit width/.get=\tikzumlStateExitDefaultWidth, state end width/.get=\tikzumlStateEndDefaultWidth, state history width/.get=\tikzumlStateHistoryDefaultWidth, state deep history width/.get=\tikzumlStateDeepHistoryDefaultWidth, state width/.get=\tikzumlStateDefaultWidth, fill state/.get=\tikzumlStateDefaultFillColor, object stereo/.get=\tikzumlObjectDefaultStereo, fill object/.get=\tikzumlObjectDefaultFillColor, call dt/.get=\tikzumlCallDefaultDT, call padding/.get=\tikzumlCallDefaultPadding, call type/.get=\tikzumlCallDefaultType, fill call/.get=\tikzumlCallDefaultFillColor, fragment type/.get=\tikzumlFragmentDefaultType, fragment inner xsep/.get=\tikzumlFragmentDefaultXSep, fragment inner ysep/.get=\tikzumlFragmentDefaultYSep, fill fragment/.get=\tikzumlFragmentDefaultFillColor, create call dt/.get=\tikzumlCreateCallDefaultDT, component width/.get=\tikzumlComponentDefaultWidth, fill component/.get=\tikzumlComponentDefaultFillColor, required interface distance/.get=\tikzumlRequiredInterfaceDefaultDistance, required interface width/.get=\tikzumlRequiredInterfaceDefaultWidth, required interface padding/.get=\tikzumlRequiredInterfaceDefaultPadding, provided interface distance/.get=\tikzumlProvidedInterfaceDefaultDistance, provided interface width/.get=\tikzumlProvidedInterfaceDefaultWidth, provided interface padding/.get=\tikzumlProvidedInterfaceDefaultPadding, port width/.get=\tikzumlPortDefaultWidth, fill port/.get=\tikzumlPortDefaultFillColor, fill assembly connector/.get=\tikzumlAssemblyConnectorDefaultFillColor } % utility : change default colors \newcommand{\tikzumlset}[1]{ \pgfkeys{/tikzuml/.cd,#1} \pgfkeys{/tikzuml/.cd, text/.get=\tikzumlDefaultTextColor, draw/.get=\tikzumlDefaultDrawColor, font/.get=\tikzumlDefaultFont, x/.get=\tikzumlDefaultX, y/.get=\tikzumlDefaultY, package type/.get=\tikzumlPackageDefaultType, fill package/.get=\tikzumlPackageDefaultFillColor, class width/.get=\tikzumlClassDefaultWidth, simple interface width/.get=\tikzumlSimpleInterfaceDefaultWidth, class type/.get=\tikzumlClassDefaultType, fill class/.get=\tikzumlClassDefaultFillColor, fill template/.get=\tikzumlClassTemplateFillColorDefaultFillColor, narynode width/.get=\tikzumlNaryNodeWidth, relation geometry/.get=\tikzumlRelationDefaultGeometry, relation angle1/.get=\tikzumlRelationDefaultAngleO, relation angle2/.get=\tikzumlRelationDefaultAngleT, relation loopsize/.get=\tikzumlRelationDefaultLoopSize, relation weight/.get=\tikzumlRelationDefaultWeight, relation pos1/.get=\tikzumlRelationDefaultPosO, relation pos2/.get=\tikzumlRelationDefaultPosT, relation pos stereo/.get=\tikzumlRelationDefaultPosStereo, note width/.get=\tikzumlNoteDefaultWidth, fill note/.get=\tikzumlNoteDefaultFillColor, fill system/.get=\tikzumlSystemDefaultFillColor, fill usecase/.get=\tikzumlUseCaseDefaultFillColor, actor below/.get=\tikzumlActorDefaultBelow, state join width/.get=\tikzumlStateJoinDefaultWidth, state decision width/.get=\tikzumlStateDecisionDefaultWidth, state initial width/.get=\tikzumlStateInitialDefaultWidth, state final width/.get=\tikzumlStateFinalDefaultWidth, state enter width/.get=\tikzumlStateEnterDefaultWidth, state exit width/.get=\tikzumlStateExitDefaultWidth, state end width/.get=\tikzumlStateEndDefaultWidth, state history width/.get=\tikzumlStateHistoryDefaultWidth, state deep history width/.get=\tikzumlStateDeepHistoryDefaultWidth, state width/.get=\tikzumlStateDefaultWidth, fill state/.get=\tikzumlStateDefaultFillColor, object stereo/.get=\tikzumlObjectDefaultStereo, fill object/.get=\tikzumlObjectDefaultFillColor, call dt/.get=\tikzumlCallDefaultDT, call padding/.get=\tikzumlCallDefaultPadding, call type/.get=\tikzumlCallDefaultType, fill call/.get=\tikzumlCallDefaultFillColor, fragment type/.get=\tikzumlFragmentDefaultType, fragment inner xsep/.get=\tikzumlFragmentDefaultXSep, fragment inner ysep/.get=\tikzumlFragmentDefaultYSep, fill fragment/.get=\tikzumlFragmentDefaultFillColor, create call dt/.get=\tikzumlCreateCallDT, component width/.get=\tikzumlComponentDefaultWidth, fill component/.get=\tikzumlComponentDefaultFillColor, required interface distance/.get=\tikzumlRequiredInterfaceDefaultDistance, required interface width/.get=\tikzumlRequiredInterfaceDefaultWidth, required interface padding/.get=\tikzumlRequiredInterfaceDefaultPadding, provided interface distance/.get=\tikzumlProvidedInterfaceDefaultDistance, provided interface width/.get=\tikzumlProvidedInterfaceDefaultWidth, provided interface padding/.get=\tikzumlProvidedInterfaceDefaultPadding, port width/.get=\tikzumlPortDefaultWidth, fill port/.get=\tikzumlPortDefaultFillColor, fill assembly connector/.get=\tikzumlAssemblyConnectorDefaultFillColor } } % 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 } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 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 simpleinterface style}=[circle, minimum height=1em, node distance=1em] \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 enumeration style}=[rectangle split, rectangle split parts=2, rectangle split part align={center, 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=\tikzumlDefaultDrawColor, -] \tikzstyle{tikzuml bidirectional association style}=[color=\tikzumlDefaultDrawColor, {Straight Barb[scale=3.5,angle'=55]}-{Straight Barb[scale=3.5,angle'=55]}] \tikzstyle{tikzuml unidirectional association style}=[color=\tikzumlDefaultDrawColor, -{Straight Barb[scale=3.5,angle'=55]}] \tikzstyle{tikzuml aggregation style}=[color=\tikzumlDefaultDrawColor, {Diamond[scale=3, open]}-] \tikzstyle{tikzuml unidirectional aggregation style}=[color=\tikzumlDefaultDrawColor, {Diamond[scale=3, open]}-{Straight Barb[scale=3.5,angle'=55]}] \tikzstyle{tikzuml composition style}=[color=\tikzumlDefaultDrawColor, {Diamond[scale=3]}-] \tikzstyle{tikzuml unidirectional composition style}=[color=\tikzumlDefaultDrawColor, {Diamond[scale=3]}-{Straight Barb[scale=3.5,angle'=55]}] \tikzstyle{tikzuml nesting style}=[color=\tikzumlDefaultDrawColor] \tikzstyle{tikzuml dependency style}=[color=\tikzumlDefaultDrawColor, -{Straight Barb[scale=3.5,angle'=55]}, dashed] \tikzstyle{tikzuml import style}=[color=\tikzumlDefaultDrawColor, -{Straight Barb[scale=3.5,angle'=55]}, dashed] \tikzstyle{tikzuml inherit style}=[color=\tikzumlDefaultDrawColor, -{Triangle[scale=2.5,open,angle'=50]}] \tikzstyle{tikzuml implements style}=[color=\tikzumlDefaultDrawColor, -{Triangle[scale=2.5,open,angle'=50]}, 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\iftikzumlpackageSimpleStyle \newif\iftikzumlclassSimpleStyle \newif\iftikzumlclassCircleShape \newif\iftikzumlpackageWithoutCoords \newif\iftikzumlclassWithoutCoords \newif\iftikzumlassocclassWithoutCoords \newif\iftikzumlnoteWithoutCoords % define a uml package % arg : package name % optional : x, y: coordinates of the package % type: stereotype of the package % name: name of the package node % draw, fill, text: colors % style: to manage every default TikZ option % no coords: to tell that the package position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newenvironment{umlpackage}[2][]{ \pgfkeys{/tikzuml/package/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, style/.style={}, name/.initial=tikzumlEmpty, type/.initial=\tikzumlPackageDefaultType, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlPackageDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, no coords/.is if=tikzumlpackageWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/package/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/package/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/package/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlpackage, invalid option \keyname} } } \pgfkeys{/tikzuml/package/.cd, #1} \pgfkeys{/tikzuml/package/.cd, x/.get=\tikzumlPackageXShift, y/.get=\tikzumlPackageYShift, name/.get=\tikzumlPackageName, type/.get=\tikzumlPackageTypeTmp, draw/.get=\tikzumlPackageDrawColor, fill/.get=\tikzumlPackageFillColor, text/.get=\tikzumlPackageTextColor } \ifthenelse{\equal{\tikzumlPackageTypeTmp}{tikzumlEmpty}}{ \def\tikzumlPackageType{} }{ \expandafter\def\expandafter\tikzumlPackageType\expandafter{$\ll$\tikzumlPackageTypeTmp$\gg$ \\} } \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=\tikzumlPackageXShift cm, yshift=\tikzumlPackageYShift cm] }{ \addtocounter{tikzumlPackageLevel}{-1} \begin{pgfonlayer}{package\thetikzumlPackageLevel} % if contains no class, and not simple, one define a fictive node to enable the fit option \ifnum\c@tikzumlPackageClassNum=0 \ifnum\c@tikzumlPackageSubPackageNum=0 \iftikzumlpackageWithoutCoords \node[inner sep=1.5ex, /tikzuml/package/style] (\tikzumlPackage@nodeName-root) {\phantom{\tikzumlPackage@nodeName}}; \else \node[inner sep=1.5ex, /tikzuml/package/style] (\tikzumlPackage@nodeName-root) at (0,0) {\phantom{\tikzumlPackage@nodeName}}; \fi \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=\tikzumlPackageDrawColor, fill=\tikzumlPackageFillColor, text=\tikzumlPackageTextColor, font=\tikzumlDefaultFont, inner sep=1.5ex, /tikzuml/package/style, fit = \csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname] (\tikzumlPackage@nodeName) {}; \node[draw=\tikzumlPackageDrawColor, fill=\tikzumlPackageFillColor, text=\tikzumlPackageTextColor, font=\tikzumlDefaultFont, minimum height=1.5em, outer ysep=-0.3, anchor=south west] (\tikzumlPackage@nodeName-caption) at (\tikzumlPackage@nodeName.north west) {\begin{tabular}{c} \tikzumlPackageType \textbf{\tikzumlPackage@name}\end{tabular}}; \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: type of class (class, interface, typedef, enum) % tags: tagged values of class % template: template parameters % simple: if used, class is empty and drawn with a rectangle % circle: if used with simple, class is empty and drawn with a circle % draw, fill, fill template, and text: colors % style: to manage every default TikZ option % no coords: to tell that the class position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlclass}[4][]{ \pgfkeys{/tikzuml/class/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlClassDefaultWidth, type/.initial=\tikzumlClassDefaultType, tags/.initial={}, style/.style={}, template/.initial={}, name/.initial=tikzumlEmpty, draw/.initial=\tikzumlDefaultDrawColor, fill template/.initial=\tikzumlClassTemplateFillColorDefaultFillColor, fill/.initial=\tikzumlClassDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, simple/.is if=tikzumlclassSimpleStyle, circle/.is if=tikzumlclassCircleShape, no coords/.is if=tikzumlclassWithoutCoords, simple=false, circle=false, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/class/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/class/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/class/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlclass, invalid option \keyname} } } \pgfkeys{/tikzuml/class/.cd,#1} \iftikzumlclassSimpleStyle \iftikzumlclassCircleShape \pgfkeys{/tikzuml/class/.cd, width/.initial=\tikzumlSimpleInterfaceDefaultWidth} \fi \fi \pgfkeys{/tikzuml/class/.cd, x/.get=\tikzumlClassX, y/.get=\tikzumlClassY, width/.get=\tikzumlClassMinimumWidth, type/.get=\tikzumlClassTypeTmp, tags/.get=\tikzumlClassTagsTmp, template/.get=\tikzumlClassTemplateFillColorParam, name/.get=\tikzumlClassName, draw/.get=\tikzumlClassDrawColor, fill/.get=\tikzumlClassFillColor, text/.get=\tikzumlClassTextColor, fill template/.get=\tikzumlClassTemplateFillColor } \ifthenelse{\equal{\tikzumlClassTypeTmp}{class}\OR\equal{\tikzumlClassTypeTmp}{object}}{ \def\tikzumlClassType{} }{ \expandafter\def\expandafter\tikzumlClassType\expandafter{$\ll$\tikzumlClassTypeTmp$\gg$ \\} } \ifthenelse{\equal{\tikzumlClassTagsTmp}{}}{ \def\tikzumlClassTags{} }{ \def\tikzumlClassTags{\\ \{\tikzumlClassTagsTmp\}} } \ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{ \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{\tikzumlClassName}{tikzumlEmpty}}{}{ \def\tikzumlClassNodeName{\tikzumlClassName} } \StrSubstitute{\tikzumlClassNodeName}{:}{@COLON@}[\tikzumlClassNodeName] \StrSubstitute{\tikzumlClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlClassNodeName] \ifthenelse{\equal{\tikzumlClassTypeTmp}{abstract}}{ \let\tikzumlClassNameOld\tikzumlClassName \def\tikzumlClassName{{\emph \tikzumlClassNameOld}} }{} \ifthenelse{\equal{\tikzumlClassTypeTmp}{object}}{ \let\tikzumlClassNameOld\tikzumlClassName \def\tikzumlClassName{{\underline \tikzumlClassNameOld}} }{} \ifthenelse{\equal{\tikzumlClassTypeTmp}{interface}}{ \let\tikzumlClassNameOld\tikzumlClassName \def\tikzumlClassName{{\emph \tikzumlClassNameOld}} }{} \def\tikzumlClassPos{\tikzumlClassX,\tikzumlClassY} \def\tikzumlClassAttributes{#3} \def\tikzumlClassOperations{#4} \iftikzumlclassSimpleStyle \iftikzumlclassWithoutCoords \iftikzumlclassCircleShape \node[tikzuml simpleinterface style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) {}; \node[anchor=south] (\tikzumlClassNodeName-label) at (\tikzumlClassNodeName.north) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular} }; \else \node[tikzuml simpleclass style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular} }; \fi \else \iftikzumlclassCircleShape \node[tikzuml simpleinterface style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) at (\tikzumlClassPos) {}; \node[anchor=south] (\tikzumlClassNodeName-label) at (\tikzumlClassNodeName.north){\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular} }; \else \node[tikzuml simpleclass style, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) at (\tikzumlClassPos) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular} }; \fi \fi \else \ifthenelse{\equal{\tikzumlClassTypeTmp}{enumeration}}{ \def\tikzumlClassStyleTmp{tikzuml enumeration style} }{ \def\tikzumlClassStyleTmp{tikzuml class style} } \iftikzumlclassWithoutCoords \node[\tikzumlClassStyleTmp, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular} \nodepart{second} \begin{tabular}{l} \tikzumlClassAttributes \end{tabular} \ifthenelse{\equal{\tikzumlClassTypeTmp}{enumeration}}{}{ \nodepart{third} \begin{tabular}{l} \tikzumlClassOperations \end{tabular} } }; \else \node[\tikzumlClassStyleTmp, draw=\tikzumlClassDrawColor, fill=\tikzumlClassFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlClassMinimumWidth, /tikzuml/class/style] (\tikzumlClassNodeName) at (\tikzumlClassPos) {\begin{tabular}{c}\tikzumlClassVPadding \tikzumlClassType \tikzumlClassHPadding \textbf{\tikzumlClassName} \tikzumlClassHPadding \tikzumlClassTags \end{tabular} \nodepart{second} \begin{tabular}{l} \tikzumlClassAttributes \end{tabular} \ifthenelse{\equal{\tikzumlClassTypeTmp}{enumeration}}{}{ \nodepart{third} \begin{tabular}{l} \tikzumlClassOperations \end{tabular} } }; \fi \fi \ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{}{ \draw (\tikzumlClassNodeName.north east) node[tikzuml template style, name=\tikzumlClassNodeName-template, draw=\tikzumlClassDrawColor, fill=\tikzumlClassTemplateFillColor, text=\tikzumlClassTextColor, font=\tikzumlDefaultFont] {\tikzumlClassTemplateFillColorParam}; } % add to fit \ifnum\c@tikzumlPackageLevel>0 \edef\tikzumlPackageFitOld{\csname tikzumlPackageFit\tikzumlPackage@parent @@\tikzumlPackage@fitname\endcsname} \ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{ \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 \def\tikzumlComponentFitTmp{\csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname} \ifthenelse{\equal{\tikzumlClassTemplateFillColorParam}{}}{ \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][]{ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{type}}{ \errmessage{TIKZUML ERROR : in umlabstract, forbidden option type} }{} } } \pgfkeys{/tikzuml/class/.cd, #1} \umlclass[type=abstract,#1]{#2}{#3}{#4} } \newcommand{\umlobj}[4][]{ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{type}}{ \errmessage{TIKZUML ERROR : in umlobj, forbidden option type} }{} } } \pgfkeys{/tikzuml/class/.cd, #1} \umlclass[type=object,#1]{#2}{#3}{#4} } \newcommand{\umlinterface}[4][]{ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{type}}{ \errmessage{TIKZUML ERROR : in umlinterface, forbidden option type} }{} } } \pgfkeys{/tikzuml/class/.cd, #1} \umlclass[type=interface,#1]{#2}{#3}{#4} } \newcommand{\umltypedef}[4][]{ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{type}}{ \errmessage{TIKZUML ERROR : in umltypedef, forbidden option type} }{} } } \pgfkeys{/tikzuml/class/.cd, #1} \umlclass[type=typedef,#1]{#2}{#3}{#4} } \newcommand{\umlenum}[3][]{ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{type}}{ \errmessage{TIKZUML ERROR : in umlenum, forbidden option type} }{} } } \pgfkeys{/tikzuml/class/.cd, #1} \umlclass[type=enumeration,#1]{#2}{#3}{} } % shortcut to define an empty class \newcommand{\umlemptyclass}[2][]{\umlclass[#1]{#2}{}{}} \newcommand{\umlsimpleclass}[2][]{ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{simple}}{ \errmessage{TIKZUML ERROR : in umlsimpleclass, forbidden option simple} }{} } } \pgfkeys{/tikzuml/class/.cd, #1} \umlemptyclass[simple, #1]{#2} } \newcommand{\umlsimpleinterface}[2][]{ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{simple}}{ \errmessage{TIKZUML ERROR : in umlsimpleinterface, forbidden option simple} }{ \ifthenelse{\equal{\keyname}{circle}}{ \errmessage{TIKZUML ERROR : in umlsimpleinterface, forbidden option circle} }{} } } } \pgfkeys{/tikzuml/class/.cd, #1} \umlsimpleclass[circle, #1]{#2} } \newcommand{\umlsimpleobj}[2][]{ \pgfkeys{/tikzuml/class/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{simple}}{ \errmessage{TIKZUML ERROR : in umlsimpleobj, forbidden option simple} }{ \ifthenelse{\equal{\keyname}{object}}{ \errmessage{TIKZUML ERROR : in umlsimpleobj, forbidden option object} }{} } } } \pgfkeys{/tikzuml/class/.cd, #1} \umlsimpleclass[type=object, #1]{#2} } \newcommand\hunderfill{\leavevmode\leaders\vtop{\vskip1.175mm\hrule width .05pt}\hfill\kern0pt } % define commands for uml constraints \newcommand{\umlcon}[2]{#1 \hfill \{#2\}} \newcommand{\umlstatic}[1]{\underline{#1}\hunderfill\underline{\{static\}}} \newcommand{\umlpvirt}[1]{\textit{\umlcon{#1}{pure virtual}}} \newcommand{\umlvirt}[1]{\umlcon{#1}{virtual}} \newcommand{\umloverrd}[1]{\umlcon{#1}{override}} \newcommand{\umlquery}[1]{\umlcon{#1}{query}} % define node for n-ary association \newcommand{\umlNarynode}[2][]{ \def\tikzumlNaryNodeAnchor{.north} \def\tikzumlNaryNodeLabelPos{above} \pgfkeys{/tikzuml/narynode/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlNaryNodeDefaultWidth, name/.initial=tikzumlEmpty, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlClassDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, style/.style={}, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \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} }{ \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/narynode/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/narynode/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlNarynode, invalid option \keyname} } } } } } } } }}} \pgfkeys{/tikzuml/narynode/.cd,#1} \pgfkeys{/tikzuml/narynode/.cd, x/.get=\tikzumlNaryNodeX, y/.get=\tikzumlNaryNodeY, width/.get=\tikzumlNaryNodeMinimumWidth, name/.get=\tikzumlNaryNodeName, draw/.get=\tikzumlNaryNodeDrawColor, fill/.get=\tikzumlNaryNodeFillColor, text/.get=\tikzumlNaryNodeTextColor } \def\tikzumlNaryName{#2} \ifthenelse{\equal{\tikzumlNaryNodeName}{tikzumlEmpty}}{ \edef\tikzumlNaryNodeName{\tikzumlNaryName} }{ \edef\tikzumlNaryNodeName{\tikzumlNaryNodeName} } \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlNaryNode@nodeName{\tikzumlNaryNodeName}}\x \StrSubstitute{\tikzumlNaryNode@nodeName}{:}{@COLON@}[\tikzumlNaryNode@nodeName] \StrSubstitute{\tikzumlNaryNode@nodeName}{\_}{@UNDERSCORE@}[\tikzumlNaryNode@nodeName] \def\tikzumlNarynodePos{\tikzumlNaryNodeX,\tikzumlNaryNodeY} \node[tikzuml narynode style, draw=\tikzumlNaryNodeDrawColor, fill=\tikzumlNaryNodeFillColor, text=\tikzumlNaryNodeTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlNaryNodeMinimumWidth, minimum height=\tikzumlNaryNodeMinimumWidth, /tikzuml/narynode/style] (\tikzumlNaryNode@nodeName) at (\tikzumlNarynodePos) {}; \draw (\tikzumlNaryNode@nodeName\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 (\tikzumlNaryNode@nodeName)} \stepcounter{tikzumlPackageClassNum} \fi } \newdimen\tikzumlNestingSymbolSize % main command to define a relation between two classes % args : src class % dest class % optional : geometry: geometry of the line % weight: barycentric weight of the middle part when geometry is a 3-line % arm1, arm2: lengths of first or last part when geometry id a 3-line % arg1, arg2, arg: name of the src/dest/dest side class type attribute defined by the relation % mult1, mult2, mult: multiplicity of the src/dest/dest side class type attribute defined by the relation % pos1, pos2, pos: position of the src/dest/dest side class type attribute defined by the relation % align1, align2, align: text justification of the src/dest/dest side class type attribute defined by the relation % anchor1, anchor2: src/dest anchors on linked classes % angle1, angle2, loopsize: start angle, end angle and size of the relation (only if recursive) % stereo: stereotype of the relation % st:pos, st:anchor, st:fill: stereotype position, anchor, and background % style: style of the relation (association, aggregation, composition, inherit, ...) % name: rootname used for naming nodes of the relation % recursive mode: type of recursive arrow (transition for state diagrams, or default) % recursive direction start/end: when transition relation, start/end directions of the relation arrow \newcommand{\umlrelation}[3][]{ \pgfkeys{/tikzuml/relation/.cd, geometry/.initial=\tikzumlRelationDefaultGeometry, weight/.initial=\tikzumlRelationDefaultWeight, arm1/.initial=auto, arm2/.initial=auto, arg1/.initial={}, arg2/.initial={}, arg/.initial={}, mult1/.initial={}, mult2/.initial={}, mult/.initial={}, pos1/.initial=\tikzumlRelationDefaultPosO, pos2/.initial=\tikzumlRelationDefaultPosT, pos/.initial=tikzumlEmpty, align1/.initial={}, align2/.initial={}, align/.initial={}, anchor1/.initial=tikzumlEmpty, anchor2/.initial=tikzumlEmpty, angle1/.initial=\tikzumlRelationDefaultAngleO, angle2/.initial=\tikzumlRelationDefaultAngleT, loopsize/.initial=\tikzumlRelationDefaultLoopSize, stereo/.initial={}, st:pos/.initial=\tikzumlRelationDefaultPosStereo, st:anchor/.initial=center, st:fill/.initial=none, style/.initial=->, style2/.style={}, name/.initial=relation-\thetikzumlRelationNum, recursive mode/.initial=default, recursive direction start/.initial=right, recursive direction end/.initial=bottom, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \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}}{}{ \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/relation/.cd, style2/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/relation/.cd, style2/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlrelation, invalid option \keyname} } } } \pgfkeys{/tikzuml/relation/.cd,#1} \pgfkeys{/tikzuml/relation/.cd, geometry/.get=\tikzumlRelationGeometry, weight/.get=\tikzumlRelationWeight, arm1/.get=\tikzumlRelationArmO, arm2/.get=\tikzumlRelationArmT, arg1/.get=\tikzumlRelationAttrName, arg2/.get=\tikzumlRelationAttrNameTO, arg/.get=\tikzumlRelationAttrNameTT, mult1/.get=\tikzumlRelationMultiplicity, mult2/.get=\tikzumlRelationMultiplicityTO, mult/.get=\tikzumlRelationMultiplicityTT, pos1/.get=\tikzumlRelationPosition, pos2/.get=\tikzumlRelationPositionTO, pos/.get=\tikzumlRelationPositionTT, align1/.get=\tikzumlRelationAlign, align2/.get=\tikzumlRelationAlignTO, align/.get=\tikzumlRelationAlignTT, anchor1/.get=\tikzumlRelationSrcAnchor, anchor2/.get=\tikzumlRelationDestAnchor, angle1/.get=\tikzumlRelationStartAngle, angle2/.get=\tikzumlRelationEndAngle, loopsize/.get=\tikzumlRelationLoopSize, stereo/.get=\tikzumlRelationStereoType, st:pos/.get=\tikzumlRelationPositionStereotype, st:anchor/.get=\tikzumlRelationStereotypeAnchor, st:fill/.get=\tikzumlRelationStereotypeFill, style/.get=\tikzumlRelationStyle, name/.get=\tikzumlRelationName, recursive mode/.get=\tikzumlRelationRecursiveMode, recursive direction start/.get=\tikzumlRelationRecursiveDirectionStart, recursive direction end/.get=\tikzumlRelationRecursiveDirectionEnd } \def\tikzumlSrcClassName{#2} % managing \_ in class names for node names \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlSrcClassNodeName{\tikzumlSrcClassName}}\x \StrSubstitute{\tikzumlSrcClassNodeName}{:}{@COLON@}[\tikzumlSrcClassNodeName] \StrSubstitute{\tikzumlSrcClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlSrcClassNodeName] \def\tikzumlDestClassName{#3} \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlDestClassNodeName{\tikzumlDestClassName}}\x \StrSubstitute{\tikzumlDestClassNodeName}{:}{@COLON@}[\tikzumlDestClassNodeName] \StrSubstitute{\tikzumlDestClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlDestClassNodeName] % managing alias keys \def\tikzumlRelationAttrNameT{\tikzumlRelationAttrNameTO\tikzumlRelationAttrNameTT} \def\tikzumlRelationMultiplicityT{\tikzumlRelationMultiplicityTO\tikzumlRelationMultiplicityTT} \def\tikzumlRelationAlignT{\tikzumlRelationAlignTO\tikzumlRelationAlignTT} \def\posAttrName{} \def\posMultiplicity{} \def\posAttrNameT{} \def\posMultiplicityT{} \ifthenelse{\equal{\tikzumlRelationPositionTT}{tikzumlEmpty}}{ \def\tikzumlRelationPositionT{\tikzumlRelationPositionTO} }{ \def\tikzumlRelationPositionT{\tikzumlRelationPositionTT} } \def\attrAlign{} \def\multAlign{} \def\attrAlignT{} \def\multAlignT{} \ifthenelse{\equal{\tikzumlRelationAlign}{left}}{ \def\attrAlign{above right} \def\multAlign{below right} }{ \ifthenelse{\equal{\tikzumlRelationAlign}{right}}{ \def\attrAlign{above left} \def\multAlign{below left} }{} } \ifthenelse{\equal{\tikzumlRelationAlignT}{left}}{ \def\attrAlignT{above right} \def\multAlignT{below right} }{ \ifthenelse{\equal{\tikzumlRelationAlignT}{right}}{ \def\attrAlignT{above left} \def\multAlignT{below left} }{} } % def stereotype \ifthenelse{\equal{\tikzumlRelationStereoType}{}}{ \def\stereotype{} }{ \def\stereotype{$\ll$\tikzumlRelationStereoType$\gg$} } % def anchors macros \ifthenelse{\equal{\tikzumlRelationSrcAnchor}{tikzumlEmpty}}{ \def\tikzumlRelationSrcAnchor{} }{ \let\tikzumlRelationSrcAnchorold\tikzumlRelationSrcAnchor \def\tikzumlRelationSrcAnchor{.\tikzumlRelationSrcAnchorold} } \ifthenelse{\equal{\tikzumlRelationDestAnchor}{tikzumlEmpty}}{ \def\tikzumlRelationDestAnchor{} }{ \let\tikzumlRelationDestAnchorold\tikzumlRelationDestAnchor \def\tikzumlRelationDestAnchor{.\tikzumlRelationDestAnchorold} } \setcounter{pos}{100*\real{\tikzumlRelationPosition}} \setcounter{posT}{100*\real{\tikzumlRelationPositionT}} \setcounter{posStereo}{100*\real{\tikzumlRelationPositionStereotype}} \pgfmathsetmacro{\tikzumlRelationWeightT}{1.0-\tikzumlRelationWeight} %\newcounter{tikzumlControlNodesNum} %\setcounter{tikzumlControlNodesNum}{0} \node[inner sep=0] (\tikzumlRelationName-middle) at (barycentric cs:\tikzumlSrcClassNodeName=\tikzumlRelationWeightT,\tikzumlDestClassNodeName=\tikzumlRelationWeight) {}; % straight line \ifthenelse{\equal{\tikzumlRelationGeometry}{--}} { \ifthenelse{\equal{\tikzumlSrcClassNodeName}{\tikzumlDestClassNodeName}}{ \def\arcNum{1} \def\arcNumT{1} \ifthenelse{\equal{\tikzumlRelationRecursiveMode}{default}}{ \xdef\tikzumlLastArc{node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \xdef\tikzumlPath{(\tikzumlSrcClassNodeName) edge[in=\tikzumlRelationEndAngle, out=\tikzumlRelationStartAngle, distance=\tikzumlRelationLoopSize] \tikzumlLastArc node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} (\tikzumlDestClassNodeName) } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveMode}{transition}}{ \xdef\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {}} \xdef\tikzumlMidOneArc{node[midway, inner sep=0, name=\tikzumlRelationName-3, anchor=center] {}} \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{\tikzumlRelationRecursiveDirectionEnd}}{ \def\numArcs{3} \xdef\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {}} \begin{pgfonlayer}{connections} \draw (\tikzumlSrcClassNodeName) edge[in=\tikzumlRelationEndAngle, out=\tikzumlRelationStartAngle, distance=\tikzumlRelationLoopSize, draw=none] node[midway, inner sep=0, name=\tikzumlRelationName-tmp, anchor=center] {} (\tikzumlDestClassNodeName); \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}\OR\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{ \node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle -| \tikzumlRelationName-tmp) {}; \node[inner sep=0, name=\tikzumlRelationName-4] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle -| \tikzumlRelationName-tmp) {}; }{ \node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle |- \tikzumlRelationName-tmp) {}; \node[inner sep=0, name=\tikzumlRelationName-4] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle |- \tikzumlRelationName-tmp) {}; } \end{pgfonlayer} }{ \def\numArcs{4} \xdef\tikzumlMidTwoArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {}} \xdef\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-7, anchor=center] {}} \begin{pgfonlayer}{connections} \draw (\tikzumlSrcClassNodeName) edge[in=\tikzumlRelationEndAngle, out=\tikzumlRelationStartAngle, distance=\tikzumlRelationLoopSize, draw=none] node[midway, name=\tikzumlRelationName-4, anchor=center] {} (\tikzumlDestClassNodeName); \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}\OR\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{ \node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle -| \tikzumlRelationName-4) {}; \node[inner sep=0, name=\tikzumlRelationName-6] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle |- \tikzumlRelationName-4) {}; }{ \node[inner sep=0, name=\tikzumlRelationName-2] at (\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle |- \tikzumlRelationName-4) {}; \node[inner sep=0, name=\tikzumlRelationName-6] at (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle -| \tikzumlRelationName-4) {}; } \end{pgfonlayer} } \ifnum\numArcs=4 \ifnum\theposStereo>300 \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-300)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype}} \else \ifnum\theposStereo<100 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype}} \else \ifnum\theposStereo>200 \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100} \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype}} \else \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100} \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype}} \fi \fi \fi \ifthenelse{\thepos=300\OR\thepos=100}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{ \def\posAttrName{above right} \def\posMultiplicity{below left} }{ \def\posAttrName{above left} \def\posMultiplicity{below right} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{ \def\posAttrName{above left} \def\posMultiplicity{below right} }{ \def\posAttrName{above right} \def\posMultiplicity{below left} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{ \def\posAttrName{above right} \def\posMultiplicity{below left} }{ \def\posAttrName{above left} \def\posMultiplicity{below right} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{ \def\posAttrName{above left} \def\posMultiplicity{below right} }{ \def\posAttrName{above right} \def\posMultiplicity{below left} } } } } }{} \ifthenelse{\thepos=200}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{ \def\posAttrName{above left} \def\posMultiplicity{below right} }{ \def\posAttrName{above right} \def\posMultiplicity{below left} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{ \def\posAttrName{above right} \def\posMultiplicity{below left} }{ \def\posAttrName{above left} \def\posMultiplicity{below right} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{ \def\posAttrName{above left} \def\posMultiplicity{below right} }{ \def\posAttrName{above right} \def\posMultiplicity{below left} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{ \def\posAttrName{above right} \def\posMultiplicity{below left} }{ \def\posAttrName{above left} \def\posMultiplicity{below right} } } } } }{} \ifnum\thepos>300 \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-300)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \else \ifnum\thepos<100 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \else \ifnum\thepos>200 \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100} \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \else \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100} \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \fi \fi \ifthenelse{\theposT=300\OR\theposT=100}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} }{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} }{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} }{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} }{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} } } } } }{} \ifthenelse{\theposT=200}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{ \def\posAttrNameT{above left} \def\posMultiplicity{below right} }{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{bottom}}{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} }{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} }{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionEnd}{left}}{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} }{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} } } } } }{} \ifnum\theposT>300 \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-300)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \else \ifnum\theposT<100 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \else \ifnum\theposT>200 \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100} \xdef\tikzumlMidTwoArc{\tikzumlMidTwoArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \else \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100} \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \fi \fi \else \ifnum\theposStereo>200 \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \else \ifnum\theposStereo<100 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \else \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100} \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \fi \fi \ifthenelse{\thepos=100}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrName{above right} \def\posMultiplicity{below left} }{ \def\posAttrName{above left} \def\posMultiplicity{below right} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrName{above left} \def\posMultiplicity{below right} }{ \def\posAttrName{above right} \def\posMultiplicity{below left} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrName{above right} \def\posMultiplicity{below left} }{ \def\posAttrName{above left} \def\posMultiplicity{below right} } }{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrName{above left} \def\posMultiplicity{below right} }{ \def\posAttrName{above right} \def\posMultiplicity{below left} } } } } }{} \ifthenelse{\thepos=200}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrName{above left} \def\posMultiplicity{below right} }{ \def\posAttrName{above right} \def\posMultiplicity{below left} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrName{above right} \def\posMultiplicity{below left} }{ \def\posAttrName{above left} \def\posMultiplicity{below right} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrName{above left} \def\posMultiplicity{below right} }{ \def\posAttrName{above right} \def\posMultiplicity{below left} } }{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrName{above right} \def\posMultiplicity{below left} }{ \def\posAttrName{above left} \def\posMultiplicity{below right} } } } } }{} \ifnum\thepos>200 \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \else \ifnum\thepos<100 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \else \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100} \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \fi \ifthenelse{\theposT=100}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} }{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} }{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} }{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} } }{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} }{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} } } } } }{} \ifthenelse{\theposT=200}{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{right}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} }{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{left}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} }{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} } }{ \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{top}}{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} }{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} } }{ \ifthenelse{\tikzumlRelationEndAngle<\tikzumlRelationStartAngle}{ \def\posAttrNameT{above right} \def\posMultiplicityT{below left} }{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} } } } } }{} \ifnum\theposT>200 \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \else \ifnum\theposT<100 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \else \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100} \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \fi \fi \ifthenelse{\equal{\tikzumlRelationRecursiveDirectionStart}{\tikzumlRelationRecursiveDirectionEnd}}{ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle) -- \tikzumlFirstArc (\tikzumlRelationName-2.center) -- \tikzumlMidOneArc (\tikzumlRelationName-4.center) -- \tikzumlLastArc (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle) } \ifnum\thetikzumlStateLevel>0 \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname} \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5)} \fi }{ \xdef\tikzumlPath{(\tikzumlSrcClassNodeName.\tikzumlRelationStartAngle) -- \tikzumlFirstArc (\tikzumlRelationName-2.center) -- \tikzumlMidOneArc (\tikzumlRelationName-4.center) -- \tikzumlMidTwoArc (\tikzumlRelationName-6.center) -- \tikzumlLastArc (\tikzumlDestClassNodeName.\tikzumlRelationEndAngle) } \ifnum\thetikzumlStateLevel>0 \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname} \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5) (\tikzumlRelationName-6) (\tikzumlRelationName-7)} \fi } }{} } }{ \def\arcNum{1} \def\arcNumT{1} \node[inner sep=0] (\tikzumlRelationName-1) at (\tikzumlRelationName-middle) {}; \xdef\tikzumlLastArc{ node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) } \ifnum\thetikzumlStateLevel>0 \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname} \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) } \fi } }{ % first vertical then horizontal line \ifthenelse{\equal{\tikzumlRelationGeometry}{|-}} { %\setcounter{tikzumlControlNodesNum}{1} \def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} } \def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-3, anchor=center]{} } \begin{pgfonlayer}{connections} \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor |- \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {}; \end{pgfonlayer} \ifnum\theposStereo>100 \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \else \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \fi \ifnum\thepos>100 \pgfmathsetmacro{\tikzumlRelationPosition}{(\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=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \ifnum\arcNum=2 \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \ifnum\theposT>100 \pgfmathsetmacro{\tikzumlRelationPositionT}{(\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=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \ifnum\arcNumT=2 \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) } \ifnum\thetikzumlStateLevel>0 \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname} \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) } \fi }{ % first horizontal then vertical line \ifthenelse{\equal{\tikzumlRelationGeometry}{-|}} { %\setcounter{tikzumlControlNodesNum}{1} \def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center]{} } \def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-3, anchor=center] {} } \begin{pgfonlayer}{connections} \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor -| \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {}; \end{pgfonlayer} \ifnum\theposStereo>100 \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \else \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \fi \ifnum\thepos>100 \pgfmathsetmacro{\tikzumlRelationPosition}{(\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=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \ifnum\arcNum=2 \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \ifnum\theposT>100 \pgfmathsetmacro{\tikzumlRelationPositionT}{(\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=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \ifnum\arcNumT=2 \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) } \ifnum\thetikzumlStateLevel>0 \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname} \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) } \fi }{ % first vertical, then horizontal, finally vertical line \ifthenelse{\equal{\tikzumlRelationGeometry}{|-|}} { %\setcounter{tikzumlControlNodesNum}{2} \def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} } \def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {} } \def\tikzumlMidOneArc{ } \begin{pgfonlayer}{connections} \ifthenelse{\equal{\tikzumlRelationArmO}{auto}}{ \ifthenelse{\equal{\tikzumlRelationArmT}{auto}}{ \node[inner sep=0] (\tikzumlRelationName-3) at (\tikzumlRelationName-middle) {}; \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor |- \tikzumlRelationName-3) {}; \node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-3 -| \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {}; }{ \draw (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor)+(0,\tikzumlRelationArmT) node[inner sep=0, name=\tikzumlRelationName-4] {}; \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlRelationName-4 -| \tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) {}; \node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {}; } }{ \draw (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor)+(0,\tikzumlRelationArmO) node[inner sep=0, name=\tikzumlRelationName-2] {}; \node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-2 -| \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {}; \node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {}; } \end{pgfonlayer} \ifnum\theposStereo>200 \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \else \ifnum\theposStereo<100 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \else \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100} \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \fi \fi \ifthenelse{\thepos=200\OR\thepos=100}{ \def\posAttrName{above left} \def\posMultiplicity{below right} }{} \ifthenelse{\thepos>200}{ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100} \def\arcNum{3} }{ \ifthenelse{\thepos<100}{ \def\arcNum{1} }{ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100} \def\arcNum{2} } } \ifnum\arcNum=1 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \ifnum\arcNum=2 \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \ifnum\arcNum=3 \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \ifthenelse{\theposT=200\OR\theposT=100}{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} }{} \ifthenelse{\theposT>200}{ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100} \def\arcNumT{3} }{ \ifthenelse{\theposT<100}{ \def\arcNumT{1} }{ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100} \def\arcNumT{2} } } \ifnum\arcNumT=1 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \ifnum\arcNumT=2 \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \ifnum\arcNumT=3 \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlMidOneArc (\tikzumlRelationName-4.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) } \ifnum\thetikzumlStateLevel>0 \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname} \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5) } \fi }{ % first horizontal, then vertical, finally horizontal line \ifthenelse{\equal{\tikzumlRelationGeometry}{-|-}} { %\setcounter{tikzumlControlNodesNum}{2} \def\tikzumlFirstArc{node[midway, inner sep=0, name=\tikzumlRelationName-1, anchor=center] {} } \def\tikzumlLastArc{node[midway, inner sep=0, name=\tikzumlRelationName-5, anchor=center] {} } \def\tikzumlMidOneArc{} \begin{pgfonlayer}{connections} \ifthenelse{\equal{\tikzumlRelationArmO}{auto}}{ \ifthenelse{\equal{\tikzumlRelationArmT}{auto}}{ \node[inner sep=0] (\tikzumlRelationName-3) at (\tikzumlRelationName-middle) {}; \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor -| \tikzumlRelationName-3) {}; \node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-3 |- \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {}; }{ \draw (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor)+(\tikzumlRelationArmT,0) node[inner sep=0, name=\tikzumlRelationName-4] {}; \node[inner sep=0] (\tikzumlRelationName-2) at (\tikzumlRelationName-4 |- \tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) {}; \node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {}; } }{ \draw (\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor)+(\tikzumlRelationArmO,0) node[inner sep=0, name=\tikzumlRelationName-2] {}; \node[inner sep=0] (\tikzumlRelationName-4) at (\tikzumlRelationName-2 |- \tikzumlDestClassNodeName\tikzumlRelationDestAnchor) {}; \node[inner sep=0] (\tikzumlRelationName-3) at (barycentric cs:\tikzumlRelationName-2=0.5,\tikzumlRelationName-4=0.5) {}; } \end{pgfonlayer} \ifnum\theposStereo>200 \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-200)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \else \ifnum\theposStereo<100 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \else \pgfmathsetmacro{\tikzumlRelationPositionStereotype}{(\theposStereo-100)/100} \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionStereotype, anchor=\tikzumlRelationStereotypeAnchor, fill=\tikzumlRelationStereotypeFill] {\stereotype} } \fi \fi \ifthenelse{\thepos=200\OR\thepos=100}{ \def\posAttrName{above left} \def\posMultiplicity{below right} }{} \ifthenelse{\thepos>200}{ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-200)/100} \def\arcNum{3} }{ \ifthenelse{\thepos<100}{ \def\arcNum{1} }{ \pgfmathsetmacro{\tikzumlRelationPosition}{(\thepos-100)/100} \def\arcNum{2} } } \ifnum\arcNum=1 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \ifnum\arcNum=2 \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \ifnum\arcNum=3 \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPosition, \posAttrName, \attrAlign] {\tikzumlRelationAttrName} node[pos=\tikzumlRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlRelationMultiplicity} } \fi \ifthenelse{\theposT=200\OR\theposT=100}{ \def\posAttrNameT{above left} \def\posMultiplicityT{below right} }{} \ifthenelse{\theposT>200}{ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-200)/100} \def\arcNumT{3} }{ \ifthenelse{\theposT<100}{ \def\arcNumT{1} }{ \pgfmathsetmacro{\tikzumlRelationPositionT}{(\theposT-100)/100} \def\arcNumT{2} } } \ifnum\arcNumT=1 \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \ifnum\arcNumT=2 \xdef\tikzumlMidOneArc{\tikzumlMidOneArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \ifnum\arcNumT=3 \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlRelationAttrNameT} node[pos=\tikzumlRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlRelationMultiplicityT} } \fi \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlRelationName-2.base) -- \tikzumlMidOneArc (\tikzumlRelationName-4.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlRelationDestAnchor) } \ifnum\thetikzumlStateLevel>0 \def\tikzumlStateFitTmp{\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname} \expandafter\xdef\csname tikzumlStateFit\tikzumlState@parent @@\tikzumlState@fitname\endcsname{\tikzumlStateFitTmp (\tikzumlRelationName-1) (\tikzumlRelationName-2) (\tikzumlRelationName-3) (\tikzumlRelationName-4) (\tikzumlRelationName-5) } \fi }{ \errmessage{TIKZUML ERROR : Unknown geometry value !!! It should be in the following list : --, |-, -|, |-|, -|-} } } } } } \begin{pgfonlayer}{connections} \ifthenelse{\equal{\tikzumlRelationStyle}{tikzuml nesting style}}{ \pgfarrowsdeclare{nested}{nested}{} { \tikzumlNestingSymbolSize=0.2pt \advance\tikzumlNestingSymbolSize by .5\pgflinewidth \pgfsetdash{}{0pt} % do not dash \pgfsetroundjoin % fix join \pgfsetroundcap % fix cap \pgfpathmoveto{\pgfpoint{-16*\tikzumlNestingSymbolSize}{0pt}} \pgfpatharc{180}{90}{8*\tikzumlNestingSymbolSize} \pgfpatharc{90}{0}{8*\tikzumlNestingSymbolSize} \pgfpatharc{0}{-90}{8*\tikzumlNestingSymbolSize} \pgfpatharc{-90}{-180}{8*\tikzumlNestingSymbolSize} \pgfpathmoveto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{8*\tikzumlNestingSymbolSize}} \pgfpathlineto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{-8*\tikzumlNestingSymbolSize}} \pgfusepathqstroke } \draw[auto, nested-, font=\tikzumlDefaultFont, \tikzumlRelationStyle, /tikzuml/relation/style2] \tikzumlPath ; }{ \draw[auto, font=\tikzumlDefaultFont, \tikzumlRelationStyle, /tikzuml/relation/style2] \tikzumlPath ; } \end{pgfonlayer} \stepcounter{tikzumlRelationNum} } % shortcuts of \umlrelation \newcommand{\umlHVrelation}[3][]{ \pgfkeys{/tikzuml/HVrelation/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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{\umlcompos}[3][]{\umlrelation[style={tikzuml composition style}, #1]{#2}{#3}} \newcommand{\umlunicompos}[3][]{\umlrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}} \newcommand{\umlimport}[3][]{\umlrelation[style={tikzuml import style}, #1]{#2}{#3}} \newcommand{\umlnest}[3][]{\umlrelation[style={tikzuml nesting 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 \let\keyvalue=\pgfkeyscurrentvalue \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{\umlHVcompos}[3][]{\umlHVrelation[style={tikzuml composition style}, #1]{#2}{#3}} \newcommand{\umlHVunicompos}[3][]{\umlHVrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}} \newcommand{\umlHVimport}[3][]{\umlHVrelation[style={tikzuml import style}, #1]{#2}{#3}} \newcommand{\umlHVnest}[3][]{\umlHVrelation[style={tikzuml nesting 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 \let\keyvalue=\pgfkeyscurrentvalue \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{\umlVHcompos}[3][]{\umlVHrelation[style={tikzuml composition style}, #1]{#2}{#3}} \newcommand{\umlVHunicompos}[3][]{\umlVHrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}} \newcommand{\umlVHimport}[3][]{\umlVHrelation[style={tikzuml import style}, #1]{#2}{#3}} \newcommand{\umlVHnest}[3][]{\umlVHrelation[style={tikzuml nesting 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 \let\keyvalue=\pgfkeyscurrentvalue \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{\umlHVHcompos}[3][]{\umlHVHrelation[style={tikzuml composition style}, #1]{#2}{#3}} \newcommand{\umlHVHunicompos}[3][]{\umlHVHrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}} \newcommand{\umlHVHimport}[3][]{\umlHVHrelation[style={tikzuml import style}, #1]{#2}{#3}} \newcommand{\umlHVHnest}[3][]{\umlHVHrelation[style={tikzuml nesting 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 \let\keyvalue=\pgfkeyscurrentvalue \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{\umlVHVcompos}[3][]{\umlVHVrelation[style={tikzuml composition style}, #1]{#2}{#3}} \newcommand{\umlVHVunicompos}[3][]{\umlVHVrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}} \newcommand{\umlVHVimport}[3][]{\umlVHVrelation[style={tikzuml import style}, #1]{#2}{#3}} \newcommand{\umlVHVnest}[3][]{\umlVHVrelation[style={tikzuml nesting 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 \let\keyvalue=\pgfkeyscurrentvalue \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 : arg1, arg2, arg: name of the src/dest/dest side class type attribute defined by the relation % mult1, mult2, mult: multiplicity of the src/dest/dest side class type attribute defined by the relation % pos1, pos2, pos: position of the src/dest/dest side class type attribute defined by the relation % align1, align2, align: text justification of the src/dest/dest side class type attribute defined by the relation % anchor1, anchor2: src/dest anchors on linked classes % stereo: stereotype of the relation % st:pos, st:anchor, st:fill: stereotype position, anchor, and background % style: style of the relation (association, aggregation, composition, inherit, ...) % name: rootname used for naming nodes of the relation \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={}, st:pos/.initial=1, st:anchor/.initial=center, st:fill/.initial=none, style/.initial=->, name/.initial=relation-\thetikzumlRelationNum, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \errmessage{TIKZUML ERROR : in umlCNrelation, invalid option \keyname} } } \pgfkeys{/tikzuml/relation/.cd,#1} \pgfkeys{/tikzuml/relation/.cd, arg1/.get=\tikzumlCNRelationAttrName, arg2/.get=\tikzumlCNRelationAttrNameTO, arg/.get=\tikzumlCNRelationAttrNameTT, mult1/.get=\tikzumlCNRelationMultiplicity, mult2/.get=\tikzumlCNRelationMultiplicityTO, mult/.get=\tikzumlCNRelationMultiplicityTT, pos1/.get=\tikzumlCNRelationPosition, pos2/.get=\tikzumlCNRelationPositionTO, pos/.get=\tikzumlCNRelationPositionTT, align1/.get=\tikzumlCNRelationAlign, align2/.get=\tikzumlCNRelationAlignTO, align/.get=\tikzumlCNRelationAlignTT, anchor1/.get=\tikzumlCNRelationSrcAnchor, anchor2/.get=\tikzumlCNRelationDestAnchor, stereo/.get=\tikzumlCNRelationStereoType, st:pos/.get=\tikzumlCNRelationPositionStereotype, st:anchor/.get=\tikzumlCNRelationStereotypeAnchor, st:fill/.get=\tikzumlCNRelationStereotypeFill, style/.get=\tikzumlCNRelationStyle, name/.get=\tikzumlCNRelationName } % managing \_ in class names for node names \def\tikzumlSrcClassName{#2} \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlSrcClassNodeName{\tikzumlSrcClassName}}\x \StrSubstitute{\tikzumlSrcClassNodeName}{:}{@COLON@}[\tikzumlSrcClassNodeName] \StrSubstitute{\tikzumlSrcClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlSrcClassNodeName] \def\tikzumlDestClassName{#4} \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlDestClassNodeName{\tikzumlDestClassName}}\x \StrSubstitute{\tikzumlDestClassNodeName}{:}{@COLON@}[\tikzumlDestClassNodeName] \StrSubstitute{\tikzumlDestClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlDestClassNodeName] % managing alias keys \def\tikzumlCNRelationAttrNameT{\tikzumlCNRelationAttrNameTO\tikzumlCNRelationAttrNameTT} \def\tikzumlCNRelationMultiplicityT{\tikzumlCNRelationMultiplicityTO\tikzumlCNRelationMultiplicityTT} \def\tikzumlCNRelationAlignT{\tikzumlCNRelationAlignTO\tikzumlCNRelationAlignTT} \def\orientationT{\orientationTO\orientationTT} \ifthenelse{\equal{\tikzumlCNRelationPositionTT}{tikzumlEmpty}}{ \def\tikzumlCNRelationPositionT{\tikzumlCNRelationPositionTO} }{ \def\tikzumlCNRelationPositionT{\tikzumlCNRelationPositionTT} } \def\attrAlign{} \def\multAlign{} \def\attrAlignT{} \def\multAlignT{} \ifthenelse{\equal{\tikzumlCNRelationAlign}{left}}{ \def\attrAlign{above right} \def\multAlign{below right} }{ \ifthenelse{\equal{\tikzumlCNRelationAlign}{right}}{ \def\attrAlign{above left} \def\multAlign{below left} }{} } \ifthenelse{\equal{\tikzumlCNRelationAlignT}{left}}{ \def\attrAlignT{above right} \def\multAlignT{below right} }{ \ifthenelse{\equal{\tikzumlCNRelationAlignT}{right}}{ \def\attrAlignT{above left} \def\multAlignT{below left} }{} } % def stereotype \ifthenelse{\equal{\tikzumlCNRelationStereoType}{}}{ \def\stereotype{} }{ \def\stereotype{$\ll$\tikzumlCNRelationStereoType$\gg$} } % def anchors macros \ifthenelse{\equal{\tikzumlCNRelationSrcAnchor}{tikzumlEmpty}}{ \def\tikzumlCNRelationSrcAnchor{} }{ \let\tikzumlCNRelationSrcAnchorold\tikzumlCNRelationSrcAnchor \def\tikzumlCNRelationSrcAnchor{.\tikzumlCNRelationSrcAnchorold} } \ifthenelse{\equal{\tikzumlCNRelationDestAnchor}{tikzumlEmpty}}{ \def\tikzumlCNRelationDestAnchor{} }{ \let\tikzumlCNRelationDestAnchorold\tikzumlCNRelationDestAnchor \def\tikzumlCNRelationDestAnchor{.\tikzumlCNRelationDestAnchorold} } \setcounter{pos}{100*\real{\tikzumlCNRelationPosition}} \setcounter{posT}{100*\real{\tikzumlCNRelationPositionT}} \setcounter{posStereo}{100*\real{\tikzumlCNRelationPositionStereotype}} % straight line %\setcounter{tikzumlControlNodesNum}{1} \def\tikzumlFirstArc{node[midway, name=\tikzumlCNRelationName-1, anchor=center] {} } \def\tikzumlLastArc{node[midway, name=\tikzumlCNRelationName-3, anchor=center]{} } \def\posAttrName{} \def\posMultiplicity{} \def\posAttrNameT{} \def\posMultiplicityT{} \begin{pgfonlayer}{connections} \node (\tikzumlCNRelationName-2) at (#3) {}; \end{pgfonlayer} \ifnum\theposStereo>100 \pgfmathsetmacro{\tikzumlCNRelationPositionStereotype}{(\theposStereo-100)/100} \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlCNRelationPositionStereotype, anchor=\tikzumlCNRelationStereotypeAnchor, fill=\tikzumlCNRelationStereotypeFill] {\stereotype} } \else \xdef\tikzumlFirstArc{\tikzumlFirstArc node[pos=\tikzumlCNRelationPositionStereotype, anchor=\tikzumlCNRelationStereotypeAnchor, fill=\tikzumlCNRelationStereotypeFill] {\stereotype} } \fi \ifnum\thepos>100 \pgfmathsetmacro{\tikzumlCNRelationPosition}{(\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=\tikzumlCNRelationPosition, \posAttrName, \attrAlign] {\tikzumlCNRelationAttrName} node[pos=\tikzumlCNRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlCNRelationMultiplicity} } \fi \ifnum\arcNum=2 \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlCNRelationPosition, \posAttrName, \attrAlign] {\tikzumlCNRelationAttrName} node[pos=\tikzumlCNRelationPosition, swap, \posMultiplicity, \multAlign] {\tikzumlCNRelationMultiplicity} } \fi \ifnum\theposT>100 \pgfmathsetmacro{\tikzumlCNRelationPositionT}{(\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=\tikzumlCNRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlCNRelationAttrNameT} node[pos=\tikzumlCNRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlCNRelationMultiplicityT} } \fi \ifnum\arcNumT=2 \xdef\tikzumlLastArc{\tikzumlLastArc node[pos=\tikzumlCNRelationPositionT, \posAttrNameT, \attrAlignT] {\tikzumlCNRelationAttrNameT} node[pos=\tikzumlCNRelationPositionT, swap, \posMultiplicityT, \multAlignT] {\tikzumlCNRelationMultiplicityT} } \fi \xdef\tikzumlPath{(\tikzumlSrcClassNodeName\tikzumlCNRelationSrcAnchor) -- \tikzumlFirstArc (\tikzumlCNRelationName-2.base) -- \tikzumlLastArc (\tikzumlDestClassNodeName\tikzumlCNRelationDestAnchor) } \begin{pgfonlayer}{connections} \ifthenelse{\equal{\tikzumlCNRelationStyle}{tikzuml nesting style}}{ \pgfarrowsdeclare{nested}{nested}{} { \tikzumlNestingSymbolSize=0.2pt \advance\tikzumlNestingSymbolSize by .5\pgflinewidth \pgfsetdash{}{0pt} % do not dash \pgfsetroundjoin % fix join \pgfsetroundcap % fix cap \pgfpathmoveto{\pgfpoint{-16*\tikzumlNestingSymbolSize}{0pt}} \pgfpatharc{180}{90}{8*\tikzumlNestingSymbolSize} \pgfpatharc{90}{0}{8*\tikzumlNestingSymbolSize} \pgfpatharc{0}{-90}{8*\tikzumlNestingSymbolSize} \pgfpatharc{-90}{-180}{8*\tikzumlNestingSymbolSize} \pgfpathmoveto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{8*\tikzumlNestingSymbolSize}} \pgfpathlineto{\pgfpoint{-8*\tikzumlNestingSymbolSize}{-8*\tikzumlNestingSymbolSize}} \pgfusepathqstroke } \draw[auto, \tikzumlCNRelationStyle, nested-, font=\tikzumlDefaultFont] \tikzumlPath ; }{ \draw[auto, \tikzumlCNRelationStyle, font=\tikzumlDefaultFont] \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{\umlCNcompos}[4][]{\umlCNrelation[style={tikzuml composition style}, #1]{#2}{#3}{#4}} \newcommand{\umlCNunicompos}[4][]{\umlCNrelation[style={tikzuml unidirectional composition style}, #1]{#2}{#3}{#4}} \newcommand{\umlCNimport}[4][]{\umlCNrelation[style={tikzuml import style}, #1]{#2}{#3}{#4}} \newcommand{\umlCNnest}[4][]{\umlCNrelation[style={tikzuml nesting 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 \let\keyvalue=\pgfkeyscurrentvalue \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: width of the note % geometry: geometry of the relation between the note and what it is about % weight: barycentric weight for a 3-line relation % arm: length of the first arm % anchor1, anchor2: anchors of the relation % draw, fill, text: colors % style: to manage every default TikZ option % no coords: to tell that the note position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlnote}[3][]{ \pgfkeys{/tikzuml/note/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlNoteDefaultWidth, geometry/.initial=\tikzumlRelationDefaultGeometry, weight/.initial=\tikzumlRelationDefaultWeight, arm/.initial=auto, style/.style={}, anchor1/.initial=tikzumlEmpty, anchor2/.initial=tikzumlEmpty, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlNoteDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, no coords/.is if=tikzumlnoteWithoutCoords, no coords=false, px/.initial=0, py/.initial=0, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/note/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/note/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/note/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\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=\tikzumlNoteTextWidth, geometry/.get=\tikzumlNoteGeometry, weight/.get=\tikzumlNoteWeight, arm/.get=\tikzumlNoteArm, anchor1/.get=\tikzumlNoteSrcAnchor, anchor2/.get=\tikzumlNoteDestAnchor, draw/.get=\tikzumlNoteDrawColor, fill/.get=\tikzumlNoteFillColor, text/.get=\tikzumlNoteTextColor, px/.get=\tikzumlNotePointerX, py/.get=\tikzumlNotePointerY, } \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} } \iftikzumlnoteWithoutCoords \node[text=\tikzumlNoteTextColor, text width=\tikzumlNoteTextWidth, font=\tikzumlDefaultFont, outer sep=0, inner xsep=1ex, inner ysep=3ex, /tikzuml/note/style] (note-\thetikzumlNoteNum-coord) {#3}; \else \node[text=\tikzumlNoteTextColor, text width=\tikzumlNoteTextWidth, font=\tikzumlDefaultFont, outer sep=0, inner xsep=1ex, inner ysep=3ex, /tikzuml/note/style] (note-\thetikzumlNoteNum-coord) at (\tikzumlNoteX, \tikzumlNoteY) {#3}; \fi \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=\tikzumlNoteDrawColor, fill=\tikzumlNoteFillColor] (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=\tikzumlNoteTextColor, text width=\tikzumlNoteTextWidth, outer sep=0, inner xsep=1ex, inner ysep=3ex, font=\tikzumlDefaultFont] (note-\thetikzumlNoteNum) at (note-\thetikzumlNoteNum-coord) {#3}; \draw[draw=\tikzumlNoteDrawColor] (note-\thetikzumlNoteNum-right-top) -| (note-\thetikzumlNoteNum-top-right); \pgfmathsetmacro{\tikzumlNoteWeightT}{1.0-\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 : --, |-, -|, |-|, -|-} } } } \ifthenelse{\equal{\tikzumlNotePointerX}{0}\AND\equal{\tikzumlNotePointerY}{0}}{ \begin{pgfonlayer}{connections} \draw[densely dashed] (note-\thetikzumlNoteNum-coord\tikzumlNoteSrcAnchor) \tikzumlnotepath (\tikzumlClassNodeName\tikzumlNoteDestAnchor); \end{pgfonlayer} }{ \begin{pgfonlayer}{main} \draw ([shift={(\tikzumlNotePointerX,\tikzumlNotePointerY)}]\tikzumlClassNodeName) node[circle,inner sep=3pt,fill=\tikzumlNoteFillColor,draw=\tikzumlNoteDrawColor] (note-\thetikzumlNoteNum-pointer) {}; \draw[densely dashed] (note-\thetikzumlNoteNum-coord\tikzumlNoteSrcAnchor) \tikzumlnotepath (note-\thetikzumlNoteNum-pointer); \end{pgfonlayer} } \stepcounter{tikzumlNoteNum} } % shortcuts for note with geometry \newcommand{\umlHVnote}[3][]{ \pgfkeys{/tikzuml/note/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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: width of the class node % type: type of of class (class, interface, typedef, enum) % template: template parameters % name: name of the class node % geometry: geometry of the line % weight: barycentric weight of the middle part when geometry is a 3-line % arm: length of first part when geometry id a 3-line % anchor1, anchor2: src/dest anchors on linked classes % style: style of the association class (association, aggregation, composition, inherit, ...) % draw, fill, fill template, text: colors % style: to manage every default TikZ option % no coords: to tell that the class position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlassocclass}[5][]{ \pgfkeys{/tikzuml/assocclass/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlClassDefaultWidth, type/.initial=\tikzumlClassDefaultType, style/.style={}, template/.initial={}, name/.initial=tikzumlEmpty, geometry/.initial=\tikzumlRelationDefaultGeometry, weight/.initial=\tikzumlRelationDefaultWeight, arm/.initial=auto, anchor1/.initial=tikzumlEmpty, anchor2/.initial=tikzumlEmpty, draw/.initial=\tikzumlDefaultDrawColor, fill template/.initial=\tikzumlClassTemplateFillColorDefaultFillColor, fill/.initial=\tikzumlClassDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, no coords/.is if=tikzumlassocclassWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/assocclass/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/assocclass/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/assocclass/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlassocclass, invalid option \keyname} } } \pgfkeys{/tikzuml/assocclass/.cd,#1} \pgfkeys{/tikzuml/assocclass/.cd, x/.get=\tikzumlAssocClassX, y/.get=\tikzumlAssocClassY, width/.get=\tikzumlAssocClassMinimumWidth, type/.get=\tikzumlAssocClassTypeTmp, template/.get=\tikzumlAssocClassTemplateParam, name/.get=\tikzumlAssocClassName, geometry/.get=\tikzumlAssocClassGeometry, weight/.get=\tikzumlAssocClassWeight, arm/.get=\tikzumlAssocClassArm, anchor1/.get=\tikzumlAssocClassSrcAnchor, anchor2/.get=\tikzumlAssocClassDestAnchor, draw/.get=\tikzumlAssocClassDrawColor, fill/.get=\tikzumlAssocClassFillColor, text/.get=\tikzumlAssocClassTextColor, fill template/.get=\tikzumlAssocClassTemplateFillColor } \ifthenelse{\equal{\tikzumlAssocClassTypeTmp}{class}\OR\equal{\tikzumlAssocClassTypeTmp}{abstract}}{ \def\tikzumlAssocClassType{} }{ \def\tikzumlAssocClassType{$\ll$\tikzumlAssocClassTypeTmp$\gg$ \\} } \ifthenelse{\equal{\tikzumlAssocClassTemplateParam}{}}{ \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{\tikzumlAssocClassName}{tikzumlEmpty}}{}{ \def\tikzumlAssocClassNodeName{\tikzumlAssocClassName} } \StrSubstitute{\tikzumlAssocClassNodeName}{:}{@COLON@}[\tikzumlAssocClassNodeName] \StrSubstitute{\tikzumlAssocClassNodeName}{\_}{@UNDERSCORE@}[\tikzumlAssocClassNodeName] \ifthenelse{\equal{\tikzumlAssocClassTypeTmp}{abstract}}{ \let\tikzumlAssocClassNameOld\tikzumlAssocClassName \def\tikzumlAssocClassName{{\it \tikzumlAssocClassNameOld}} }{} \def\tikzumlAssocClassPos{\tikzumlAssocClassX,\tikzumlAssocClassY} \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} } \iftikzumlassocclassWithoutCoords \node[tikzuml class style, draw=\tikzumlAssocClassDrawColor, fill=\tikzumlAssocClassFillColor, text=\tikzumlAssocClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlAssocClassMinimumWidth, /tikzuml/assocclass/style] (\tikzumlAssocClassNodeName) {\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} }; \else \node[tikzuml class style, draw=\tikzumlAssocClassDrawColor, fill=\tikzumlAssocClassFillColor, text=\tikzumlAssocClassTextColor, font=\tikzumlDefaultFont, minimum width=\tikzumlAssocClassMinimumWidth, /tikzuml/assocclass/style] (\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} }; \fi \ifthenelse{\equal{\tikzumlAssocClassTemplateParam}{}}{}{ \draw (\tikzumlAssocClassNodeName.north east) node[tikzuml template style, name=\tikzumlAssocClassNodeName-template, draw=\tikzumlAssocClassDrawColor, fill=\tikzumlAssocClassTemplateFillColor, text=\tikzumlAssocClassTextColor, font=\tikzumlDefaultFont] {\tikzumlAssocClassTemplateParam}; } \pgfmathsetmacro{\tikzumlAssocClassWeightT}{1.0-\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{\tikzumlAssocClassTemplateParam}{}}{ \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} \newif\iftikzumlusecaseWithoutCoords \newif\iftikzumlactorWithoutCoords % 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=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlSystemDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \errmessage{TIKZUML ERROR : in umlsystem, invalid option \keyname} } } \pgfkeys{/tikzuml/system/.cd, #1} \pgfkeys{/tikzuml/system/.cd, x/.get=\tikzumlSystemXShift, y/.get=\tikzumlSystemYShift, draw/.get=\tikzumlSystemDrawColor, fill/.get=\tikzumlSystemFillColor, text/.get=\tikzumlSystemTextColor } \stepcounter{tikzumlSystemLevel} \begin{scope}[xshift=\tikzumlSystemXShift cm, yshift=\tikzumlSystemYShift 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=\tikzumlSystemTextColor, font=\tikzumlDefaultFont] (\tikzumlSystemName-caption-tmp) at (\tikzumlSystemName-tmp.north) {\tikzumlSystemName}; \node[draw=\tikzumlSystemDrawColor, fill=\tikzumlSystemFillColor, text=\tikzumlSystemTextColor, font=\tikzumlDefaultFont, inner ysep=1em, inner xsep=2ex, fit = (\tikzumlSystemName-tmp) (\tikzumlSystemName-caption-tmp)] (\tikzumlSystemName) {}; \node[text=\tikzumlSystemTextColor, font=\tikzumlDefaultFont] (\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: name of the node % width: node width % draw, fill, text: colors % style: to manage every default TikZ option % no coords: to tell that the use case position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlusecase}[2][]{ \stepcounter{tikzumlUseCaseNum} \pgfkeys{/tikzuml/usecase/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=auto, name/.initial=usecase-\thetikzumlUseCaseNum, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlUseCaseDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, style/.style={}, no coords/.is if=tikzumlusecaseWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/usecase/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/usecase/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/usecase/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlusecase, invalid option \keyname} } } \pgfkeys{/tikzuml/usecase/.cd, #1} \pgfkeys{/tikzuml/usecase/.cd, x/.get=\tikzumlUseCaseX, y/.get=\tikzumlUseCaseY, width/.get=\tikzumlUseCaseTextWidth, name/.get=\tikzumlUseCaseName, draw/.get=\tikzumlUseCaseDrawColor, fill/.get=\tikzumlUseCaseFillColor, text/.get=\tikzumlUseCaseTextColor } \def\tikzumlUseCaseText{#2} \def\tikzumlUseCasePos{\tikzumlUseCaseX,\tikzumlUseCaseY} \ifthenelse{\equal{\tikzumlUseCaseTextWidth}{auto}}{ \iftikzumlusecaseWithoutCoords \node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, /tikzuml/usecase/style] (\tikzumlUseCaseName) {\tikzumlUseCaseText}; \else \node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, /tikzuml/usecase/style] (\tikzumlUseCaseName) at (\tikzumlUseCasePos) {\tikzumlUseCaseText}; \fi }{ \iftikzumlusecaseWithoutCoords \node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, text width=\tikzumlUseCaseTextWidth, /tikzuml/usecase/style] (\tikzumlUseCaseName) {\tikzumlUseCaseText}; \else \node[tikzuml usecase style, draw=\tikzumlUseCaseDrawColor, fill=\tikzumlUseCaseFillColor, text=\tikzumlUseCaseTextColor, font=\tikzumlDefaultFont, text width=\tikzumlUseCaseTextWidth, /tikzuml/usecase/style] (\tikzumlUseCaseName) at (\tikzumlUseCasePos) {\tikzumlUseCaseText}; \fi } % add to fit \ifnum\c@tikzumlSystemLevel>0 \let\tikzumlSystemFitOld\tikzumlSystemFit \xdef\tikzumlSystemFit{\tikzumlSystemFitOld (\tikzumlUseCaseName)} \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=\tikzumlPicturedActorScale}% \begin{tikzpicture}[#1] \coordinate (head) at (0,5ex); \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=\tikzumlPicturedActorScale*0.3333ex, minimum size=\tikzumlPicturedActorScale*3ex, anchor=base] at (head) {}; \end{tikzpicture} } % define an actor % arg : var name % optional : x, y: coordinates of the actor % scale: scale factor of the actor symbol % below: distance between the actor symbol and its name below % draw, text: colors % style: to manage every default TikZ option % no coords: to tell that the actor position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlactor}[2][]{ \stepcounter{tikzumlActorNum} \pgfkeys{/tikzuml/actor/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, scale/.initial=1, below/.initial=\tikzumlActorDefaultBelow, draw/.initial=\tikzumlDefaultDrawColor, head/.initial=yellow!30, text/.initial=\tikzumlDefaultTextColor, style/.style={}, no coords/.is if=tikzumlactorWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/actor/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/actor/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/actor/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlactor, invalid option \keyname} } } \pgfkeys{/tikzuml/actor/.cd, #1} \pgfkeys{/tikzuml/actor/.cd, x/.get=\tikzumlActorX, y/.get=\tikzumlActorY, scale/.get=\tikzumlActorScale, below/.get=\tikzumlActorBelow, draw/.get=\tikzumlActorDrawColor, head/.get=\tikzumlActorHeadColor, text/.get=\tikzumlActorTextColor } \def\tikzumlActorName{#2} \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlActorNodeName{\tikzumlActorName}}\x \def\tikzumlActorPos{\tikzumlActorX,\tikzumlActorY} \iftikzumlactorWithoutCoords \node[tikzuml actor style, text=\tikzumlActorTextColor, font=\tikzumlDefaultFont, /tikzuml/actor/style] (\tikzumlActorNodeName) {\picturedactor{scale=\tikzumlActorScale, fill=\tikzumlActorHeadColor, draw=\tikzumlActorDrawColor, thick}}; \else \node[tikzuml actor style, text=\tikzumlActorTextColor, font=\tikzumlDefaultFont, /tikzuml/actor/style] (\tikzumlActorNodeName) at (\tikzumlActorPos) {\picturedactor{scale=\tikzumlActorScale, fill=\tikzumlActorHeadColor, draw=\tikzumlActorDrawColor, thick}}; \fi \node[text=\tikzumlActorTextColor, font=\tikzumlDefaultFont, below=\tikzumlActorScale*\tikzumlActorBelow] at (\tikzumlActorNodeName) {\tikzumlActorName}; } % shortcuts for include and extend relation \newcommand{\umlinclude}[3][]{ \pgfkeys{/tikzuml/includerelation/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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=\tikzumlDefaultDrawColor, rounded corners, -{Straight Barb[scale=3.5,angle'=55]}] \newcounter{tikzumlStateJoinNum} \newcounter{tikzumlStateDecisionNum} \newcounter{tikzumlStateInitialNum} \newcounter{tikzumlStateFinalNum} \newcounter{tikzumlStateEnterNum} \newcounter{tikzumlStateExitNum} \newcounter{tikzumlStateEndNum} \newcounter{tikzumlStateHistoryNum} \newcounter{tikzumlStateDeepHistoryNum} \newcounter{tikzumlStateLevel} \newcounter{tikzumlStateSubStateNum} \newcounter{tikzumlStateText} \newif\iftikzumlstatejoinWithoutCoords \newif\iftikzumlstatedecisionWithoutCoords \newif\iftikzumlstateinitialWithoutCoords \newif\iftikzumlstatefinalWithoutCoords \newif\iftikzumlstateenterWithoutCoords \newif\iftikzumlstateexitWithoutCoords \newif\iftikzumlstateendWithoutCoords \newif\iftikzumlstatehistoryWithoutCoords \newif\iftikzumlstatedeephistoryWithoutCoords \newif\iftikzumlstateWithoutCoords % define a uml join state % args : name of the state % optional : x,y: coordinates of the state % width: width of the state node % name: name of the state node % color: color of the join symbol % style: to manage every default TikZ option % no coords: to tell that the state position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlstatejoin}[1][]{ \pgfkeys{/tikzuml/statejoin/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateJoinDefaultWidth, name/.initial=statejoin-\thetikzumlStateJoinNum, color/.initial=\tikzumlDefaultDrawColor, style/.style={}, no coords/.is if=tikzumlstatejoinWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/statejoin/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/statejoin/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/statejoin/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlstatejoin, invalid option \keyname} } } \pgfkeys{/tikzuml/statejoin/.cd, #1} \pgfkeys{/tikzuml/statejoin/.cd, x/.get=\tikzumlStateJoinX, y/.get=\tikzumlStateJoinY, width/.get=\tikzumlStateJoinMinimumWidth, name/.get=\tikzumlStateJoinName, color/.get=\tikzumlStateJoinColor } \def\tikzumlStateJoinPos{\tikzumlStateJoinX,\tikzumlStateJoinY} \iftikzumlstatejoinWithoutCoords \node[circle, minimum size=\tikzumlStateJoinMinimumWidth, draw=\tikzumlStateJoinColor, fill=\tikzumlStateJoinColor, /tikzuml/statejoin/style] (\tikzumlStateJoinName) {}; \else \node[circle, minimum size=\tikzumlStateJoinMinimumWidth, draw=\tikzumlStateJoinColor, fill=\tikzumlStateJoinColor, /tikzuml/statejoin/style] (\tikzumlStateJoinName) at (\tikzumlStateJoinPos) {}; \fi % 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} } % define a uml decision state % args : name of the state % optional : x,y: coordinates of the state % width: width of the state node % name: name of the state node % color: color of the join symbol % style: to manage every default TikZ option % no coords: to tell that the state position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlstatedecision}[1][]{ \pgfkeys{/tikzuml/statedecision/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateDecisionDefaultWidth, name/.initial=statedecision-\thetikzumlStateDecisionNum, color/.initial=\tikzumlDefaultDrawColor, style/.style={}, no coords/.is if=tikzumlstatedecisionWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/statedecision/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/statedecision/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/statedecision/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlstatedecision, invalid option \keyname} } } \pgfkeys{/tikzuml/statedecision/.cd, #1} \pgfkeys{/tikzuml/statedecision/.cd, x/.get=\tikzumlStateDecisionX, y/.get=\tikzumlStateDecisionY, width/.get=\tikzumlStateDecisionMinimumWidth, name/.get=\tikzumlStateDecisionName, color/.get=\tikzumlStateDecisionColor } \def\tikzumlStateDecisionPos{\tikzumlStateDecisionX,\tikzumlStateDecisionY} \iftikzumlstatedecisionWithoutCoords \node[rectangle, rotate=45, minimum size=\tikzumlStateDecisionMinimumWidth, draw=\tikzumlStateDecisionColor, /tikzuml/statedecision/style] (\tikzumlStateDecisionName) {}; \else \node[rectangle, rotate=45, minimum size=\tikzumlStateDecisionMinimumWidth, draw=\tikzumlStateDecisionColor, /tikzuml/statedecision/style] (\tikzumlStateDecisionName) at (\tikzumlStateDecisionPos) {}; \fi % 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} } % define a uml initial state % args : name of the state % optional : x,y: coordinates of the state % width: width of the state node % name: name of the state node % entry, do, exit: entry/do/exit action of the state % color: color of the join symbol % style: to manage every default TikZ option % no coords: to tell that the state position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlstateinitial}[1][]{ \pgfkeys{/tikzuml/stateinitial/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateInitialDefaultWidth, name/.initial=stateinitial-\thetikzumlStateInitialNum, color/.initial=\tikzumlDefaultDrawColor, style/.style={}, no coords/.is if=tikzumlstateinitialWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/stateinitial/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/stateinitial/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/stateinitial/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlstateinitial, invalid option \keyname} } } \pgfkeys{/tikzuml/stateinitial/.cd, #1} \pgfkeys{/tikzuml/stateinitial/.cd, x/.get=\tikzumlStateInitialX, y/.get=\tikzumlStateInitialY, width/.get=\tikzumlStateInitialMinimumWidth, name/.get=\tikzumlStateInitialName, color/.get=\tikzumlStateInitialColor } \def\tikzumlStateInitialPos{\tikzumlStateInitialX,\tikzumlStateInitialY} \iftikzumlstateinitialWithoutCoords \node[circle, minimum size=\tikzumlStateInitialMinimumWidth, fill=\tikzumlStateInitialColor, /tikzuml/stateinitial/style] (\tikzumlStateInitialName) {}; \else \node[circle, minimum size=\tikzumlStateInitialMinimumWidth, fill=\tikzumlStateInitialColor, /tikzuml/stateinitial/style] (\tikzumlStateInitialName) at (\tikzumlStateInitialPos) {}; \fi % 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} } % define a uml final state % args : name of the state % optional : x,y: coordinates of the state % width: width of the state node % name: name of the state node % color: color of the join symbol % style: to manage every default TikZ option % no coords: to tell that the state position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlstatefinal}[1][]{ \pgfkeys{/tikzuml/statefinal/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateFinalDefaultWidth, name/.initial=statefinal-\thetikzumlStateFinalNum, color/.initial=\tikzumlDefaultDrawColor, style/.style={}, no coords/.is if=tikzumlstatefinalWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/statefinal/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/statefinal/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/statefinal/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlstatefinal, invalid option \keyname} } } \pgfkeys{/tikzuml/statefinal/.cd, #1} \pgfkeys{/tikzuml/statefinal/.cd, x/.get=\tikzumlStateFinalX, y/.get=\tikzumlStateFinalY, width/.get=\tikzumlStateFinalMinimumWidth, name/.get=\tikzumlStateFinalName, color/.get=\tikzumlStateFinalColor } \def\tikzumlStateFinalPos{\tikzumlStateFinalX,\tikzumlStateFinalY} \iftikzumlstatefinalWithoutCoords \node[circle, minimum size=\tikzumlStateFinalMinimumWidth, draw=\tikzumlStateFinalColor, fill=\tikzumlStateFinalColor, double, double distance=0.1cm, /tikzuml/statefinal/style] (\tikzumlStateFinalName) {}; \else \node[circle, minimum size=\tikzumlStateFinalMinimumWidth, draw=\tikzumlStateFinalColor, fill=\tikzumlStateFinalColor, double, double distance=0.1cm, /tikzuml/statefinal/style] (\tikzumlStateFinalName) at (\tikzumlStateFinalPos) {}; \fi % 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} } % define a uml enter state % args : name of the state % optional : x,y: coordinates of the state % width: width of the state node % name: name of the state node % color: color of the join symbol % style: to manage every default TikZ option % no coords: to tell that the state position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlstateenter}[1][]{ \pgfkeys{/tikzuml/stateenter/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateEnterDefaultWidth, name/.initial=stateenter-\thetikzumlStateEnterNum, color/.initial=\tikzumlDefaultDrawColor, style/.style={}, no coords/.is if=tikzumlstateenterWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/stateenter/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/stateenter/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/stateenter/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlstateenter, invalid option \keyname} } } \pgfkeys{/tikzuml/stateenter/.cd, #1} \pgfkeys{/tikzuml/stateenter/.cd, x/.get=\tikzumlStateEnterX, y/.get=\tikzumlStateEnterY, width/.get=\tikzumlStateEnterMinimumWidth, name/.get=\tikzumlStateEnterName, color/.get=\tikzumlStateEnterColor } \def\tikzumlStateEnterPos{\tikzumlStateEnterX,\tikzumlStateEnterY} \iftikzumlstateenterWithoutCoords \node[circle, minimum size=\tikzumlStateEnterMinimumWidth, draw=\tikzumlStateEnterColor, /tikzuml/stateenter/style] (\tikzumlStateEnterName) {}; \else \node[circle, minimum size=\tikzumlStateEnterMinimumWidth, draw=\tikzumlStateEnterColor, /tikzuml/stateenter/style] (\tikzumlStateEnterName) at (\tikzumlStateEnterPos) {}; \fi % 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} } % define a uml exit state % args : name of the state % optional : x,y: coordinates of the state % width: width of the state node % name: name of the state node % color: color of the join symbol % style: to manage every default TikZ option % no coords: to tell that the state position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlstateexit}[1][]{ \pgfkeys{/tikzuml/stateexit/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateExitDefaultWidth, name/.initial=stateexit-\thetikzumlStateExitNum, color/.initial=\tikzumlDefaultDrawColor, style/.style={}, no coords/.is if=tikzumlstateexitWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/stateexit/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/stateexit/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/stateexit/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlstateexit, invalid option \keyname} } } \pgfkeys{/tikzuml/stateexit/.cd, #1} \pgfkeys{/tikzuml/stateexit/.cd, x/.get=\tikzumlStateExitX, y/.get=\tikzumlStateExitY, width/.get=\tikzumlStateExitMinimumWidth, name/.get=\tikzumlStateExitName, color/.get=\tikzumlStateExitColor } \def\tikzumlStateExitPos{\tikzumlStateExitX,\tikzumlStateExitY} \iftikzumlstateexitWithoutCoords \node[circle, minimum size=\tikzumlStateExitMinimumWidth, draw=\tikzumlStateExitColor, /tikzuml/stateexit/style] (\tikzumlStateExitName) {}; \else \node[circle, minimum size=\tikzumlStateExitMinimumWidth, draw=\tikzumlStateExitColor, /tikzuml/stateexit/style] (\tikzumlStateExitName) at (\tikzumlStateExitPos) {}; \fi \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} } % define a uml end state % args : name of the state % optional : x,y: coordinates of the state % width: width of the state node % name: name of the state node % color: color of the join symbol % style: to manage every default TikZ option % no coords: to tell that the state position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlstateend}[1][]{ \pgfkeys{/tikzuml/stateend/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateEndDefaultWidth, name/.initial=stateend-\thetikzumlStateEndNum, color/.initial=\tikzumlDefaultDrawColor, style/.style={}, no coords/.is if=tikzumlstateendWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/stateend/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/stateend/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/stateend/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlstateend, invalid option \keyname} } } \pgfkeys{/tikzuml/stateend/.cd, #1} \pgfkeys{/tikzuml/stateend/.cd, x/.get=\tikzumlStateEndX, y/.get=\tikzumlStateEndY, width/.get=\tikzumlStateEndMinimumWidth, name/.get=\tikzumlStateEndName, color/.get=\tikzumlStateEndColor } \def\tikzumlStateEndPos{\tikzumlStateEndX,\tikzumlStateEndY} \iftikzumlstateendWithoutCoords \node[circle, minimum size=\tikzumlStateEndMinimumWidth, /tikzuml/stateend/style] (\tikzumlStateEndName) {}; \else \node[circle, minimum size=\tikzumlStateEndMinimumWidth, /tikzuml/stateend/style] (\tikzumlStateEndName) at (\tikzumlStateEndPos) {}; \fi \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} } % define a uml history state % args : name of the state % optional : x,y: coordinates of the state % width: width of the state node % name: name of the state node % color: color of the join symbol % style: to manage every default TikZ option % no coords: to tell that the state position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlstatehistory}[1][]{ \pgfkeys{/tikzuml/statehistory/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateHistoryDefaultWidth, name/.initial=statehistory-\thetikzumlStateHistoryNum, color/.initial=\tikzumlDefaultDrawColor, style/.style={}, no coords/.is if=tikzumlstatehistoryWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/statehistory/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/statehistory/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/statehistory/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlstatehistory, invalid option \keyname} } } \pgfkeys{/tikzuml/statehistory/.cd, #1} \pgfkeys{/tikzuml/statehistory/.cd, x/.get=\tikzumlStateHistoryX, y/.get=\tikzumlStateHistoryY, width/.get=\tikzumlStateHistoryMinimumWidth, name/.get=\tikzumlStateHistoryName, color/.get=\tikzumlStateHistoryColor } \def\tikzumlStateHistoryPos{\tikzumlStateHistoryX,\tikzumlStateHistoryY} \iftikzumlstatehistoryWithoutCoords \node[circle, minimum size=\tikzumlStateHistoryMinimumWidth, draw=\tikzumlStateHistoryColor, /tikzuml/statehistory/style] (\tikzumlStateHistoryName) {\picturedhistory{draw=\tikzumlStateHistoryColor}}; \else \node[circle, minimum size=\tikzumlStateHistoryMinimumWidth, draw=\tikzumlStateHistoryColor, /tikzuml/statehistory/style] (\tikzumlStateHistoryName) at (\tikzumlStateHistoryPos) {\picturedhistory{draw=\tikzumlStateHistoryColor}}; \fi % 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} } % define a uml deep-history state % args : name of the state % optional : x,y: coordinates of the state % width: width of the state node % name: name of the state node % color: color of the join symbol % style: to manage every default TikZ option % no coords: to tell that the state position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \newcommand{\umlstatedeephistory}[1][]{ \pgfkeys{/tikzuml/statedeephistory/.cd, x/.initial=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateDeepHistoryDefaultWidth, name/.initial=statedeephistory-\thetikzumlStateDeepHistoryNum, color/.initial=\tikzumlDefaultDrawColor, style/.style={}, no coords/.is if=tikzumlstatedeephistoryWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/statedeephistory/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/statedeephistory/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/statedeephistory/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlstatedeephistory, invalid option \keyname} } } \pgfkeys{/tikzuml/statedeephistory/.cd, #1} \pgfkeys{/tikzuml/statedeephistory/.cd, x/.get=\tikzumlStateDeepHistoryX, y/.get=\tikzumlStateDeepHistoryY, width/.get=\tikzumlStateDeepHistoryMinimumWidth, name/.get=\tikzumlStateDeepHistoryName, color/.get=\tikzumlStateDeepHistoryColor } \def\tikzumlStateDeepHistoryPos{\tikzumlStateDeepHistoryX,\tikzumlStateDeepHistoryY} \iftikzumlstatedeephistoryWithoutCoords \node[circle, minimum size=\tikzumlStateDeepHistoryMinimumWidth, draw=\tikzumlStateDeepHistoryColor, /tikzuml/statedeephistory/style] (\tikzumlStateDeepHistoryName) {\pictureddeephistory{draw=\tikzumlStateDeepHistoryColor}}; \else \node[circle, minimum size=\tikzumlStateDeepHistoryMinimumWidth, draw=\tikzumlStateDeepHistoryColor, /tikzuml/statedeephistory/style] (\tikzumlStateDeepHistoryName) at (\tikzumlStateDeepHistoryPos) {\pictureddeephistory{draw=\tikzumlStateDeepHistoryColor}}; \fi % 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 : x,y: coordinates of the state % width: width of the state node % name: name of the state node % entry, do, exit: entry/do/exit action of the state % draw, fill, text: colors % style: to manage every default TikZ option % no coords: to tell that the state position is defined relatively % to another node (automatically used with TikZ options above, below, left, right, below left, ...) \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=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlStateDefaultWidth, name/.initial={}, entry/.initial={}, do/.initial={}, exit/.initial={}, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlStateDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, style/.style={}, no coords/.is if=tikzumlstateWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/state/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/state/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/state/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlstate, invalid option \keyname} } } \pgfkeys{/tikzuml/state/.cd, #1} \pgfkeys{/tikzuml/state/.cd, x/.get=\tikzumlStateXShift, y/.get=\tikzumlStateYShift, width/.get=\tikzumlStateMinimumWidth, name/.get=\tikzumlStateName, entry/.get=\tikzumlStateEntry, do/.get=\tikzumlStateDo, exit/.get=\tikzumlStateExit, draw/.get=\tikzumlStateDrawColor, fill/.get=\tikzumlStateFillColor, text/.get=\tikzumlStateTextColor } \ifthenelse{\equal{\tikzumlStateName}{}}{ \edef\tikzumlState@name{#2} }{ \edef\tikzumlState@name{\tikzumlStateName} } \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=\tikzumlStateXShift cm, yshift=\tikzumlStateYShift cm] }{ \def\tikzumlstaterootlabel{\phantom{\tikzumlState@nodeName}} \def\tikzumlstaterootinnerysep{0.5ex} \def\tikzumlstatebodyinnerysep{2ex} \ifthenelse{\equal{\tikzumlStateEntry}{}}{}{ \ifnum\c@tikzumlStateText=0 \def\tikzumlStateText{entry/\tikzumlStateEntry} \else \let\tikzumlStateTextOld\tikzumlStateText \ifthenelse{\equal{\tikzumlStateText}{tikzumlEmpty}}{ \def\tikzumlStateText{entry/\tikzumlStateEntry} }{ \expandafter\def\expandafter\tikzumlStateText\expandafter{\tikzumlStateTextOld \\ entry/\tikzumlStateEntry} } \fi \setcounter{tikzumlStateText}{1} \ifnum\c@tikzumlStateSubStateNum=0 \def\tikzumlstatebodyinnerysep{0} \def\tikzumlstaterootinnerysep{0} \fi } \ifthenelse{\equal{\tikzumlStateDo}{}}{}{ \ifnum\c@tikzumlStateText=0 \def\tikzumlStateText{do/\tikzumlStateDo} \else \let\tikzumlStateTextOld\tikzumlStateText \ifthenelse{\equal{\tikzumlStateText}{tikzumlEmpty}}{ \def\tikzumlStateText{do/\tikzumlStateDo} }{ \expandafter\def\expandafter\tikzumlStateText\expandafter{\tikzumlStateTextOld \\ do/\tikzumlStateDo} } \fi \setcounter{tikzumlStateText}{1} \ifnum\c@tikzumlStateSubStateNum=0 \def\tikzumlstatebodyinnerysep{0} \def\tikzumlstaterootinnerysep{0} \fi } \ifthenelse{\equal{\tikzumlStateExit}{}}{}{ \ifnum\c@tikzumlStateText=0 \def\tikzumlStateText{exit/\tikzumlStateExit} \else \let\tikzumlStateTextOld\tikzumlStateText \ifthenelse{\equal{\tikzumlStateText}{tikzumlEmpty}}{ \def\tikzumlStateText{exit/\tikzumlStateExit} }{ \expandafter\def\expandafter\tikzumlStateText\expandafter{\tikzumlStateTextOld \\ exit/\tikzumlStateExit} } \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 \iftikzumlstateWithoutCoords \node[inner ysep=\tikzumlstaterootinnerysep, minimum width=\tikzumlStateMinimumWidth, /tikzuml/state/style] (\tikzumlState@nodeName-root) {\tikzumlstaterootlabel}; \else \node[inner ysep=\tikzumlstaterootinnerysep, minimum width=\tikzumlStateMinimumWidth, /tikzuml/state/style] (\tikzumlState@nodeName-root) at (0,0) {\tikzumlstaterootlabel}; \fi \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, /tikzuml/state/style ] (\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}; \ifnum\c@tikzumlStateText=1 \node[rounded corners, draw=\tikzumlStateDrawColor, fill=\tikzumlStateFillColor, name=\tikzumlState@nodeName, fit=(\tikzumlState@nodeName-body) (\tikzumlState@nodeName-texttmp) (\tikzumlState@nodeName-captiontmp)] {}; \else \node[rounded corners, draw=\tikzumlStateDrawColor, fill=\tikzumlStateFillColor, name=\tikzumlState@nodeName, fit=(\tikzumlState@nodeName-body) (\tikzumlState@nodeName-captiontmp)] {}; \fi \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, to be used inside umlstate environment \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 and object diagrams % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \tikzstyle{tikzuml synchron-msg style}=[color=\tikzumlDefaultDrawColor, -{Triangle[scale=2.5,angle'=50]}] \tikzstyle{tikzuml asynchron-msg style}=[color=\tikzumlDefaultDrawColor, -{Straight Barb[scale=3.5,angle'=55]}] \tikzstyle{tikzuml return-msg style}=[color=\tikzumlDefaultDrawColor, dashed, -{Straight Barb[scale=3.5,angle'=55]}] \tikzstyle{tikzuml call return style}=[color=\tikzumlDefaultDrawColor, dashed, -{Straight Barb[scale=3.5,angle'=55]}] \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} \newif\iftikzumlobjectNoDDots \newif\iftikzumlcreatecallNoDDots % 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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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=\tikzumlDefaultFont] }{ % 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[dashed] (\id) -- (end-\id); } \end{pgfonlayer} \end{scope} } % define an object diagram \newenvironment{umlobjdiag}{ \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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=\tikzumlDefaultFont] }{ % 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 database 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 entity 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 boundary 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 control 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 % stereo: stereotype of the object (object, actor, database, boundary, control, entity, multiobject) % class: class of the object % scale: scale factor of the object symbol % draw, fill, text; colors % no ddots: when used, disable printing of double dots \newcommand{\umlobject}[2][]{ \stepcounter{tikzumlObjectNum} \edef\tikzumlobject@ddot{:} \edef\tikzumlobject@kern{\,} \pgfkeys{/tikzuml/obj/.cd, x/.initial=tikzumlEmpty, y/.initial=\tikzumlDefaultX, stereo/.initial=\tikzumlObjectDefaultStereo, class/.initial={}, scale/.initial=1, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlObjectDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, no ddots/.is if=tikzumlobjectNoDDots, no ddots=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \errmessage{TIKZUML ERROR : in umlobject, 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=\tikzumlObjectDrawColor, fill/.get=\tikzumlObjectFillColor, text/.get=\tikzumlObjectTextColor } \iftikzumlobjectNoDDots \edef\tikzumlobject@ddot{} \edef\tikzumlobject@kern{} \fi \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 \expandafter\xdef\expandafter\tikzumlIdList\expandafter{\tikzumlIdListOld,\tikzumlObjectName} \fi \tikzstyle{tikzuml object box style}=[rectangle, text=\tikzumlObjectTextColor, font=\tikzumlDefaultFont] \ifthenelse{\equal{\tikzumlObjectStereo}{object}}{ \tikzstyle{tikzuml object box style}+=[draw=\tikzumlObjectDrawColor, fill=\tikzumlObjectFillColor] }{ \ifthenelse{\equal{\tikzumlObjectStereo}{multi}}{ \tikzstyle{tikzuml object box style}+=[fill=\tikzumlObjectFillColor] }{} } \ifdefempty{\tikzumlObjectName}{ \def\tikzumlObjectNC{@COLON@\tikzumlObjectClass} }{ \def\tikzumlObjectNC{\tikzumlObjectName} } \ifnum\tikzumlInCreateCall=1 \draw (\tikzumlCreateCallObjectSrc -| \tikzumlObjectX,0) node[tikzuml object box style] (\tikzumlObjectNC) {\underline{\textbf{\tikzumlObjectName\tikzumlobject@kern\tikzumlobject@ddot\tikzumlobject@kern\tikzumlObjectClass}}}; \else \node[tikzuml object box style] (\tikzumlObjectNC) at (\tikzumlObjectX,\tikzumlObjectY) {\underline{\textbf{\tikzumlObjectName\tikzumlobject@kern\tikzumlobject@ddot\tikzumlobject@kern\tikzumlObjectClass}}}; \fi \ifthenelse{\equal{\tikzumlObjectStereo}{multi}}{ \draw (\tikzumlObjectNC.north east)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-tr, coordinate] {}; \draw (\tikzumlObjectNC.north west)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-tl, coordinate] {}; \draw (\tikzumlObjectNC.south east)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-br, coordinate] {}; \draw (\tikzumlObjectNC-tr)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-ttr, coordinate] {}; \draw (\tikzumlObjectNC-tl)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-ttl, coordinate] {}; \draw (\tikzumlObjectNC-br)+(0.4ex,0.4ex) node[name=\tikzumlObjectNC-tbr, coordinate] {}; \fill[fill=\tikzumlObjectFillColor] (\tikzumlObjectNC-ttl |- \tikzumlObjectNC.north) -- (\tikzumlObjectNC-ttl) -- (\tikzumlObjectNC-ttr) -- (\tikzumlObjectNC-tbr) -- (\tikzumlObjectNC-tbr -| \tikzumlObjectNC.east) -- (\tikzumlObjectNC.north east) -- (\tikzumlObjectNC-ttl |- \tikzumlObjectNC.north); \draw[draw=\tikzumlObjectDrawColor] (\tikzumlObjectNC-ttl |- \tikzumlObjectNC.north) -- (\tikzumlObjectNC-ttl) -- (\tikzumlObjectNC-ttr) -- (\tikzumlObjectNC-tbr) -- (\tikzumlObjectNC-tbr -| \tikzumlObjectNC.east); \fill[fill=\tikzumlObjectFillColor] (\tikzumlObjectNC-tl |- \tikzumlObjectNC.north) -- (\tikzumlObjectNC-tl) -- (\tikzumlObjectNC-tr) -- (\tikzumlObjectNC-br) -- (\tikzumlObjectNC-br -| \tikzumlObjectNC.east) -- (\tikzumlObjectNC.north east) -- (\tikzumlObjectNC-tl |- \tikzumlObjectNC.north); \draw[draw=\tikzumlObjectDrawColor] (\tikzumlObjectNC-tl |- \tikzumlObjectNC.north) -- (\tikzumlObjectNC-tl) -- (\tikzumlObjectNC-tr) -- (\tikzumlObjectNC-br) -- (\tikzumlObjectNC-br -| \tikzumlObjectNC.east); \draw[draw=\tikzumlObjectDrawColor] (\tikzumlObjectNC.north west) rectangle (\tikzumlObjectNC.south east); }{ \ifthenelse{\equal{\tikzumlObjectStereo}{object}}{}{ \node[above=1ex, name=\tikzumlObjectNC-picture] at (\tikzumlObjectNC) {\csname pictured\tikzumlObjectStereo \endcsname{draw=\tikzumlObjectDrawColor, fill=\tikzumlObjectFillColor, scale=\tikzumlObjectScale}}; } } } % shortcuts for objects \newcommand{\umlbasicobject}[2][]{ \pgfkeys{/tikzuml/basicobj/.cd, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{stereo}}{ \errmessage{TIKZUML ERROR : in umlmulti, forbidden option stereo} }{} } } \pgfkeys{/tikzuml/multiobj/.cd, #1} \umlobject[stereo=multi, #1]{#2} } \newcounter{tikzumlSDNodeNum} % define a hidden node to lengthen lifeline of a object % args : object node % optional : dt: distance between the sdnode and the last call defined on the lifeline of the object % name: name of the sdnode \newcommand{\umlsdnode}[2][]{ \pgfkeys{/tikzuml/sdnode/.cd, dt/.initial=0, name/.initial=tikzumlEmpty} \pgfkeys{/tikzuml/sdnode/.cd, #1} \pgfkeys{/tikzuml/sdnode/.cd, dt/.get=\tikzumlSDNodeDT, name/.get=\tikzumlSDNodeName} \ifthenelse{\equal{\tikzumlSDNodeName}{tikzumlEmpty}}{ \expandafter\def\expandafter\tikzumlSDNode@nodeName{sdnode-\thetikzumlSDNodeNum} }{ \expandafter\def\expandafter\tikzumlSDNode@nodeName{\tikzumlSDNodeName} } \stepcounter{tikzumlSDNodeNum} \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlSDNode@objnodeName{#2}}\x \draw (\expandafter\csname tikzumlLastChild@\tikzumlSDNode@objnodeName \endcsname)+(0,-\tikzumlSDNodeDT ex) node[name=\tikzumlSDNode@nodeName,coordinate] {}; % update last node drawn on sender lifeline \expandafter\xdef\csname tikzumlLastChild@\tikzumlSDNode@objnodeName \endcsname{\tikzumlSDNode@nodeName} } \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: name of the call % op: operation name and input args % return: return value % type: type of the call (synchron, asynchron) % draw, fill, text: colors % padding: 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=\tikzumlCallDefaultDT, name/.initial={call-\thetikzumlCallNum}, op/.initial={}, return/.initial={}, type/.initial=\tikzumlCallDefaultType, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlCallDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, padding/.initial=\tikzumlCallDefaultPadding, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \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=\tikzumlCallDrawColor, fill/.get=\tikzumlCallFillColor, text/.get=\tikzumlCallTextColor } \edef\tikzumlfillcall{\tikzumlCallFillColor} \edef\tikzumldrawcall{\tikzumlCallDrawColor} \edef\tikzumltextcall{\tikzumlCallTextColor} \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 \ifstrequal{\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 \ifstrequal{\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) {}; }{ \ifstrequal{\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{\tikzumlCallDefaultFillColor}{\tikzumlCallFillColor}}{}{ \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,-\tikzumlCallPadding ex) node[font=\tikzumlDefaultFont, text=\tikzumltextcall, midway, right, name=\tikzumlCall@nodeName-op] {\tikzumlCallOp} -- ++(-2.5*\tikzumlCallPadding ex,0); % 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=\tikzumlDefaultFont, 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=\tikzumlDefaultFont, text=\tikzumltextcall, midway, above=-0.4ex, name=\tikzumlCall@nodeName-op] {\tikzumlCallOp}; }{ \draw[\tikzumlcallstyle, \tikzumldrawcall] (st-\tikzumlCall@nodeName.west) -- (et-\tikzumlCall@nodeName.east) node[font=\tikzumlDefaultFont, 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=\tikzumlDefaultFont, 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=\tikzumlDefaultFont, 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: name of fragment % type: type of fragment (opt, alt, break, loop, par, critical, ignore, consider, assert, neg, weak, strict, ref) % label: label of fragment (ex : condition for opt, iterator for loop, ...) % inner xsep, inner 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=\tikzumlFragmentDefaultType, label/.initial=tikzumlEmpty, inner xsep/.initial=\tikzumlFragmentDefaultXSep, inner ysep/.initial=\tikzumlFragmentDefaultYSep, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlFragmentDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \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=\tikzumlFragmentDrawColor, fill/.get=\tikzumlFragmentFillColor, text/.get=\tikzumlFragmentTextColor } \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=\tikzumlFragmentTextColor, font=\tikzumlDefaultFont, anchor=north east, name=\tikzumlFragment@name-type] at (\tikzumlFragment@name-back.north west) {\tikzumlFragmentType}; \node[text=\tikzumlFragmentTextColor, font=\tikzumlDefaultFont, anchor=north west, name=\tikzumlFragment@name-label] at (\tikzumlFragment@name-type.south west) {\tikzumlFragmentLabel}; % draw final fragment box \begin{pgfonlayer}{fragment\thetikzumlFragmentLevel} \node[draw=\tikzumlFragmentDrawColor, fill=\tikzumlFragmentFillColor, outer sep=0, inner sep=0, font=\tikzumlDefaultFont, fit=(\tikzumlFragment@name-back) (\tikzumlFragment@name-type) (\tikzumlFragment@name-label), name=\tikzumlFragment@name] {}; \end{pgfonlayer} \draw[draw=\tikzumlFragmentDrawColor] (\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 % stereo: stereotype of the new object % class: class type of the new object % dt: time delay from last event % name: name of the call % draw, fill, text: colors % no ddots: when used, disable printing of double dots \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=\tikzumlObjectDefaultStereo, class/.initial={}, dt/.initial=\tikzumlCreateCallDefaultDT, name/.initial=call-\thetikzumlCallNum, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlCallDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, draw obj/.initial=\tikzumlDefaultDrawColor, fill obj/.initial=\tikzumlObjectDefaultFillColor, text obj/.initial=\tikzumlDefaultTextColor, no ddots/.is if=tikzumlcreatecallNoDDots, no ddots=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \errmessage{TIKZUML ERROR : in umlcreatecall, invalid option \keyname} } } \pgfkeys{/tikzuml/createcall/.cd, #1} \pgfkeys{/tikzuml/createcall/.cd, x/.get=\tikzumlCreateCallX, stereo/.get=\tikzumlCreateCallStereo, class/.get=\tikzumlCreateCallClass, dt/.get=\tikzumlCreateCallDT, name/.get=\tikzumlCreateCallName, draw/.get=\tikzumlCreateCallDrawColor, fill/.get=\tikzumlCreateCallFillColor, text/.get=\tikzumlCreateCallTextColor, draw obj/.get=\tikzumlCreateCallObjectDrawColor, fill obj/.get=\tikzumlCreateCallObjectFillColor, text obj/.get=\tikzumlCreateCallObjectTextColor } \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\tikzumlCreateCallDTold\tikzumlCreateCallDT \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCreateCallDTold} \edef\tikzumlCreateCallDT{\pgfmathresult} \addtocounter{tikzumlCallStartFragmentNum}{-1} \fi \ifnum\thetikzumlCallEndFragmentNum>0 \let\tikzumlCreateCallDTold\tikzumlCreateCallDT \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCreateCallDTold} \edef\tikzumlCreateCallDT{\pgfmathresult} \addtocounter{tikzumlCallEndFragmentNum}{-1} \fi \ifnum\thetikzumlFragmentPartNum>0 \let\tikzumlCreateCallDTold\tikzumlCreateCallDT \pgfmathparse{0.5*\tikzumlFragment@paddingy+\tikzumlCreateCallDTold} \edef\tikzumlCreateCallDT{\pgfmathresult} \fi % managing parent-child structure \ifnum\thetikzumlCallLevel>0 \let\tikzumlCall@nameold\tikzumlCall@name \def\tikzumlCall@name{\tikzumlCreateCallName} \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{\tikzumlCreateCallName} \fi \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlCreateCall@nodeName{\tikzumlCall@name}}\x \draw (\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname)+(0,-\tikzumlCreateCallDT ex) node[name=st-\tikzumlCreateCall@nodeName, tikzuml activity style] {}; \xdef\tikzumlCreateCallObjectSrc{st-\tikzumlCreateCall@nodeName} \iftikzumlcreatecallNoDDots \umlobject[x=\tikzumlCreateCallX, stereo=\tikzumlCreateCallStereo, class=\tikzumlCreateCallClass, draw=\tikzumlCreateCallObjectDrawColor, fill=\tikzumlCreateCallObjectFillColor, text=\tikzumlCreateCallObjectTextColor, no ddots]{#3} \else \umlobject[x=\tikzumlCreateCallX, stereo=\tikzumlCreateCallStereo, class=\tikzumlCreateCallClass, draw=\tikzumlCreateCallObjectDrawColor, fill=\tikzumlCreateCallObjectFillColor, text=\tikzumlCreateCallObjectTextColor]{#3} \fi \draw (\csname tikzumlLastChild@\tikzumlCreateCallSrc@nodeName \endcsname |- #3)+(0,-0.5*\tikzumlCreateCallDT 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, \tikzumlCreateCallDrawColor] (st-\tikzumlCreateCall@nodeName) -- (#3) node[midway, above, font=\tikzumlDefaultFont, text=\tikzumlCreateCallTextColor, name=\tikzumlCreateCall@nodeName-op] {create}; \end{pgfonlayer} \ifnum\thetikzumlCallLevel=0 \begin{pgfonlayer}{activity} \draw[draw=\tikzumlCreateCallDrawColor, fill=\tikzumlCreateCallFillColor] (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=\tikzumlDefaultDrawColor, -] \newcounter{tikzumlComponentLevel} \newcounter{tikzumlComponentSubComponentNum} \newcounter{tikzumlConnectorNum} \setcounter{tikzumlConnectorNum}{1} \newif\iftikzumlcomponentWithoutCoords \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=\tikzumlDefaultX, y/.initial=\tikzumlDefaultX, width/.initial=\tikzumlComponentDefaultWidth, name/.initial={}, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlComponentDefaultFillColor, text/.initial=\tikzumlDefaultTextColor, style/.style={}, no coords/.is if=tikzumlcomponentWithoutCoords, no coords=false, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{above}\OR \equal{\keyname}{left}\OR \equal{\keyname}{below}\OR \equal{\keyname}{right}\OR \equal{\keyname}{above left}\OR \equal{\keyname}{above right}\OR \equal{\keyname}{below left}\OR \equal{\keyname}{below right} }{ \IfSubStr{\keyvalue}{ of }{ \pgfkeys{/tikzuml/component/.cd, no coords} }{} }{} \ifx\keyvalue\pgfkeysnovalue \pgfkeys{/tikzuml/component/.cd, style/.append style/.expand once={\keyname}} \else \pgfkeys{/tikzuml/component/.cd, style/.append style/.expand twice={\expandafter\keyname\expandafter=\keyvalue}} \fi %\errmessage{TIKZUML ERROR : in umlcomponent, invalid option \keyname} } } \pgfkeys{/tikzuml/component/.cd, #1} \pgfkeys{/tikzuml/component/.cd, x/.get=\tikzumlComponentXShift, y/.get=\tikzumlComponentYShift, width/.get=\tikzumlComponentMinimumWidth, name/.get=\tikzumlComponentName, draw/.get=\tikzumlComponentDrawColor, fill/.get=\tikzumlComponentFillColor, text/.get=\tikzumlComponentTextColor } \ifthenelse{\equal{\tikzumlComponentName}{}}{ \edef\tikzumlComponent@name{#2} }{ \edef\tikzumlComponent@name{\tikzumlComponentName} } \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=\tikzumlComponentXShift cm, yshift=\tikzumlComponentYShift 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 \iftikzumlcomponentWithoutCoords \node[inner ysep=0.5ex, minimum width=\tikzumlComponentMinimumWidth, font=\tikzumlDefaultFont, /tikzuml/component/style] (\tikzumlComponent@nodeName-root) {\phantom{\tikzumlComponent@nodeName}}; \else \node[inner ysep=0.5ex, minimum width=\tikzumlComponentMinimumWidth, font=\tikzumlDefaultFont, /tikzuml/component/style] (\tikzumlComponent@nodeName-root) at (0,0) {\phantom{\tikzumlComponent@nodeName}}; \fi \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=\tikzumlDefaultFont, fit = \csname tikzumlComponentFit\tikzumlComponent@parent @@\tikzumlComponent@fitname\endcsname] (\tikzumlComponent@nodeName-body) {}; \node[above, font=\tikzumlDefaultFont] (\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=\tikzumlComponentDrawColor, fill=\tikzumlComponentFillColor, font=\tikzumlDefaultFont} }; \node[draw=\tikzumlComponentDrawColor, fill=\tikzumlComponentFillColor, name=\tikzumlComponent@nodeName, /tikzuml/component/style, fit=(\tikzumlComponent@nodeName-body) (\tikzumlComponent@nodeName-captiontmp)] {}; \node[font=\tikzumlDefaultFont] (\tikzumlComponent@nodeName-caption) at (\tikzumlComponent@nodeName-captiontmp) {\tikzumlComponent@caption}; \draw (\tikzumlComponent@nodeName-caption.north -| \tikzumlComponent@nodeName.east) node[font=\tikzumlDefaultFont, xshift=-1ex, below=-1ex, name=\tikzumlComponent@nodeName-logo] {\picturedcomponent{draw=\tikzumlComponentDrawColor, fill=\tikzumlComponentFillColor, font=\tikzumlDefaultFont} }; \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 component \newcommand{\umlbasiccomponent}[2][]{\begin{umlcomponent}[#1]{#2} \end{umlcomponent}} \newcommand{\umlrequiredinterface}[2][]{ \def\tikzumlInterfaceWithPort{tikzumlFalse} \pgfkeys{/tikzuml/requiredinterfacerelation/.cd, interface/.initial={}, distance/.initial=\tikzumlRequiredInterfaceDefaultDistance, name/.initial=tikzumlEmpty, width/.initial=\tikzumlRequiredInterfaceDefaultWidth, padding/.initial=\tikzumlRequiredInterfaceDefaultPadding, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlComponentDefaultFillColor, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{with port}}{ \def\tikzumlInterfaceWithPort{tikzumlTrue} }{} } } \pgfkeys{/tikzuml/requiredinterfacerelation/.cd, #1} \pgfkeys{/tikzuml/requiredinterfacerelation/.cd, interface/.get=\tikzumlRequiredInterfaceLabel, distance/.get=\tikzumlRequiredInterfaceDistance, name/.get=\tikzumlRequiredInterfaceName, width/.get=\tikzumlRequiredInterfaceWidth, padding/.get=\tikzumlRequiredInterfacePadding, draw/.get=\tikzumlRequiredInterfaceDrawColor, fill/.get=\tikzumlRequiredInterfaceFillColor } \ifthenelse{\equal{\tikzumlRequiredInterfaceName}{tikzumlEmpty}}{ \edef\tikzumlRequiredInterface@interfacename{#2-east-interface} \edef\tikzumlRequiredInterface@portname{#2-east-port} \edef\tikzumlRequiredInterface@paddingname{#2-east-padding} }{ \edef\tikzumlRequiredInterface@interfacename{\tikzumlRequiredInterfaceName} \edef\tikzumlRequiredInterface@portname{\tikzumlRequiredInterfaceName-port} \edef\tikzumlRequiredInterface@paddingname{\tikzumlRequiredInterfaceName-padding} } \edef\tikzumlRequiredInterface@name{#2} \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlRequiredInterface@nodeName{\tikzumlRequiredInterface@name}}\x \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlRequiredInterface@interfacenodeName{\tikzumlRequiredInterface@interfacename}}\x \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlRequiredInterface@portnodeName{\tikzumlRequiredInterface@portname}}\x \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlRequiredInterface@paddingnodeName{\tikzumlRequiredInterface@paddingname}}\x \ifthenelse{\equal{\tikzumlInterfaceWithPort}{tikzumlTrue}}{ \node[inner sep=0.5*\tikzumlRequiredInterfaceWidth, rectangle, draw=\tikzumlRequiredInterfaceDrawColor, fill=\tikzumlRequiredInterfaceFillColor] (\tikzumlRequiredInterface@portnodeName) 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@interfacenodeName-tmp] {}; \clip (\tikzumlRequiredInterface@interfacenodeName-tmp.north) rectangle (\tikzumlRequiredInterface@interfacenodeName-tmp.south -| \tikzumlRequiredInterface@interfacenodeName-tmp.west); \node[inner sep=0, text width=\tikzumlRequiredInterfaceWidth, circle, draw=\tikzumlRequiredInterfaceDrawColor] (\tikzumlRequiredInterface@interfacenodeName) at (\tikzumlRequiredInterface@interfacenodeName-tmp) {}; \end{scope} \node[above] at (\tikzumlRequiredInterface@interfacenodeName.north) {\tikzumlRequiredInterfaceLabel}; \umlrelation[style={tikzuml connector style}, #1]{\tikzumlRequiredInterface@portnodeName}{\tikzumlRequiredInterface@interfacenodeName} \draw (\tikzumlRequiredInterface@interfacenodeName)+(\tikzumlRequiredInterfacePadding,0) node[name=\tikzumlRequiredInterface@paddingnodeName] {}; % 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@paddingnodeName) (\tikzumlRequiredInterface@portnodeName) } \fi } \newcommand{\umlprovidedinterface}[2][]{ \def\tikzumlInterfaceWithPort{tikzumlFalse} \pgfkeys{/tikzuml/providedinterfacerelation/.cd, interface/.initial={}, distance/.initial=\tikzumlProvidedInterfaceDefaultDistance, name/.initial=tikzumlEmpty, width/.initial=\tikzumlProvidedInterfaceDefaultWidth, padding/.initial=\tikzumlProvidedInterfaceDefaultPadding, draw/.initial=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlComponentDefaultFillColor, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \ifthenelse{\equal{\keyname}{with port}}{ \def\tikzumlInterfaceWithPort{tikzumlTrue} }{} } } \pgfkeys{/tikzuml/providedinterfacerelation/.cd, #1} \pgfkeys{/tikzuml/providedinterfacerelation/.cd, interface/.get=\tikzumlProvidedInterfaceLabel, distance/.get=\tikzumlProvidedInterfaceDistance, name/.get=\tikzumlProvidedInterfaceName, width/.get=\tikzumlProvidedInterfaceWidth, padding/.get=\tikzumlProvidedInterfacePadding, draw/.get=\tikzumlProvidedInterfaceDrawColor, fill/.get=\tikzumlProvidedInterfaceFillColor } \ifthenelse{\equal{\tikzumlProvidedInterfaceName}{tikzumlEmpty}}{ \edef\tikzumlProvidedInterface@interfacename{#2-west-interface} \edef\tikzumlProvidedInterface@portname{#2-west-port} \edef\tikzumlProvidedInterface@paddingname{#2-west-padding} }{ \edef\tikzumlProvidedInterface@interfacename{\tikzumlProvidedInterfaceName} \edef\tikzumlProvidedInterface@portname{\tikzumlProvidedInterfaceName-port} \edef\tikzumlProvidedInterface@paddingname{\tikzumlProvidedInterfaceName-padding} } \edef\tikzumlProvidedInterface@name{#2} \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlProvidedInterface@nodeName{\tikzumlProvidedInterface@name}}\x \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlProvidedInterface@interfacenodeName{\tikzumlProvidedInterface@interfacename}}\x \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlProvidedInterface@portnodeName{\tikzumlProvidedInterface@portname}}\x \begingroup \def\_{_}\edef\x{\endgroup \def\noexpand\tikzumlProvidedInterface@paddingnodeName{\tikzumlProvidedInterface@paddingname}}\x \ifthenelse{\equal{\tikzumlInterfaceWithPort}{tikzumlTrue}}{ \node[inner sep=0.5*\tikzumlProvidedInterfaceWidth, rectangle, draw=\tikzumlProvidedInterfaceDrawColor, fill=\tikzumlProvidedInterfaceFillColor] (\tikzumlProvidedInterface@portnodeName) at (\tikzumlProvidedInterface@nodeName.west) {}; }{ \node[inner sep=0] (\tikzumlProvidedInterface@portnodeName) at (\tikzumlProvidedInterface@nodeName.west) {}; } \draw (\tikzumlProvidedInterface@nodeName)+(-\tikzumlProvidedInterfaceDistance,0) node[inner sep=0, text width=\tikzumlProvidedInterfaceWidth, circle, draw=\tikzumlProvidedInterfaceDrawColor, fill=\tikzumlProvidedInterfaceFillColor, name=\tikzumlProvidedInterface@interfacenodeName] {}; \node[above] at (\tikzumlProvidedInterface@interfacenodeName.north) {\tikzumlProvidedInterfaceLabel}; \umlrelation[style={tikzuml connector style}, #1]{\tikzumlProvidedInterface@portnodeName}{\tikzumlProvidedInterface@interfacenodeName} \draw (\tikzumlProvidedInterface@interfacenodeName)+(-\tikzumlProvidedInterfacePadding,0) node[name=\tikzumlProvidedInterface@paddingnodeName] {}; % 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@paddingnodeName) (\tikzumlProvidedInterface@portnodeName) } \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} \newlength{\tikzuml@AC@labelXShift} \newlength{\tikzuml@AC@labelYShift} \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=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorFillColor] (\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=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorFillColor] (\tikzuml@ACInterface@nodeName-ic) at (\tikzuml@AC@xic,\tikzuml@AC@yic) {}; \end{scope} \pgfmathsetlength{\tikzuml@AC@labelXShift}{0pt} \pgfmathsetlength{\tikzuml@AC@labelYShift}{0pt} \ifthenelse{\equal{\tikzumlAssemblyConnectorLabelPosition}{right}}{ \pgfmathsetlength{\tikzuml@AC@labelXShift}{0.5*\tikzuml@AC@width} }{ \ifthenelse{\equal{\tikzumlAssemblyConnectorLabelPosition}{left}}{ \pgfmathsetlength{\tikzuml@AC@labelXShift}{-0.5*\tikzuml@AC@width} }{ \ifthenelse{\equal{\tikzumlAssemblyConnectorLabelPosition}{above}}{ \pgfmathsetlength{\tikzuml@AC@labelYShift}{0.5*\tikzuml@AC@width} }{ \ifthenelse{\equal{\tikzumlAssemblyConnectorLabelPosition}{below}}{ \pgfmathsetlength{\tikzuml@AC@labelYShift}{-0.5*\tikzuml@AC@width} }{} } } } \node[\tikzumlAssemblyConnectorLabelPosition, font=\tikzumlDefaultFont, xshift=\tikzuml@AC@labelXShift, yshift=\tikzuml@AC@labelYShift] at (\tikzuml@ACInterface@nodeName-interface.center) {\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={}, labelpos/.initial=above, arm1/.initial={auto}, arm2/.initial={auto}, name/.initial=connector-\thetikzumlConnectorNum, width/.initial=1em, anchor1/.initial={}, anchor2/.initial={}, draw/.initial=\tikzumlDefaultDrawColor, fill assembly connector/.initial=\tikzumlAssemblyConnectorDefaultFillColor, fill port/.initial=\tikzumlPortDefaultFillColor, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \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, labelpos/.get=\tikzumlAssemblyConnectorLabelPosition, width/.get=\tikzumlAssemblyConnectorWidth, arm1/.get=\tikzumlAssemblyConnectorStartArm, arm2/.get=\tikzumlAssemblyConnectorEndArm, anchor1/.get=\tikzumlAssemblyConnectorStartAnchorTmp, anchor2/.get=\tikzumlAssemblyConnectorEndAnchorTmp, draw/.get=\tikzumlAssemblyConnectorDrawColor, fill assembly connector/.get=\tikzumlAssemblyConnectorFillColor, fill port/.get=\tikzumlAssemblyConnectorPortFillColor } \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{\tikzumlAssemblyConnectorStartAnchorTmp}{}}{ }{ \def\tikzumlAssemblyConnectorStartAnchor{\tikzumlAssemblyConnectorStartAnchorTmp} } \ifthenelse{\equal{\tikzumlAssemblyConnectorEndAnchorTmp}{}}{ }{ \def\tikzumlAssemblyConnectorEndAnchor{\tikzumlAssemblyConnectorEndAnchorTmp} } \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=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorPortFillColor] (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port) at (\tikzumlAssemblyConnectorStart@nodeName-\tikzumlAssemblyConnectorLabel@nodeName-port-tmp) {}; \node[inner sep=0.5*\tikzumlAssemblyConnectorWidth, rectangle, draw=\tikzumlAssemblyConnectorDrawColor, fill=\tikzumlAssemblyConnectorPortFillColor] (\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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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=\tikzumlDefaultDrawColor, fill/.initial=\tikzumlPortDefaultFillColor, width/.initial=\tikzumlPortDefaultWidth, .unknown/.code={ \let\keyname=\pgfkeyscurrentname \let\keyvalue=\pgfkeyscurrentvalue \errmessage{TIKZUML ERROR : in umlport forbidden option \keyname} } } \pgfkeys{/tikzuml/port/.cd, #1} \pgfkeys{/tikzuml/port/.cd, width/.get=\tikzumlPortWidth, draw/.get=\tikzumlPortDrawColor, fill/.get=\tikzumlPortFillColor} \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=\tikzumlPortDrawColor, fill=\tikzumlPortFillColor] (\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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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 \let\keyvalue=\pgfkeyscurrentvalue \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-umld.sty %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%