% package identification
\def\tb@PACKAGENAME{pgfuml}
\def\tb@VERSION{1 }
\def\tb@DATE{2009/05/04}
\def\tb@AUTHOR{Fabien Dagnat <Fabien.Dagnat@telecom-bretagne.eu>}
\def\tb@PRESENTATION{tikz macros for drawing UML diagrams}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{\tb@PACKAGENAME}[\tb@DATE]
\typeout{^^J\tb@PACKAGENAME\space version \tb@VERSION of \tb@DATE, Author : \tb@AUTHOR^^J}

% requirements
\RequirePackage{pgfextra}% which require tikz
\RequirePackage{pgfoptions}
  \usetikzlibrary{arrows,shapes,calc,fit,backgrounds}
\input{tbpgfshapes} % the needed shapes

\RequirePackage[T1]{fontenc}% for guillemet
\RequirePackage{xkeyval}
\RequirePackage{ifthen}
\RequirePackage{calc}
\RequirePackage{relsize}

%\RequirePackage{debugPGF}

\newlength\uml@xtemp
\newlength\uml@ytemp
\newlength\uml@xa
\newlength\uml@xb
\newlength\uml@diff@x
\newlength\uml@diff@y
\newlength\uml@ya
\newlength\uml@yb
\newlength\uml@ltemp
\newlength\inherit@min@sep
\newlength\inherit@mult@sep

\newlength\uml@dim@z
\setlength\uml@dim@z{1mm}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% user utility macros
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% stereotype macro, put #1 between guillemets
\newcommand*{\stereotype}[1]{\guillemotleft\,#1\,\guillemotright}
% feature of classes typesetting = #1\,#2\,:\,#3 (taking care of empty args)
\newcommand{\feature}[3][]{%
  \def\@temp{#1}%
  \ifx\@temp\@empty%
  \else%
    #1\,%
  \fi%
  #2%
  \def\@temp{#3}%
  \ifx\@temp\@empty%
  \else%
    \,:\,#3%
  \fi%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% internal utility functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% distance between the two points
\newcommand{\pgfuml@distance}[3]{%#1 -> result length #2 -> first length #3 -> second length
  \pgfmathsetlength{#1}{abs(#2-(#3))}
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% CLASS
%%%%
%%%% options are:
%%%%   name, the name of the class
%%%%   label, the label used for the class
%%%%   param, the generic parameter
%%%%   name font, the font for the name part of the class
%%%%   body font, the font for the rest of the class
%%%%   parts, how many parts of the class are displayed
%%%%   stereotype, stereotype for the class
%%%%   width, the minimum width of the class
%%%%   name height, the minimum height of the class name part 
%%%%   abstract, a boolean indicating whether the class is abstract or not
%%%%   interface, a boolean indicating whether the class is an interface or not
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% ifs, counters and co
\newif\ifabstract
\newif\ifinterface

% graphical style for classes and their generic parameters
\pgfkeys{/tikz/uml class/.style={draw,inner xsep=5pt,inner ysep=2pt,class shape}}
\pgfkeys{/tikz/uml param/.style={rectangle,draw,inner sep=0pt,dashed,fill opacity=0.8,minimum width=8mm,minimum height=6mm}}

% class options
\pgfkeys{/pgfuml/class/.is family}
\pgfkeys{/pgfuml/class,%
  name/.store in=\class@name,param/.store in=\class@param,parts/.store in=\class@parts,parts/.value required,%
  label/.initval=pgfuml@class,name font/.initval=\ttfamily\bfseries,body font/.initval=\ttfamily,%
  stereotype/.initval=\pgfkeysnovalue,width/.initval=2cm,name height/.initval=1.5em,%
  fill/.initval=none,param fill/.initval=white,%
  abstract/.is if=abstract,interface/.is if=interface,%
}

% default class options + options given in #1
\newcommand*{\pgfuml@class@SetOptions}[1]{%
  \reinit{/pgfuml/class}{label,fill,param fill,name font,body font,stereotype,width,name height}%
  \pgfkeys{/pgfuml/class,name=,param=,abstract=false,interface=false,parts=0,#1}%
}

% separating parts by closing current tabular, emitting a nodepart and reopening a tabular
% #1 is optional and may contain the name of the part (default is method)
\newcommand{\separator}[1][method]{%
  \end{tabular}%
  \nodepart{#1}%
  \pgfkeysvalueof{/pgfuml/class/body font}%
  \begin{tabular}{@{}l@{}}%
}

% class name part is put in a centered tabular
\newcommand{\pgfuml@class@name}[1]{%
  \pgfkeysvalueof{/pgfuml/class/name font}%
  \begin{tabular}{@{}c@{}}%
    % if it is an interface, the stereotype interface
    \pgfextra@ifnovalue{/pgfuml/class/stereotype}%
    \ifnovalue%
      \ifinterface%
        \stereotype{interface}\\[0.4ex]%
      \else%
      \fi%
    \else%
      \ifinterface%
        \stereotype{interface}\\%
      \else%
      \fi%
      \pgfkeysvalueof{/pgfuml/class/stereotype}\\[0.4ex]%
    \fi%
    #1%
  \end{tabular}%
}

% class body part is put in a left aligned tabular
\newcommand{\pgfuml@class@body}[1]{%
  \pgfkeysvalueof{/pgfuml/class/body font}%
  \begin{tabular}{@{}l@{}}%
    #1%
  \end{tabular}%
}

% if the body of the class is not empty and parts is set to 1, we put it to 2
\newcommand*{\pgfuml@class@SetParts}[1]{%
  \def\uml@temp{#1}%
  \ifx\uml@temp\@empty%
  \else%
    \def\zero{0}
    \ifx\class@parts\zero\relax%
      \def\class@parts{3}%
    \else%
    \fi%
  \fi%
}
% the main macro umlclass takes three arguments:
% #1: a list of options
% #2: a tikz position
% #3: a body for the class
\def\umlclass{\@ifnextchar[\@umlclass{\@umlclass[]}}
\def\@umlclass[#1](#2)#3{%
  \pgfuml@class@SetOptions{#1}%
  % if abstract option has been given add italic to the name font
  \ifabstract%
    \pgfqkeys{/pgfuml/class}{name font/.add={}{\itshape}}%
  \else\fi%
  % if interface option has been given add italic to the name font
  \ifinterface%
    \pgfqkeys{/pgfuml/class}{name font/.add={}{\itshape},}%
  \else\fi%
  \pgfuml@class@SetParts{#3}%
  % The class is drawn using uml class style
  \pgfkeysgetvalue{/pgfuml/class/label}{\class@label}%
  \pgfkeysgetvalue{/pgfuml/class/fill}{\class@fill}
  \pgfkeysgetvalue{/pgfuml/class/width}{\class@width}
  \pgfkeysgetvalue{/pgfuml/class/name height}{\class@height}
  \draw (#2) node[uml class,class parts=\class@parts,minimum width=\class@width,minimum height=\class@height,fill=\class@fill] (\class@label) {%
    \pgfuml@class@name{\class@name}%
    \nodepart{attribute}%
    \pgfuml@class@body{#3}%
  };%
  % Param, if there is one is drawn using uml param style
  \ifx\class@param\@empty\else%
    \pgfkeysgetvalue{/pgfuml/class/param fill}{\class@param@fill}
    \draw (\class@label.north east) node[uml param,fill=\class@param@fill] {\texttt{\class@param}};%
  \fi%
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% OPTIONS FOR RELATIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfoptions@macro@def{asso}%
\pgfoptions@macro@def{relation}%
\pgfoptions@macro@def{inherit}%
\pgfoptions@macro@def{implem}%

% asso and relation options
\pgfoptions@new@boolean@options{inherit,asso,relation,implem}{dashed,D,S,CV,CH,inv route}%
\pgfoptions@new@store@options{inherit,asso,relation,implem}{start shift,end shift}{0mm}%
\pgfoptions@new@store@options{inherit,asso,relation,implem}{sep}{1pt}%
\pgfoptions@new@store@options{inherit,asso,relation,implem}{sepl,sepln}{2pt}%
\pgfoptions@new@store@options{inherit,asso,relation,implem}{C sep}{2cm}%
\pgfoptions@new@boolean@options{asso,relation}{O}%
\pgfoptions@new@store@options{asso,relation}{O anchor}{north east}%
\pgfoptions@new@store@options{asso,relation}{O sep}{1cm}%
\pgfoptions@new@store@options{asso,implem,relation}{name pos,S pos}{0.5}%

\pgfoptions@new@style@options{inherit,implem,relation,asso}{shift}{start shift=#1,end shift=#1}

\pgfoptions@new@store@options{relation}{arrow}{}%

\pgfoptions@new@store@options{asso,implem}{font}{\tikz@textfont}%
\pgfoptions@new@store@options{asso,implem}{name anchor}{}%

\pgfoptions@new@boolean@options{asso}{compo,agre,nav start,nav end}%
\pgfoptions@new@store@options{asso}{name,arity start,arity end,name start,name end}{}%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% RELATION
%%%%
%%%% options are:
%%%%   arrow, 
%%%%   dashed, a boolean indicating whether the association line is dashed
%%%%   D, a boolean indicating whether the association is direct
%%%%   S, a boolean indicating whether the association is a S kind
%%%%   CH, a boolean indicating whether the association is a CH kind
%%%%   CV, a boolean indicating whether the association is a CV kind
%%%%   C sep, the distance between the middle of the two classes and the association line (only for C kind)
%%%%   inv route, a boolean indicating whether the association has to be reversed (see doc)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% drawing the relation line (either through a middle point or direct)
\newif\ifV
\def\pgfuml@sens#1{\@pgfuml@sens#1}
\def\@pgfuml@sens{\@ifnextchar-\@pgfuml@sensh{\@pgfuml@sensv}}
\def\@pgfuml@sensh#1#2{\Vtrue}
\def\@pgfuml@sensv#1#2{\Vfalse}
\newcommand*{\pgfuml@relation@draw@middle}[4]{%#1 -> ext 1 #2 -> line 1 #3 -> line2 #4 -> ext 2
  % determine line endpoints
  \path (#1) #2 (middle) node[pos=0,coordinate] (start) {}  
                  #3 (#4) node[pos=1,coordinate] (end) {};
%  \draw (start) node[fill=magenta,circle,inner sep=0pt,minimum size=2pt] {};
%  \draw (end) node[fill=magenta,circle,inner sep=0pt,minimum size=2pt] {};
  % apply shift corrections
  \pgfuml@shift{#1}{start}{\relation@startshift}{start}%
  \pgfuml@shift{#4}{end}{\relation@endshift}{end}%
  \pgfuml@sens{#2}%
  \ifrelation@O%
  \else%
    \ifV% middle is vertical
      \node[coordinate] (middle) at ([yshift=0.5*\relation@startshift+0.5*\relation@endshift]middle) {};%
    \else% middle is horizontal
      \node[coordinate] (middle) at ([xshift=0.5*\relation@startshift+0.5*\relation@endshift]middle) {};%
    \fi%
  \fi%
  % finally draw the line
  \pgfmathsetmacro{\relation@namepos}{2*\relation@namepos}%
  \ifdim\relation@namepos cm>1cm%
    \pgfmathsetmacro{\relation@namepos}{\relation@namepos-1}%
    \draw[\relation@arrow,\relation@dash] (start) #2 (middle) #3 (end) node[pos=\relation@namepos,coordinate] (name) {};%
  \else%
    \draw[\relation@arrow,\relation@dash] (start) #2 (middle) node[pos=\relation@namepos,coordinate] (name) {} #3 (end) ;%
  \fi%
% \draw (name) node[fill=magenta,circle,inner sep=0pt,minimum size=2pt] {};
}
\newcommand*{\pgfuml@relation@draw@direct}[3]{%#1 -> ext 1 #2 -> -> line #3 -> ext 2
%  \message{draw direct '#1' #2 '#3'}
  % determine line endpoints
  \path (#1) #2 (#3) node[pos=0,coordinate] (start) {} 
                             node[pos=1,coordinate] (end) {};
%   \draw (start) node[fill=green,circle,inner sep=0pt,minimum size=2pt] {};
%   \draw (end) node[fill=green,circle,inner sep=0pt,minimum size=2pt] {};
  %  apply shift corrections
  \pgfuml@shift{#1}{start}{\relation@startshift}{start}%
  \pgfuml@shift{#3}{end}{\relation@endshift}{end}%
%   \draw (start) node[fill=red,circle,inner sep=0pt,minimum size=2pt] {};
%   \draw (end) node[fill=red,circle,inner sep=0pt,minimum size=2pt] {};
  % finally draw the line
  \draw[\relation@arrow,\relation@dash] (start) #2 (end) node[pos=0.5,coordinate] (middle) {}%
  node[pos=\relation@namepos,coordinate] (name) {} ;%
}
\def\@zmm{0mm}
\newcommand*{\pgfuml@shift}[4]{%#1 -> class, #2 -> extremity, #3 -> shift, #4 -> resulting point label
%  \message{shift sur class #1 de #2 d'une distance de #3}
  \expandafter\def\expandafter\pgfuml@temp@shift\expandafter{#3}%
%  \show\pgfuml@temp@shift
  \ifx\pgfuml@shift\@zmm%
  \else%
    \getcoordinate{#1.north east}{\uml@xne}{\uml@yne}%
    \getcoordinate{#1.south west}{\uml@xsw}{\uml@ysw}%
    \getcoordinate{#2}{\uml@xtemp}{\uml@ytemp}%
    \pgfuml@distance{\uml@diff@temp}{\uml@xtemp}{\uml@xne}%
    \ifthenelse{\lengthtest{\uml@diff@temp<\uml@dim@z}}{%
      % EAST
      \node[coordinate] (#4) at ([yshift=#3]#1.east) {};
    }{%
      \pgfuml@distance{\uml@diff@temp}{\uml@xtemp}{\uml@xsw}%
      \ifthenelse{\lengthtest{\uml@diff@temp<\uml@dim@z}}{%
        % WEST
        \node[coordinate] (#4) at ([yshift=#3]#1.west) {};
      }{%
        \pgfuml@distance{\uml@diff@temp}{\uml@ytemp}{\uml@yne}%
        \ifthenelse{\lengthtest{\uml@diff@temp<\uml@dim@z}}{%
          % NORTH
          \node[coordinate] (#4) at ([xshift=#3]#1.north) {};
        }{%
          % SOUTH
          \node[coordinate] (#4) at ([xshift=#3]#1.south) {};
        }%
      }%
    }%
  \fi%
}
\newcommand*{\pgfuml@middle@O}[1]{%#1 -> anchor
  \getcoordinate{#1}{\uml@xtemp}{\uml@ytemp}%
  \ifthenelse{\lengthtest{\uml@xtemp>\uml@xa}}{%
    \ifthenelse{\lengthtest{\uml@ytemp>\uml@ya}}{%
      % NORTH EAST
      \path ($(#1) + (\relation@Osep,\relation@Osep)$) node[coordinate] (middle) {};%
    }{%
      % SOUTH EAST
      \path ($(#1) + (\relation@Osep,-\relation@Osep)$) node[coordinate] (middle) {};%
    }%
  }{%
    \ifthenelse{\lengthtest{\uml@ytemp>\uml@ya}}{%
      % NORTH WEST
      \path ($(#1) + (-\relation@Osep,\relation@Osep)$) node[coordinate] (middle) {};%
    }{%
      % SOUTH WEST
      \path ($(#1) + (-\relation@Osep,-\relation@Osep)$) node[coordinate] (middle) {};%
    }%
  }%
}
% main macro
\def\umlrelation{\@ifnextchar[\@umlrelation{\@umlrelation[]}}
\def\@umlrelation[#1](#2)(#3){%
%  \message{relation(#1) '#2' -- '#3'}
  % reset options and set the given ones
  \pgfoptions@SetOptions{relation}{arrow=,#1}
  \getcoordinate{#2}{\uml@xa}{\uml@ya}%
  \getcoordinate{#3}{\uml@xb}{\uml@yb}%
  % setting line style (dashed, arrow heads, ...)
  %DASH
  \def\relation@dash{}%
  \ifrelation@dashed%
    \def\relation@dash{dashed}%
  \else\fi%
  % calling the right typesetting macro
  \ifrelation@D%
    \pgfuml@relation@draw@direct{#2}{--}{#3}%
  \else%
    \ifrelation@O%
      % O relation kind
      \pgfuml@middle@O{#2.\relation@Oanchor}%
      \pgfuml@relation@draw@middle{#2}{-|}{-|}{#3}%
    \else
      \ifrelation@S%
        % S relation kind
        \draw ($\relation@Spos*(#3) + (#2) - \relation@Spos*(#2)$) node[coordinate] (middle) {};%
% pour S pos       \draw ($1/2*(#2) + 1/2*(#3)$) node[coordinate] (middle) {};%
        \ifrelation@invroute%
          \pgfuml@relation@draw@middle{#2}{|-}{-|}{#3}%
        \else%
          \pgfuml@relation@draw@middle{#2}{-|}{|-}{#3}%
        \fi%
      \else%
        \ifrelation@CV%
          % CV relation kind
          \ifrelation@invroute%
            \draw ([xshift=\relation@Csep]$1/2*(#2) + 1/2*(#3)$) node[coordinate] (middle) {};%
          \else%
            \draw ([xshift=-\relation@Csep]$1/2*(#2) + 1/2*(#3)$) node[coordinate] (middle) {};%
          \fi%
          \pgfuml@relation@draw@middle{#2}{-|}{|-}{#3}%
        \else%
          \ifrelation@CH%
            % CH relation kind
            \ifrelation@invroute%
              \draw ([yshift=-\relation@Csep]$1/2*(#2) + 1/2*(#3)$) node[coordinate] (middle) {};%
            \else%
              \draw ([yshift=\relation@Csep]$1/2*(#2) + 1/2*(#3)$) node[coordinate] (middle) {};%
            \fi%
            \pgfuml@relation@draw@middle{#2}{|-}{-|}{#3}%
          \else
            % It seems that sometimes 0 is not 0...
            % x distance between the two classes 
            \pgfuml@distance{\uml@diff@x}{\uml@xa+\relation@startshift}{\uml@xb+\relation@endshift}
            \ifthenelse{\lengthtest{\uml@diff@x<\uml@dim@z}}{%
              % Vertical
              \pgfuml@relation@draw@direct{#2}{--}{#3}%
            }{
              % y distance between the two classes
              \pgfuml@distance{\uml@diff@y}{\uml@ya+\relation@startshift}{\uml@yb+\relation@endshift}
              \ifthenelse{\lengthtest{\uml@diff@y<\uml@dim@z}}{%
                % Horizontal
                \pgfuml@relation@draw@direct{#2}{--}{#3}%
              }{
                % L relation kind
                \ifrelation@invroute%
                  \pgfuml@relation@draw@direct{#2}{-|}{#3}%
                \else%
                  \pgfuml@relation@draw@direct{#2}{|-}{#3}%
                \fi%
              }
            }
          \fi%CH
        \fi%CV
      \fi%S
    \fi%O
  \fi%D
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% ASSOCIATION
%%%%
%%%% options are those of RELATION:
%%%%   name, the name of the association
%%%%   name anchor, the position of the name of the association
%%%%   arity start, the cardinality at the start of the association
%%%%   arity end, the cardinality at the end of the association
%%%%   name start, the name at the start of the association
%%%%   name end, the name at the end of the association
%%%%   sep, the distance between extremities annotation and the class
%%%%   agre, a boolean indicating whether an aggregation arrow is at the beginning of the association
%%%%   compo, a boolean indicating whether a composition arrow is at the beginning of the association
%%%%   nav start, a boolean indicating whether an arrow is at the beginning of the association
%%%%   nav end, a boolean indicating whether an arrow is at the end of the association
%%%% and those of RELATION:
%%%%   dashed, a boolean indicating whether the line is dashed
%%%%   D, a boolean indicating whether the relation is direct
%%%%   S, a boolean indicating whether the relation is a S kind
%%%%   CH, a boolean indicating whether the relation is a CH kind
%%%%   CV, a boolean indicating whether the relation is a CV kind
%%%%   C sep, the distance between the middle of the two classes and the relation line (only for C kind)
%%%%   inv route, a boolean indicating whether the relation has to be reversed (see doc)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newlength\uml@xne
\newlength\uml@yne
\newlength\uml@xsw
\newlength\uml@ysw
\newlength\uml@diff@temp
\newcommand*{\pgfuml@extremities}[4]{%#1 -> class, #2 -> extremity, #3 -> arity, #4 -> name
%  \message{draw extremity '#2' of class '#1'}
  \getcoordinate{#1.north east}{\uml@xne}{\uml@yne}%
  \getcoordinate{#1.south west}{\uml@xsw}{\uml@ysw}%
  \getcoordinate{#2}{\uml@xtemp}{\uml@ytemp}%
%   \showthe\uml@xne
%   \showthe\uml@xtemp
%   \showthe\uml@yne
%   \showthe\uml@ytemp
  \pgfuml@distance{\uml@diff@temp}{\uml@xtemp}{\uml@xne}%
  \ifthenelse{\lengthtest{\uml@diff@temp<\uml@dim@z}}{%
    % EAST
    \draw ([xshift=\asso@sep,yshift=\asso@sepl]#2) node[above right,font=\asso@font] {#3};
    \draw ([xshift=\asso@sep,yshift=-\asso@sepl]#2) node[below right,font=\asso@font] {#4};
  }{%
    \pgfuml@distance{\uml@diff@temp}{\uml@xtemp}{\uml@xsw}%
    \ifthenelse{\lengthtest{\uml@diff@temp<\uml@dim@z}}{%
      % WEST
      \draw ([xshift=-\asso@sep,yshift=\asso@sepl]#2) node[above left,font=\asso@font] {#3};
      \draw ([xshift=-\asso@sep,yshift=-\asso@sepl]#2) node[below left,font=\asso@font] {#4};
    }{%
      \pgfuml@distance{\uml@diff@temp}{\uml@ytemp}{\uml@yne}%
      \ifthenelse{\lengthtest{\uml@diff@temp<\uml@dim@z}}{%
        % NORTH
        \draw ([yshift=\asso@sep,xshift=-\asso@sepl]#2) node[above left,font=\asso@font] {#3};
        \draw ([yshift=\asso@sep,xshift=\asso@sepl]#2) node[above right,font=\asso@font] {#4};
      }{%
        % SOUTH
        \draw ([yshift=-\asso@sep,xshift=-\asso@sepl]#2) node[below left,font=\asso@font] {#3};
        \draw ([yshift=-\asso@sep,xshift=\asso@sepl]#2) node[below right,font=\asso@font] {#4};
      }%
    }%
  }%
}
\newcommand*{\pgfuml@nameanchor}[1]{%
  \ifx\asso@nameanchor\@empty\relax%
    \def\asso@nameanchor{#1}%
  \else\fi%
}
% Setting association line style
\def\pgfuml@asso@SetLinestyle{
%  \message{Setting style}
  \def\asso@relation@options{}%
  \getOptionSetup{inv route,S,D,CH,CV,dashed,start shift,end shift,sep,sepl,sepln,S pos,C sep,name pos,O,O anchor,O sep}{asso}%
  \pgfoptions@append@list@to@list{\asso@relation@options}{\optionResult}
  %ARROW
  \def\asso@arrow{}%
  \ifasso@agre%
    \def\asso@arrow{open diamond-}%
  \else\fi%
  \ifasso@compo%
    \def\asso@arrow{diamond-}%
  \else\fi%
  \ifasso@navstart%
    \def\asso@arrow{<-}%
  \else\fi%
  \ifasso@navend%
    \ifx\asso@arrow\@empty%
      \def\asso@arrow{->}%
    \else%
      \let\asso@old@arrow=\asso@arrow
      \def\asso@arrow{\asso@old@arrow>}%
    \fi%
  \else\fi%
  \ifx\asso@arrow\@empty%
  \else%
    \pgfoptions@append{arrow=\asso@arrow}{\asso@relation@options}%
  \fi%
%  \message{option to be transmitted are '\asso@relation@options'}
}
% main macro
\def\umlasso{\@ifnextchar[\@umlasso{\@umlasso[]}}
\def\@umlasso[#1](#2)(#3){%
  % reset options and set the given ones
  \pgfoptions@SetOptions{asso}{#1}%
  \ifx\asso@font\@empty%
    \expandafter\def\expandafter\asso@font\expandafter{\tikz@textfont}%
  \else%
  \fi%
  \getcoordinate{#2}{\uml@xa}{\uml@ya}%
  \getcoordinate{#3}{\uml@xb}{\uml@yb}%
  % setting line style (dashed, arrow heads, ...)
  \pgfuml@asso@SetLinestyle
  % calling the right typesetting macro
  \expandafter\umlrelation\expandafter[\asso@relation@options](#2)(#3)%
  % positioning arities and names
  % Test if there is annotation at the start
  \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgfuml@temp\expandafter\expandafter\expandafter{\expandafter\asso@aritystart\asso@namestart}
  \ifx\pgfuml@temp\@empty%
  \else%
    \pgfuml@extremities{#2}{start}{\asso@aritystart}{\texttt{\asso@namestart}}%
  \fi%
  \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgfuml@temp\expandafter\expandafter\expandafter{\expandafter\asso@arityend\asso@nameend}
  \ifx\pgfuml@temp\@empty%
  \else%
    \ifasso@O%
    \else%
      \pgfmathsetlength{\uml@ltemp}{((\uml@xb>\uml@xa)*(\uml@ya>\uml@yb))+((\uml@xa>\uml@xb)*(\uml@yb>\uml@ya))}  
      \ifthenelse{\lengthtest{\uml@ltemp>0mm}}{%
        \pgfuml@extremities{#3}{end}{\texttt{\asso@nameend}}{\asso@arityend}%
      }{%
        \pgfuml@extremities{#3}{end}{\asso@arityend}{\texttt{\asso@nameend}}%
      }%
    \fi%
  \fi%
  \ifasso@O%
    \getcoordinate{name}{\uml@xtemp}{\uml@ytemp}%
    \ifthenelse{\lengthtest{\uml@xtemp>\uml@xa}}{%
      \ifthenelse{\lengthtest{\uml@ytemp>\uml@ya}}{%
        % NORTH EAST
        \pgfuml@nameanchor{above right}%
        \pgfuml@extremities{#3}{end}{\texttt{\asso@nameend}}{\asso@arityend}%
      }{%
        % SOUTH EAST
        \pgfuml@nameanchor{below right}%
        \pgfuml@extremities{#3}{end}{\asso@arityend}{\texttt{\asso@nameend}}%
      }%
    }{%
      \ifthenelse{\lengthtest{\uml@ytemp>\uml@ya}}{%
        % NORTH WEST
        \pgfuml@nameanchor{above left}%
        \pgfuml@extremities{#3}{end}{\asso@arityend}{\texttt{\asso@nameend}}%
      }{%
        % SOUTH WEST
        \pgfuml@nameanchor{below left}%        
        \pgfuml@extremities{#3}{end}{\texttt{\asso@nameend}}{\asso@arityend}%
      }%
    }%
  \else
    \ifasso@S%
      \ifasso@invroute%
        \pgfuml@nameanchor{above}%
      \else%
        \pgfuml@nameanchor{right}%
      \fi%
    \else%
      \ifasso@CV%
        \pgfuml@nameanchor{right}%
      \else%
        \ifasso@CH%
          \pgfuml@nameanchor{above}%
        \else
          % It seems that sometimes 0 is not 0...
          % x distance between the two classes 
          \pgfuml@distance{\uml@diff@x}{\uml@xa+\relation@startshift}{\uml@xb+\relation@endshift}
          \ifthenelse{\lengthtest{\uml@diff@x<\uml@dim@z}}{%
            \pgfuml@nameanchor{right}%
          }{
            % y distance between the two classes
            \pgfuml@distance{\uml@diff@y}{\uml@ya+\relation@startshift}{\uml@yb+\relation@endshift}
            \ifthenelse{\lengthtest{\uml@diff@y<\uml@dim@z}}{%
              \pgfuml@nameanchor{above}%
            }{
              \ifthenelse{\lengthtest{\uml@xb > \uml@xa}}{%
                \ifasso@invroute%
                  \pgfuml@nameanchor{above left}%
                \else%
                  \pgfuml@nameanchor{above right}%
                \fi%
              }{%
                \ifasso@invroute%
                  \pgfuml@nameanchor{above right}%
                \else%
                  \pgfuml@nameanchor{above left}%
                \fi%
              }%
            }
          }
        \fi%CH
      \fi%CV
    \fi%S
  \fi%O
  % finally, the name of the asso in the middle
  \draw (name) node[\asso@nameanchor=\asso@sepln,font=\asso@font] {\textit{\asso@name}};
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% INHERITANCE
%%%%
%%%% options are those of RELATION:
%%%%   dashed, a boolean indicating whether the line is dashed
%%%%   D, a boolean indicating whether the relation is direct
%%%%   S, a boolean indicating whether the relation is a S kind
%%%%   CH, a boolean indicating whether the relation is a CH kind
%%%%   CV, a boolean indicating whether the relation is a CV kind
%%%%   C sep, the distance between the middle of the two classes and the relation line (only for C kind)
%%%%   inv route, a boolean indicating whether the relation has to be reversed (see doc)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% main macro
\def\umlinherit{\@ifnextchar[\@umlinherit{\@umlinherit[]}}
\def\@umlinherit[#1](#2)(#3){%
  % reset options and set the given ones
  \pgfoptions@SetOptions{inherit}{#1}%
  % setting line style (dashed, arrow heads, ...)
  \def\inherit@relation@options{arrow=-open triangle 45}%
  \getOptionSetup{inv route,S,D,CH,CV,dashed,start shift,end shift,C sep}{inherit}%
  \pgfoptions@append@list@to@list{\inherit@relation@options}{\optionResult}%
  % calling the right typesetting macro
  \expandafter\umlrelation\expandafter[\inherit@relation@options](#2)(#3)%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% IMPLEMENTS
%%%%
%%%% options are those of RELATION:
%%%%   dashed, a boolean indicating whether the line is dashed
%%%%   D, a boolean indicating whether the relation is direct
%%%%   S, a boolean indicating whether the relation is a S kind
%%%%   CH, a boolean indicating whether the relation is a CH kind
%%%%   CV, a boolean indicating whether the relation is a CV kind
%%%%   C sep, the distance between the middle of the two classes and the relation line (only for C kind)
%%%%   inv route, a boolean indicating whether the relation has to be reversed (see doc)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% main macro
\def\umlimplem{\@ifnextchar[\@umlimplem{\@umlimplem[]}}
\def\@umlimplem[#1](#2)(#3){%
  % reset options and set the given ones
  \pgfoptions@SetOptions{implem}{#1}%
  \ifx\implem@font\@empty%
    \expandafter\def\expandafter\implem@font\expandafter{\tikz@textfont}%
  \else%
  \fi%
  \getcoordinate{#2}{\uml@xa}{\uml@ya}%
  \getcoordinate{#3}{\uml@xb}{\uml@yb}%
  % setting line style (dashed, arrow heads, ...)
  \def\implem@relation@options{dashed,arrow=-open triangle 45}%
  \getOptionSetup{inv route,S,D,CH,CV,start shift,end shift,C sep,name pos,sepln}{implem}%
  \pgfoptions@append@list@to@list{\implem@relation@options}{\optionResult}%
  % calling the right typesetting macro
  \expandafter\umlrelation\expandafter[\implem@relation@options](#2)(#3)%
  \def\implem@nameanchor{}%
  \ifimplem@D%
  \else%
    \ifimplem@S%
      \ifimplem@invroute%
        \def\implem@nameanchor{above}%
      \else%
      \fi%
    \else%
      \ifimplem@CV%
      \else%
        \ifimplem@CH%
          \def\implem@nameanchor{above}%
        \else
          % It seems that sometimes 0 is not 0...
          % x distance between the two classes
          \pgfuml@distance{\uml@diff@x}{\uml@xa+\relation@startshift}{\uml@xb+\relation@endshift}
          \ifthenelse{\lengthtest{\uml@diff@x<\uml@dim@z}}{%
          }{
            % y distance between the two classes
            \pgfuml@distance{\uml@diff@y}{\uml@ya+\relation@startshift}{\uml@yb+\relation@endshift}
            \ifthenelse{\lengthtest{\uml@diff@y<\uml@dim@z}}{%
              \def\implem@nameanchor{above}%
            }{
              \ifthenelse{\lengthtest{\uml@xb > \uml@xa}}{%
                \ifimplem@invroute%
                  \def\implem@nameanchor{above left}%
                \else%
                  \def\implem@nameanchor{above right}%
                \fi%
              }{%
                \ifimplem@invroute%
                  \def\implem@nameanchor{above right}%
                \else%
                  \def\implem@nameanchor{above left}%
                \fi%
              }%
            }
          }
        \fi%CH
      \fi%CV
    \fi%S
  \fi%D
  % finally, the name of the implem in the middle
  \draw (name) node[\implem@nameanchor=\implem@sepln,font=\implem@font] {\textit{implements}};
}

% obsolete => use umlasso
%\def\umldep(#1)(#2){\draw[dashed,->] (#1) -- (#2);}

\newcommand{\pgfuml@findjoin}[2]{%
  % let's get the classes bounding box
  \def\resultFit{}%
  \@for\@aclass:=#1\do{%
    \edef\resultFit{(\@aclass) \resultFit}%
  }
  \node[fit=\resultFit,inner sep=0pt] (bb) {};%
  % getting the extremes coordinate for positioning
  \getcoordinate{#2.north east}{\uml@xne}{\uml@yne}%
  \getcoordinate{#2.south west}{\uml@xsw}{\uml@ysw}%
  \getcoordinate{bb.north east}{\pgf@xa}{\pgf@ya}%
  \getcoordinate{bb.south west}{\pgf@xb}{\pgf@yb}%
  % let's find the joining point and the arrow kind
  \ifdim\uml@ysw>\pgf@ya%
    % the mother is strictly higher in y
    \setlength\inherit@min@sep{\uml@ysw - \pgf@ya}%
    \draw ([yshift=-0.66\inherit@min@sep]#2.south) node[coordinate] (join) {};
    \def\uml@arrow{|-}
  \else
    \ifdim\pgf@yb>\uml@yne%
      % the mother is strictly lower in y
      \setlength\inherit@min@sep{\pgf@yb - \uml@yne}%
      \draw ([yshift=0.66\inherit@min@sep]#2.north) node[coordinate] (join) {};
      \def\uml@arrow{|-}
    \else
      \ifdim\uml@xsw>\pgf@xa%
        % the mother is strictly higher in x (but not in y)
        \setlength\inherit@min@sep{\uml@xsw - \pgf@xa}%
        \draw ([xshift=-0.66\inherit@min@sep]#2.west) node[coordinate] (join) {};
        \def\uml@arrow{-|}
      \else
        % the mother is strictly lower in x (but not in y)
        \setlength\inherit@min@sep{\pgf@xb - \uml@xne}%
        \draw ([xshift=0.66\inherit@min@sep]#2.east) node[coordinate] (join) {};
        \def\uml@arrow{-|}
      \fi
    \fi
  \fi
}

% several classes (#1) inherit from one class (#2)
\def\umlinheritmult(#1)(#2){%
  % let's find the join point
  \pgfuml@findjoin{#1}{#2}
  % let's draw all the paths
  \draw[-open triangle 45] (join) -- (#2);
  \@for\@aclass:=#1\do{%
    \draw (\@aclass) \uml@arrow (join);
  }
}
% several classes (#1) implements from one interface (#2)
\def\umlimplemmult(#1)(#2){
  % let's find the join point
  \pgfuml@findjoin{#1}{#2}
  % let's draw all the paths
  \draw[dashed,-open triangle 45] (join) -- node {\textit{implements}} (#2);
  \@for\@aclass:=#1\do{%
    \draw[dashed] (\@aclass) \uml@arrow (join);
  }
}

\newcommand{\actor}[2][]{%
  {%
    \begin{tabular}[t]{c}%
      \begin{tikzpicture}[#1]
        \draw (0,1.6) circle (0.3cm);%        la tete
        \draw (0,.65) -- (0,1.3);%    le tronc
        \draw (-0.25,0) -- (0,0.65);% jambe gauche
        \draw (0.25,0) -- (0,0.65);%  jambe droite
        \draw (-0.5,1) -- (0.5,1);%       les bras
      \end{tikzpicture}\\
      #2%
    \end{tabular}%
  }%
}

\def\umlactor{\@ifnextchar[\@umlactor{\@umlactor[]}}
\def\@umlactor[#1](#2)#3{%
  \draw (#2) node (#3) {\actor[#1]{#3}};
}
\define@key[pgfuml]{func}{label}{\def\func@label{#1}}
\define@key[pgfuml]{func}{width}{\def\func@width{#1}}
\presetkeys[pgfuml]{func}{label=,width=}{}
\def\umlfunc{\@ifnextchar[\@umlfunc{\@umlfunc[]}}
\def\@umlfunc[#1](#2)#3{%
  \setkeys[pgfuml]{func}{#1}%
  \ifx\func@label\@empty%
    \ifx\func@width\@empty%
      \draw (#2) node[ellipse,draw] {#3};
    \else%
      \draw (#2) node[ellipse,draw,text width=\func@width,text badly centered] {#3};
    \fi%
  \else%
    \ifx\func@width\@empty%
      \draw (#2) node[ellipse,draw] (\func@label) {#3};
    \else%
      \draw (#2) node[ellipse,draw,text width=\func@width,text badly centered] (\func@label) {#3};
    \fi%
  \fi%
}
\def\umlsyst{\@ifnextchar[\@umlsyst{\@umlsyst[]}}
\def\@umlsyst[#1](#2)#3#4{
  \draw (#2) node[draw,inner xsep=5mm,inner ysep=3mm,rounded corners,#1] {
    \begin{tikzpicture}[color=black,inner sep=2mm,remember picture=true] 
      #4
      \draw ([yshift=-4mm]current bounding box.south) node[anchor=north] {\emph{#3}}; 
    \end{tikzpicture} 
  };
}
\newlength{\seq@pos}
\newlength{\seq@start}
\newlength{\seq@step}
\newlength{\umlstep}
\newlength{\seq@base}
\define@key[pgfuml]{seq}{step}{\setlength\umlstep{#1}\setlength\seq@step{#1}}
\define@key[pgfuml]{seq}{start}{\setlength\seq@start{#1}}
\define@key[pgfuml]{seq}{base}{\setlength\seq@base{#1}}
\define@key[pgfuml]{seq}{font}{\def\seq@font{#1}}
\presetkeys[pgfuml]{seq}{step=10mm,start=5mm,base=0mm,font=\normalsize}{}
\def\diagseq{\@ifnextchar[\@diagseq{\@diagseq[]}}
\def\@diagseq[#1]{%
  \setkeys[pgfuml]{seq}{#1}%
  \setlength{\seq@pos}{\seq@start}
  \begin{tikzpicture}[>=stealth,font=\seq@font,every node/.style={inner sep=3pt}]
}
\def\enddiagseq{%
  \end{tikzpicture}
}
\newcommand*{\umlspace}{\addtolength{\seq@pos}{\seq@step}}
\newcommand*{\umlhalfspace}{\addtolength{\seq@pos}{\seq@step/2}}
\define@key[pgfuml]{selfsend}{label}{\def\selfsend@label{#1}}
\presetkeys[pgfuml]{selfsend}{label=}{}
\def\umlselfsend{\@ifnextchar[\@umlselfsend{\@umlselfsend[]}}
\def\@umlselfsend[#1](#2)#3{
  \setkeys[pgfuml]{selfsend}{#1}%
  \addtolength{\seq@pos}{\seq@step}
  \pgfextractx{\uml@xa}{\pgfpointanchor{#2}{center}}
  \ifx\selfsend@label\@empty\relax
    \draw[-triangle 45,thick] (\uml@xa,\seq@base-\seq@pos) -| ([xshift=5mm]\uml@xa,\seq@base-\seq@pos-0.5\seq@step) node[right] {\smaller\texttt{#3}} |-  (\uml@xa,\seq@base-\seq@pos-\seq@step);
  \else
    \draw[-triangle 45,thick] (\uml@xa,\seq@base-\seq@pos) -| ([xshift=5mm]\uml@xa,\seq@base-\seq@pos-0.5\seq@step) node[right] (\selfsend@label) {\smaller\texttt{#3}} |-  (\uml@xa,\seq@base-\seq@pos-\seq@step);
  \fi
  \addtolength{\seq@pos}{\seq@step}
}
\define@key[pgfuml]{send}{label}{\def\send@label{#1}}
\define@key[pgfuml]{send}{origin}{\def\send@origin{#1}}
\presetkeys[pgfuml]{send}{label=}{}
\presetkeys[pgfuml]{send}{origin=}{}
\def\umlsend{\@ifnextchar[\@umlsend{\@umlsend[]}}
\def\@umlsend[#1](#2)(#3)#4{
  \setkeys[pgfuml]{send}{#1}%
  \addtolength{\seq@pos}{\seq@step}
  \pgfextractx{\uml@xa}{\pgfpointanchor{#2}{center}}
  \pgfextractx{\uml@xb}{\pgfpointanchor{#3}{center}}
  \ifx\send@label\@empty\relax
    \draw[-triangle 45,thick] (\uml@xa,\seq@base-\seq@pos) -- node[pos=0.5,above] {\smaller\texttt{#4}} (\uml@xb,\seq@base-\seq@pos) node[pos=0,coordinate] (\send@origin) {};
  \else
    \draw[-triangle 45,thick] (\uml@xa,\seq@base-\seq@pos) -- node[pos=0.5,above] (\send@label) {\smaller\texttt{#4}} (\uml@xb,\seq@base-\seq@pos) node[pos=0,coordinate] (\send@origin) {};
  \fi
}
\define@key[pgfuml]{resp}{label}{\def\resp@label{#1}}
\presetkeys[pgfuml]{resp}{label=}{}
\def\umlresp{\@ifnextchar[\@umlresp{\@umlresp[]}}
\def\@umlresp[#1](#2)(#3)#4{
  \setkeys[pgfuml]{resp}{#1}%
  \addtolength{\seq@pos}{\seq@step}
  \pgfextractx{\uml@xa}{\pgfpointanchor{#2}{center}}
  \pgfextractx{\uml@xb}{\pgfpointanchor{#3}{center}}
  \ifx\resp@label\@empty
    \draw[-triangle 45,thick,dashed] (\uml@xa,\seq@base-\seq@pos) -- node[pos=0.5,above] {\smaller\texttt{#4}} (\uml@xb,\seq@base-\seq@pos);
  \else
    \draw[-triangle 45,thick,dashed] (\uml@xa,\seq@base-\seq@pos) -- node[pos=0.5,above] (\resp@label) {\smaller\texttt{#4}} (\uml@xb,\seq@base-\seq@pos);
  \fi
}
\define@key[pgfuml]{create}{label}{\def\create@label{#1}}
\presetkeys[pgfuml]{create}{label=}{}
\def\umlcreate{\@ifnextchar[\@umlcreate{\@umlcreate[]}}
\def\@umlcreate[#1](#2)(#3){
  \setkeys*[pgfuml]{create}{#1}%
  \pgfextracty{\uml@ya}{\pgfpointanchor{#2}{center}}
  \ifx\create@label\@empty%
    \stepcounter{classCounter}%
    \edef\create@label{theclass\@arabic\c@classCounter}%
  \else%
  \fi%
  \addtolength{\seq@pos}{\seq@step}
  \umlclass[#1,label=\create@label](#3,\uml@ya-\seq@pos){}
  \draw[-triangle 45,thick] ([yshift=-\seq@pos]#2.center) -- node[above] {\smaller<<create>>} (\create@label);
}
%\def\umldestroy{\@ifnextchar[\@umldestroy{\@umldestroy[]}}
\def\umldestroy(#1)(#2){
  \addtolength{\seq@pos}{\seq@step}
  \pgfextractx{\uml@xa}{\pgfpointanchor{#1}{center}}
  \pgfextractx{\uml@xb}{\pgfpointanchor{#2}{center}}
  \draw[-triangle 45,thick] (\uml@xa,\seq@base-\seq@pos) -- node[pos=0.5,above] {\smaller<<destroy>>} (\uml@xb,\seq@base-\seq@pos);
  \draw (\uml@xb,\seq@base-\seq@pos-\seq@step/3) node[cross out,draw,line width=0.6pt] (fv) {};
  \draw (#2) -- (fv.center);
}
\def\umldefclass{\@ifnextchar[\@umldefclass{\@umldefclass[]}}
\def\@umldefclass[#1](#2){
  \umlclass[#1](#2,\seq@base-\seq@pos+\seq@start){}
}
\def\umlclassend(#1){
  \addtolength{\seq@pos}{0.5\seq@step}
  \@for\@aclass:=#1\do{%
    \pgfextractx{\uml@xa}{\pgfpointanchor{\@aclass}{center}}%
    \begin{pgfonlayer}{background}%
      \draw (\@aclass) -- (\uml@xa,\seq@base-\seq@pos);
    \end{pgfonlayer}%
  }
}
\newlength{\seq@pos@loop@begin}
\newlength{\seq@pos@loop@end}
\def\umlloop#1(#2)(#3)#4{%
  \setlength{\seq@pos@loop@begin}{\seq@pos}
  \addtolength{\seq@pos@loop@begin}{\seq@step/2}
  \addtolength{\seq@pos}{\seq@step/2}
  #4
  \setlength{\seq@pos@loop@end}{\seq@pos}
  \addtolength{\seq@pos@loop@end}{\seq@step/2}
  \draw ([yshift=-\seq@pos@loop@begin,xshift=-3mm]#2) rectangle ([yshift=-\seq@pos@loop@end,xshift=3mm]#3);
  \draw ([yshift=-\seq@pos@loop@begin,xshift=-3mm]#2) node[draw,anchor=north west] {\bf\smaller loop};
  \draw ([yshift=-\seq@pos@loop@begin,xshift=6mm]#2) node[anchor=north west] {\bf\smaller{} [#1]};
}
\newlength{\seq@pos@alt@begin}
\newlength{\seq@pos@alt@middle}
\newlength{\seq@pos@alt@other}
\newlength{\seq@pos@alt@end}
\newlength{\my@width}
\newlength{\my@height}
\define@key[pgfuml]{alt}{label}{\def\alt@label{#1}}
\presetkeys[pgfuml]{alt}{label=}{}
\def\umlalt{\@ifnextchar[\@umlalt{\@umlalt[]}}
\def\@umlalt[#1](#2)(#3)#4#5#6#7{%
  \setkeys[pgfuml]{alt}{#1}%
  \setlength{\seq@pos@alt@begin}{\seq@pos}
  \addtolength{\seq@pos@alt@begin}{\seq@step/2}
  \addtolength{\seq@pos}{\seq@step/2}
  #5
  \setlength{\seq@pos@alt@middle}{\seq@pos}
  \addtolength{\seq@pos@alt@middle}{\seq@step/2}
  \addtolength{\seq@pos}{\seq@step/2}
  #7
  \setlength{\seq@pos@alt@end}{\seq@pos}
  \addtolength{\seq@pos@alt@end}{\seq@step/2}
  \node[coordinate] (le_prem) at ([yshift=-\seq@pos@alt@begin,xshift=-3mm]#2) {X};
  \node[coordinate] (la_fin) at ([yshift=-\seq@pos@alt@end,xshift=3mm]#3) {X};
  \draw (le_prem) rectangle ([yshift=-\seq@pos@alt@middle,xshift=3mm]#3);
  \draw ([yshift=-\seq@pos@alt@middle,xshift=-3mm]#2) rectangle (la_fin);
  \getcoordinate{le_prem}{\pgf@xa}{\pgf@ya}%
  \getcoordinate{la_fin}{\pgf@xb}{\pgf@yb}%
  \setlength{\my@width}{\pgf@xb-\pgf@xa}%
  \setlength{\my@height}{\seq@pos@alt@end-\seq@pos@alt@begin}%
  \path (le_prem) -- node[coordinate] (le_milieu) {} (la_fin);
  \node[minimum width=\my@width,minimum height=\my@height] (\alt@label) at (le_milieu) {};
  \draw (le_prem) node[draw,fill=white,anchor=north west] {\bf\smaller alt};
  \draw ([yshift=-\seq@pos@alt@begin,xshift=6mm]#2) node[anchor=north west] {\bf\smaller{}[#4]};
  \draw ([yshift=-\seq@pos@alt@middle,xshift=6mm]#2) node[anchor=north west] {\bf\smaller{}[#6]};
}
\def\umlaltII(#1)(#2)#3#4#5#6#7#8{%
  \setlength{\seq@pos@alt@begin}{\seq@pos}
  \addtolength{\seq@pos@alt@begin}{\seq@step/2}
  \addtolength{\seq@pos}{\seq@step/2}
  #4
  \setlength{\seq@pos@alt@middle}{\seq@pos}
  \addtolength{\seq@pos@alt@middle}{\seq@step/2}
  \addtolength{\seq@pos}{\seq@step/2}
  #6
  \setlength{\seq@pos@alt@other}{\seq@pos}
  \addtolength{\seq@pos@alt@other}{\seq@step/2}
  \addtolength{\seq@pos}{\seq@step/2}
  #8
  \setlength{\seq@pos@alt@end}{\seq@pos}
  \addtolength{\seq@pos@alt@end}{\seq@step/2}
  \draw ([yshift=-\seq@pos@alt@begin,xshift=-3mm]#1) rectangle ([yshift=-\seq@pos@alt@middle,xshift=3mm]#2);
  \draw ([yshift=-\seq@pos@alt@middle,xshift=-3mm]#1) rectangle ([yshift=-\seq@pos@alt@other,xshift=3mm]#2);
  \draw ([yshift=-\seq@pos@alt@other,xshift=-3mm]#1) rectangle ([yshift=-\seq@pos@alt@end,xshift=3mm]#2);
  \draw ([yshift=-\seq@pos@alt@begin,xshift=-3mm]#1) node[draw,fill=white,anchor=north west] {\bf\smaller alt};
  \draw ([yshift=-\seq@pos@alt@begin,xshift=6mm]#1) node[anchor=north west] {\bf\smaller{}[#3]};
  \draw ([yshift=-\seq@pos@alt@middle,xshift=6mm]#1) node[anchor=north west] {\bf\smaller{}[#5]};
  \draw ([yshift=-\seq@pos@alt@other,xshift=6mm]#1) node[anchor=north west] {\bf\smaller{}[#7]};
}

\newlength\note@width
\newlength\note@height
\define@key[pgfuml]{note}{label}{\def\note@label{#1}}
\define@key[pgfuml]{note}{width}{\setlength\note@width{#1}}
\define@key[pgfuml]{note}{height}{\setlength\note@height{#1}}
\presetkeys[pgfuml]{note}{label=,width=3cm,height=2mm}{}
\def\umlnote{\@ifnextchar[\@umlnote{\@umlnote[]}}
\def\@umlnote[#1](#2)#3{%
  \setkeys[pgfuml]{note}{#1}%
  \ifx\note@label\@empty
    \draw (#2) node[uml note,draw,inner sep=2mm,text badly centered,text width=\note@width,minimum height=\note@height] {#3};
  \else
    \draw (#2) node[uml note,draw,inner sep=2mm,text badly centered,text width=\note@width,minimum height=\note@height] (\note@label) {#3};
  \fi
}


\pgfdeclareshape{uml note}
{
  \inheritsavedanchors[from=rectangle] % this is nearly a rectangle
  \inheritanchorborder[from=rectangle]
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{mid}
  \inheritanchor[from=rectangle]{mid west}
  \inheritanchor[from=rectangle]{mid east}
  \inheritanchor[from=rectangle]{base}
  \inheritanchor[from=rectangle]{base west}
  \inheritanchor[from=rectangle]{base east}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchor[from=rectangle]{south east}
  \foregroundpath{
    % store lower right in xa/ya and upper right in xb/yb
    \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
    \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
    \pgfutil@tempdima=\pgf@xb%
    \pgfutil@tempdimb=\pgf@yb%
    \advance\pgfutil@tempdima by-2mm%
    \advance\pgfutil@tempdimb by-2mm%
    \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
    \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
    \pgfpathlineto{\pgfqpoint{\pgfutil@tempdima}{\pgf@yb}}
    \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgfutil@tempdimb}}
    \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
    \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
    \pgfpathmoveto{\pgfqpoint{\pgfutil@tempdima}{\pgf@yb}}
    \pgfpathlineto{\pgfqpoint{\pgfutil@tempdima}{\pgfutil@tempdimb}}
    \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgfutil@tempdimb}}
 }
}

% %%AFaire :
% % - v\'erifier la syntaxe des lignes de vie
% % - fin de ligne de vie automatique dans diagseq
% % - augmenter cas de test sur le placement relatif

%%% Local Variables: 
%%% mode: latex
%%% ispell-dictionary: "english"
%%% End: 

% LocalWords:  arity arities
