3069 lines
116 KiB
TeX
3069 lines
116 KiB
TeX
%% MSC Macro Package
|
|
%% msc.sty
|
|
%%
|
|
%% Copyright 2022 V. Bos, T. van Deursen, P. Kordy, and S. Mauw
|
|
%
|
|
% This work 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.
|
|
%
|
|
% This work has the LPPL maintenance status `maintained'.
|
|
%
|
|
% The Current Maintainer of this work is P. Kordy
|
|
%
|
|
% This program consists of the files
|
|
% msc.sty
|
|
% manual.tex
|
|
% manual_macros.tex
|
|
% biblio.bib
|
|
% README
|
|
% COPYRIGHT
|
|
|
|
% Contact address:
|
|
% Reynaldo Gil Pons
|
|
% Université du Luxembourg
|
|
% Maison du Nombre
|
|
% 6 Av. de la Fonte
|
|
% L-4364 Esch-sur-Alzette
|
|
% Email: reynaldo.gilpons@uni.lu
|
|
% Website: http://satoss.uni.lu/mscpackage/
|
|
|
|
\def\mscdate{2022/05/13}% update this whenever this file changes
|
|
\def\mscversion{2.00}% update this whenever a new version is ready
|
|
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
|
|
\ProvidesPackage{msc}[\mscdate, v\mscversion]
|
|
\typeout{msc version \mscversion. (\mscdate)}
|
|
\RequirePackage{tikz,xstring,calc}
|
|
\usetikzlibrary{
|
|
positioning,
|
|
fit,
|
|
calc,
|
|
arrows,
|
|
decorations.markings,
|
|
shapes.misc,
|
|
shapes.geometric,
|
|
shapes.symbols
|
|
}
|
|
\pgfdeclarelayer{background} %background for drawing grid
|
|
\pgfsetlayers{background,main}
|
|
|
|
|
|
% {string}{target1}{target2}{code for match}{code for no match}
|
|
\newcommand*{\msc@StrEqEither}[5]{
|
|
\IfEqCase{#1}{{#2}{#4}{#3}{#4}}[#5]
|
|
}
|
|
\newcommand*{\msc@caseFiveEither}[8]{
|
|
\IfEqCase{#1}{{#2}{#7}{#3}{#7}{#4}{#7}{#5}{#7}{#6}{#7}}[#8]
|
|
}
|
|
%\newlength{\msc@textheight}
|
|
%\newlength{\msc@textdepth}
|
|
%\newlength{\msc@textwidth}
|
|
\newsavebox{\msc@box}
|
|
\newcommand{\msc@savebox}[1]{
|
|
\savebox{\msc@box}{\pgfinterruptpicture#1\endpgfinterruptpicture}
|
|
}
|
|
%
|
|
%% \tracingmacros=2 \tracingcommands=2 %used for debugging
|
|
% "msc" is a family
|
|
\pgfkeys{/msc/.is family}
|
|
% set up a search path:
|
|
\pgfkeys{/msc/.search also={/tikz}}
|
|
% \pgfkeys{/msc/message/.search also={/msc}}
|
|
\newif\ifmsc@isstar
|
|
\newif\ifmsc@ismessreplay
|
|
\def\mscset{\pgfqkeys{/msc}}
|
|
\def\mscget#1{\pgfkeysvalueof{/msc/#1}}
|
|
% * Arrow *
|
|
\pgfarrowsdeclare{mscarrow}{mscarrow}
|
|
{
|
|
\pgfmathparse{\pgfgetarrowoptions{mscarrow}}%
|
|
\ifpgfmathunitsdeclared%
|
|
\pgfmathparse{\pgfmathresult pt}%
|
|
\else%
|
|
\pgfmathparse{\pgfmathresult*\pgflinewidth}%
|
|
\fi%
|
|
\let\thickness=\pgfmathresult
|
|
% \edef\msc@thickness=\pgfmathresult
|
|
\pgfutil@tempdima=0.28pt%
|
|
\pgfutil@tempdimb=\pgfmathresult pt
|
|
\ifdim\pgfinnerlinewidth>0pt%
|
|
\pgfmathsetlength\pgfutil@tempdimb{.6\pgfutil@tempdimb-.4*\pgfinnerlinewidth}%
|
|
\fi%
|
|
\advance\pgfutil@tempdima by.3\pgfutil@tempdimb%
|
|
\pgfarrowsleftextend{-3\pgfutil@tempdima}
|
|
\pgfarrowsrightextend{+5\pgfutil@tempdima}
|
|
}
|
|
{
|
|
\pgfmathparse{\pgfgetarrowoptions{mscarrow}}%
|
|
\ifpgfmathunitsdeclared%
|
|
\pgfmathparse{\pgfmathresult pt}%
|
|
\else%
|
|
\pgfmathparse{\pgfmathresult*\pgflinewidth}%
|
|
\fi%
|
|
\let\thickness=\pgfmathresult
|
|
\pgfsetlinewidth{\thickness pt}
|
|
\pgfutil@tempdima=0.28pt%
|
|
\pgfutil@tempdimb=\pgflinewidth%
|
|
\ifdim\pgfinnerlinewidth>0pt%
|
|
\pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}%
|
|
\fi%
|
|
\advance\pgfutil@tempdima by.3\pgfutil@tempdimb%
|
|
\pgfpathmoveto{\pgfqpoint{5\pgfutil@tempdima}{0pt}}
|
|
\pgfpathlineto{\pgfqpoint{-3\pgfutil@tempdima}{4\pgfutil@tempdima}}
|
|
\pgfpathlineto{\pgfpointorigin}
|
|
\pgfpathlineto{\pgfqpoint{-3\pgfutil@tempdima}{-4\pgfutil@tempdima}}
|
|
\pgfusepathqfill
|
|
}
|
|
\newlength{\actionheight} % height of action symbols
|
|
\newlength{\actionwidth} % width of action symbol
|
|
\newlength{\bottomfootdist} % distance between bottom of foot symbol and frame
|
|
\newlength{\msccommentdist} % distance of comment to its instance
|
|
\newlength{\conditionheight} % height of condition symbols
|
|
\newlength{\conditionoverlap} % overlap of condition symbol
|
|
\newlength{\envinstdist} % distance between environments and nearest instance line
|
|
\newlength{\firstlevelheight} % height of level just below head symbols
|
|
\newlength{\gatesymbolradius} % radius of the gate symbol
|
|
\newlength{\hmscconditionheight} % height of hmsc condition symbol
|
|
\newlength{\hmscconditionwidth} % width of hmsc condition symbol
|
|
\newlength{\hmscconnectionradius} % radius of hmsc connection symbols
|
|
\newlength{\hmscreferenceheight} % % height of hmsc and mscdoc reference symbol
|
|
\newlength{\hmscreferencewidth} % width of hmsc and mscdoc reference symbol
|
|
\newlength{\hmscstartsymbolwidth} % width of hmsc start/end symbol
|
|
\newlength{\inlineoverlap} % overlap of inline symbol
|
|
\newlength{\instbarwidth} % default width of vertical instance bars
|
|
\newlength{\instdist} % distance between (vertical) instance lines
|
|
\newlength{\instfootheight} % height of foot symbols
|
|
\newlength{\instheadheight} % height of head symbols
|
|
\newlength{\instwidth} % width of header and foot symbols
|
|
\newlength{\labeldist} % distance between labels and message lines or head symbol boxes
|
|
\newlength{\lastlevelheight} % height of level just above foot symbols
|
|
\newlength{\leftnamedist} % distance between left of frame and (top of) msc title
|
|
\newlength{\levelheight} % height of a level
|
|
\newlength{\lostsymbolradius} % radius of the lost and found symbols
|
|
\newlength{\markdist} % distance between mark and its instance
|
|
\newlength{\measuredist} % user definable length for horizontal measure distance
|
|
\newlength{\measuresymbolwidth} % width of measure symbols
|
|
\newlength{\mscdocreferenceheight} % minimal height of mscdoc reference
|
|
\newlength{\mscdocreferencewidth} % minimal width of mscdoc reference
|
|
\newlength{\referenceoverlap} % overlap of reference symbol
|
|
\newlength{\regionbarwidth} % the width of the coregion start and end symbol
|
|
\newlength{\selfmesswidth} % length of horizontal arms of self messages
|
|
\newlength{\stopwidth} % width of the stop symbol
|
|
\newlength{\timerwidth} % width of the timer symbols
|
|
\newlength{\topheaddist} % distance between top of head symbols and frame
|
|
\newlength{\topnamedist} % distance between top of frame and (top of) msc title
|
|
\mscset{%
|
|
%mscdoc keys
|
|
/msc/mscdoc margin/.code={
|
|
\mscset{
|
|
north mscdoc margin/.initial=#1,
|
|
south mscdoc margin/.initial=#1,
|
|
east mscdoc margin/.initial=#1,
|
|
west mscdoc margin/.initial=#1
|
|
}
|
|
},
|
|
top mscdoc margin/.style={north mscdoc margin=#1},
|
|
bottom mscdoc margin/.style={south mscdoc margin=#1},
|
|
left mscdoc margin/.style={west mscdoc margin=#1},
|
|
right mscdoc margin/.style={east mscdoc margin=#1},
|
|
/msc/mscdoc margin=0.5cm,
|
|
/msc/mscdoc keyword/.initial=mscdoc,
|
|
%hmsc keys
|
|
/msc/hmsc keyword/.initial=hmsc,
|
|
/msc/hmsc margin/.code={
|
|
\mscset{
|
|
north hmsc margin/.initial=#1,
|
|
south hmsc margin/.initial=#1,
|
|
east hmsc margin/.initial=#1,
|
|
west hmsc margin/.initial=#1
|
|
}
|
|
},
|
|
top hmsc margin/.style={north hmsc margin=#1},
|
|
bottom hmsc margin/.style={south hmsc margin=#1},
|
|
left hmsc margin/.style={west hmsc margin=#1},
|
|
right hmsc margin/.style={east hmsc margin=#1},
|
|
/msc/hmsc margin=0.5cm,
|
|
%msc keys
|
|
/msc/msc keyword/.initial=msc,
|
|
/msc/inline overlap/.code={
|
|
\mscset{
|
|
right inline overlap/.initial=#1,
|
|
left inline overlap/.initial=#1
|
|
}
|
|
},
|
|
environment distance/.code={
|
|
\mscset{
|
|
right environment distance/.initial=#1,
|
|
left environment distance/.initial=#1
|
|
}
|
|
}, % distance between environments and the % first level
|
|
/msc/reference overlap/.code={
|
|
\mscset{
|
|
right reference overlap/.initial=#1,
|
|
left reference overlap/.initial=#1
|
|
}
|
|
},
|
|
/msc/message options/.is family, %options for message
|
|
/msc/action options/.is family, %options for action and naction
|
|
/msc/msccomment options/.is family, %options for message comments
|
|
% Default value keys
|
|
/msc/line width/.initial=0.7pt,
|
|
side/.initial=left, %side on which to draw self message
|
|
position/.initial=above, %how to draw mscmark - possible %values:above mid below
|
|
/msc/side/.belongs to family=/msc/message options,
|
|
/msc/side/.belongs to family=/msc/msccomment options,
|
|
/msc/msccomment distance/.belongs to family=/msc/msccomment options,
|
|
/msc/offset/.belongs to family=/msc/msccomment options,
|
|
/msc/offset/.belongs to family=/msc/message options,
|
|
/msc/timer width/.belongs to family=/msc/msccomment options,
|
|
/msc/self message width/.belongs to family=/msc/msccomment options,
|
|
/msc/label distance/.belongs to family=/msc/msccomment options,
|
|
/msc/label position/.initial=above, %position of label in self message
|
|
/msc/label position/.belongs to family=/msc/message options,
|
|
/msc/level shift/.initial=0, %level shift in message
|
|
/msc/offset/.initial=2, %level shift in timers/self message etc
|
|
/msc/dummy text/.initial={ }, %text used for determining the size of dummy node
|
|
/msc/level shift/.belongs to family=/msc/message options,
|
|
/msc/pos/.initial=0.5, %placement of label in message
|
|
/msc/pos/.belongs to family=/msc/message options,
|
|
level offset/.initial=1, %level shift in nextlevel
|
|
level offset/.default=1,
|
|
/tikz/font=\small,
|
|
/msc/draw frame/.initial=, %color of the frame - if "none" we do not draw - "empty" uses last color usually black
|
|
/msc/draw frame/.default=,
|
|
/msc/draw head/.initial=, %color of the instance head
|
|
/msc/draw head/.default=,
|
|
/msc/draw foot/.initial=, %color of the instance foot
|
|
/msc/draw foot/.default=,
|
|
/msc/draw grid/.initial=none, %style to draw help lines - if empty we do
|
|
%not draw, other possible values are "none", "grid" or "color grid"
|
|
/msc/draw grid/.default=grid,
|
|
/msc/draw color grid/.style={draw grid=color grid},
|
|
% the lengths
|
|
fat/.initial=normal,
|
|
fat/.default=fat,
|
|
%sizes
|
|
/tikz/font=\normalsize, % use normal size of font
|
|
action height/.initial=\the\actionheight, % height of action symbols
|
|
action height/.code={\setlength{\actionheight}{#1}},
|
|
action width/.initial=\the\actionwidth, % width of action symbol
|
|
action width/.code={\setlength{\actionwidth}{#1}},
|
|
foot distance/.initial=\the\bottomfootdist, % distance between bottom of foot symbol and frame
|
|
foot distance/.code={\setlength{\bottomfootdist}{#1}},
|
|
msccomment distance/.initial=\the\msccommentdist, % distance of comment to its instance
|
|
msccomment distance/.code={\setlength{\msccommentdist}{#1}}, % distance of comment to its instance
|
|
condition height/.initial=\the\conditionheight, % height of condition symbols
|
|
condition height/.code={\setlength{\conditionheight}{#1}}, % height of condition symbols
|
|
condition overlap/.initial=\the\conditionoverlap, % overlap of condition symbol
|
|
condition overlap/.code={\setlength{\conditionoverlap}{#1}}, % overlap of condition symbol
|
|
first level height/.initial=\the\firstlevelheight, % height of level just below head symbols
|
|
first level height/.code={\setlength{\firstlevelheight}{#1}},
|
|
gate symbol radius/.initial=\the\gatesymbolradius, % radius of the gate symbol
|
|
gate symbol radius/.code={\setlength{\gatesymbolradius}{#1}},
|
|
hmsc condition height/.initial=\the\hmscconditionheight, % height of hmsc condition symbol
|
|
hmsc condition height/.code={\setlength{\hmscconditionheight}{#1}},
|
|
hmsc condition width/.initial=\the\hmscconditionwidth, % width of hmsc condition symbol
|
|
hmsc condition width/.code={\setlength{\hmscconditionwidth}{#1}},
|
|
hmsc connection radius/.initial=\the\hmscconnectionradius, % radius of hmsc connection symbols
|
|
hmsc connection radius/.code={\setlength{\hmscconnectionradius}{#1}},
|
|
reference height/.initial=\the\hmscreferenceheight, % height of hmsc and mscdoc reference symbol
|
|
reference height/.code={\setlength{\hmscreferenceheight}{#1}},
|
|
reference width/.initial=\the\hmscreferencewidth, % width of hmsc and mscdoc reference symbol
|
|
reference width/.code={\setlength{\hmscreferencewidth}{#1}}, % width of hmsc and mscdoc reference symbol
|
|
hmsc symbol width/.initial=\the\hmscstartsymbolwidth, % width of hmsc start/end symbol
|
|
hmsc symbol width/.code={\setlength{\hmscstartsymbolwidth}{#1}}, % width of hmsc start/end symbol
|
|
instance distance/.initial=\the\instdist, % distance between (vertical) instance lines
|
|
instance distance/.code={\setlength{\instdist}{#1}},
|
|
foot height/.initial=\the\instfootheight, % height of foot symbols
|
|
foot height/.code={\setlength{\instfootheight}{#1}},
|
|
head height/.initial=\the\instheadheight, % height of head symbols
|
|
head height/.code={\setlength{\instheadheight}{#1}},
|
|
instance width/.initial=\the\instwidth, % width of header and foot symbols
|
|
instance width/.code={\setlength{\instwidth}{#1}},
|
|
label distance/.initial=\the\labeldist, % distance between labels and message lines or head symbol boxes
|
|
label distance/.code={\setlength{\labeldist}{#1}},
|
|
last level height/.initial=\the\lastlevelheight, % height of level just above foot symbols
|
|
last level height/.code={\setlength{\lastlevelheight}{#1}},
|
|
title distance/.initial=\the\leftnamedist, % distance between left of frame and (top of) msc title
|
|
title distance/.code={\setlength{\leftnamedist}{#1}},
|
|
level height/.initial=\the\levelheight, % height of a level
|
|
level height/.code={\setlength{\levelheight}{#1}},
|
|
lost symbol radius/.initial=\the\lostsymbolradius, % radius of the lost and found symbols
|
|
lost symbol radius/.code={\setlength{\lostsymbolradius}{#1}},
|
|
mark distance/.initial=\the\markdist, % distance between mark and its instance
|
|
mark distance/.code={\setlength{\markdist}{#1}},
|
|
measure distance/.initial=\the\measuredist, % user definable length for horizontal measure distance
|
|
measure distance/.code={\setlength{\measuredist}{#1}},
|
|
measure symbol width/.initial=\the\measuresymbolwidth, % width of measure symbols
|
|
measure symbol width/.code={\setlength{\measuresymbolwidth}{#1}},
|
|
% reference overlap/.initial=\the\referenceoverlap, % overlap of reference symbol
|
|
% reference overlap/.code={\setlength{\referenceoverlap}{#1}},
|
|
region width/.initial=\the\regionbarwidth, % the width of the coregion start and end symbol
|
|
region width/.code={\setlength{\regionbarwidth}{#1}},
|
|
% region width/.initial=0.4cm, % the width of the activation, suspension and coregion rectangle
|
|
self message width/.initial=\the\selfmesswidth, % length of horizontal arms of self messages
|
|
self message width/.code={\setlength{\selfmesswidth}{#1}},
|
|
stop width/.initial=\the\stopwidth, % width of the stop symbol
|
|
stop width/.code={\setlength{\stopwidth}{#1}},
|
|
timer width/.initial=\the\timerwidth, % width of the timer symbols
|
|
timer width/.code={\setlength{\timerwidth}{#1}},
|
|
head top distance/.initial=\the\topheaddist, % distance between top of head symbols and frame
|
|
head top distance/.code={\setlength{\topheaddist}{#1}},
|
|
title top distance/.initial=\the\topnamedist, % distance between top of frame and (top of) msc title
|
|
title top distance/.code={\setlength{\topnamedist}{#1}},
|
|
instance end/.initial=stop, % type of ending for the instance foot (foot or stop) - changed to follow ITU-T Z.120
|
|
title position/.initial=left, % justification of the title: left, right or center
|
|
arrow scale/.initial=1.5, % scale for the
|
|
% arrows
|
|
msc scale/.initial=1, % sets the scale factor
|
|
msc scale/.code={ % that scales everynthing including text but one must be
|
|
\pgfutil@ifundefined{msc@tikzstarted}{\relax}{ % careful with rotation transformations
|
|
\mscset{
|
|
/tikz/scale=#1,
|
|
/tikz/every node/.style={scale=#1}}
|
|
}
|
|
\mscset{msc scale/.initial=#1}
|
|
},
|
|
%Styles
|
|
every instance head/.style={}, % style applied to all instance heads
|
|
every instance foot/.style={}, % style applied to all instance feet
|
|
every instance line/.style={}, % style applied to all instance lines
|
|
every message/.style={}, % style applied to all message arrows
|
|
every msccomment/.style={}, % style applied to all msccomments
|
|
every mscmark/.style={}, % style applied to all mscmarks
|
|
every action/.style={}, % style applied to all actions and nactions
|
|
every action node/.style={}, % style applied to all actions and nactions nodes
|
|
every region/.style={}, % style applied to all regions
|
|
every coregion/.style={}, % style applied to all coregions
|
|
every suspension/.style={}, % style applied to all suspension regions
|
|
every activation/.style={}, % style applied to all activation regions
|
|
every timer/.style={}, % style applied to simple timers
|
|
every measure/.style={}, % style applied to all measures
|
|
every lostfound/.style={}, % style applied to all lost and found messages
|
|
every condition/.style={}, % style applied to all conditions
|
|
every order/.style={}, % style applied to all orders
|
|
every reference/.style={}, % style applied to all references
|
|
every inline/.style={}, % style applied to all inline expressions
|
|
large values/.style={%
|
|
/tikz/font=\normalsize,
|
|
/tikz/line width=0.8pt,
|
|
/msc/line width=0.8pt,
|
|
action height=0.75cm,
|
|
/msc/action height/.belongs to family=/msc/action options,
|
|
action width=1.25cm,
|
|
/msc/action width/.belongs to family=/msc/action options,
|
|
foot distance=1cm,
|
|
msccomment distance=1.5cm,
|
|
condition height=0.75cm,
|
|
condition overlap=0.6cm,
|
|
environment distance=2.5cm,
|
|
first level height=0.75cm,
|
|
gate symbol radius=0.5mm,
|
|
hmsc condition height=0.8cm,
|
|
hmsc condition width=1.6cm,
|
|
hmsc connection radius=0.06cm,
|
|
reference height=0.8cm,
|
|
reference width=1.6cm,
|
|
hmsc symbol width=0.85cm,
|
|
inline overlap=1.5cm,
|
|
instance distance=1.25cm,
|
|
foot height=0.25cm,
|
|
head height=0.6cm,
|
|
instance width=1.75cm,
|
|
label distance=1ex,
|
|
last level height=0.5cm,
|
|
title distance=0.3cm,
|
|
level height=0.75cm,
|
|
lost symbol radius=0.15cm,
|
|
mark distance=1cm,
|
|
measure distance=0.75cm,
|
|
measure symbol width=0.25cm,
|
|
reference overlap=1.5cm,
|
|
region width=0.5cm,
|
|
self message width=0.75cm,
|
|
stop width=0.6cm,
|
|
timer width=0.4cm,
|
|
head top distance=1.5cm,
|
|
title top distance=0.3cm,
|
|
arrow scale=2
|
|
},
|
|
normal values/.style={%
|
|
% /tikz/font=\small,%
|
|
/tikz/line width=0.7pt,
|
|
/msc/line width=0.7pt,
|
|
action height=0.6cm,
|
|
action width=1.25cm,
|
|
foot distance=0.7cm,
|
|
msccomment distance=1.1cm,
|
|
condition height=0.6cm,
|
|
condition overlap=0.5cm,
|
|
environment distance=2cm,
|
|
first level height=0.6cm,
|
|
gate symbol radius=0.5mm,
|
|
hmsc condition height=0.7cm,
|
|
hmsc condition width=1.4cm,
|
|
hmsc connection radius=0.05cm,
|
|
reference height=0.7cm,
|
|
reference width=1.4cm,
|
|
hmsc symbol width=0.7cm,
|
|
inline overlap=1cm,
|
|
instance distance=0.6cm,
|
|
foot height=0.2cm,
|
|
head height=0.55cm,
|
|
instance width=1.6cm,
|
|
label distance=1ex,
|
|
last level height=0.4cm,
|
|
title distance=0.2cm,
|
|
level height=0.5cm,
|
|
lost symbol radius=0.12cm,
|
|
mark distance=1cm,
|
|
measure distance=0.6cm,
|
|
measure symbol width=0.2cm,
|
|
reference overlap=1cm,
|
|
region width=0.4cm,
|
|
self message width=0.6cm,
|
|
stop width=0.5cm,
|
|
timer width=0.3cm,
|
|
head top distance=1.3cm,
|
|
title top distance=0.2cm,
|
|
arrow scale=1.5
|
|
},
|
|
small values/.style={%
|
|
/tikz/font=\small,%
|
|
/tikz/line width=0.6pt,
|
|
/msc/line width=0.6pt,
|
|
action height=0.5cm,
|
|
action width=1.2cm,
|
|
foot distance=0.5cm,
|
|
msccomment distance=0.75cm,
|
|
condition height=0.5cm,
|
|
condition overlap=0.4cm,
|
|
environment distance=1.2cm,
|
|
first level height=0.4cm,
|
|
gate symbol radius=0.5mm,
|
|
hmsc condition height=0.6cm,
|
|
hmsc condition width=1.2cm,
|
|
hmsc connection radius=0.04cm,
|
|
reference height=0.6cm,
|
|
reference width=1.2cm,
|
|
hmsc symbol width=0.4cm,
|
|
inline overlap=0.75cm,
|
|
instance distance=0.3cm,
|
|
foot height=0.15cm,
|
|
head height=0.5cm,
|
|
instance width=1.2cm,
|
|
label distance=0.8ex,
|
|
last level height=0.3cm,
|
|
title distance=0.1cm,
|
|
level height=0.4cm,
|
|
lost symbol radius=0.08cm,
|
|
mark distance=0.4cm,
|
|
measure distance=0.4cm,
|
|
measure symbol width=0.15cm,
|
|
reference overlap=0.75cm,
|
|
region width=0.2cm,
|
|
self message width=0.4cm,
|
|
stop width=0.3cm,
|
|
timer width=0.2cm,
|
|
head top distance=1.2cm,
|
|
title top distance=0.1cm,
|
|
arrow scale=1.2
|
|
},
|
|
/msc/start symbol/.style={draw,/tikz/line width=\mscget{line width},
|
|
inner sep=0,
|
|
isosceles triangle,isosceles triangle apex angle=60,
|
|
shape border rotate=-90,minimum width=\mscget{hmsc symbol width}},
|
|
/msc/end symbol/.style={start symbol,shape border rotate=90},
|
|
%style to %draw hmsc condition
|
|
/msc/condition/.style={draw,/tikz/line width=\mscget{line width},
|
|
minimum width=\mscget{hmsc condition width},
|
|
minimum height=\mscget{hmsc condition height},
|
|
inner sep=0pt,
|
|
signal pointer angle=120,
|
|
signal to=east and west,
|
|
signal},
|
|
/msc/connection/.style={draw,/tikz/line width=\mscget{line width},
|
|
minimum width=2*(\mscget{hmsc connection radius}) + \mscget{line width},
|
|
circle
|
|
},
|
|
/msc/reference/.style={draw,/tikz/line width=\mscget{line width},
|
|
minimum width=\mscget{reference width},
|
|
minimum height=\mscget{reference height},
|
|
inner sep=2pt,
|
|
rounded corners=0.125cm,
|
|
rectangle,
|
|
},
|
|
mscdash/.style={%
|
|
dash pattern=on 4pt off 4pt
|
|
},
|
|
suspension dash/.style={%
|
|
dash pattern=on 7pt off 7pt,
|
|
dash phase=3.5pt
|
|
},
|
|
settimer style/.style={%
|
|
/tikz/line width=\mscget{line width}, draw,
|
|
to path={-- ++(60:#1) -- ++(-#1,0) -- ++(-60:2*#1) -- ++(-#1,0) -- ++(60:#1) -- (\tikztotarget)}
|
|
},
|
|
timeout style/.style={%
|
|
settimer style={#1}, arrow style
|
|
},
|
|
stoptimer style/.style={%
|
|
/tikz/line width=\mscget{line width}, draw,
|
|
to path={ ++(0.5*#1,0.5*#1) -- ++(-#1,-#1) ++(0,#1) -- ++(#1,-#1) ++(-0.5*#1,0.5*#1) -- (\tikztotarget)}
|
|
},
|
|
set mscarrow thickness/.code={
|
|
\pgfsetarrowoptions{mscarrow}{#1}},
|
|
arrow style/.default=\mscget{arrow scale}*\mscget{line width},
|
|
arrow style/.style={set mscarrow thickness=#1,
|
|
shorten >=\mscget{line width}/2,
|
|
-mscarrow
|
|
},
|
|
instance head/.style={%
|
|
rectangle,
|
|
text height=1.5ex,%
|
|
inner sep=2pt,
|
|
% text width=\mscget{instance width}, text centered,%uncomment to get old behaviour
|
|
% transform shape,
|
|
/tikz/line width=\mscget{line width},
|
|
minimum height=\mscget{head height},%
|
|
minimum width=\mscget{instance width},%
|
|
label={[text height=1.5ex,text depth=0ex,
|
|
inner sep=0pt, /tikz/label distance=\mscget{label
|
|
distance}-\mscget{line width}-0.1ex]above:#1}%
|
|
},
|
|
replay/.style={%
|
|
/tikz/line width=\mscget{line width},
|
|
line cap=butt,
|
|
mscdash
|
|
},
|
|
msccomment/.style={%
|
|
/tikz/line width=\mscget{line width},
|
|
line cap=round,
|
|
},
|
|
msccomment line/.style={%
|
|
mscdash
|
|
},
|
|
message/.style={%
|
|
/tikz/line width=\mscget{line width},
|
|
arrow style,
|
|
line cap=round,
|
|
},
|
|
%action/.style={%
|
|
%/tikz/line width=\mscget{line width},
|
|
%line cap=round,
|
|
%},
|
|
instance line/.style={%
|
|
/tikz/line width=\mscget{line width},
|
|
draw,%orange
|
|
% line cap=round
|
|
},
|
|
message loop/.default=\mscget{self message width},
|
|
message loop/.style={%
|
|
to path={-- ++(#1,0) coordinate (msc@somepoint) -- (msc@somepoint |-
|
|
\tikztotarget) \tikztonodes -- (\tikztotarget)}
|
|
},
|
|
order loop/.default=\mscget{self message width},
|
|
order loop/.style={%
|
|
set mscarrow thickness=\mscget{arrow scale}*\mscget{line width},
|
|
decoration={markings, mark=at position \mscget{pos} with {\arrow{mscarrow}}},
|
|
/tikz/line width=\mscget{line width},postaction={decorate},
|
|
line cap=round,
|
|
mscdash,
|
|
to path={-- ++(#1,0) coordinate (msc@somepoint) -- (msc@somepoint |-
|
|
\tikztotarget) \tikztonodes -- (\tikztotarget)}
|
|
},
|
|
order/.style={%
|
|
set mscarrow thickness=\mscget{arrow scale}*\mscget{line width},
|
|
decoration={markings, mark=at position \mscget{pos} with {\arrow{mscarrow}}},
|
|
/tikz/line width=\mscget{line width},postaction={decorate},
|
|
line cap=round,
|
|
mscdash,
|
|
},
|
|
settimeout style/.default={\mscget{self message width}}{\mscget{timer width}},
|
|
settimeout style/.style 2 args={/msc,
|
|
/tikz/line width=\mscget{line width}, draw, arrow style,
|
|
to path={-- ++(#1,0) coordinate (msc@somepoint) -- ++(60:#2) --
|
|
++(-#2,0)--++(-60:2*#2) coordinate (msc@somepoin) -- ++(-#2,0) --(msc@somepoint)
|
|
($ (msc@somepoint)!0.866*#2!(\tikztotarget-|msc@somepoint) $) --
|
|
(\tikztotarget-|msc@somepoint) -> (\tikztotarget)
|
|
}
|
|
},
|
|
setstoptimer style/.default={\mscget{self message width}}{\mscget{timer width}},
|
|
setstoptimer style/.style 2 args={/msc,
|
|
/tikz/line width=\mscget{line width}, draw,
|
|
to path={-- ++(#1,0) coordinate (msc@somepoint) -- ++(60:#2) --
|
|
++(-#2,0)--++(-60:2*#2) coordinate (msc@somepoin) -- ++(-#2,0) --(msc@somepoint)
|
|
($ (msc@somepoint)!0.866*#2!(\tikztotarget-|msc@somepoint) $) --
|
|
(\tikztotarget-|msc@somepoint) ++(0.5*#2,0.5*#2) -- ++(-#2,-#2)
|
|
++(0,#2) -- ++(#2,-#2) ++(-0.5*#2,0.5*#2) --
|
|
(\tikztotarget)
|
|
}},
|
|
measure style/.default={\mscget{measure distance}}{\mscget{measure symbol width}},
|
|
measure style/.style 2 args={%
|
|
/tikz/line width=\mscget{line width}, mscdash,
|
|
to path={-- ++(#1,0) coordinate (a)
|
|
($ (a)!0.866*#2!(\tikztotarget-|a)$) -- ($(\tikztotarget-|a) !0.866*#2!(a) $)
|
|
(a|-\tikztotarget) \tikztonodes coordinate (b) -- (\tikztotarget)
|
|
\pgfextra{ \path[draw,/msc/mscdash,/tikz/line width=\mscget{line width}];}
|
|
(a)--($ (a)!#2!30:(\tikztotarget-|a)$) coordinate (a1)--($ (a1)!#2!60:(a)$) --cycle(a)
|
|
(b)--($ (b)!#2!30:(a)$) coordinate (b1)--($ (b1)!#2!60:(b)$) --cycle(b)
|
|
\pgfextra{ \path[draw,solid,/tikz/line width=\mscget{line width}];}
|
|
(\tikztotarget)
|
|
}},
|
|
measure* style/.default={\mscget{measure distance}}{\mscget{measure symbol width}},
|
|
measure* style/.style 2 args={%
|
|
/tikz/line width=\mscget{line width}, mscdash,
|
|
to path={
|
|
-- ++(#1,0) coordinate (a)-- (\tikztotarget-|a) coordinate (b)\tikztonodes
|
|
-- (\tikztotarget)
|
|
\pgfextra{ \path[draw,/msc/mscdash,/tikz/line width=\mscget{line width}];}
|
|
(a)--($ (a)!#2!210:(b)$) coordinate (a1)--($ (a1)!#2!60:(a)$) --cycle(a)
|
|
(b)--($ (b)!#2!210:(a)$) coordinate (b1)--($ (b1)!#2!60:(b)$) --cycle(b)
|
|
\pgfextra{ \path[draw,solid,/tikz/line width=\mscget{line width}];}
|
|
(\tikztotarget)
|
|
}},
|
|
measurestart style/.default={\mscget{measure distance}}{\mscget{measure symbol width}},
|
|
measurestart style/.style 2 args={%
|
|
/tikz/line width=\mscget{line width}, mscdash,
|
|
to path={
|
|
-- ++(#1,0) coordinate (a)
|
|
($ (a)!0.866*#2!(\tikztotarget-|a)$)-- ($(\tikztotarget-|a)! 0.5*#2!(a) $) \tikztonodes
|
|
(\tikztotarget -| a) coordinate (b)
|
|
\pgfextra{ \path[draw,/msc/mscdash,/tikz/line width=\mscget{line width}];}
|
|
(a)--($ (a)!#2!30:(\tikztotarget-|a)$) coordinate (a1)--($ (a1)!#2!60:(a)$) --cycle(a)
|
|
(b) circle (0.5*#2)
|
|
\pgfextra{ \path[draw,solid,/tikz/line width=\mscget{line width}];}
|
|
(\tikztotarget)
|
|
}},
|
|
measurestart* style/.default={\mscget{measure distance}}{\mscget{measure symbol width}},
|
|
measurestart* style/.style 2 args={%
|
|
/tikz/line width=\mscget{line width}, mscdash,
|
|
to path={
|
|
-- ++(#1,0) coordinate (a) -- ($(\tikztotarget-|a)! 0.5*#2!(a) $) \tikztonodes
|
|
(\tikztotarget -| a) coordinate (b)
|
|
\pgfextra{ \path[draw,/msc/mscdash,/tikz/line width=\mscget{line width}];}
|
|
(a)--($ (a)!#2!210:(b)$) coordinate (a1)--($ (a1)!#2!60:(a)$) --cycle(a)
|
|
(b) circle (0.5*#2)
|
|
\pgfextra{ \path[draw,solid,/tikz/line width=\mscget{line width}];}
|
|
(\tikztotarget)
|
|
}},
|
|
found style/.default={2*\mscget{lost symbol radius}},
|
|
found style/.style={%
|
|
/msc, /tikz/line width=\mscget{line width},arrow style,
|
|
to path={
|
|
(\tikztotarget) circle (0.5*#1)
|
|
\pgfextra{ \path[draw,solid,/tikz/line width=\mscget{line width}];}
|
|
($ (\tikztotarget)! 0.5*#1 !(\tikztostart) $) -> (\tikztostart)
|
|
\tikztonodes
|
|
}},
|
|
lost style/.default={2*\mscget{lost symbol radius}},
|
|
lost style/.style={%
|
|
/msc, /tikz/line width=\mscget{line width},arrow style,
|
|
to path={
|
|
(\tikztotarget) circle (0.5*#1)
|
|
\pgfextra{ \path[draw,solid,fill,/tikz/line width=\mscget{line width}];}
|
|
(\tikztostart) -> ($ (\tikztotarget)! 0.50*#1 !(\tikztostart) $)
|
|
\tikztonodes
|
|
}},
|
|
}
|
|
\mscset{normal values}
|
|
%special treatments of keys that can be specified as right or left but could not
|
|
%be in the old verison of msc
|
|
\setlength{\envinstdist}{\mscget{left environment distance}}
|
|
\setlength{\inlineoverlap}{\mscget{left inline overlap}}
|
|
\setlength{\referenceoverlap}{\mscget{left reference overlap}}
|
|
\mscset{
|
|
left environment distance/.initial=\the\envinstdist, % distance between environments and the % first level
|
|
right environment distance/.initial=\the\envinstdist, % distance between
|
|
left inline overlap/.initial=\the\inlineoverlap,
|
|
right inline overlap/.initial=\the\inlineoverlap,
|
|
left reference overlap/.initial=\the\referenceoverlap,
|
|
right reference overlap/.initial=\the\referenceoverlap
|
|
}
|
|
\def\msc@save@target#1{%
|
|
\def\msc@target{#1}}
|
|
\def\msc@save@start#1{%
|
|
\def\msc@start{#1}}
|
|
%defining styles to draw grid with help lines - usage e.g. \draw (0,-10) to[/msc/color grid] (10,0);
|
|
\mscset{
|
|
/msc/grid/.style={
|
|
to path={%
|
|
\pgfextra{%
|
|
\edef\msc@@target{(\tikztotarget)}%
|
|
\tikz@scan@one@point\msc@save@target\msc@@target\relax
|
|
\edef\msc@@start{(\tikztostart)}%
|
|
\tikz@scan@one@point\msc@save@start\msc@@start\relax
|
|
\draw[/msc/grid/minor lines] (\tikztostart) grid (\tikztotarget);
|
|
\draw[/msc/grid/major lines,line cap=rect] (\tikztostart) grid (\tikztotarget);
|
|
\msc@start
|
|
\pgfmathsetmacro{\msc@xa}{\the\pgf@x/1cm}
|
|
\pgfmathsetmacro{\msc@ya}{\the\pgf@y/1cm}
|
|
\msc@target
|
|
\pgfmathsetmacro{\msc@xb}{\the\pgf@x/1cm}
|
|
\pgfmathsetmacro{\msc@yb}{\the\pgf@y/1cm}
|
|
\pgfmathsetmacro{\msc@xc}{\msc@xa + \mscget{grid/major step}}
|
|
\pgfmathsetmacro{\msc@yc}{\msc@ya + \mscget{grid/major step}}
|
|
\foreach \x in {\msc@xa,\msc@xc,...,\msc@xb}
|
|
\node[/msc/grid/x labelstyle] at (\x,\msc@ya) {\pgfmathprintnumber{\x}};
|
|
\foreach \y in {\msc@ya,\msc@yc,...,\msc@yb}
|
|
\node[/msc/grid/y labelstyle] at (\msc@xa,\y) {\pgfmathprintnumber{\y}};
|
|
}
|
|
}
|
|
},
|
|
/msc/color grid/.style={
|
|
/msc/grid/labelstyle/.style={font=\tiny,text=blue},
|
|
/msc/grid/minor line width=0.2pt,
|
|
/msc/grid/major line width=0.4pt,
|
|
/msc/grid/minor lines/.style={
|
|
draw=green!10,line cap=rect,
|
|
/tikz/line width=\mscget{grid/minor line width},
|
|
step=\mscget{grid/minor step}
|
|
},
|
|
/msc/grid/major lines/.style={
|
|
draw=red!10,line cap=rect,
|
|
/tikz/line width=\mscget{grid/major line width},
|
|
step=\mscget{grid/major step}
|
|
},
|
|
/msc/grid
|
|
},
|
|
/msc/grid/.cd,
|
|
minor lines/.style={
|
|
help lines,line cap=rect,dotted,
|
|
step=\mscget{grid/minor step}
|
|
},
|
|
major lines/.style={
|
|
help lines,line cap=rect,
|
|
/tikz/line width=\mscget{grid/major line width},
|
|
step=\mscget{grid/major step}
|
|
},
|
|
labelstyle/.style={font=\scriptsize,text=black},
|
|
x labelstyle/.style={/msc/grid/labelstyle,below},
|
|
y labelstyle/.style={/msc/grid/labelstyle,left},
|
|
minor step/.initial=.2,
|
|
major step/.initial=1,
|
|
minor line width/.initial=0.3pt,
|
|
major line width/.initial=0.5pt,
|
|
}
|
|
% And some internal counters
|
|
\newcount\c@mscinstcnt %number of intstances
|
|
\newcount\c@condition %number of conditions
|
|
\newcount\c@msclevelcnt %current level
|
|
% \newcount\c@maxlevelcnt %maximum level seen
|
|
%\advance\c@mscinstcnt by1
|
|
\global\let\msc@tempa\relax
|
|
\global\let\msc@tempb\relax
|
|
%\newdimen\msc@x
|
|
%\newdimen\msc@y
|
|
|
|
\newcommand{\mscgetx}[2]{%
|
|
\tikz@scan@one@point\pgfutil@firstofone#1\relax
|
|
\edef#2{\the\pgf@x}%
|
|
}
|
|
|
|
\newcommand{\mscgety}[2]{%
|
|
\tikz@scan@one@point\pgfutil@firstofone#1\relax
|
|
\edef#2{\the\pgf@y}%
|
|
}
|
|
|
|
% store the shifted level in #2 and level at which to draw message in #3
|
|
% also update \c@maxlevelcnt
|
|
% #1 - level difference
|
|
\def\msc@getlevel shift#1#2#3{
|
|
\pgfkeys{/pgf/number format/precision=0}
|
|
\pgfmathparse{\the\c@msclevelcnt + #1}
|
|
\pgfmathparse{max(\pgfmathresult,0)}
|
|
\pgfmathroundto{\pgfmathresult}
|
|
\edef#2{\pgfmathresult} %calculate destination level
|
|
\pgfmathparse{max((\the\c@msclevelcnt),#2)}
|
|
\pgfmathroundto{\pgfmathresult}
|
|
\xdef#3{\pgfmathresult} %calculate at which level to draw message
|
|
\pgfmathparse{max(#3,\c@maxlevelcnt)}
|
|
\pgfmathroundto{\pgfmathresult}
|
|
\xdef\c@maxlevelcnt{\pgfmathresult} %update global max level counter
|
|
}
|
|
|
|
%
|
|
% * Shapes *
|
|
%
|
|
%
|
|
%% A rectangle with right side open
|
|
%
|
|
\pgfdeclareshape{right open rectangle}
|
|
{%
|
|
\nodeparts{text}
|
|
%%
|
|
%% Anchors
|
|
%%
|
|
\inheritsavedanchors[from=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}
|
|
\backgroundpath{
|
|
% 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
|
|
\pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
|
|
\pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
|
|
\pgfpathclose
|
|
}
|
|
}
|
|
%
|
|
%% A rectangle with left side open
|
|
%
|
|
\pgfdeclareshape{left open rectangle}
|
|
{%
|
|
\nodeparts{text}
|
|
%%
|
|
%% Anchors
|
|
%%
|
|
\inheritsavedanchors[from=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}
|
|
\backgroundpath{
|
|
% 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
|
|
\pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
|
|
\pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
|
|
\pgfpathclose
|
|
}
|
|
}
|
|
%
|
|
%% A rectangle with sloped sides
|
|
%
|
|
\pgfdeclareshape{condition shape}
|
|
{%
|
|
\nodeparts{text}
|
|
%%
|
|
%% Anchors
|
|
%%
|
|
\inheritsavedanchors[from=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}
|
|
\backgroundpath{
|
|
% store lower right in xa/ya and upper right in xb/yb
|
|
% 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
|
|
\pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
|
|
\pgfmathparse{\pgf@xa-(\pgf@yb-\pgf@ya)*0.5}
|
|
\pgf@xc=\pgfmathresult pt\relax
|
|
\pgfmathparse{\pgf@yb*0.5+\pgf@ya*0.5}
|
|
\pgf@yc=\pgfmathresult pt\relax
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yc}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
|
|
\pgfmathparse{\pgf@xb+(\pgf@yb-\pgf@ya)*0.5}
|
|
\pgf@xc=\pgfmathresult pt\relax
|
|
\pgfmathparse{\pgf@yb*0.5+\pgf@ya*0.5}
|
|
\pgf@yc=\pgfmathresult pt\relax
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yc}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
|
|
\pgfpathclose
|
|
}
|
|
}
|
|
%% A rectangle with sloped sides and strike out
|
|
%
|
|
\pgfdeclareshape{ncondition shape}
|
|
{%
|
|
\nodeparts{text}
|
|
%%
|
|
%% Anchors
|
|
%%
|
|
\inheritsavedanchors[from=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}
|
|
\backgroundpath{
|
|
% store lower right in xa/ya and upper right in xb/yb
|
|
% 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
|
|
\pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
|
|
\pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
|
|
\pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
|
|
\pgfmathparse{\pgf@xa-(\pgf@yb-\pgf@ya)*0.5}
|
|
\pgf@xc=\pgfmathresult pt\relax
|
|
\pgfmathparse{\pgf@yb*0.5+\pgf@ya*0.5}
|
|
\pgf@yc=\pgfmathresult pt\relax
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yc}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
|
|
\pgfmathparse{\pgf@xb+(\pgf@yb-\pgf@ya)*0.5}
|
|
\pgf@xc=\pgfmathresult pt\relax
|
|
\pgfmathparse{\pgf@yb*0.5+\pgf@ya*0.5}
|
|
\pgf@yc=\pgfmathresult pt\relax
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yc}}
|
|
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
|
|
\pgfpathclose
|
|
}
|
|
}
|
|
|
|
|
|
% \declinst[*] declares a new msc-instance and draws its head symbol
|
|
% the starred versions makes a fat instance.
|
|
% #1: msc/tikz options
|
|
% #2: nickname that can be used in \mess
|
|
% #3: name of the instance (above instance head symbol)
|
|
% #4: name of the instance (inside instance head symbol)
|
|
% Keys used:
|
|
% /msc/instance/nick - contains number for instance with nick
|
|
% /msc/instanceno/n - contains nick for instance with n, where n is a number
|
|
%\declinst(*){nickname}{instancenameabove}{instancenamewithin}
|
|
\def\declinst{\pgfutil@ifnextchar*{\msc@isstartrue\msc@declinst@nostar}{\msc@isstarfalse\msc@declinst@nostar*}}
|
|
\def\msc@declinst@nostar*{\pgfutil@ifnextchar[\msc@declinst@noopt{\msc@declinst@noopt[]}}
|
|
\def\msc@declinst@noopt[#1]#2#3#4{%
|
|
\msc@nameinstance{#2}{#1}
|
|
\msc@previousinstance{#2}
|
|
\begin{pgfscope}
|
|
\mscset{#1}
|
|
\node[/msc,draw=\mscget{draw head},
|
|
instance head={#3}, name={msc@node#2},
|
|
right=\mscget{instance distance} of msc@node\msc@inst@name.south east,
|
|
% inner sep=2pt,
|
|
anchor=south west, every instance head,#1]{#4};
|
|
\end{pgfscope}
|
|
\advance\c@msclevelcnt by -1\relax
|
|
\msc@createlevelnodes{#2}{0}
|
|
\coordinate (msc@lastlevel#2) at (msc@node#2.south);
|
|
\advance\c@msclevelcnt by 1\relax
|
|
\msc@drawinstanceline{#2}{1}
|
|
}
|
|
% \dummyinst(*)[options]{createdinst}
|
|
\def\dummyinst{\pgfutil@ifnextchar*{\msc@isstartrue\msc@dummyinst@nostar}{\msc@isstarfalse\msc@dummyinst@nostar*}}
|
|
\def\msc@dummyinst@nostar*{\pgfutil@ifnextchar[\msc@dummyinst@noopt{\msc@dummyinst@noopt[]}}
|
|
\def\msc@dummyinst@noopt[#1]#2{%
|
|
\msc@nameinstance{#2}{#1}
|
|
\mscset{
|
|
instance/#2/status/.initial=off
|
|
}
|
|
\begin{pgfscope}
|
|
\mscset{#1}
|
|
\msc@previousinstance{#2}
|
|
\pgfmathparse{max(\mscget{instance width}, width(\mscget{dummy text})
|
|
+\pgfkeysvalueof{/pgf/inner xsep}*2+\mscget{line width}/2)}
|
|
\edef\msc@x{\pgfmathresult pt}
|
|
\node[/msc, name={msc@node#2},
|
|
inner sep=2pt,
|
|
right=\mscget{instance distance} of msc@node\msc@inst@name.south east,
|
|
minimum width=\msc@x,
|
|
minimum height=\mscget{head height},
|
|
anchor=south west, #1]{};
|
|
\end{pgfscope}
|
|
\advance\c@msclevelcnt by -1\relax
|
|
\msc@createlevelnodes{#2}{0}
|
|
\coordinate (msc@lastlevel#2) at (msc@node#2.south);
|
|
\advance\c@msclevelcnt by 1\relax
|
|
}
|
|
|
|
\def\inststart{\startinst}%old name of the command
|
|
%dd siple command \startinst[options]{instname}{text above}{text inside}
|
|
\def\startinst{\pgfutil@ifnextchar[\msc@startinst{\msc@startinst[]}}
|
|
\def\msc@startinst[#1]{
|
|
\begin{pgfscope}
|
|
\edef\msc@option{#1}\edef\msc@name{}\edef\msc@creator{}
|
|
\pgfkeysactivatefamily{/msc/message options}
|
|
\pgfkeysfiltered{/msc,#1}
|
|
\msc@create
|
|
}
|
|
% \create[options]{name}[label position]{creator}[pos]{createdinst}{instancenameabove}{instancenamewithin}
|
|
\def\create{
|
|
\begin{pgfscope}
|
|
\def\msc@option{}
|
|
\pgfutil@ifnextchar[\msc@create@opt{\msc@create@opt[]}
|
|
}
|
|
\def\msc@create@opt[#1]#2{
|
|
\pgfkeysactivatefamily{/msc/message options}
|
|
\pgfkeysfiltered{/msc,#1}
|
|
\edef\msc@option{#1}
|
|
\def\msc@name{#2}
|
|
\pgfutil@ifnextchar[\msc@create@label{\msc@create@label[]}
|
|
}
|
|
\def\msc@create@label[#1]#2{
|
|
\ifx#1t \mscset{label position=above}
|
|
\else \ifx#1b \mscset{label position=below}
|
|
\fi\fi
|
|
\edef\msc@creator{#2}
|
|
\pgfutil@ifnextchar[\msc@create{\msc@create@pos[\mscget{pos}]}
|
|
}
|
|
\def\msc@create@pos[#1]{
|
|
\mscset{pos/.expanded=#1}
|
|
\msc@create
|
|
}
|
|
%\create{insance name}{label above}{label inside}
|
|
\def\msc@create#1#2#3{
|
|
% \mscset{pos/.expanded=#1}
|
|
\pgfkeysifdefined{/msc/instance/#1/no}{
|
|
\IfStrEq{off}{\mscget{instance/#1/status}}{
|
|
\IfStrEq{fat}{\mscget{instance/#1/type}}{
|
|
\edef\msc@tempa{(msc@node#1.east)++(-\mscget{line width}/2,0) coordinate (msc@node#1@r0)
|
|
coordinate (msc@node#1@r\the\c@msclevelcnt)
|
|
(msc@node#1.west)++(\mscget{line width}/2,0) coordinate (msc@node#1@l0)
|
|
coordinate (msc@node#1@l\the\c@msclevelcnt)}
|
|
}{%
|
|
\edef\msc@tempa{(msc@node#1.east)++(-\mscget{line width}/2,0)
|
|
coordinate (msc@node#1@r\the\c@msclevelcnt)
|
|
(msc@node#1.west)++(\mscget{line width}/2,0)
|
|
coordinate (msc@node#1@l\the\c@msclevelcnt)}
|
|
}
|
|
\edef\msc@tempb{
|
|
[/msc, draw=\mscget{draw head}, instance head={#2}, name={msc@node#1}, every
|
|
instance head,
|
|
append after command={(msc@node#1.south) coordinate (msc@lastlevel#1)
|
|
\msc@tempa},
|
|
\msc@option] at (msc@node#1|-msc@level\the\c@msclevelcnt){\unexpanded\expandafter{#3}};
|
|
}
|
|
\adddraw{#1}{\the\c@msclevelcnt}{\expandafter\node\msc@tempb}
|
|
\pgfkeysifdefined{/msc/instance/\msc@creator/no}{
|
|
\edef\msc@tempb{[\msc@option]{\unexpanded\expandafter{\msc@name}}{\msc@creator}{#1}}
|
|
\expandafter\mess\msc@tempb
|
|
}{}
|
|
\end{pgfscope}
|
|
\mscset{instance/#1/status=on}
|
|
}{
|
|
\msc@instancestarted{#1}\end{pgfscope}
|
|
}
|
|
% \mscset{instance/#1/type=fat}
|
|
}{\msc@instundefinederr{#1}\end{pgfscope}}
|
|
}
|
|
|
|
% creates nodes to which we draw a line when advancing a level
|
|
% #1 instance name
|
|
%associates name with number #1 in corresponding pgfkeys. It updates
|
|
%the right evironment
|
|
% #1 name of instance
|
|
% #2 options
|
|
\def\msc@nameinstance#1#2{
|
|
\pgfkeysifdefined{/msc/instance/#1/no}{
|
|
\msc@nicknamedefinederr{#1}
|
|
}{
|
|
\advance\c@mscinstcnt by2\relax
|
|
\mscset{%update envright keys
|
|
instance/envright/no/.initial/.expanded=\the\c@mscinstcnt,
|
|
instanceno/\the\c@mscinstcnt/name/.initial/.expanded=envright
|
|
}
|
|
\advance\c@mscinstcnt by-1\relax%
|
|
\mscset{
|
|
instance/#1/no/.initial/.expanded=\the\c@mscinstcnt,
|
|
instanceno/\the\c@mscinstcnt/name/.initial/.expanded=#1,%
|
|
instance/#1/status/.initial=on, %possible values: on, off (no draw),
|
|
instance/#1/cover/.initial=0, %how many times instance is covered
|
|
instance/#1/region/.initial=normal, %possible %values:normal,coregion,suspension,activation,seminormal
|
|
instance/#1/region level/.initial=0,
|
|
instance/#1/region width/.initial=0pt
|
|
}
|
|
}
|
|
\begin{pgfscope}%parse options in scope not to propagate them
|
|
\mscset{#2}%
|
|
\ifnum\c@mscinstcnt<2\relax %the first instance
|
|
\coordinate[below=\mscget{first level height} of msc@level0] (msc@level1);
|
|
\fi
|
|
\ifmsc@isstar
|
|
\xdef\msc@tempa{fat}
|
|
\else
|
|
\xdef\msc@tempa{\mscget{fat}}
|
|
\fi
|
|
\end{pgfscope}
|
|
\mscset{/msc/instance/#1/type/.initial/.expand once=\msc@tempa}
|
|
\iftikz@fullytransformed %when fully transformed lines width is wrong - submitted bug nr 3597513.
|
|
\pgfmathparse{\msc@tempa + (0.5-0.5/\pgf@pt@bb)*\mscget{line width}}
|
|
\xdef\msc@tempa{\pgfmathresult}
|
|
\fi
|
|
}
|
|
%assigns the name of the previous instance to the \msc@inst@name
|
|
% #1 name or number of the instance
|
|
\def\msc@previousinstance#1{%
|
|
\pgfkeysifdefined{/msc/instanceno/#1/name}%
|
|
{ \pgfmathsetcount{\c@pgf@counta}{#1} }
|
|
{ \pgfkeysifdefined{/msc/instance/#1/no}
|
|
{\pgfmathsetcount{\c@pgf@counta}{\mscget{instance/#1/no}}}%
|
|
{\msc@instundefinederr{#1}}
|
|
}
|
|
\advance\c@pgf@counta by -1\relax%
|
|
\edef\msc@inst@name{\mscget{instanceno/\the\c@pgf@counta/name}}
|
|
}
|
|
|
|
\def\msc@numsplit#1.#2{\def\msc@ta{#1}\def\msc@tb{#2}}
|
|
% \nextlevel increases \msc@currentheight by #1 * \level height
|
|
% (optional) #1: a nonnegative integer number (defaults to 1)
|
|
% or tkiz options
|
|
%
|
|
\def\nextlevel{
|
|
\pgfutil@ifnextchar[\msc@nextlevelopt{\msc@nextlevelopt[1]}
|
|
}
|
|
\def\msc@nextlevelopt[#1]{%
|
|
\let\msc@tempheight\relax
|
|
\if!\ifnum9<1#1!\else_\fi
|
|
\mscset{/msc/level offset=#1}
|
|
\else
|
|
\msc@numsplit#1\relax
|
|
\if!\ifnum9<1\msc@ta!\else_\fi
|
|
\mscset{/msc/level offset=\msc@ta}%we get only
|
|
\if!\ifnum9<1\msc@tb!\else_\fi
|
|
\pgfmathsetmacro{\msc@tempheight}{0.\msc@tb*\mscget{level height}}
|
|
\msc@notpositiveintegerwarn{\msc@ta}{\msc@tb}
|
|
\fi
|
|
\fi
|
|
\fi
|
|
\mscgety{(msc@level\the\c@msclevelcnt)}{\msc@y}
|
|
\foreach \msc@tempa [evaluate=\msc@tempc using \msc@y-(\msc@tempa*\mscget{level height})] in {1 ,...,\mscget{level offset}} {%
|
|
\advance\c@msclevelcnt by 1\relax
|
|
\coordinate (msc@level\the\c@msclevelcnt) at (0,\msc@tempc pt);
|
|
\advance\c@msclevelcnt by -1\relax
|
|
\foreach \msc@tempb in {1,...,\c@mscinstcnt} {
|
|
\msc@createlevelnodes{\mscget{instanceno/\msc@tempb/name}}{\the\c@msclevelcnt}
|
|
}
|
|
% \message{-----Showing code for level=\the\c@msclevelcnt------------------- }
|
|
% \pgfkeys{/msc/level\the\c@msclevelcnt/draw/.show code,}
|
|
\pgfkeysifdefined{/msc/level\the\c@msclevelcnt/havedraw}{
|
|
\begin{pgfscope}
|
|
\mscset{/msc/level\the\c@msclevelcnt/draw}
|
|
\msc@global@set{/msc/level\the\c@msclevelcnt/draw/.code={}}
|
|
\end{pgfscope}
|
|
}{
|
|
}
|
|
\global\advance\c@msclevelcnt by 1\relax
|
|
}
|
|
\foreach \msc@tempb in {1,...,\c@mscinstcnt} {
|
|
\msc@drawinstanceline{\mscget{instanceno/\msc@tempb/name}}{\the\c@msclevelcnt}
|
|
}
|
|
\ifx\msc@tempheight\relax\else
|
|
\edef\msc@ta{\mscget{level height}}
|
|
\mscset{level height/.expanded=\msc@tempheight pt}
|
|
\nextlevel[1]
|
|
\mscset{level height/.expanded=\msc@ta}
|
|
\fi
|
|
\mscset{level offset=1}
|
|
}
|
|
|
|
% \coordinate (msc@level\the\c@msclevelcnt) at (0,#2);
|
|
% draw a line for a given instance
|
|
% #1 name of the instance
|
|
% #2 level number
|
|
\def\msc@drawinstanceline#1#2{
|
|
\IfStrEq{\mscget{instance/#1/status}}{on}{
|
|
% ifnum0<\mscget{instance/#1/cover} \else
|
|
\mscgety{(msc@level#2)}{\msc@tempa}
|
|
\mscgety{(msc@lastlevel#1)}{\msc@dil}
|
|
\pgfmathparse{max(\msc@tempa-\msc@dil,\mscget{instance/#1/cover})}
|
|
\ifnum0<\pgfmathresult\relax %draw only if last level is above current level
|
|
\mscgety{(msc@level#2)}{\msc@io}\msc@setlastlevel{#1}{\msc@io}
|
|
\else
|
|
\msc@StrEqEither{\mscget{instance/#1/region}}{normal}{seminormal}{
|
|
\draw[/msc,instance line,every instance line]
|
|
(msc@lastlevel#1-|msc@node#1@l0)--(msc@level#2-|msc@node#1@l0)
|
|
(msc@lastlevel#1-|msc@node#1@r0)--(msc@level#2-|msc@node#1@r0);
|
|
\mscgety{(msc@level#2)}{\msc@io}\msc@setlastlevel{#1}{\msc@io}
|
|
}{
|
|
% \msc@regbody{#1}{#2}
|
|
}
|
|
\fi
|
|
}{}
|
|
}
|
|
|
|
% create nodes at a current level for a given instance
|
|
% #1 name of the instance
|
|
% #2 level number
|
|
\def\msc@createlevelnodes#1#2{
|
|
%assume node msc@level#2 exists
|
|
\IfEqCase{\mscget{instance/#1/type}}{
|
|
{fat} {
|
|
\coordinate[xshift=\mscget{line width} /2](msc@node#1@l#2) at (msc@node#1.west|-msc@level#2);
|
|
\coordinate[xshift=-\mscget{line width} /2] (msc@node#1@r#2) at (msc@node#1.east|-msc@level#2);
|
|
\IfStrEq{\mscget{instance/#1/region}}{seminormal}{
|
|
\msc@global@set{instance/#1/region=normal}
|
|
}{}
|
|
}
|
|
{normal} {%
|
|
\msc@StrEqEither{\mscget{instance/#1/region}}{normal}{coregion}{%
|
|
\coordinate (msc@node#1@r#2) at (msc@node#1 |-msc@level#2);
|
|
\coordinate (msc@node#1@l#2) at (msc@node#1 |-msc@level#2);
|
|
}
|
|
{%
|
|
\msc@StrEqEither{\mscget{instance/#1/region}}{activation}{suspension} {
|
|
\path let \p1=(msc@node#1), \p2=(msc@level#2) in
|
|
coordinate(msc@node#1@l#2) at (\x1-\mscget{instance/#1/region width}/2,\y2)
|
|
coordinate(msc@node#1@r#2) at (\x1+\mscget{instance/#1/region width}/2,\y2);
|
|
}
|
|
{
|
|
\IfStrEq{\mscget{instance/#1/region}}{seminormal}{
|
|
\path let \p1=(msc@node#1), \p2=(msc@level#2) in
|
|
coordinate(msc@node#1@l#2) at (\x1-\mscget{instance/#1/region width}/2,\y2)
|
|
coordinate(msc@node#1@r#2) at (\x1+\mscget{instance/#1/region width}/2,\y2);
|
|
\msc@global@set{instance/#1/region=normal}
|
|
}{%debug message
|
|
\message{[msc] Unknown region type: \mscget{instance/#1/region} for the nick: #1}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
[\message{[msc] Unknown instance type: \mscget{instance/#1/type} for the nick: #1}]
|
|
}
|
|
% }
|
|
% { }
|
|
}
|
|
% \mess(*)[side]{name}[label position]{sender}[pos]{receiver}[level shift]
|
|
\def\mess{
|
|
\begin{pgfscope}
|
|
\def\msc@options{}
|
|
\pgfutil@ifnextchar*{\msc@isstartrue\msc@mess@nostar}{\msc@isstarfalse\msc@mess@nostar*}
|
|
}
|
|
\def\msc@mess@nostar*{\pgfutil@ifnextchar[\msc@messopt{\msc@messopt[]}}
|
|
\def\msc@messopt[#1]{%parsing of [side] and [options]
|
|
\ifx#1l \mscset{side=left}
|
|
\else \ifx#1r \mscset{side=right}
|
|
\else \ifx#1b \else \ifx#1t %ignoring t and b for backward compatibility
|
|
\else
|
|
\pgfkeysactivatefamily{/msc/message options}
|
|
\pgfkeysfiltered{/msc,#1}
|
|
\def\msc@options{#1}
|
|
% \pgfutil@ifundefined{msc@mess@side}{\def\msc@mess@side{\mscget{side}}}{}
|
|
\fi \fi \fi
|
|
\fi
|
|
\pgfutil@ifnextchar[{\msc@messopt}{\msc@mess@threeopt}
|
|
}
|
|
\def\msc@mess@threeopt#1{%parsing of {name}
|
|
\def\msc@mess@name{#1}
|
|
\pgfutil@ifnextchar[\msc@mess@twoopt{\msc@mess@twoopt[\mscget{label position}]}
|
|
}
|
|
\def\msc@mess@twoopt[#1]#2{%parsing of [label position] and {sender}
|
|
\ifx#1l \mscset{label position=left}
|
|
\else \ifx#1r \mscset{label position=right}
|
|
\else \ifx#1t \mscset{label position=above}
|
|
\else \ifx#1b \mscset{label position=below}
|
|
\fi \fi \fi \fi
|
|
\xdef\msc@sender{#2}
|
|
\pgfutil@ifnextchar[\msc@mess@oneopt{\msc@mess@oneopt[\mscget{pos}]}
|
|
}
|
|
\def\msc@mess@oneopt[#1]#2{%parsing of [placement] and {receiver}
|
|
\mscset{pos/.expanded=#1}
|
|
\xdef\msc@receiver{#2}
|
|
\IfStrEq{\msc@receiver}{\msc@sender}{
|
|
\edef\msc@tempb{\mscget{offset}}
|
|
}{
|
|
\edef\msc@tempb{\mscget{level shift}}
|
|
}
|
|
\pgfutil@ifnextchar[{\msc@mess@noopt}{\msc@mess@noopt[\msc@tempb]}
|
|
}
|
|
|
|
\def\msc@mess@noopt[#1]{%parsing of [level shift]
|
|
\def\msc@undefined{false}
|
|
\msc@getlevel shift{#1}{\msc@level shift}{\msc@tempa}
|
|
\ifx\msc@sender\msc@receiver %self message
|
|
\IfStrEq{\mscget{label position}}{above}{
|
|
\mscset{label position=\mscget{side}}
|
|
}{}
|
|
\pgfkeysifdefined{/msc/instance/\msc@receiver/no}{%instance name
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\msc@selfmess{msc@node\msc@receiver @l\the\c@msclevelcnt}{msc@node\msc@receiver @l\msc@level shift}{-\mscget{self message width}}
|
|
}{
|
|
\msc@selfmess{msc@node\msc@receiver @r\the\c@msclevelcnt}{msc@node\msc@receiver @r\msc@level shift}{\mscget{self message width}}
|
|
}
|
|
}{
|
|
\pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@receiver}{% neither instance name nor reference node
|
|
\def\msc@undefined{true}
|
|
\msc@instundefinederr{\msc@receiver}
|
|
}{% reference node
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\msc@selfmess{msc@node\msc@receiver|-msc@level\the\c@msclevelcnt}%
|
|
{msc@node\msc@receiver|-msc@level\msc@level shift}{-\mscget{self message width}}
|
|
}{
|
|
\msc@selfmess{msc@node\msc@receiver|-msc@level\the\c@msclevelcnt}%
|
|
{msc@node\msc@receiver|-msc@level\msc@level shift} {\mscget{self message width}}
|
|
}
|
|
}
|
|
}
|
|
\else %not self message
|
|
\pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@receiver} {
|
|
\def\msc@undefined{true}
|
|
\msc@instundefinederr{\msc@receiver}
|
|
}{
|
|
\mscgetx{(msc@node\msc@receiver)}{\msc@minx}
|
|
}
|
|
\pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@sender} {
|
|
\def\msc@undefined{true}
|
|
\msc@instundefinederr{\msc@sender}
|
|
}{
|
|
\mscgetx{(msc@node\msc@sender)}{\msc@maxx}
|
|
}
|
|
\IfStrEq{\msc@undefined}{false}{
|
|
\pgfkeysifdefined{/msc/instance/\msc@sender/no}{%instance name
|
|
% \pgfmathparse{\msc@maxx-\msc@minx}
|
|
\pgfmathparse{ifthenelse((\msc@maxx-\msc@minx)<0,"r","l")}
|
|
\edef\msc@left{msc@node\msc@sender @\pgfmathresult\the\c@msclevelcnt}
|
|
}{
|
|
\def\msc@left{msc@node\msc@sender|-msc@level\the\c@msclevelcnt}
|
|
}
|
|
\pgfkeysifdefined{/msc/instance/\msc@receiver/no}{%instance name
|
|
\pgfmathparse{ifthenelse((\msc@maxx-\msc@minx)<0,"l","r")}
|
|
\edef\msc@right{msc@node\msc@receiver @\pgfmathresult\msc@level shift}
|
|
}{
|
|
\def\msc@right{msc@node\msc@receiver|-msc@level\msc@level shift}
|
|
}
|
|
\msc@mess{\msc@left}{\msc@right}%stores result in \msc@tempb
|
|
}{}
|
|
\fi
|
|
\IfStrEq{\msc@undefined}{false}{
|
|
\end{pgfscope}
|
|
\addDdraw{\msc@sender}{\msc@receiver}{\msc@tempa}{\expandafter\draw\msc@tempb}
|
|
}{
|
|
\end{pgfscope}
|
|
}
|
|
}
|
|
% #1 - sender node
|
|
% #2 - receiver node
|
|
% #3 - message dist
|
|
% result defined in \msc@tempb
|
|
\def\msc@selfmess#1#2#3{
|
|
\IfStrEq{\mscget{label position}}{left}{\xdef\msc@tempc{-1}}{\xdef\msc@tempc{1}}
|
|
\xdef\msc@tempb{[\mscget{label position},/msc,message,message loop={#3},
|
|
\ifmsc@isstar replay,\fi, inner sep=0pt,
|
|
/tikz/pos=\mscget{pos}, every message, \msc@options]
|
|
(#1)
|
|
to node[xshift=\msc@tempc*\mscget{label distance}](msc@lastnode){\expandafter\noexpand\msc@mess@name}
|
|
(#2);
|
|
}%use macro to expand parameters
|
|
}
|
|
% #1 - sender node
|
|
% #2 - receiver node
|
|
% result defined in \msc@tempb
|
|
\def\msc@mess#1#2{
|
|
\IfSubStr{\mscget{label position}}{above}{\xdef\msc@tempc{1}}{\xdef\msc@tempc{-1}}
|
|
\xdef\msc@tempb{[/msc,\mscget{label position},message,
|
|
\ifmsc@isstar replay,\fi, inner sep=0pt, %
|
|
/tikz/pos=\mscget{pos}, every message, \msc@options]
|
|
(#1) ->
|
|
node[yshift=\msc@tempc*\mscget{label distance}](msc@lastnode){\unexpanded\expandafter{\msc@mess@name}}(#2);%cheating %and using eTeX expansion
|
|
% to use pure TeX see http://tex.stackexchange.com/questions/40674/replacement-for-unexpanded-without-etex-extension
|
|
}
|
|
}
|
|
%add code to be executed at given level
|
|
% #1 - name of the instance
|
|
% #2 - number of level at which to add the code
|
|
% #3 - code to be added (expanded once - so prefix with \expandafter)
|
|
\def\adddraw#1#2#3{
|
|
\msc@StrEqEither{#1}{envright}{envleft} {
|
|
\msc@global@set{/msc/levelenv/draw/.append code/.expand once={#3},
|
|
/msc/levelenv/havedraw/.initial=true}
|
|
}{
|
|
\msc@global@set{/msc/level#2/draw/.append code/.expand once={#3},
|
|
/msc/level#2/havedraw/.initial=true}
|
|
}
|
|
}
|
|
%add code to be executed at given level
|
|
% #1 - name of the instance
|
|
% #2 - name of the second instance
|
|
% #3 - number of level at which to add the code
|
|
% #4 - code to be added (expanded once - so prefix with \expandafter)
|
|
\def\addDdraw#1#2#3#4{
|
|
\msc@StrEqEither{#1}{envright}{envleft} {
|
|
\msc@global@set{/msc/levelenv/draw/.append code/.expand once={#4},
|
|
/msc/levelenv/havedraw/.initial=true}
|
|
}{
|
|
\msc@StrEqEither{#2}{envright}{envleft} {
|
|
\msc@global@set{/msc/levelenv/draw/.append code/.expand once={#4},
|
|
/msc/levelenv/havedraw/.initial=true}
|
|
}{
|
|
\msc@global@set{/msc/level#3/draw/.append code/.expand once={#4},
|
|
/msc/level#3/havedraw/.initial=true}
|
|
}
|
|
}
|
|
}
|
|
% \msccomment[position]{text}{instname}
|
|
\def\msccomment{
|
|
\begin{pgfscope}
|
|
\def\msc@options{}
|
|
\pgfutil@ifnextchar*{\msc@isstartrue\msc@msccomment@nostar}{\msc@isstarfalse\msc@msccomment@nostar*}
|
|
}
|
|
\def\msc@msccomment@nostar*{\pgfutil@ifnextchar[\msc@msccomment@opt{\msc@msccomment@opt[]}}
|
|
\def\msc@msccomment@opt[#1]{%parsing of [side] and [options]
|
|
\ifx#1l \mscset{side=left}
|
|
\else \ifx#1r \mscset{side=right}
|
|
\else
|
|
\pgfkeysactivatefamily{/msc/msccomment options}
|
|
\pgfkeysfiltered{/msc,#1}
|
|
\def\msc@options{#1}
|
|
% \pgfutil@ifundefined{msc@mess@side}{\def\msc@mess@side{\mscget{side}}}{}
|
|
\fi
|
|
\fi
|
|
\pgfutil@ifnextchar[{\msc@msccomment@opt}{\msc@msccomment@noopt}
|
|
}
|
|
|
|
\def\msc@msccomment@noopt#1#2{%parsing of {text}
|
|
\edef\msc@undefined{false}
|
|
\edef\msc@instname{#2}
|
|
\pgfkeysifdefined{/msc/instance/\msc@instname/no}{
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@node{msc@node\msc@instname @l\the\c@msclevelcnt}
|
|
} {
|
|
\edef\msc@node{msc@node\msc@instname @r\the\c@msclevelcnt}
|
|
}
|
|
}{
|
|
\pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@instname}{% neither instance name nor reference node
|
|
\edef\msc@undefined{true}
|
|
\msc@instundefinederr{\msc@instname}
|
|
}
|
|
{
|
|
\edef\msc@node{msc@node\msc@instname|-msc@level\the\c@msclevelcnt}
|
|
}
|
|
}
|
|
\IfStrEq{\msc@undefined}{false}{
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\def\msc@anchor{east}
|
|
\edef\msc@dist{-\mscget{msccomment distance}}
|
|
} {
|
|
\def\msc@anchor{west}
|
|
\edef\msc@dist{\mscget{msccomment distance}}
|
|
}
|
|
\xdef\msc@tempb{[/msc,msccomment,msccomment line,
|
|
every msccomment, \msc@options]
|
|
let \noexpand\p1 = (\msc@node)
|
|
in (\noexpand\x1+\msc@dist,\noexpand\y1)
|
|
node [/msc,draw,solid,\mscget{side} open rectangle,anchor=\msc@anchor,
|
|
append after command={(\msc@node)
|
|
-- (\noexpand\tikzlastnode)},
|
|
every msccomment, \msc@options] {#1};
|
|
}%use macro to expand parameters
|
|
\end{pgfscope}
|
|
\adddraw{#2}{\the\c@msclevelcnt}{\expandafter\draw\msc@tempb}
|
|
}{
|
|
\msc@instundefinederr{\msc@instname}\end{pgfscope}
|
|
}
|
|
}
|
|
% \action(*){name}{instance}
|
|
% \naction(*){name}{instance}
|
|
\def\naction{
|
|
\begin{pgfscope}%,append after command={node[draw,cross out]{}}
|
|
\def\msc@crossout{,append after command={
|
|
[shorten >=1.2*\noexpand\mscget{line width},
|
|
shorten <=1.2*\noexpand\mscget{line width}]
|
|
(\noexpand\tikzlastnode.north west) edge (\noexpand\tikzlastnode.south east)
|
|
(\noexpand\tikzlastnode.north east) edge (\noexpand\tikzlastnode.south west)}}
|
|
\pgfutil@ifnextchar*{\msc@isstartrue\msc@action@nostar}{\msc@isstarfalse\msc@action@nostar*}
|
|
}
|
|
\def\action{
|
|
\begin{pgfscope}
|
|
\def\msc@crossout{}
|
|
\def\msc@options{}
|
|
\pgfutil@ifnextchar*{\msc@isstartrue\msc@action@nostar}{\msc@isstarfalse\msc@action@nostar*}
|
|
}
|
|
% #1 options
|
|
% #2 name
|
|
% #3 insstance
|
|
\def\msc@action@nostar*{\pgfutil@ifnextchar[\msc@action@opt{\msc@action@opt[]}}
|
|
\def\msc@action@opt[#1]#2#3{%parsing of [side] and [options]
|
|
\pgfkeysactivatefamily{/msc/action options}
|
|
\pgfkeysfiltered{/msc,#1}
|
|
\def\msc@options{#1}
|
|
\xdef\msc@instname{#3}
|
|
\ifmsc@isstar
|
|
\def\msc@tempa{}
|
|
\else
|
|
%\msc@savebox{#2}
|
|
\edef\msc@tempa{,
|
|
%text height={min({\the\ht\msc@box},\mscget{action height})},
|
|
%text depth={\the\dp\msc@box},
|
|
%inner sep=0,
|
|
align=center,
|
|
text width={max( \mscget{action width},\noexpand\noexpand\noexpand\x2 -
|
|
\noexpand\noexpand\noexpand\x1)-2*\mscget{label distance}}
|
|
}
|
|
\fi
|
|
\pgfkeysifdefined{/msc/instance/\msc@instname/no}{
|
|
\xdef\msc@tempb{[, ]
|
|
let \noexpand\p1 = (msc@node\msc@instname @l\the\c@msclevelcnt),
|
|
\noexpand\p2 = (msc@node\msc@instname @r\the\c@msclevelcnt) in
|
|
( {\noexpand\x1+(\noexpand\x2-\noexpand\x1)/2},\noexpand\y1)
|
|
node[/msc, line cap=round,
|
|
yshift=\mscget{line width}/2, anchor=north,
|
|
minimum height=\mscget{action height},
|
|
minimum width= {max( \mscget{action width},\noexpand\x2 -
|
|
\noexpand\x1)} \msc@tempa, draw \msc@crossout,
|
|
inner sep=\mscget{label distance},
|
|
every action, /tikz/line width=\mscget{line width},\msc@options
|
|
](msc@tempnode){\unexpanded\expandafter{#2}};
|
|
\noexpand\msc@StrEqEither{\msc@instname}{envright}{envleft}{}{
|
|
\noexpand\mscgety{(msc@tempnode.south)}{\noexpand\msc@y}
|
|
\noexpand\msc@setlastlevel{\msc@instname}{\noexpand\msc@y}
|
|
}
|
|
}
|
|
\end{pgfscope}
|
|
\msc@StrEqEither{\mscget{instance/#3/region}}{normal}{seminormal}{}{
|
|
\msc@regbody{#3}{\the\c@msclevelcnt}
|
|
\msc@regbar{#3}{\mscget{instance/#3/region level}}
|
|
}
|
|
\adddraw{\msc@instname}{\the\c@msclevelcnt}{\expandafter\draw\msc@tempb}
|
|
}{
|
|
\msc@instundefinederr{\msc@instname}\end{pgfscope}
|
|
}
|
|
}
|
|
% \settimer[placement]{name}{instance}
|
|
\def\settimer{
|
|
\begin{pgfscope}
|
|
\def\msc@options{} \def\msc@timertype{settimer style}
|
|
\pgfutil@ifnextchar[\msc@timer@opt{\msc@timer@opt[]}
|
|
}
|
|
% \timeout[placement]{name}{instance}
|
|
\def\timeout{
|
|
\begin{pgfscope}
|
|
\def\msc@options{} \def\msc@timertype{timeout style}
|
|
\pgfutil@ifnextchar[\msc@timer@opt{\msc@timer@opt[]}
|
|
}
|
|
% \stoptimer[placement]{name}{instance}
|
|
\def\stoptimer{
|
|
\begin{pgfscope}
|
|
\def\msc@options{} \def\msc@timertype{stoptimer style}
|
|
\pgfutil@ifnextchar[\msc@timer@opt{\msc@timer@opt[]}
|
|
}
|
|
% #1 - options or "l" or "r"
|
|
\def\msc@timer@opt[#1]{%parsing of [side] and [options]
|
|
\ifx#1l \mscset{side=left}
|
|
\else \ifx#1r \mscset{side=right}
|
|
\else
|
|
\pgfkeysactivatefamily{/msc/msccomment options}
|
|
\pgfkeysfiltered{/msc,#1}
|
|
\def\msc@options{#1}
|
|
\fi
|
|
\fi
|
|
\pgfutil@ifnextchar[{\msc@timer@opt}{\msc@timer}
|
|
}
|
|
% #1 - label
|
|
% #2 - instance name
|
|
\def\msc@timer#1#2{
|
|
\edef\msc@undefined{false}
|
|
\edef\msc@instname{#2}
|
|
\pgfkeysifdefined{/msc/instance/\msc@instname/no}{
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@node{msc@node\msc@instname @l\the\c@msclevelcnt}
|
|
} {
|
|
\edef\msc@node{msc@node\msc@instname @r\the\c@msclevelcnt}
|
|
}
|
|
}{
|
|
\pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@instname}{% neither instance name nor reference node
|
|
\edef\msc@undefined{true}
|
|
\msc@instundefinederr{\msc@instname}
|
|
}
|
|
{
|
|
\edef\msc@node{msc@node\msc@instname|-msc@level\the\c@msclevelcnt}
|
|
}
|
|
}
|
|
\IfStrEq{\msc@undefined}{false}{
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\def\msc@anchor{east}
|
|
\edef\msc@timer@dist{-\mscget{self message width}}
|
|
\edef\msc@label@dist{-\mscget{label distance}}
|
|
} {
|
|
\edef\msc@timer@dist{\mscget{self message width}}
|
|
\def\msc@anchor{west}
|
|
\edef\msc@label@dist{\mscget{label distance}}
|
|
}
|
|
\xdef\msc@tempb{[/msc,\msc@timertype={\mscget{timer width}},
|
|
every timer, \msc@options]
|
|
let \noexpand\p1 = (\msc@node)
|
|
in (\noexpand\x1+\msc@timer@dist,\noexpand\y1)
|
|
node [xshift=\msc@label@dist,/msc,anchor=\msc@anchor]{#1} to (\noexpand\x1,\noexpand\y1);
|
|
}%use macro to expand parameters
|
|
\end{pgfscope}
|
|
\adddraw{#2}{\the\c@msclevelcnt}{\expandafter\draw\msc@tempb}
|
|
}{
|
|
\msc@instundefinederr{#2}\end{pgfscope}
|
|
}
|
|
}
|
|
%\setstoptimer[placement]{name}{instance}[offset]
|
|
\def\setstoptimer{
|
|
\begin{pgfscope}
|
|
\def\msc@options{} \def\msc@timertype{setstoptimer style}
|
|
\pgfutil@ifnextchar[\msc@fulltimer@opt{\msc@fulltimer@opt[]}
|
|
}
|
|
%\settimeout[placement]{name}{instance}[offset]
|
|
\def\settimeout{
|
|
\begin{pgfscope}
|
|
\def\msc@options{} \def\msc@timertype{settimeout style}
|
|
\pgfutil@ifnextchar[\msc@fulltimer@opt{\msc@fulltimer@opt[]}
|
|
}
|
|
|
|
% #1 - options or "l" or "r"
|
|
\def\msc@fulltimer@opt[#1]{%parsing of [side] and [options]
|
|
\ifx#1l \mscset{side=left}
|
|
\else \ifx#1r \mscset{side=right}
|
|
\else
|
|
\pgfkeysactivatefamily{/msc/msccomment options}
|
|
\pgfkeysfiltered{/msc,#1}
|
|
\def\msc@options{#1}
|
|
\fi
|
|
\fi
|
|
\pgfutil@ifnextchar[{\msc@fulltimer@opt}{\msc@fulltimer}
|
|
}
|
|
\def\msc@fulltimer#1#2{
|
|
\xdef\msc@instname{#2}
|
|
\def\msc@name{#1}
|
|
\pgfutil@ifnextchar[{\msc@fulltimer@noopt}{\msc@fulltimer@noopt[\mscget{offset}]}
|
|
}
|
|
\def\msc@fulltimer@noopt[#1]{
|
|
\edef\msc@undefined{false}
|
|
\pgfkeysifdefined{/msc/instance/\msc@instname/no}{
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@node{msc@node\msc@instname @l}
|
|
} {
|
|
\edef\msc@node{msc@node\msc@instname @r}
|
|
}
|
|
}{
|
|
\pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@instname}{% neither instance name nor reference node
|
|
\edef\msc@undefined{true}
|
|
\msc@instundefinederr{\msc@instname}
|
|
}
|
|
{
|
|
\edef\msc@node{msc@node\msc@instname|-msc@level}
|
|
}
|
|
}
|
|
\IfStrEq{\msc@undefined}{false}{
|
|
% \pgfkeysifdefined{/msc/instance/\msc@instname/no}{
|
|
\msc@getlevel shift{#1}{\msc@level shift}{\msc@drawlevel}
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@mess@dist{-\mscget{self message width}}
|
|
\edef\msc@label@dist{-\mscget{label distance}}
|
|
\def\msc@anchor{east}
|
|
}{
|
|
\edef\msc@mess@dist{\mscget{self message width}}
|
|
\edef\msc@label@dist{\mscget{label distance}}
|
|
\def\msc@anchor{west}
|
|
}
|
|
\xdef\msc@tempb{[/msc,\msc@timertype={\msc@mess@dist}{\mscget{timer width}},
|
|
every timer,\msc@options]
|
|
(\msc@node\the\c@msclevelcnt)
|
|
node [xshift=\msc@label@dist+\msc@mess@dist,/msc,anchor=\msc@anchor]{\msc@name}
|
|
to (\msc@node\msc@level shift);
|
|
}
|
|
\end{pgfscope}
|
|
\adddraw{\expandafter\noexpand\msc@instname}{\expandafter\noexpand\msc@drawlevel}{\expandafter\draw\msc@tempb}
|
|
% \edef\msc@drawlevel{0}
|
|
}{
|
|
\end{pgfscope}\msc@instundefinederr{\msc@instname}
|
|
}
|
|
}
|
|
% \mscmark[position]{name}{instname}
|
|
\def\mscmark{
|
|
\begin{pgfscope}
|
|
\def\msc@options{}
|
|
\pgfutil@ifnextchar[\msc@mark@opt{\msc@mark@opt[]}
|
|
}
|
|
\def\msc@mark@opt[#1]{%parsing of [side] and [options]
|
|
\IfEqCase{#1}{%
|
|
{l}{\mscset{side=left}}%
|
|
{r}{\mscset{side=right}}%
|
|
{t}{\mscset{position=above}}%
|
|
{b}{\mscset{position=below}}%
|
|
{tl}{\mscset{side=left,position=above}}%
|
|
{tr}{\mscset{side=right,position=above}}%
|
|
{bl}{\mscset{side=left,position=below}}%
|
|
{br}{\mscset{side=right,position=below}}%
|
|
}[%
|
|
\mscset{#1}
|
|
\def\msc@options{#1}
|
|
]
|
|
\pgfutil@ifnextchar[{\msc@mark@opt}{\msc@mark}
|
|
}
|
|
|
|
\def\msc@mark#1#2{
|
|
\def\msc@undefined{false}
|
|
\pgfkeysifdefined{/msc/instance/#2/no}{
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@node{msc@node#2@l\the\c@msclevelcnt}
|
|
} {
|
|
\edef\msc@node{msc@node#2@r\the\c@msclevelcnt}
|
|
}
|
|
}{
|
|
\pgfutil@ifundefined{pgf@sh@ns@msc@node#2}{% neither instance name nor reference node
|
|
\edef\msc@undefined{true}
|
|
\msc@instundefinederr{#2}
|
|
}
|
|
{
|
|
\edef\msc@node{msc@node#2|-msc@level\the\c@msclevelcnt}
|
|
}
|
|
}
|
|
\IfStrEq{\msc@undefined}{false}{
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@anchor@l{south east}
|
|
\edef\msc@anchor@r{south west}
|
|
\edef\msc@dist{-\mscget{mark distance}}
|
|
} {
|
|
\edef\msc@dist{\mscget{mark distance}}
|
|
\edef\msc@anchor@l{south west}
|
|
\edef\msc@anchor@r{south east}
|
|
}
|
|
\IfStrEq{\mscget{position}}{above}{
|
|
\edef\msc@mark@ydist{0.5*\mscget{mark distance}}
|
|
}{
|
|
\IfStrEq{\mscget{position}}{below}{
|
|
\edef\msc@mark@ydist{-0.5*\mscget{mark distance}}
|
|
}
|
|
{
|
|
\IfStrEq{\mscget{position}}{mid}{
|
|
\edef\msc@mark@ydist{0pt}
|
|
}{%unknown
|
|
}
|
|
}
|
|
}
|
|
\xdef\msc@tempb{[/msc,mscdash,/tikz/line width=\mscget{line width}, every mscmark, \msc@options]
|
|
(\msc@node)
|
|
++(\msc@dist,\msc@mark@ydist)
|
|
node[anchor=\msc@anchor@l,inner sep=\mscget{label distance}, append after command={
|
|
(\msc@node)--
|
|
(\noexpand\tikzlastnode .\msc@anchor@l)--(\noexpand\tikzlastnode .\msc@anchor@r)
|
|
}] {#1};
|
|
}
|
|
\end{pgfscope}
|
|
\adddraw{#2}{\the\c@msclevelcnt}{\expandafter\draw\msc@tempb}
|
|
}{}
|
|
}
|
|
% \measure(*)[placement]{name}{instance1}{instance2}[offset]
|
|
\def\measure{
|
|
\begin{pgfscope}
|
|
\def\msc@options{}
|
|
\pgfutil@ifnextchar*{\msc@isstartrue\msc@measure@nostar}{\msc@isstarfalse\msc@measure@nostar*}
|
|
}
|
|
\def\msc@measure@nostar*{\pgfutil@ifnextchar[\msc@measure@opt{\msc@measure@opt[]}}
|
|
\def\msc@measure@opt[#1]{%parsing of [side] and [options]
|
|
\ifx#1l \mscset{side=left}
|
|
\else \ifx#1r \mscset{side=right}
|
|
\else
|
|
\mscset{#1}
|
|
\def\msc@options{#1}
|
|
\fi
|
|
\fi
|
|
\pgfutil@ifnextchar[{\msc@measure@opt}{\msc@measure@noopt}
|
|
}
|
|
|
|
\def\msc@measure@noopt#1#2#3{
|
|
\def\msc@measure@name{#1}
|
|
\xdef\msc@instnameI{#2}
|
|
\xdef\msc@instnameII{#3}
|
|
\pgfutil@ifnextchar[{\msc@measure@final}{\msc@measure@final[\mscget{offset}]}
|
|
}
|
|
|
|
\def\msc@measure@final[#1]{
|
|
\pgfkeysifdefined{/msc/instance/\msc@instnameI/no}{
|
|
\pgfkeysifdefined{/msc/instance/\msc@instnameII/no}{
|
|
\msc@getlevel shift{#1}{\msc@level shift}{\msc@drawlevel}
|
|
\ifmsc@isstar\def\msc@style{measure* style}\else\def\msc@style{measure style}\fi
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@nodeI{msc@node\msc@instnameI @l\the\c@msclevelcnt}
|
|
\edef\msc@nodeII{msc@node\msc@instnameII @l\msc@level shift}
|
|
\edef\msc@dist{-\mscget{measure distance}-\noexpand\noexpand\noexpand\msc@x+
|
|
min(\noexpand\noexpand\noexpand\msc@x,\noexpand\noexpand\noexpand\msc@y)}
|
|
\edef\msc@anchor{east}
|
|
} {
|
|
\edef\msc@nodeI{msc@node\msc@instnameI @r\the\c@msclevelcnt}
|
|
\edef\msc@nodeII{msc@node\msc@instnameII @r\msc@level shift}
|
|
\edef\msc@dist{\mscget{measure distance}-\noexpand\noexpand\noexpand\msc@x
|
|
+max(\noexpand\noexpand\noexpand\msc@x,\noexpand\noexpand\noexpand\msc@y)}
|
|
\edef\msc@anchor{west}
|
|
}
|
|
\xdef\msc@tempa{
|
|
\noexpand\mscgetx{(\msc@nodeI)}{\noexpand\msc@x}
|
|
\noexpand\mscgetx{(\msc@nodeII)}{\noexpand\msc@y}
|
|
\noexpand\pgfmathparse{\msc@dist}
|
|
\noexpand\edef\noexpand\msc@dist{\noexpand\pgfmathresult}
|
|
}
|
|
\xdef\msc@tempb{[/msc,draw, mscdash,
|
|
\msc@style={\noexpand\msc@dist pt}{\mscget{measure symbol width}}, every measure,
|
|
\msc@options] (\msc@nodeI) to
|
|
node[/msc,anchor=\msc@anchor, inner sep=\mscget{label distance}, every measure, \msc@options]{\unexpanded\expandafter{\msc@measure@name}}
|
|
(\msc@nodeII);
|
|
% \noexpand\path ($(a) !\mscget{pos}! (b)$)
|
|
% node[/msc,anchor=\msc@anchor, inner sep=\mscget{label distance}, every measure, \msc@options]{text};
|
|
}
|
|
\end{pgfscope}
|
|
\addDdraw{\msc@instnameI}{\msc@instnameII}{\expandafter\noexpand\msc@drawlevel}{\expandafter\noexpand\msc@tempa}
|
|
\addDdraw{\msc@instnameI}{\msc@instnameII}{\expandafter\noexpand\msc@drawlevel}{\expandafter\draw\msc@tempb}
|
|
}{
|
|
\msc@instundefinederr{\msc@instnameII}\end{pgfscope}
|
|
}
|
|
}{
|
|
\msc@instundefinederr{\msc@instnameI}\end{pgfscope}
|
|
}
|
|
}
|
|
%\measurestart(*)[placement]{name}{instance}{gate}
|
|
\def\measurestart{
|
|
\begin{pgfscope}
|
|
\def\msc@options{}
|
|
\def\msc@sign{}
|
|
\pgfutil@ifnextchar*{\edef\msc@style{measurestart* style}\msc@measuregap@nostar}{\edef\msc@style{measurestart style}\msc@measuregap@nostar*}
|
|
}
|
|
% \measureend(*)[placement]{name}{instance}{gate}
|
|
\def\measureend{
|
|
\begin{pgfscope}
|
|
\def\msc@options{}
|
|
\def\msc@sign{-1*}
|
|
\pgfutil@ifnextchar*{\edef\msc@style{measurestart* style}\msc@measuregap@nostar}{\edef\msc@style{measurestart style}\msc@measuregap@nostar*}
|
|
}
|
|
\def\msc@measuregap@nostar*{\pgfutil@ifnextchar[\msc@measuregap@opt{\msc@measuregap@opt[]}}
|
|
\def\msc@measuregap@opt[#1]{%parsing of [side] and [options]
|
|
\ifx#1l \mscset{side=left}
|
|
\else \ifx#1r \mscset{side=right}
|
|
\else
|
|
\mscset{#1}
|
|
\def\msc@options{#1}
|
|
\fi
|
|
\fi
|
|
\pgfutil@ifnextchar[{\msc@measuregap@opt}{\msc@measuregap@noopt}
|
|
}
|
|
|
|
\def\msc@measuregap@noopt#1#2#3{
|
|
\edef\msc@text{#1}
|
|
\gdef\msc@instname{#2}
|
|
\edef\msc@gate{#3}
|
|
\pgfutil@ifnextchar[{\msc@measuregap@final}{\msc@measuregap@final[\mscget{offset}]}
|
|
}
|
|
|
|
\def\msc@measuregap@final[#1]{
|
|
\pgfkeysifdefined{/msc/instance/\msc@instname/no}{
|
|
\msc@getlevel shift{\msc@sign#1}{\msc@level shift}{\msc@drawlevel}
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@nodeI{msc@node\msc@instname @l\the\c@msclevelcnt}
|
|
\edef\msc@nodeII{msc@node\msc@instname @l\msc@level shift}
|
|
\edef\msc@dist{-\mscget{measure distance}}
|
|
\edef\msc@anchor{east}
|
|
} {
|
|
\edef\msc@nodeI{msc@node\msc@instname @r\the\c@msclevelcnt}
|
|
\edef\msc@nodeII{msc@node\msc@instname @r\msc@level shift}
|
|
\edef\msc@dist{\mscget{measure distance}}
|
|
\edef\msc@anchor{west}
|
|
}
|
|
\xdef\msc@tempb{[/msc,mscdash,draw,
|
|
\msc@style={\msc@dist}{\mscget{measure symbol width}}, every measure,
|
|
\msc@options] (\msc@nodeI) to node[/msc,anchor=\msc@anchor, inner
|
|
sep=\mscget{label distance}, every measure, \msc@options]{\msc@text} (\msc@nodeII);
|
|
\noexpand\path (b) node[/msc,anchor=\msc@anchor, inner sep=\mscget{label distance}, every measure, \msc@options]{\msc@gate};
|
|
}
|
|
\end{pgfscope}
|
|
\adddraw{\msc@instname}{\expandafter\noexpand\msc@drawlevel}{\expandafter\draw\msc@tempb}
|
|
}{
|
|
\msc@instundefinederr{\msc@instname}\end{pgfscope}
|
|
}
|
|
}
|
|
|
|
% \lost[side]{name}[label position]{gate}{instance}[pos]
|
|
\def\lost{
|
|
\begin{pgfscope}
|
|
\def\msc@options{}
|
|
\def\msc@style{lost style}
|
|
\pgfutil@ifnextchar[{\msc@lost@opt}{\msc@lost@opt[]}
|
|
}
|
|
% \found[pos]{name}[label position]{gate}{instance}[placement]
|
|
\def\found{
|
|
\begin{pgfscope}
|
|
\def\msc@options{}
|
|
\def\msc@style{found style}
|
|
\pgfutil@ifnextchar[{\msc@lost@opt}{\msc@lost@opt[]}
|
|
}
|
|
\def\msc@lost@opt[#1]#2{
|
|
\ifx#1l \mscset{side=left}
|
|
\else \ifx#1r \mscset{side=right}
|
|
\else
|
|
\mscset{#1}
|
|
\def\msc@options{#1}
|
|
\fi
|
|
\fi
|
|
\def\msc@text{#2}
|
|
\pgfutil@ifnextchar[{\msc@lost@noopt}{\msc@lost@noopt[]}
|
|
}
|
|
\def\msc@lost@noopt[#1]#2#3{
|
|
\mscset{label position=above}
|
|
\expandafter\ifx#1b \mscset{label position=below} \fi
|
|
\def\msc@gate{#2}
|
|
\xdef\msc@instname{#3}
|
|
\pgfutil@ifnextchar[{\msc@lost@final}{\msc@lost@final[\mscget{pos}]}
|
|
}
|
|
\def\msc@lost@final[#1]{
|
|
\def\msc@undefined{false}
|
|
\pgfkeysifdefined{/msc/instance/\msc@instname/no}{
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@node{msc@node\msc@instname @l\the\c@msclevelcnt}
|
|
} {
|
|
\edef\msc@node{msc@node\msc@instname @r\the\c@msclevelcnt}
|
|
}
|
|
}{
|
|
\pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@instname}{% neither instance name nor reference node
|
|
\edef\msc@undefined{true}
|
|
\msc@instundefinederr{\msc@instname}
|
|
}
|
|
{
|
|
\edef\msc@node{msc@node\msc@instname|-msc@level\the\c@msclevelcnt}
|
|
}
|
|
}
|
|
\IfStrEq{\msc@undefined}{false}{
|
|
\mscset{pos=#1}
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@dist{-\mscget{self message width}}
|
|
\edef\msc@anchor{east}
|
|
} {
|
|
\edef\msc@dist{\mscget{self message width}}
|
|
\edef\msc@anchor{west}
|
|
}
|
|
\xdef\msc@tempb{[/msc,draw,
|
|
\msc@style={2*\mscget{lost symbol radius}}, every lostfound,
|
|
\msc@options] (\msc@node) to node[/msc,\mscget{label position}, inner
|
|
sep=\mscget{label distance}, every lostfound, \msc@options]{\unexpanded\expandafter{\msc@text}}
|
|
++(\msc@dist,0);
|
|
\noexpand\path(\msc@node) ++(\msc@dist,0)
|
|
node[/msc,above,anchor=\msc@anchor,%
|
|
inner sep=\mscget{label distance}, every lostfound, \msc@options]{\msc@gate};
|
|
}
|
|
\end{pgfscope}
|
|
\adddraw{\msc@instname}{\the\c@msclevelcnt}{\expandafter\draw\msc@tempb}
|
|
}{}
|
|
}
|
|
|
|
% \condition puts a condition symbol over the given instances. The
|
|
% starred version adjusts the width and the height of the condition symbol.
|
|
% #1: name to be put inside the condition symbol
|
|
% #2: comma-separated list of instance nicknames, such that:
|
|
% - The first instance nickname is supposed to be the leftmost
|
|
% instance of the condition
|
|
% - The last instance nickname is supposed to be the rightmost
|
|
% instance of the condition
|
|
% \condition(*)[options]{text}{instancelist}
|
|
\def\condition{
|
|
\advance\c@condition by1\relax
|
|
\begin{pgfscope}
|
|
\edef\msc@shape{condition shape}
|
|
\pgfutil@ifnextchar*{\msc@isstartrue\msc@cond@star}{\msc@isstarfalse\msc@cond@star*}
|
|
}
|
|
\def\ncondition{
|
|
\begin{pgfscope}
|
|
\edef\msc@shape{ncondition shape}
|
|
\pgfutil@ifnextchar*{\msc@isstartrue\msc@cond@star}{\msc@isstarfalse\msc@cond@star*}
|
|
}
|
|
% \ncondition(*)[options]{text}{instancelist}
|
|
\def\msc@cond@star*{
|
|
\pgfutil@ifnextchar[{\msc@condition}{\msc@condition[]}
|
|
}
|
|
\newif\ifmsc@isfirst
|
|
\def\msc@condition[#1]#2#3{
|
|
\mscset{inner sep=\mscget{label distance},#1}
|
|
\msc@isfirsttrue
|
|
\@for\msc@arg:=#3\do{%
|
|
\pgfkeysifdefined{/msc/instance/\msc@arg/no}{
|
|
\ifmsc@isfirst%first instance in the list
|
|
\mscgetx{(msc@node\msc@arg @l0)}{\msc@minx}
|
|
\mscgetx{(msc@node\msc@arg @r0)}{\msc@maxx}
|
|
\mscgety{(msc@level\the\c@msclevelcnt)}{\msc@y}
|
|
\else
|
|
\mscgetx{(msc@node\msc@arg @r0)}{\msc@x}
|
|
\pgfmathparse{max(\msc@x,\msc@maxx)}
|
|
\edef\msc@maxx{\pgfmathresult pt}
|
|
\mscgetx{(msc@node\msc@arg @l0)}{\msc@x}
|
|
\pgfmathparse{min(\msc@x,\msc@minx)}
|
|
\edef\msc@minx{\pgfmathresult pt}
|
|
\fi
|
|
\msc@isfirstfalse
|
|
\xdef\msc@instname{\msc@arg}
|
|
}{
|
|
\msc@instundefinederr{\msc@arg}
|
|
}
|
|
}
|
|
\ifmsc@isfirst \else%there are proper instances
|
|
\pgfmathparse{2*\mscget{condition overlap}+\msc@maxx-\msc@minx}
|
|
\edef\msc@width{\pgfmathresult pt}
|
|
\ifmsc@isstar
|
|
\def\msc@tempr{}
|
|
\else
|
|
%\msc@savebox{\parbox{\msc@width}{#2}}
|
|
\edef\msc@tempr{%text depth={\the\dp\msc@box},
|
|
% text height={{\the\ht\msc@box+\the\dp\msc@box}},
|
|
align=center, text width=\msc@width-2*\mscget{label distance},}
|
|
\fi
|
|
\def\aa{aeee}
|
|
\xdef\msc@tempb{[/msc, draw, anchor=north,shape=\msc@shape,
|
|
\msc@tempr
|
|
inner sep=\mscget{label distance},
|
|
minimum height=\mscget{condition height},
|
|
minimum width=\msc@width,
|
|
every condition,/tikz/line width=\mscget{line width}, #1](msc@condition@\the\c@condition)
|
|
at ({(\msc@maxx+\msc@minx)/2},\msc@y) {\unexpanded\expandafter{#2}};
|
|
}
|
|
\fi
|
|
\end{pgfscope}
|
|
\adddraw{\msc@instname}{\the\c@msclevelcnt}{\expandafter\node\msc@tempb }
|
|
\@for\msc@args:=#3\do{%
|
|
\edef\msc@tempa{\noexpand\mscgety{(msc@condition@\the\c@condition.south)}{\noexpand\msc@y}
|
|
\noexpand\msc@setlastlevel{\msc@args}{\noexpand\msc@y}}
|
|
% \show\msc@tempa
|
|
\adddraw{\msc@args}{\the\c@msclevelcnt}{\msc@tempa}
|
|
}
|
|
}
|
|
% \order[side]{sender}{receiver}[level shift]
|
|
\def\order{
|
|
\begin{pgfscope}
|
|
\def\msc@options{}
|
|
\pgfutil@ifnextchar[{\msc@order@opt}{\msc@order@opt[]}
|
|
}
|
|
\def\msc@order@opt[#1]{
|
|
\ifx#1l \mscset{side=left}
|
|
\else \ifx#1r \mscset{side=right}
|
|
\else
|
|
\mscset{#1}
|
|
\def\msc@options{#1}
|
|
\fi
|
|
\fi
|
|
\pgfutil@ifnextchar[{\msc@order@opt}{\msc@order@noopt}
|
|
}
|
|
\def\msc@order@noopt#1#2{
|
|
\xdef\msc@sender{#1}
|
|
\xdef\msc@receiver{#2}
|
|
\pgfutil@ifnextchar[{\msc@order}{\msc@order[\mscget{level shift}]}
|
|
}
|
|
\def\msc@order[#1]{
|
|
\pgfkeysifdefined{/msc/instance/\msc@receiver/no}{
|
|
\pgfkeysifdefined{/msc/instance/\msc@sender/no}{
|
|
\msc@getlevel shift{#1}{\msc@level shift}{\msc@tempa}
|
|
\ifx\msc@sender\msc@receiver %self message
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\def\msc@dir{l}
|
|
\edef\msc@dist{-\mscget{self message width}}
|
|
}{
|
|
\def\msc@dir{r}
|
|
\edef\msc@dist{\mscget{self message width}}
|
|
}
|
|
\xdef\msc@tempb{[/msc, order loop={\msc@dist},
|
|
every order, \msc@options]
|
|
(msc@node\msc@sender @\msc@dir\the\c@msclevelcnt) to
|
|
(msc@node\msc@receiver @\msc@dir\msc@level shift);
|
|
}
|
|
\else
|
|
\ifnum\mscget{instance/\msc@sender/no}\expandafter<\mscget{instance/\msc@receiver/no}\relax
|
|
\def\msc@ldir{r}
|
|
\def\msc@rdir{l}
|
|
\else
|
|
\def\msc@ldir{l}
|
|
\def\msc@rdir{r}
|
|
\fi
|
|
\xdef\msc@tempb{[/msc,order,every order,\msc@options]
|
|
(msc@node\msc@sender @\msc@ldir\the\c@msclevelcnt) to
|
|
(msc@node\msc@receiver @\msc@rdir\msc@level shift);
|
|
}
|
|
\fi
|
|
\end{pgfscope}
|
|
\addDdraw{\msc@sender}{\msc@receiver}{\msc@tempa}{\expandafter\draw\msc@tempb}
|
|
}{\msc@instundefinederr{\msc@sender}\end{pgfscope}}
|
|
}{\msc@instundefinederr{\msc@receiver}\end{pgfscope}}
|
|
}
|
|
|
|
% update the lastlevel for a given instance
|
|
% #1 name of the instance
|
|
% #2 level number
|
|
\def\msc@updatelastlevel#1#2{
|
|
\msc@StrEqEither{#1}{envright}{envleft} {}{
|
|
\path let \p1 = (msc@lastlevel#1), \p2 = (msc@level#2)
|
|
in coordinate (msc@lastlevel#1) at (\x1,{min(\y1,\y2)});
|
|
}
|
|
}
|
|
% set the lastlevel for a given instance
|
|
% #1 name of the instance
|
|
% #2 new height
|
|
\def\msc@setlastlevel#1#2{
|
|
\msc@StrEqEither{#1}{envright}{envleft} {}{
|
|
\draw let \p1 = (msc@lastlevel#1) in coordinate (msc@lastlevel#1)
|
|
at (\x1,{min(\y1,#2)});
|
|
}
|
|
}
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% CO-REGIONS
|
|
%
|
|
% \coregionstart starts a coregion on instance #1 (nickname) in the current level.
|
|
\def\coregionstart{\pgfutil@ifnextchar[{\msc@coreg}{\msc@coreg[]}}
|
|
\def\msc@coreg[#1]#2{
|
|
\regionstart[#1]{coregion}{#2}}
|
|
% \coregionend ends a coregion on instance #1 (nickname) in the current level.
|
|
\def\coregionend#1{\regionend{#1}}%
|
|
%
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% REGIONS (normal, coregion, suspension, and activation)
|
|
%
|
|
%
|
|
|
|
% define the begining of a region on the instance line
|
|
%\regionstart[options]{type}{instname}
|
|
% instance/#2/region/.initial=line, %possible % values:normal,coregion,suspension,activation
|
|
\def\regionstart{\pgfutil@ifnextchar[\msc@regionstart{\msc@regionstart[]}}
|
|
\def\msc@regionstart[#1]#2#3{
|
|
\begin{pgfscope}
|
|
\mscset{#1}
|
|
\xdef\msc@tempa{\mscget{region width}}
|
|
\end{pgfscope}
|
|
\pgfkeysifdefined{/msc/instance/#3/no}{
|
|
\msc@StrEqEither{\mscget{instance/#3/region}}{normal}{seminormal}{
|
|
\msc@drawinstanceline{#2}{\the\c@msclevelcnt}
|
|
\IfEqCase{#2} {{coregion}{} {activation}{} {suspension}{}}
|
|
[\msc@unknownregionstyleerr{#2}]
|
|
\mscset{instance/#3/region={#2},
|
|
instance/#3/region level/.expand once={\the\c@msclevelcnt},
|
|
instance/#3/region width/.expand once=\msc@tempa}%
|
|
\msc@regbar{#3}{\the\c@msclevelcnt}
|
|
}
|
|
{msc@regionstartederr{#3}{\mscget{instance/#3/region}}}
|
|
}
|
|
{\msc@instundefinederr{#3}}
|
|
}
|
|
%helper function to draw region horizontal bar(s)
|
|
% #1 instname
|
|
% #2 level
|
|
\def\msc@regbar#1#2{
|
|
\xdef\msc@temp@body{}
|
|
\edef\msc@region{\mscget{instance/#1/region}}
|
|
\pgfpointanchor{msc@level#2}{center}
|
|
\edef\msc@regbar@tempb{\the\pgf@y}
|
|
\pgfpointanchor{msc@lastlevel#1}{center}
|
|
\pgfmathparse{\msc@regbar@tempb-\the\pgf@y}
|
|
\ifnum0<\pgfmathresult\relax
|
|
\else
|
|
\IfStrEq{\mscget{instance/#1/type}}{fat}{
|
|
\IfStrEq{\msc@region}{coregion}{
|
|
\xdef\msc@temp@body{
|
|
[/msc,/tikz/line width=\mscget{line width}, draw, every region,every
|
|
coregion] let \noexpand\p1=(msc@node#1@l#2) in
|
|
(\noexpand\x1-\mscget{instance/#1/region width}/2-\mscget{line width}/2,\noexpand\y1) --
|
|
(\noexpand\x1+\mscget{instance/#1/region width}/2+\mscget{line
|
|
width}/2,\noexpand\y1);
|
|
\noexpand\draw [/msc,/tikz/line width=\mscget{line width}, every region,every
|
|
coregion] let \noexpand\p1=(msc@node#1@r#2) in
|
|
(\noexpand\x1-\mscget{instance/#1/region width}/2-\mscget{line width}/2,\noexpand\y1) --
|
|
(\noexpand\x1+\mscget{instance/#1/region width}/2+\mscget{line width}/2,\noexpand\y1);
|
|
}
|
|
}{
|
|
\xdef\msc@temp@body{
|
|
[/msc,/tikz/line width=\mscget{line width}, draw, every region,every \msc@region] let
|
|
\noexpand\p1=(msc@node#1@l#2), \noexpand\p2=(msc@node#1@r#2) in
|
|
(\noexpand\x1-\mscget{line width}/2,\noexpand\y1)--(\noexpand\x2+\mscget{line width}/2,\noexpand\y2);
|
|
}
|
|
}
|
|
}{
|
|
\IfStrEq{\msc@region}{coregion}{
|
|
\xdef\msc@temp@body{
|
|
[/msc,/tikz/line width=\mscget{line width}, draw, every region,every coregion] let
|
|
\noexpand\p1=(msc@node#1@l#2) in
|
|
(\noexpand\x1-\mscget{instance/#1/region width}/2-\mscget{line width}/2,\noexpand\y1) --
|
|
(\noexpand\x1+\mscget{instance/#1/region width}/2+\mscget{line width}/2,\noexpand\y1);
|
|
}
|
|
}{
|
|
\xdef\msc@temp@body{
|
|
[/msc,/tikz/line width=\mscget{line width}, draw, every region, every \msc@region]
|
|
let
|
|
\noexpand\p1=(msc@node#1@l#2), \noexpand\p2=(msc@node#1@r#2) in
|
|
(\noexpand\x1-\mscget{line width}/2,\noexpand\y1)--(\noexpand\x2+\mscget{line width}/2,\noexpand\y2);
|
|
}
|
|
}
|
|
}
|
|
% \show\msc@temp@body
|
|
\adddraw{#1}{\the\c@msclevelcnt}{\expandafter\path\msc@temp@body}
|
|
\adddraw{#1}{\the\c@msclevelcnt}{\mscgety{(msc@lastlevel#1)}{\msc@yo}\msc@setlastlevel{#1}{\msc@yo-\mscget{line width}/2}}
|
|
\fi
|
|
}
|
|
% draw the instance line with the region
|
|
% #1 instname
|
|
% #2 level
|
|
\def\msc@regbody#1#2{
|
|
\xdef\msc@temp@body{;}
|
|
\pgfpointanchor{msc@level#2}{center}
|
|
\edef\msc@regbody@tempb{\the\pgf@y}
|
|
\pgfpointanchor{msc@lastlevel#1}{center}
|
|
\pgfmathparse{\msc@regbody@tempb-\the\pgf@y}
|
|
\ifnum0<\pgfmathresult\relax
|
|
\else
|
|
\IfEqCase{\mscget{instance/#1/region}}{
|
|
{coregion}{
|
|
\IfStrEq{\mscget{instance/#1/type}}{fat}{
|
|
\xdef\msc@temp@body{
|
|
[/msc,/tikz/line width=\mscget{line width}, draw, mscdash, every region, every coregion]
|
|
let \noexpand\noexpand\noexpand\p1=(msc@node#1@r#2), \noexpand\noexpand\noexpand\p2=(msc@lastlevel#1) in
|
|
(\noexpand\noexpand\noexpand\x1,\noexpand\noexpand\noexpand\y2)--
|
|
(\noexpand\noexpand\noexpand\x1,{min(\noexpand\noexpand\noexpand\y2,\noexpand\noexpand\noexpand\y1)});
|
|
}
|
|
}{\xdef\msc@temp@body{;}}
|
|
\xdef\msc@temp@body{
|
|
[/msc,/tikz/line width=\mscget{line width}, draw, mscdash, every region, every coregion]
|
|
let \noexpand\p1=(msc@node#1@l#2), \noexpand\p2=(msc@lastlevel#1) in
|
|
(\noexpand\x1,\noexpand\y2)--(\noexpand\x1,{min(\noexpand\y2,\noexpand\y1)});\noexpand\path\msc@temp@body
|
|
}
|
|
}%
|
|
{activation}{
|
|
\xdef\msc@temp@body{
|
|
[/msc,fill=lightgray,/tikz/line width=\mscget{line width},every region, every activation]
|
|
(msc@node#1@l#2|-msc@lastlevel#1) rectangle(msc@node#1@r#2);
|
|
\noexpand\draw[/msc,/tikz/line width=\mscget{line width},every region, every activation]
|
|
(msc@node#1@l#2) -- (msc@node#1@l#2|-msc@lastlevel#1)
|
|
(msc@node#1@r#2) -- (msc@node#1@r#2|-msc@lastlevel#1);
|
|
}
|
|
}%
|
|
{suspension}{
|
|
\xdef\msc@temp@body{
|
|
[/msc,draw,suspension dash,
|
|
/tikz/line width=\mscget{line width},every region, every activation]
|
|
(msc@node#1@r#2)--(msc@node#1@r#2|-msc@lastlevel#1)
|
|
(msc@node#1@l#2)--(msc@node#1@l#2|-msc@lastlevel#1);
|
|
}
|
|
}%
|
|
}[]
|
|
\adddraw{#1}{\the\c@msclevelcnt}{\expandafter\path\msc@temp@body}
|
|
\fi
|
|
}
|
|
% define the end of region
|
|
%\regionend{instname}
|
|
\def\regionend#1{
|
|
\pgfkeysifdefined{/msc/instance/#1/no}{
|
|
\edef\msc@region{\mscget{instance/#1/region}}
|
|
\IfStrEq{\msc@region}{normal}{
|
|
\msc@regionnotstartederr{#1}
|
|
}
|
|
\msc@regbody{#1}{\the\c@msclevelcnt}
|
|
\msc@regbar{#1}{\mscget{instance/#1/region level}}
|
|
\msc@regbar{#1}{\the\c@msclevelcnt}
|
|
\adddraw{#1}{\the\c@msclevelcnt}{\msc@updatelastlevel{#1}{\the\c@msclevelcnt}}
|
|
\msc@StrEqEither{\msc@region}{suspension}{activation}{
|
|
\mscset{instance/#1/region=seminormal}
|
|
}{\mscset{instance/#1/region=normal}}
|
|
}
|
|
{
|
|
\msc@instundefinederr{#1}
|
|
}
|
|
}
|
|
%macro stores first character in \msc@fst and last character in \msc@lst
|
|
\def\msc@fl#1{\msc@flx#1\empty\empty\empty}
|
|
\def\msc@flx#1#2#3\empty{%
|
|
\edef\msc@fst{#1}%
|
|
\edef\msc@cdar{#2}%
|
|
\edef\msc@cddr{#3}%
|
|
\ifx\msc@cddr\empty
|
|
\let\msc@lst\msc@cdar
|
|
\else
|
|
\expandafter\msc@flxx
|
|
\fi
|
|
#3}
|
|
\def\msc@flxx#1#2\empty{%
|
|
\edef\msc@car{#1}%
|
|
\ifx\msc@car\empty
|
|
\else
|
|
\let\msc@lst\msc@car
|
|
\expandafter\msc@flxx
|
|
\fi
|
|
#2\empty}
|
|
%\referencestart[options][lo][ro]{nickname}{text}{leftinstance}{rightinstance}
|
|
\def\referencestart{
|
|
\begin{pgfscope}\gdef\msc@options{}
|
|
\pgfutil@ifnextchar[\msc@refstartlo{\msc@refstartloro}}
|
|
\def\msc@refstartloro{
|
|
\edef\msc@lo{\mscget{left reference overlap}}
|
|
\edef\msc@ro{\mscget{right reference overlap}}
|
|
\msc@refstart
|
|
}
|
|
\def\msc@refstartlo[#1]{
|
|
\expandafter\expandafter\expandafter\msc@fl\expandafter{#1}
|
|
\msc@caseFiveEither{\msc@fst}{1}{2}{3}{4}{5}{
|
|
\edef\msc@lo{#1} \pgfutil@ifnextchar[\msc@refstartro{\msc@refstartro[\mscget{right reference overlap}]}
|
|
}{
|
|
\msc@caseFiveEither{\msc@fst}{6}{7}{8}{9}{0}{
|
|
\edef\msc@lo{#1} \pgfutil@ifnextchar[\msc@refstartro{\msc@refstartro[\mscget{right reference overlap}]}
|
|
}{
|
|
\msc@StrEqEither{\msc@fst}{-}{.}{
|
|
\edef\msc@lo{#1} \pgfutil@ifnextchar[\msc@refstartro{\msc@refstartro[\mscget{right reference overlap}]}
|
|
}{
|
|
\mscset{#1}
|
|
\xdef\msc@options{#1}
|
|
\pgfutil@ifnextchar[\msc@refstartlo{\msc@refstartloro}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
\def\msc@refstartro[#1]{
|
|
\edef\msc@ro{#1}\msc@refstart
|
|
}
|
|
\def\msc@refstart#1#2#3#4{
|
|
\pgfkeysifdefined{/msc/instance/#3/no}{
|
|
\pgfkeysifdefined{/msc/instance/#4/no}{
|
|
\path[draw] (msc@level\the\c@msclevelcnt-|msc@node#3@l0) ++(-\msc@lo,0) coordinate
|
|
(msc@node#1left)
|
|
(msc@level\the\c@msclevelcnt-|msc@node#4@r0) ++(\msc@ro,0) coordinate
|
|
(msc@node#1right);
|
|
\end{pgfscope}
|
|
\msc@cover{#3}{#4}{+}
|
|
\mscset{
|
|
reference/#1/options/.style/.expanded=\msc@options,
|
|
reference/#1/left/.initial=#3,
|
|
reference/#1/text/.initial={#2},
|
|
reference/#1/right/.initial=#4
|
|
}
|
|
}{
|
|
\end{pgfscope}\msc@instundefinederr{#4}
|
|
}
|
|
}{
|
|
\end{pgfscope}\msc@instundefinederr{#3}
|
|
}
|
|
}
|
|
\def\msc@cover#1#2#3{
|
|
\pgfmathparse{\mscget{instance/#2/cover} #3 1}
|
|
\mscset{instance/#2/cover/.expand once=\pgfmathresult}
|
|
\IfStrEq{#1}{#2}{}{
|
|
\ifnum0<\mscget{instance/\msc@inst@name/no}
|
|
\msc@previousinstance{#2}
|
|
\msc@cover{#1}{\msc@inst@name}{#3}
|
|
\msc@regbody{\msc@inst@name}{\the\c@msclevelcnt}
|
|
\else
|
|
\fi
|
|
}
|
|
}
|
|
\def\referenceend#1{
|
|
\pgfkeysifdefined{/msc/reference/#1/left}{%calculating framearch
|
|
\mscgetx{(msc@node#1left)}{\msc@xa}
|
|
\mscgetx{(msc@node#1right)}{\msc@xb}
|
|
\mscgety{(msc@node#1left)}{\msc@yb}
|
|
\mscgety{(msc@level\the\c@msclevelcnt)}{\msc@ya}
|
|
\pgfmathparse{0.25/2 *min(\msc@xb-\msc@xa,\msc@yb-\msc@ya)}
|
|
\edef\msc@tempa{\pgfmathresult}
|
|
\msc@cover{\mscget{reference/#1/left}}{\mscget{reference/#1/right}}{-}
|
|
\node[/msc,fit={(msc@node#1left) (msc@node#1right)
|
|
(msc@node#1right|-msc@level\the\c@msclevelcnt)},
|
|
draw,rectangle, rounded corners=\msc@tempa pt, inner sep=0,/tikz/line
|
|
width=\mscget{line width},every reference,
|
|
/msc/reference/#1/options
|
|
]{\mscget{reference/#1/text}};
|
|
}{
|
|
\msc@refundefinederr{#1}
|
|
}
|
|
}
|
|
%\inlinestart[options][lo][ro]{nickname}{text}{leftinstance}{rightinstance}
|
|
\def\inlinestart{
|
|
\begin{pgfscope}
|
|
\gdef\msc@options{}
|
|
\pgfutil@ifnextchar[\msc@inlstartlo{\msc@inlstartloro}
|
|
}
|
|
\def\msc@inlstartloro{
|
|
\edef\msc@lo{\mscget{left inline overlap}}
|
|
\edef\msc@ro{\mscget{right inline overlap}}
|
|
\msc@inlstart
|
|
}
|
|
|
|
\def\msc@inlstartlo[#1]{
|
|
\expandafter\expandafter\expandafter\msc@fl\expandafter{#1}
|
|
\msc@caseFiveEither{\msc@fst}{1}{2}{3}{4}{5}{
|
|
\edef\msc@lo{#1}
|
|
\pgfutil@ifnextchar[\msc@inlstartro{\msc@inlstartro[\mscget{right inline overlap}]}
|
|
}{
|
|
\msc@caseFiveEither{\msc@fst}{6}{7}{8}{9}{0}{
|
|
\edef\msc@lo{#1} \pgfutil@ifnextchar[\msc@inlstartro{\msc@inlstartro[\mscget{right inline overlap}]}
|
|
}{
|
|
\msc@StrEqEither{\msc@fst}{-}{.}{
|
|
\edef\msc@lo{#1}
|
|
\pgfutil@ifnextchar[\msc@inlstartro{\msc@inlstartro[\mscget{right inline overlap}]}
|
|
}{
|
|
\mscset{#1}
|
|
\xdef\msc@options{#1}
|
|
\pgfutil@ifnextchar[\msc@inlstartlo{\msc@inlstartloro}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
\def\msc@inlstartro[#1]{
|
|
\edef\msc@ro{#1}\msc@inlstart
|
|
}
|
|
%msc@inlstart{nickname}{text}{leftinstance}{rightinstance}
|
|
\def\msc@inlstart#1#2#3#4{
|
|
\pgfkeysifdefined{/msc/instance/#3/no}{
|
|
\pgfkeysifdefined{/msc/instance/#4/no}{
|
|
\path[draw] (msc@level\the\c@msclevelcnt-|msc@node#3@l0) ++(-\msc@lo,0) coordinate
|
|
(msc@node#1left)
|
|
(msc@level\the\c@msclevelcnt-|msc@node#4@r0) ++(\msc@ro,0) coordinate
|
|
(msc@node#1right);
|
|
\end{pgfscope}
|
|
\mscset{
|
|
inline/#1/options/.style/.expanded=\msc@options,
|
|
inline/#1/left/.initial={#3},
|
|
inline/#1/text/.initial={#2}
|
|
}
|
|
}{
|
|
\end{pgfscope}\msc@instundefinederr{#4}
|
|
}
|
|
}{
|
|
\end{pgfscope}\msc@instundefinederr{#3}
|
|
}
|
|
}
|
|
%\inlineseparator[options]{nickname}
|
|
\def\inlineseparator{
|
|
\begin{pgfscope}
|
|
\pgfutil@ifnextchar[\msc@inlseparator{\msc@inlseparator[]}
|
|
}
|
|
\def\msc@inlseparator[#1]#2{
|
|
\pgfkeysifdefined{/msc/inline/#2/left}{
|
|
\mscset{#1}
|
|
\end{pgfscope}
|
|
\path[/msc,draw, mscdash,
|
|
/tikz/line width=\mscget{line width},
|
|
dash phase=2pt,
|
|
every inline,inline/#2/options,#1]
|
|
(msc@node#2left|-msc@level\the\c@msclevelcnt)--(msc@node#2right|-msc@level\the\c@msclevelcnt);
|
|
}{
|
|
\msc@inlundefinederr{#2}
|
|
\end{pgfscope}
|
|
}
|
|
}
|
|
%\inlineend{nickname}
|
|
\def\inlineend{
|
|
\pgfutil@ifnextchar*{\msc@isstartrue\msc@inlineend}{\msc@isstarfalse\msc@inlineend*}
|
|
}
|
|
\def\msc@inlineend*#1{
|
|
\pgfkeysifdefined{/msc/inline/#1/text}{
|
|
\path[/msc,draw,
|
|
/tikz/line width=\mscget{line width},
|
|
every inline,inline/#1/options]
|
|
(msc@node#1left) node[/msc,draw,chamfered rectangle,
|
|
chamfered rectangle corners=south east,
|
|
chamfered rectangle xsep=\mscget{label distance}/2,
|
|
chamfered rectangle ysep=\mscget{label distance}/2,
|
|
inner sep=\mscget{label distance}/4,
|
|
xshift=-\mscget{line width}/2, yshift=\mscget{line width}/2,
|
|
anchor=north west,inline/#1/options](a)
|
|
{\mscget{inline/#1/text}}
|
|
(msc@node#1left|-msc@level\the\c@msclevelcnt)++(0,-\mscget{line width}/2)
|
|
--(msc@node#1left)--(msc@node#1right)--
|
|
(msc@node#1right|-msc@level\the\c@msclevelcnt)--++(0,-\mscget{line width}/2);
|
|
\ifmsc@isstar
|
|
\inlineseparator{#1}
|
|
\else
|
|
\inlineseparator[solid]{#1}
|
|
\fi
|
|
}{
|
|
\msc@refundefinederr{#1}
|
|
}
|
|
}
|
|
%\gate(*)[options][hpos][vpos]{gatename}{instname}
|
|
\def\gate{
|
|
\begin{pgfscope}
|
|
\def\msc@options{}
|
|
\pgfutil@ifnextchar*{\msc@isstartrue\msc@gate@star}{\msc@isstarfalse\msc@gate@star*}
|
|
}
|
|
\def\msc@gate@star*{
|
|
\pgfutil@ifnextchar[{\msc@gate@opt}{\msc@gate@opt[]}
|
|
}
|
|
\def\msc@gate@opt[#1]{
|
|
\IfStrEq{#1}{l}{\mscset{side=left} \pgfutil@ifnextchar[\msc@gate{\msc@gate[]}
|
|
}{
|
|
\IfStrEq{#1}{r}{\mscset{side=right}\pgfutil@ifnextchar[\msc@gate{\msc@gate[]}
|
|
}{
|
|
\mscset{#1}
|
|
\def\msc@options{#1}
|
|
\pgfutil@ifnextchar[\msc@gate@opt{\msc@gate[]}
|
|
}
|
|
}
|
|
}
|
|
\def\msc@gate[#1]#2#3{
|
|
\def\msc@undefined{false}
|
|
\ifx#1c \mscset{position=mid} \else
|
|
\ifx#1b \mscset{position=below} \else
|
|
\ifx#1t \mscset{position=above} \fi \fi \fi
|
|
\pgfkeysifdefined{/msc/instance/#3/no}{%instance name
|
|
\IfStrEq{\mscget{side}}{left}{
|
|
\edef\msc@node{msc@node#3@l\the\c@msclevelcnt}
|
|
}{
|
|
\edef\msc@node{msc@node#3@r\the\c@msclevelcnt}
|
|
}
|
|
}{
|
|
\pgfutil@ifundefined{pgf@sh@ns@msc@node#3}{% neither instance name nor reference node
|
|
\def\msc@undefined{true}
|
|
\msc@instundefinederr{#3}
|
|
}
|
|
{
|
|
\edef\msc@node{msc@node#3|-msc@level\the\c@msclevelcnt}
|
|
}
|
|
}
|
|
\IfStrEq{\msc@undefined}{false}{
|
|
\ifmsc@isstar
|
|
\xdef\msc@tempb{[fill,\msc@options] (\msc@node)
|
|
node[\mscget{position}
|
|
\mscget{side}]{\unexpanded\expandafter{#2}} circle (\mscget{gate symbol radius});}
|
|
\edef\msc@tempa{\noexpand\noexpand\noexpand\path[fill,line width=0pt](\msc@node) circle (\mscget{gate symbol radius});}
|
|
\else
|
|
\xdef\msc@tempb{[\msc@options] (\msc@node) node[\mscget{position} \mscget{side}]{\unexpanded\expandafter{#2}};}
|
|
\fi
|
|
}{}
|
|
\end{pgfscope}
|
|
\adddraw{#3}{\the\c@msclevelcnt}{\expandafter\path\msc@tempb}
|
|
}
|
|
|
|
\def\inststop{\stop*}%old name of command
|
|
%\stop(*)[options]{instancename}
|
|
\def\stop{\pgfutil@ifnextchar*{\msc@isstartrue\msc@stop@nostar}{\msc@isstarfalse\msc@stop@nostar*}}
|
|
\def\msc@stop@nostar*{\pgfutil@ifnextchar[\msc@stop{\msc@stop[]}}
|
|
\def\msc@stop[#1]#2{
|
|
\pgfkeysifdefined{/msc/instance/#2/no}{
|
|
\IfStrEq{on}{\mscget{instance/#2/status}}{
|
|
\msc@global@set{instance/#2/status=off}
|
|
\begin{pgfscope}
|
|
\mscset{#1}
|
|
\ifmsc@isstar \mscset{instance end=foot} \fi
|
|
\IfStrEq{\mscget{instance end}}{foot}{
|
|
\xdef\msc@tempb{[/msc,fill=\mscget{draw foot},/tikz/line width=\mscget{line width}, every instance foot,#1]
|
|
(msc@lastlevel#2-|msc@node#2.east)
|
|
++(0,-\mscget{foot height}) rectangle
|
|
(msc@lastlevel#2-|msc@node#2.west)
|
|
(msc@lastlevel#2-|msc@node#2.south)
|
|
++(0,-\mscget{foot height})
|
|
coordinate (msc@foot#2);
|
|
}
|
|
}{
|
|
\xdef\msc@tempb{[/msc,draw=\mscget{draw foot}, /tikz/line width=\mscget{line width},
|
|
every instance foot,#1]
|
|
(msc@node#2@l\the\c@msclevelcnt) ++(-\mscget{line width}/2,0)--
|
|
($(msc@node#2@l\the\c@msclevelcnt)!0.5!(msc@node#2@r\the\c@msclevelcnt)$)
|
|
coordinate (msc@foot#2)
|
|
++(\mscget{stop width}/2,\mscget{stop width}/2)
|
|
-- ++(-\mscget{stop width},-\mscget{stop width})
|
|
++(0,\mscget{stop width})
|
|
-- ++(\mscget{stop width},-\mscget{stop width})
|
|
++(-\mscget{stop width}/2,\mscget{stop width}/2)
|
|
-- (msc@node#2@r\the\c@msclevelcnt)
|
|
--++(\mscget{line width}/2,0);
|
|
}
|
|
}
|
|
\end{pgfscope}
|
|
\adddraw{#2}{\the\c@msclevelcnt}{\expandafter\path\msc@tempb}
|
|
}{}
|
|
}{\msc@instundefinederr{#2}}
|
|
}
|
|
|
|
\def\mscunit{cm}%
|
|
\def\msckeywordstyle#1{\textbf{#1}}
|
|
\newcommand{\setmsckeyword}[1]{\mscset{/msc/msc keyword={#1}}}
|
|
\newcommand{\setmsckeywordstyle}[1]{\def\msckeywordstyle{#1}}%
|
|
\newcommand{\drawframe}[1]{\IfStrEq{#1}{yes}{\mscset{draw frame=}}{\IfStrEq{#1}{no}{\mscset{draw frame=none}}{}}}%
|
|
\newcommand{\drawinsthead}[1]{\IfStrEq{#1}{yes}{\mscset{draw head=}}{\IfStrEq{#1}{no}{\mscset{draw head=none}}{}}}
|
|
\newcommand{\drawinstfoot}[1]{\IfStrEq{#1}{yes}{\mscset{draw foot=}}{\IfStrEq{#1}{no}{\mscset{draw foot=none}}{}}}
|
|
\newcommand{\showgrid}{\mscset{draw grid}}
|
|
\newcommand{\nogrid}{\mscset{draw grid={none}}}
|
|
\newcommand{\setmscscale}[1]{\mscset{msc scale=#1}}%
|
|
\newcommand{\messarrowscale}[1]{\mscset{arrow scale=#1}}%
|
|
|
|
%\mscset but globally
|
|
\def\msc@global@set#1{\globaldefs=1\relax\mscset{#1}\globaldefs=0\relax}%
|
|
|
|
% the msc-environment
|
|
% \begin{msc}[options][headerpos]{mscname}
|
|
% ...definition of the MSC...
|
|
% \end{msc}
|
|
%\regionend{instname}
|
|
\def\msc{%
|
|
\pgfutil@ifnextchar[\msc@mscopt{\msc@mscopt[l]}
|
|
}
|
|
\def\msc@mscopt[#1]{%
|
|
% \msc@titlejustification says how the title should be justified
|
|
% Justification is relative to the total width of the msc
|
|
% l: left (default)
|
|
% c: centered
|
|
% r: right
|
|
\ifx#1l
|
|
\mscset{title position=left}
|
|
\else \ifx#1c
|
|
\mscset{title position=center}
|
|
\else \ifx#1r
|
|
\mscset{title position=right}
|
|
\else
|
|
\pgfutil@ifundefined{msc@tikzstarted}
|
|
{
|
|
\tikzpicture[/msc,#1]%
|
|
\def\msc@tikzstarted{}}%
|
|
{
|
|
\relax}
|
|
\fi
|
|
\fi
|
|
\fi
|
|
\pgfutil@ifnextchar[{\msc@mscopt}{\msc@mscnoopt}
|
|
}
|
|
% core of msc with options parsed -
|
|
\def\msc@mscnoopt#1{% parse name
|
|
% #1: mscname
|
|
\pgfutil@ifundefined{msc@tikzstarted}
|
|
{
|
|
\tikzpicture\def\msc@tikzstarted{}%
|
|
}%
|
|
{\relax}
|
|
% Options handling ends here
|
|
\c@mscinstcnt 0\relax% initialize number of instances to 0
|
|
\c@condition 0\relax% initialize number of condition to 0
|
|
\c@msclevelcnt 1\relax% initialize level to 1
|
|
\gdef\c@maxlevelcnt{0}% initialize maximum encountered level to 0
|
|
% \msc@global@set{
|
|
% }
|
|
\mscset{
|
|
/tikz/scale/.expanded=\mscget{msc scale},
|
|
/tikz/every node/.style/.expanded={scale/.expanded=\mscget{msc scale}},
|
|
instance/envleft/no/.initial=0,
|
|
instance/envright/no/.initial=1,
|
|
instanceno/0/name/.initial=envleft,%
|
|
instanceno/1/name/.initial=envright,
|
|
instance/envleft/type/.initial=environment,
|
|
instance/envright/type/.initial=environment,
|
|
instance/envleft/region/.initial=normal,
|
|
instance/envright/region/.initial=normal,
|
|
instance/envleft/status/.initial=on,
|
|
instance/envright/status/.initial=on,
|
|
/msc/msc/name/.initial={#1}
|
|
}
|
|
\pgfmathparse{0-\mscget{head top distance} - \mscget{head height}}
|
|
\xdef\msc@tempa{\pgfmathresult}
|
|
\coordinate (msc@level0) at (0,\msc@tempa pt);
|
|
\coordinate (msc@nodeenvright) at (0,\msc@tempa pt);
|
|
\coordinate (msc@nodeenvleft) at (0,\msc@tempa pt);
|
|
\coordinate (msc@footenvleft) at (msc@nodeenvleft);
|
|
\coordinate[below=\mscget{first level height} of msc@level0] (msc@level1);
|
|
}
|
|
\def\msc@drawgrid{
|
|
\begin{pgfonlayer}{background}
|
|
\pgfpointanchor{current bounding box}{south west}
|
|
\pgfmathparse{ceil(\pgf@x/\pgf@xx)}%pgf@xx stores 1 of current unit (e.g. 1cm)
|
|
\edef\msg@xa{\pgfmathresult}%
|
|
\pgfmathparse{ceil(\pgf@y/\pgf@yy)}%
|
|
\edef\msg@ya{\pgfmathresult}%
|
|
\pgfpointanchor{current bounding box}{north east}
|
|
\pgfmathparse{floor(\pgf@x/\pgf@xx)}%
|
|
\edef\msg@xb{\pgfmathresult}%
|
|
\pgfmathparse{floor(\pgf@y/\pgf@yy)}%
|
|
\edef\msg@yb{\pgfmathresult}%
|
|
\path (\msg@xa,\msg@ya) to[/msc/\mscget{draw grid}](\msg@xb,\msg@yb);
|
|
\end{pgfonlayer}
|
|
}
|
|
%\def\endmsc[options]
|
|
\def\endmsc{%
|
|
% \let\setlength\msc@OrigSL
|
|
\pgfutil@ifnextchar[\msc@endmsc{\msc@endmsc[]}
|
|
\endtikzpicture
|
|
\global\let\msc@tikzstarted\relax
|
|
}
|
|
\def\msc@endmsc[#1]{
|
|
\begin{pgfscope}
|
|
\mscset{#1}
|
|
\ifnum0<\c@mscinstcnt\relax
|
|
\ifnum\c@msclevelcnt<\c@maxlevelcnt\relax
|
|
\pgfmathparse{\c@maxlevelcnt-\the\c@msclevelcnt}
|
|
\pgfkeys{/pgf/number format/precision=0}
|
|
\pgfmathroundto{\pgfmathresult}
|
|
\nextlevel[\pgfmathresult]%add missing levels
|
|
\fi
|
|
\mscset{level height=\mscget{last level height}}
|
|
\nextlevel %add last but one level
|
|
\foreach \msc@tempa in {1,...,\c@mscinstcnt} {%
|
|
\stop[instance end=foot,#1]{\mscget{instanceno/\msc@tempa/name}}
|
|
}
|
|
\nextlevel %add last level just to draw outstanding foots
|
|
\else
|
|
\coordinate (msc@footenvleft) at (msc@nodeenvright);
|
|
\coordinate[below=\mscget{first level height} of msc@level0] (msc@level1);
|
|
\fi
|
|
\msc@drawenvironment
|
|
\IfStrEq{none}{\mscget{draw grid}}{}{%we draw help grid
|
|
\msc@drawgrid
|
|
}
|
|
\end{pgfscope}
|
|
}
|
|
\def\msc@drawenvironment{
|
|
\path[line width=\mscget{line width}]
|
|
let \p1=(msc@node\mscget{instanceno/1/name}.north),
|
|
\p2=(msc@foot\mscget{instanceno/\the\c@mscinstcnt/name}.south),
|
|
\p3=(current bounding box.south east),
|
|
\p4=(current bounding box.north west) in
|
|
({\x2+max(\mscget{right environment distance},\x3-\x2)},
|
|
{\y2+min(-\mscget{foot distance},\y3-\y2)}) coordinate(msc@env@se) [draw=\mscget{draw frame}] rectangle
|
|
({\x1+min(-\mscget{left environment distance},\x4-\x1)},
|
|
{\y1+max(\mscget{head top distance},\y4-\y1)}) coordinate(msc@env@nw);
|
|
\path let \p1=(msc@env@nw),
|
|
\p2=(msc@env@se) in
|
|
(\x1,\y1) +(\mscget{title distance},-\mscget{title top distance})
|
|
node[rectangle, anchor=north west, inner sep=0, align=\mscget{title
|
|
position}, text
|
|
width=(\x2-\x1)-2*\mscget{title distance}]
|
|
{\msckeywordstyle{\mscget{msc keyword}} \mscget{msc/name}};
|
|
\foreach \msc@tempa in {0,...,\c@msclevelcnt} {%create nodes for environment
|
|
\path let \p1=(msc@env@se),
|
|
\p2=(msc@env@nw),
|
|
\p3=(msc@level\msc@tempa) in
|
|
(\x2,\y3) coordinate[name=msc@nodeenvleft@r\msc@tempa,
|
|
alias=msc@nodeenvleft@l\msc@tempa] --
|
|
(\x1,\y3) coordinate[name=msc@nodeenvright@l\msc@tempa,
|
|
alias=msc@nodeenvright@r\msc@tempa];
|
|
}
|
|
\pgfkeysifdefined{/msc/levelenv/havedraw}{
|
|
% \tikzset{/msc/levelenv/draw/.show code}
|
|
\mscset{/msc/levelenv/draw}
|
|
\msc@global@set{/msc/levelenv/draw/.code={}}
|
|
}{}
|
|
}
|
|
% \setmscvalues assigns compatible values to all msc-parameters
|
|
% Currently, three sets of values are supported: large, normal
|
|
% and small.
|
|
\def\setmscvalues#1{%
|
|
\IfEqCase{#1}{%
|
|
{large}{\mscset{#1 values}}%
|
|
{normal}{\mscset{#1 values}}%
|
|
{small}{\mscset{#1 values}}%
|
|
}[\msc@unknownmscvalueserr{#1}]
|
|
}
|
|
%
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% HMSC
|
|
%
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
\def\msckeywordstyle#1{\textbf{#1}}
|
|
\newcommand{\sethmsckeyword}[1]{\mscset{/msc/hmsc keyword={#1}}}%
|
|
\newcommand{\sethmsckeywordstyle}[1]{\def\hmsckeywordstyle{#1}}%
|
|
|
|
% \begin{hmsc}[headerpos]{hmscname}(llx,lly)(urx,ury)
|
|
\def\hmsc{\def\msc@key{hmsc} \pgfutil@ifnextchar[\msc@hmscopt{\msc@hmscopt[]}}
|
|
\def\msc@hmscopt[#1]{%
|
|
\msc@global@set{/msc/draw code/.code={}}
|
|
\ifx#1l
|
|
\mscset{title position=left}
|
|
\else \ifx#1c
|
|
\mscset{title position=center}
|
|
\else \ifx#1r
|
|
\mscset{title position=right}
|
|
\else
|
|
\pgfutil@ifundefined{msc@tikzstarted}{
|
|
\tikzpicture[#1]%
|
|
\def\msc@tikzstarted{}
|
|
}{\relax}
|
|
\fi
|
|
\fi
|
|
\fi
|
|
\pgfutil@ifnextchar[{\msc@hmscopt}{\msc@hmscnoopt}
|
|
}
|
|
|
|
\def\msc@hmscnoopt#1{%
|
|
% #1: mscname
|
|
\pgfutil@ifundefined{msc@tikzstarted}{
|
|
\tikzpicture\def\msc@tikzstarted{}%
|
|
}{\relax}
|
|
\mscset{
|
|
/tikz/scale/.expanded=\mscget{msc scale},
|
|
/tikz/every node/.style/.expanded={scale/.expanded=\mscget{msc scale}},
|
|
/msc/\msc@key/name/.initial={#1}}
|
|
\pgfutil@ifnextchar({\msc@hmsc}{}
|
|
}
|
|
|
|
\def\msc@hmsc(#1,#2)(#3,#4){
|
|
\path (#1,#4) coordinate(msc@\msc@key @nw)
|
|
(#3,#2) coordinate(msc@\msc@key @se);
|
|
}
|
|
%\end{hmsc}[options]
|
|
\def\endhmsc{\def\msc@key{hmsc}\pgfutil@ifnextchar[\msc@endhmsc{\msc@endhmsc[]}
|
|
\endtikzpicture
|
|
\global\let\msc@tikzstarted\relax
|
|
}
|
|
\def\msc@endhmsc[#1]{
|
|
\begin{pgfscope}
|
|
\mscset{#1}
|
|
\pgfutil@ifundefined{pgf@sh@ns@msc@\msc@key @nw}{%use bounding box
|
|
\path (current bounding box.north west)
|
|
++(-\mscget{west \msc@key\space margin},
|
|
\mscget{north \msc@key\space margin}+\mscget{title top distance}+\heightof{\mscget{msc@key/name}}+\depthof{\mscget{\msc@key/name}})
|
|
coordinate(msc@\msc@key @nw) (current bounding box.south east)
|
|
++(\mscget{east \msc@key\space margin},-\mscget{south \msc@key\space margin})
|
|
coordinate(msc@\msc@key @se);
|
|
}{}
|
|
\IfStrEq{\mscget{title position}}{left}{%
|
|
\path (msc@\msc@key @nw) +(\mscget{title distance},-\mscget{title top distance})
|
|
node[anchor=north west,inner sep=0]
|
|
{\msckeywordstyle{\mscget{\msc@key\space keyword}} \mscget{\msc@key/name}};
|
|
}{
|
|
\IfStrEq{\mscget{title position}}{center}{%
|
|
\path let \p1=(msc@\msc@key @nw),
|
|
\p2=(msc@\msc@key @se) in
|
|
(\x1/2+\x2/2,\y1) +(0,-\mscget{title top distance})
|
|
node[anchor=north,inner sep=0]
|
|
{\msckeywordstyle{\mscget{\msc@key\space keyword}} \mscget{\msc@key/name}};
|
|
}{
|
|
\IfStrEq{\mscget{title position}}{right}{%
|
|
\path let \p1=(msc@\msc@key @nw),
|
|
\p2=(msc@\msc@key @se) in
|
|
(\x2,\y1) +(-\mscget{title distance},-\mscget{title top distance})
|
|
node[anchor=north east,inner sep=0]
|
|
{\msckeywordstyle{\mscget{\msc@key\space keyword}} \mscget{\msc@key/name}};
|
|
}{}
|
|
}
|
|
}
|
|
\path[draw=\mscget{draw frame},line width=\mscget{line width}] (msc@\msc@key @nw)|-(msc@\msc@key @se)|-(msc@\msc@key @nw);
|
|
\IfStrEq{none}{\mscget{draw grid}}{}{%we draw help grid
|
|
\msc@drawgrid
|
|
}
|
|
\end{pgfscope}
|
|
\mscset{/msc/draw code}
|
|
\msc@global@set{/msc/draw code/.code={}}
|
|
}
|
|
%\hmscstartsymbol{nickname}(x,y)
|
|
\def\hmscstartsymbol{
|
|
\edef\msc@nodetype{start symbol}
|
|
\pgfutil@ifnextchar[\msc@nodenotext{\msc@nodenotext[]}
|
|
}
|
|
\def\msc@nodenotext[#1]#2{
|
|
\edef\msc@options{#1} \edef\msc@name{#2}\def\msc@text{}
|
|
\pgfutil@ifnextchar({\msc@nodeAt}{
|
|
\edef\msc@tempb{[/msc,\msc@nodetype,#1](\msc@name){};}
|
|
\expandafter\node\msc@tempb
|
|
}
|
|
}
|
|
\def\msc@nodetext[#1]#2#3{
|
|
\edef\msc@options{#1} \edef\msc@name{#2}\def\msc@text{#3}
|
|
\pgfutil@ifnextchar({\msc@nodeAt}{
|
|
\def\msc@tempb{[/msc,\msc@nodetype,#1](#2){#3};}
|
|
\expandafter\node\msc@tempb
|
|
}
|
|
}
|
|
|
|
\def\msc@nodeAt(#1,#2){
|
|
\edef\msc@tempb{[/msc,\msc@nodetype,\msc@options](\msc@name) at (#1,#2) {\unexpanded\expandafter{\msc@text}};}
|
|
\expandafter\node\msc@tempb
|
|
}
|
|
%\hmscendsymbol{nickname}(x,y)
|
|
\def\hmscendsymbol{
|
|
\edef\msc@nodetype{end symbol}
|
|
\pgfutil@ifnextchar[\msc@nodenotext{\msc@nodenotext[]}
|
|
}
|
|
%\hmscreference{nickname}{text}(x,y)
|
|
\def\hmscreference{
|
|
\edef\msc@nodetype{reference}
|
|
\pgfutil@ifnextchar[\msc@nodetext{\msc@nodetext[]}
|
|
}
|
|
%\hmsc condition{nickname}{text}(x,y)
|
|
\def\hmsccondition{
|
|
\edef\msc@nodetype{condition}
|
|
\pgfutil@ifnextchar[\msc@nodetext{\msc@nodetext[]}
|
|
}
|
|
%\hmscconnection{nickname}(x,y)
|
|
\def\hmscconnection{
|
|
\edef\msc@nodetype{connection}
|
|
\pgfutil@ifnextchar[\msc@nodenotext{\msc@nodenotext[]}
|
|
}
|
|
%\arrow{from-nickname}[coord-list]{to-n
|
|
\def\arrow{\pgfutil@ifnextchar[\msc@arrowopt{\msc@arrowopt[]}}
|
|
\def\msc@arrowopt[#1]#2{
|
|
\def\msc@options{#1}
|
|
\edef\msc@node{#2}
|
|
\edef\msc@tempa{}
|
|
\pgfutil@ifnextchar[\msc@arrowgetpath{\msc@arrow}
|
|
}
|
|
\def\msc@arrowgetpath[#1]{
|
|
\StrSubstitute{#1}{(}{--(}[\msc@tempa]
|
|
\msc@arrow
|
|
}
|
|
\def\msc@arrow#1{
|
|
\edef\msc@tempb{[/msc,/tikz/line width=\mscget{line width},arrow style,\msc@options] (\msc@node)\msc@tempa--(#1);}
|
|
\expandafter\draw\msc@tempb
|
|
}
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% MSC documents
|
|
%
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% \mscdockeyword is the keyword representation of msc
|
|
\def\mscdockeywordstyle#1{\textbf{#1}}
|
|
\newcommand{\setmscdockeyword}[1]{\mscset{/msc/mscdoc keyword/.initial=mscdoc}}
|
|
\newcommand{\setmscdockeywordstyle}[1]{\def\mscdockeywordstyle{#1}}%
|
|
|
|
%\begin{mscdoc}[headerpos]{mscdocname}(llx,lly)(urx,ury)
|
|
\def\mscdoc{\edef\msc@key{mscdoc} \pgfutil@ifnextchar[\msc@hmscopt{\msc@hmscopt[]}}
|
|
%\end{mscdoc}[options]
|
|
\def\endmscdoc{\edef\msc@key{mscdoc}
|
|
\pgfutil@ifnextchar[\msc@endhmsc{\msc@endhmsc[]}
|
|
\endtikzpicture
|
|
\global\let\msc@tikzstarted\relax
|
|
}
|
|
%\hmscreference{nickname}{text}(x,y)
|
|
\def\reference{\pgfutil@ifnextchar[\msc@nodenoname{\msc@nodenoname[]}}
|
|
\def\msc@nodenoname[#1]#2{
|
|
\edef\msc@options{#1} \def\msc@text{#2}
|
|
\pgfutil@ifnextchar({\msc@nodenonameAt}{
|
|
\edef\msc@tempb{[/msc,reference,#1](\msc@name){\unexpanded\expandafter{\msc@text}};}
|
|
\expandafter\node\msc@tempb
|
|
}
|
|
}
|
|
\def\msc@nodenonameAt(#1,#2){
|
|
\edef\msc@tempb{[/msc,reference,every reference,\msc@options] at (#1,#2) {\unexpanded\expandafter{\msc@text}};}
|
|
\expandafter\node\msc@tempb
|
|
}
|
|
\def\separator{\pgfutil@ifnextchar[\msc@separator{\msc@separator[]}}
|
|
\def\msc@separator[#1]#2{
|
|
\begin{pgfscope}
|
|
\mscset{#1}
|
|
\xdef\msc@tempb{[/msc,/tikz/line width=\mscget{line width},mscdash]
|
|
let \noexpand\p1=(msc@mscdoc@nw), \noexpand\p2=(msc@mscdoc@se) in
|
|
(\noexpand\x1,#2)--(\noexpand\x2,#2);}
|
|
\end{pgfscope}
|
|
\mscset{/msc/draw code/.append code/.expand once={\expandafter\draw\msc@tempb}}
|
|
}
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% Error and help messages
|
|
% We use the standard LaTeX2e facilities to generate error and help
|
|
% messages (for more info, see file lterror.dtx of LaTeX2e distribution).
|
|
%
|
|
%
|
|
% nickname already defined
|
|
\gdef\msc@nicknamedefinederr#1{%
|
|
\PackageError{msc}{% error message
|
|
nickname #1 already defined}{% help text
|
|
You tried to use the nickname '#1' for a new\MessageBreak
|
|
msc object (instance, reference, inline expression, etc.),\MessageBreak
|
|
but the nickname is already assigned to another msc object.\MessageBreak
|
|
press <enter> to continue (the new msc object will be ignored).}%
|
|
}
|
|
%instance already started
|
|
\gdef\msc@instancestarted#1{%
|
|
\PackageError{msc}{% error message
|
|
instance #1 is already active}{% help text
|
|
You tried to create instance '#1' but this instance is \MessageBreak
|
|
already active. Maybe try to stop it using "stop" command .\MessageBreak
|
|
press <enter> to continue.}%
|
|
}
|
|
% no such msc reference error
|
|
\gdef\msc@refundefinederr#1{%
|
|
\PackageError{msc}{% error message
|
|
undefined reference with nickname: #1}{% help text
|
|
You used '#1' as an reference nickname, but\MessageBreak
|
|
there is no reference with that nickname.}%
|
|
}
|
|
% no such msc reference error
|
|
\gdef\msc@inlundefinederr#1{%
|
|
\PackageError{msc}{% error message
|
|
undefined inline with nickname: #1}{% help text
|
|
You used '#1' as an inline nickname, but\MessageBreak
|
|
there is no inline with that nickname.}%
|
|
}
|
|
% no such msc instance error
|
|
\gdef\msc@instundefinederr#1{%
|
|
\PackageError{msc}{% error message
|
|
undefined msc instance: #1}{% help text
|
|
You used '#1' as an msc instance nickname, but\MessageBreak
|
|
there is no msc instance with that nickname.}%
|
|
}
|
|
% level height is not a positive integer
|
|
\gdef\msc@notpositiveintegerwarn#1#2{%
|
|
\PackageWarning{msc}{% error message
|
|
parameter #1.#2 is a float when integer was expected -
|
|
recovering by advancing by #1+1 levels where last level is scaled by 0.#2}
|
|
}
|
|
\gdef\msc@notpositiveintegererr#1{%
|
|
\PackageError{msc}{% error message
|
|
Could not parse as number: #1}{% help text
|
|
The nextlevel should be a positive integer but instead #1 was given.}%
|
|
}
|
|
|
|
% unknown region style error
|
|
\gdef\msc@unknownregionstyleerr#1{%
|
|
\PackageError{msc}{% error message
|
|
unknown region style: #1}{% help text
|
|
Known msc region styles are "coregion", "suspension", and "activation".\MessageBreak
|
|
You used '#1'.}%
|
|
}
|
|
% region not started error
|
|
\gdef\msc@regionnotstartederr#1{%
|
|
\PackageError{msc}{% error message
|
|
no region is started for the instance "#1"}{% help text
|
|
You tried to end a region for the instance "#1", \MessageBreak
|
|
but no region has been started.}%
|
|
}
|
|
% region already started error
|
|
\gdef\msc@regionstartederr#1#2{%
|
|
\PackageError{msc}{% error message
|
|
region #2 is already started}{% help text
|
|
You tried to start new region for the instance "#1", \MessageBreak
|
|
while the previous region is still active.}%
|
|
}
|
|
% unknown self message label position error
|
|
\gdef\msc@unknownmscvalueserr#1{%
|
|
\PackageError{msc}{% error message
|
|
unknown set of msc-values: #1}{% help text
|
|
Known sets of msc-values are "normal" and "small".\MessageBreak
|
|
You used '#1'.}%
|
|
}
|
|
%################################################################################
|
|
%
|
|
\gdef\msc@illegaltitleplacement#1{%
|
|
\PackageError{msc}{%
|
|
illegal title placement specifier: #1}{% help text
|
|
Valid title placement specifiers are:\MessageBreak
|
|
l (left)\MessageBreak
|
|
c (center)\MessageBreak
|
|
r (right)}
|
|
}
|
|
%reading /usr/share/texlive/texmf-dist/tex/latex/base/latex.ltx
|