%% %% This is file `messagepassing.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% messagepassing.dtx (with options: `package') %% This is a generated file. %% Copyright (C) 2022 by Martin Vassor %% %% This file may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either %% version 1.3 of this license or (at your option) any later %% version. The latest version of this license is in: %% %% http://www.latex-project.org/lppl.txt %% %% and version 1.3 or later is part of all distributions of %% LaTeX version 2005/12/01 or later. %% \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{messagepassing}[2022/02/18 v1.0 A package to draw message passing diagrams] \RequirePackage{tikz} \usetikzlibrary{quotes, calc, arrows.meta} \RequirePackage{xparse} \RequirePackage{float} \newcounter{processnb} \setcounter{processnb}{0} \newcounter{maxtime} \pgfdeclarelayer{background} \pgfsetlayers{background,main} \newfloat{float_messagepassing}{t b h p}{.mp} \floatname{float_messagepassing}{Execution} \newif\ifmp@vertical\mp@verticalfalse \DeclareOption{vertical}{ \mp@verticaltrue } \newif\ifmp@annotatevertical\mp@annotateverticalfalse \DeclareOption{annotatevertical}{ \mp@annotateverticaltrue } \ProcessOptions\relax \ifmp@vertical \newcommand{\mp@processnameanchor}{south} \newcommand{\mp@timeticksanchor}{east} \newcommand{\mp@messagelabelanchor}{south} \newcommand{\mp@stateintervalanchor}{north west} \newcommand{\mp@checkpointanchor}{east} \newcommand{\mp@verticalrotation}{270} \ifmp@annotatevertical \newcommand{\mp@annotaterotation}{270} \else \newcommand{\mp@annotaterotation}{0} \fi \else \newcommand{\mp@processnameanchor}{east} \newcommand{\mp@timeticksanchor}{north} \newcommand{\mp@messagelabelanchor}{west} \newcommand{\mp@stateintervalanchor}{south west} \newcommand{\mp@checkpointanchor}{north} \newcommand{\mp@verticalrotation}{0} \newcommand{\mp@annotaterotation}{0} \fi \newcommand{\mp@oobcolor}{red} \newcommand{\oobcolor}[1]{ \renewcommand\mp@oobcolor{#1} } \newcommand{\mp@colouredboxcolor}{red} \newcommand{\colouredboxcolor}[1]{ \renewcommand\mp@colouredboxcolor{#1} } \newif\iftimeline \ExplSyntaxOn %% 1st argument: tikz arguments %% 2nd argument: Float caption (turns in floating) %% 3rd argument: Float placement (`p` by default) %% 4th argument: Float label \NewDocumentEnvironment{messagepassing} {o o o o} { \timelinefalse \setcounter{processnb}{0} \IfNoValueTF{#2} { }{ \IfNoValueTF{#3}{ \begin{float_messagepassing}[p] } { \begin{float_messagepassing}[#3] } \begin{center} } \IfNoValueTF{#1}{ \begin{tikzpicture}[rotate=\mp@verticalrotation] } { \begin{tikzpicture}[rotate=\mp@verticalrotation, #1] } }{ %% Draw timeline if boolean is true \iftimeline \begin{pgfonlayer}{background} \setcounter{maxtime}{\@maxtime} \addtocounter{maxtime}{-1} \coordinate (maxtime) at (\@maxtime, 0); \addtocounter{processnb}{1} \coordinate (timeline) at (0, -\value{processnb}); \draw (timeline) node [anchor=\mp@processnameanchor] {{\it time}}; \draw[->] (timeline) -- ($(timeline) + (maxtime)$); \foreach \i in {0,...,\value{maxtime}} { \draw ($(timeline) + (\i, 0) + (0, 0.1)$) -- ($(timeline) + (\i, 0) + (0, -0.1)$) node [anchor=\mp@timeticksanchor] {$\i$}; } \end{pgfonlayer} \else \fi \end{tikzpicture} \IfNoValueTF{#2} { \linebreak } { \end{center} \caption{#2} \IfNoValueTF{#4} { }{ \label{#4} } \end{float_messagepassing} } } \ExplSyntaxOff %% #1: name \newcommand{\newprocess}[1]{ \addtocounter{processnb}{1} \coordinate (#1) at (0, -\value{processnb}); \draw (#1) node[anchor=\mp@processnameanchor] {$#1$}; } %% #1: name %% #2: width \newcommand{\newprocesswithlength}[2]{ \newprocess{#1} \processlength{#1}{#2} } %% #1: name %% #2: state interval name \newcommand{\newprocesswithstateinterval}[2]{ \newprocess{#1} \stateinterval{#1}{0}{#2} } %% #1: name %% #2: width %% #3: crash name \newcommand{\newprocesswithcrash}[3]{ \newprocess{#1}{#2} \crash{#1}{#2}{#3} } %% #1: sender's name %% #2: send date %% #3: receiver's name %% #4: receive date \newcommand{\send}[4]{ \draw[->] (#1) +(#2, 0) -- ($ (#3) +(#4, 0) $); } %% #1: sender's name %% #2: send date %% #3: receiver's name %% #4: receive date %% #5: message name \newcommand{\sendwithname}[5]{ \draw[->] (#1) +(#2, 0) -- ($ (#3) +(#4, 0) $) node[anchor=\mp@messagelabelanchor, pos=0.3] {#5}; } %% #1: process name %% #2: process width \newcommand{\processlength}[2]{ \draw (#1) -- +(#2, 0); } %% #1: sender's name %% #2: send date %% #3: receiver's name %% #4: receive date %% #5: state interval name \newcommand{\sendwithstateinterval}[5] { \send{#1}{#2}{#3}{#4} \stateinterval{#3}{#4}{#5} } %% #1: sender's name %% #2: send date %% #3: receiver's name %% #4: receive date %% #5: state interval name %% #6: message name \newcommand{\sendwithstateintervalandname}[6] { \sendwithname{#1}{#2}{#3}{#4}{#6} \stateinterval{#3}{#4}{#5} } %% #1: sender's name %% #2: send date %% #3: receiver's name %% #4: receive date %% #5: OoB message name \newcommand{\sendoutofband}[5]{ \draw[->, color=\mp@oobcolor] (#1) +(#2, 0) -- ($ (#3) +(#4, 0) $) node[anchor=\mp@messagelabelanchor, pos=0.3] {#5}; } %% #1: process's name %% #2: state interval date %% #3: state interval name \newcommand{\stateinterval}[3] { \stateintervalspecial{#1}{#2}{#3}{#3} } %% #1: process's name %% #2: state interval date %% #3: coordinate name %% #4: state interval label \newcommand{\stateintervalspecial}[4] { \coordinate (#3) at ($ (#1) +(#2, 0) $); \draw (#3) + (0, 0.1) -- +(0, -0.1) node[anchor=\mp@stateintervalanchor] {$#4$}; } %% #1: process's name %% #2: checkpoint date %% #3: checkpoint name \newcommand{\checkpoint}[3]{ \coordinate (#3) at ($ (#1) + (#2, 0) $); \fill (#3) + (-0.05, 0.1) rectangle +(0.05, -0.1); \draw (#3) + (0, -0.1) node[anchor=\mp@checkpointanchor] {$#3$}; } %% #1: process's name %% #2: checkpoint date %% #3: checkpoint coordinate name %% #4: checkpoint label \newcommand{\checkpointspecial}[4]{ \coordinate (#3) at ($ (#1) + (#2, 0) $); \fill (#3) + (-0.05, 0.1) rectangle +(0.05, -0.1); \draw (#3) + (0, -0.1) node[anchor=\mp@checkpointanchor] {#4}; } %% #1: process's name %% #2: crash date %% #3: crash name \newcommand{\crash}[3]{ \coordinate (#3) at ($ (#1) + (#2, 0) $); \draw (#3) + (-0.1, -0.1) -- +(0.1, 0.1); \draw (#3) + (0.1, -0.1) -- +(-0.1, 0.1); } %% #1: process's name %% #2: restart date %% #3: restart length \newcommand{\restart}[3]{ \draw (#1) + (#2, 0) -- ($ (#1) + (#2, 0) + (#3, 0) $); } %% #1: first process's name %% #2: second process's name %% #3: begining of the grey box %% #4: end of the grey box %% #5: caption \newcommand{\colouredbox}[5]{ \begin{pgfonlayer}{background} \fill[color=\mp@colouredboxcolor!20] ($(#1) + (#3, 0)$) rectangle ($(#2) + (#4, 0)$) node[midway, color = \mp@colouredboxcolor, rotate=\mp@annotaterotation]{#5}; \end{pgfonlayer} } %% #1: Timeline length \newcommand{\drawtimeline}[1]{ \timelinetrue \def\@maxtime{#1} } %% #1: process's name %% #2: annotation date %% #3: annotation \newcommand{\annotate}[3]{ \annotatexplicit{#1}{#2}{#3}{#3} } %% Same than annotate, but with the coordinate name provided explicitly %% #1: process's name %% #2: annotation date %% #3: annotation %% #4: coordinate name \newcommand{\annotatexplicit}[4]{ \coordinate (#4) at ($ (#1) +(#2, 0.1) $); \draw (#4) node[rotate=\mp@annotaterotation, anchor=south] {#3}; } \endinput %% %% End of file `messagepassing.sty'.