%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Start of pgf-umlcd.sty % % Some macros for UML Class Diagrams. % Home page of project: http://pgf-umlcd.googlecode.com/ % Author: Xu Yuan , Humboldt University, Berlin % Style from: http://www.ibm.com/developerworks/cn/rational/r-uml/ % \usetikzlibrary{arrows,shapes.multipart,backgrounds,fit} \tikzstyle{help lines}+=[blue!50,very thin,dashed] \newcommand{\umltextcolor}{black} \newcommand{\umldrawcolor}{purple} \newcommand{\umlfillcolor}{yellow!20} \tikzstyle{umlcolor}=[color=\umldrawcolor,fill=\umlfillcolor,text=\umltextcolor] \tikzstyle{umlcd style}=[umlcolor, >=angle 90] \tikzstyle{package}=[matrix, column sep=1mm, row sep=1cm, node distance=2cm] \tikzstyle{packagename}=[rectangle, minimum height=2em] \tikzstyle{umlcd style implement line}=[color=\umldrawcolor, open triangle 45-,dashed] \tikzstyle{objectline}=[color=\umldrawcolor, diamond->] \tikzstyle{umlcd style inherit line}=[color=\umldrawcolor, open triangle 45-] \tikzstyle{splitline}=[color=\umldrawcolor, dotted,font=\itshape] \tikzstyle{umlcd style class}=[rectangle split, rectangle split parts=3, every text node part/.style={text centered}, draw, minimum height=2em, umlcolor, minimum width=2cm, text width=5cm, minimum height=1cm, node distance=2cm] \tikzstyle{umlcd style dashed line}=[color=\umldrawcolor, >=angle 90,dashed] \tikzstyle{umlcd style school}=[] \newif\ifschool\schoolfalse \DeclareOption{school}{\tikzstyle{umlcd style school}=[rounded corners] \schooltrue} \newif\ifsimplified\simplifiedfalse \DeclareOption{simplified}{\simplifiedtrue} \ProcessOptions\relax % declare layers \pgfdeclarelayer{background} \pgfdeclarelayer{connectionlayers} \pgfsetlayers{background,connectionlayers,main} \newcounter{umlcdClassAttributesNum} \newcounter{umlcdClassOperationsNum} \newcounter{umlcdClassAbstractClassNum} \newcounter{umlcdClassInterfaceNum} \newcounter{umlcdClassSplitPartNum} \def\umlcdPackageFit{} \newenvironment{class}[3][]% { \begin{classAndInterfaceCommon}{#1}{#2}{#3} }% {\calcuateNumberOfParts{} \node[this umlcd style, anchor=north] (\umlcdClassName) at (\umlcdClassPos) {\textbf{\umlcdClassName} \insertAttributesAndOperations{} }; \end{classAndInterfaceCommon} } \newenvironment{interface}[3][]% { \begin{classAndInterfaceCommon}{#1}{#2}{#3} }% {\calcuateNumberOfParts{} \node[this umlcd style, anchor=north] (\umlcdClassName) at (\umlcdClassPos) {$<<$interface$>>$ \\ \textbf{\umlcdClassName} \insertAttributesAndOperations{} }; \end{classAndInterfaceCommon} } \newenvironment{abstractclass}[3][]% { \begin{classAndInterfaceCommon}{#1}{#2}{#3} }% {\calcuateNumberOfParts{} \node[this umlcd style, anchor=north] (\umlcdClassName) at (\umlcdClassPos) {$<<$abstract$>>$ \\ \textbf{\umlcdClassName} \insertAttributesAndOperations{} }; \end{classAndInterfaceCommon} } \newenvironment{object}[3][]% { \begin{classAndInterfaceCommon}{#1}{#2}{#3} }% { % customized \ifsimplified \calcuateNumberOfParts{} \else \ifnum\c@umlcdClassOperationsNum>0 \setcounter{umlcdClassSplitPartNum}{3} \protected@xdef\umlcdSplitPart{3} \else \setcounter{umlcdClassSplitPartNum}{2} \protected@xdef\umlcdSplitPart{2} \fi \fi \node[this umlcd style, anchor=north, umlcd style school] (\umlcdClassName) at (\umlcdClassPos) { \ifschool \textbf{\umlcdClassName} \else \underline{\textbf{\umlcdClassName}} \fi \insertAttributesAndOperations{} }; \end{classAndInterfaceCommon} } \newcommand*{\insertAttributesAndOperations} { \ifnum\c@umlcdClassSplitPartNum>1 \nodepart{second} \fi \umlcdClassAttributes \ifnum\c@umlcdClassSplitPartNum>2 \nodepart{third} \fi \umlcdClassOperations } \newcommand*{\calcuateNumberOfParts} { % calcuate the number of parts \ifsimplified \setcounter{umlcdClassSplitPartNum}{1} \ifnum\c@umlcdClassAttributesNum>0 \stepcounter{umlcdClassSplitPartNum} \fi \ifnum\c@umlcdClassOperationsNum>0 \stepcounter{umlcdClassSplitPartNum} \fi \else \setcounter{umlcdClassSplitPartNum}{3}% three parts by default \fi \protected@xdef\umlcdSplitPart{3} \ifnum\c@umlcdClassSplitPartNum=1 \protected@xdef\umlcdSplitPart{1} \fi \ifnum\c@umlcdClassSplitPartNum=2 \protected@xdef\umlcdSplitPart{2} \fi } \newenvironment*{classAndInterfaceCommon}[3] { \def\umlcdClassName{#2}% \def\umlcdClassPos{#3} \def\umlcdClassAttributes{}% \def\umlcdClassOperations{}% \def\umlcdClassAbstractClass{}% \def\umlcdClassInterface{}% \setcounter{umlcdClassAttributesNum}{0}% \setcounter{umlcdClassOperationsNum}{0}% \setcounter{umlcdClassAbstractClassNum}{0}% \setcounter{umlcdClassInterfaceNum}{0}% \tikzstyle{this umlcd style}=[umlcd style class, rectangle split parts=\umlcdSplitPart, #1] }% { %% connections \begin{pgfonlayer}{connectionlayers} \ifnum\c@umlcdClassAbstractClassNum>0 \foreach \c in {\umlcdClassAbstractClass}{ \draw [umlcd style inherit line] (\c) -- (\umlcdClassName); } \fi \ifnum\c@umlcdClassInterfaceNum>0 \foreach \c in {\umlcdClassInterface}{ \draw [umlcd style implement line] (\c) -- (\umlcdClassName); } \fi \end{pgfonlayer} %% add to fit \let\umlcdPackageFitOld\umlcdPackageFit \protected@xdef\umlcdPackageFit{\umlcdPackageFitOld (\umlcdClassName)} } \newcommand{\attribute}[1]{% \ifnum\c@umlcdClassAttributesNum=0 \protected@xdef\umlcdClassAttributes{#1} \else \let\umlcdClassAttributesOld\umlcdClassAttributes \protected@xdef\umlcdClassAttributes{\umlcdClassAttributesOld \ \newline #1} \fi \stepcounter{umlcdClassAttributesNum} } \newcommand{\operation}[2][1]{% \stepcounter{umlcdClassOperationsNum} \def\virtualoperation{#2} \ifnum0=#1 \def\virtualoperation{\textit{#2}} \fi \ifnum\c@umlcdClassOperationsNum=1 \protected@xdef\umlcdClassOperations{\virtualoperation} \else \let\umlcdClassOperationsOld\umlcdClassOperations \protected@xdef\umlcdClassOperations{\umlcdClassOperationsOld \ \newline \virtualoperation} \fi } \newcommand{\inherit}[1] { \stepcounter{umlcdClassAbstractClassNum} \ifnum\c@umlcdClassAbstractClassNum=1 \protected@xdef\umlcdClassAbstractClass{#1} \else \let\umlcdClassAbstractClassOld\umlcdClassAbstractClass \protected@xdef\umlcdClassAbstractClass{\umlcdClassAbstractClassOld, #1} \fi } \newcommand{\implement}[1] { \stepcounter{umlcdClassInterfaceNum} \ifnum\c@umlcdClassInterfaceNum=1 \protected@xdef\umlcdClassInterface{#1} \else \let\umlcdClassInterfaceOld\umlcdClassInterface \protected@xdef\umlcdClassInterface{\umlcdClassInterfaceOld, #1} \fi } \newcommand{\association}[6]{ \draw [umlcd style] (#1) -- (#4) node[near start, above]{#2} node[near start, below]{#3} node[near end, above]{#5} node[near end, below]{#6}; } \newcommand{\unidirectionalAssociation}[4]{ \draw [umlcd style, ->] (#1) -- (#4) node[near end, above]{#2} node[near end, below]{#3}; } \newcommand{\aggregation}[4] { \draw[umlcd style, open diamond->] (#1) -- (#4) node[near end, above]{#2} node[near end, below]{#3}; } \newcommand{\composition}[4] { \draw[umlcd style, fill=\umldrawcolor, diamond->] (#1) -- (#4) node[near end, above]{#2} node[near end, below]{#3}; } \newenvironment{package}[1]{ \def\umlcdPackageFit{} \def\umlcdPackageName{#1} }{ \begin{pgfonlayer}{background} \node[umlcd style, draw, inner sep=0.5cm, fit = \umlcdPackageFit] (\umlcdPackageName) {}; \node[umlcd style, draw, outer ysep=-0.5, anchor=south west] (\umlcdPackageName caption) at (\umlcdPackageName.north west) {\umlcdPackageName}; \end{pgfonlayer} } \newcommand{\switchUmlcdSchool}{ \ifschool \tikzstyle{umlcd style school}=[] \schoolfalse \else \tikzstyle{umlcd style school}=[rounded corners] \schooltrue \fi } %%% End of pgf-umlcd.sty %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%