Skip to content

Instantly share code, notes, and snippets.

@cookieofcode
Last active July 20, 2019 12:23
Show Gist options
  • Save cookieofcode/8a33fd3a64a7bd3f8461173dfb4a2ece to your computer and use it in GitHub Desktop.
Save cookieofcode/8a33fd3a64a7bd3f8461173dfb4a2ece to your computer and use it in GitHub Desktop.
Add divider for the LaTeX TikZ-UML package
\NeedsTeXFormat{LaTeX2e}[1995/12/01]%
\ProvidesPackage{tikz-uml-divider}
%
% define a uml divider 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
% draw, fill, text: colors
% padding: time padding from call start and to call end
\newenvironment{umldivider}[3][]{%
\stepcounter{tikzumlCallNum}%
\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={},%
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,%
padding/.get=\tikzumlCallPadding,%
draw/.get=\tikzumlCallDrawColor, fill/.get=\tikzumlCallFillColor,%
text/.get=\tikzumlCallTextColor%
}%
%
\edef\tikzumlfillcall{\tikzumlCallFillColor}%
\edef\tikzumldrawcall{\tikzumlCallDrawColor}%
\edef\tikzumltextcall{\tikzumlCallTextColor}%
%
\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%
%
%
% top node of activity period of call sender
\begin{pgfonlayer}{connections}%
\pgfmathparse{\tikzumlCallDT+\tikzumlcallSrc}%
\draw (\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname)+(0,-\pgfmathresult ex) node[coordinate, name=tikzumlTmpNode] {};%
\node[tikzuml activity style] (st-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};%
%
% update last node drawn on sender lifeline
\expandafter\xdef\csname tikzumlLastChild@\tikzumlCallStartNodeName \endcsname{st-\tikzumlCall@nodeName}%
%
% top node of activity period of call receiver
\ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{%
\draw (st-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlCallPadding ex) node[coordinate, name=tikzumlTmpNode] {};%
\node[tikzuml activity style] (et-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};%
}{%
\node[tikzuml activity style] (et-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- st-\tikzumlCall@nodeName) {};%
}%
%
% update last node drawn on receiver lifeline
\expandafter\xdef\csname tikzumlLastChild@\tikzumlCallEndNodeName \endcsname{et-\tikzumlCall@nodeName}%
\xdef\tikzumlCallBottomSrc{et-\tikzumlCall@nodeName}%
\end{pgfonlayer}%
%
\stepcounter{tikzumlCallLevel}%
}{%
\addtocounter{tikzumlCallLevel}{-1}%
%
% bottom nodes of activity periods of call sender and receiver
\begin{pgfonlayer}{connections}%
\ifnum\tikzumlCall@lastchildNum=\thetikzumlCallNum%
%
% this test occurs a bug with latex package preview
\ifthenelse{\equal{\tikzumlCallStartNodeName}{\tikzumlCallEndNodeName}}{%
\draw (\tikzumlCallBottomSrc)+(0,-\tikzumlCallPadding ex) node[coordinate, name=tikzumlTmpNode] {};%
\node[tikzuml activity style] (eb-\tikzumlCall@nodeName) at (\tikzumlCallEndNodeName |- tikzumlTmpNode) {};%
\draw (eb-\tikzumlCall@nodeName)+(0,-0.75*\tikzumlCallPadding ex) node[coordinate, name=tikzumlTmpNode] {};%
\node[tikzuml activity style] (sb-\tikzumlCall@nodeName) at (\tikzumlCallStartNodeName |- tikzumlTmpNode) {};%
}{%
\pgfmathsetmacro{\tikzumlCallPaddingd}{0.5*\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}%
%
%
% 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}%
{%
% draw call arrows
\pgfextractx{\tikzumlCall@xa}{\pgfpointanchor{\tikzumlCallStartNodeName}{center}}%
\pgfextractx{\tikzumlCall@xb}{\pgfpointanchor{\tikzumlCallEndNodeName}{center}}%
%
\draw[thick,double] (st-\tikzumlCall@nodeName.west) -- (et-\tikzumlCall@nodeName.east) node[pos=.5, draw, fill=white,align=center] {\tikzumlCallOp};
%
}%
\end{pgfonlayer}%
}%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment