我的目标是能够在图形文本中配置序列图的垂直条是虚线、直线、粗线等等。根据图表,我希望可以在这些选项之间进行选择。
到目前为止,我已经确定了代码的位置和组织方式。事实上,我想知道是否可以添加以下选项:
\begin{sequencediagram}[OPTION]
其中 OPTION 可以是“点状”、“粗状”或空(对于简单的条形图 b)
pgf-umlsd.sty
我注意到(这一行关联) 显示此条的是第 321 行:
\draw[OPTION] (inst\t) -- ++(0,-\theseqlevel*\unitfactor-2.2*\unitfactor);
当我手动编辑它们时,用空、“dotted”或“thik”替换 OPTION,它会按图中预期的方式工作。但我想让它在主文本中可配置。
所以,现在我不知道如何将此选项“编码”为变量。有没有简单的方法可以做到这一点?
最小工作示例。
主文本:
\documentclass{article}
\usepackage{pgf-umlsd}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\begin{document}
\begin{sequencediagram}
\newthread{a}{:A}
\newinst{b}{:B}
\begin{call}{a}{getStuff()}{b}{}
\end{call}
\end{sequencediagram}
\end{document}
uml-pgf.sty:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Start of pgf-umlsd.sty
%
% Some macros for UML Sequence Diagrams.
% Home page of project: http://pgf-umlsd.googlecode.com/
% Author: Xu Yuan <[email protected]>, Southeast University, China
% Contributor: Nobel Huang <[email protected]>, Southeast University, China
%
% History:
% v0.6 2011/07/27
% - Fix Issue 6 reported by [email protected]
% - diagram without a thread
% - allows empty diagram
% - New manual
% v0.5 2009/09/30 Fix Issue 2 reported by vlado.handziski
% - Nested callself is supported
% - Rename sdloop and sdframe to sdblock
% v0.4 2008/12/08 Fix Issue 1 reported by MathStuf:
% Nested sdloop environment hides outer loop
% v0.3 2008/11/10 in Berlin, fix for the PGF cvs version:
% - the list items in \foreach are not evaluated by default now,
% the `evaluate' opinion should be used
% v0.2 2008/03/20 create project at http://pgf-umlsd.googlecode.com/
% - use `shadows' library
% Thanks for Dr. Ludger Humbert's <[email protected]> feedback!
% - reduce the parameter numbers, the user can write the content
% of instance (such as no colon)
% - the user can redefine the `inststyle'
% - new option: switch underlining of the instance text
% - new option: switch rounded corners
% v0.1 2008/01/25 first release at http://www.fauskes.net/pgftikzexamples/
%
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
\ProvidesPackage{pgf-umlsd}[2009/09/30 v0.5 Some LaTeX macros for UML
Sequence Diagrams.]
\usetikzlibrary{arrows,shadows}
% Options
% ? the instance name under line ?
\newif\ifpgfumlsdunderline\pgfumlsdunderlinetrue
\DeclareOption{underline}{\pgfumlsdunderlinetrue}
\DeclareOption{underline=true}{\pgfumlsdunderlinetrue}
\DeclareOption{underline=false}{\pgfumlsdunderlinefalse}
% ? the instance box with rounded corners ?
\newif\ifpgfumlsdroundedcorners\pgfumlsdroundedcornersfalse
\DeclareOption{roundedcorners}{\pgfumlsdroundedcornerstrue}
\DeclareOption{roundedcorners=true}{\pgfumlsdroundedcornerstrue}
\DeclareOption{roundedcorners=false}{\pgfumlsdroundedcornersfalse}
\ProcessOptions
% declare layers
\pgfdeclarelayer{background}
\pgfdeclarelayer{threadground}
\pgfsetlayers{background,threadground,main}
% new counters
\newcounter{preinst}
\newcounter{instnum}
\newcounter{threadnum}
\newcounter{seqlevel} % level
\newcounter{callevel}
\newcounter{callselflevel}
\newcounter{blocklevel}
% new an instance
% Example:
% \newinst[edge distance]{var}{name:class}
\newcommand{\newinst}[3][0.2]{
\stepcounter{instnum}
\path (inst\thepreinst.east)+(#1,0) node[inststyle] (inst\theinstnum)
{\ifpgfumlsdunderline
\underline{#3}
\else
#3
\fi};
\path (inst\theinstnum)+(0,-0.5*\unitfactor) node (#2) {};
\tikzstyle{instcolor#2}=[]
\stepcounter{preinst}
}
% new an instance thread
% Example:
% \newinst[color]{var}{name}{class}
\newcommand{\newthread}[3][gray!30]{
\newinst{#2}{#3}
\stepcounter{threadnum}
\node[below of=inst\theinstnum,node distance=0.8cm] (thread\thethreadnum) {};
\tikzstyle{threadcolor\thethreadnum}=[fill=#1]
\tikzstyle{instcolor#2}=[fill=#1]
}
% draw running (thick) line, should not call directly
\newcommand*{\drawthread}[2]{
\begin{pgfonlayer}{threadground}
\draw[threadstyle] (#1.west) -- (#1.east) -- (#2.east) -- (#2.west) -- cycle;
\end{pgfonlayer}
}
% a function call
% Example:
% \begin{call}[height]{caller}{function}{callee}{return}
% \end{call}
\newenvironment{call}[5][2]{
\stepcounter{seqlevel}
\stepcounter{callevel} % push
\path
(#2)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (cf\thecallevel) {}
(#4.\threadbias)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (ct\thecallevel) {};
\draw[->,>=triangle 60] ({cf\thecallevel}) -- (ct\thecallevel)
node[midway, above] {#3};
\def\l\thecallevel{#1}
\def\f\thecallevel{#2}
\def\t\thecallevel{#4}
\def\returnvalue{#5}
\tikzstyle{threadstyle}+=[instcolor#2]
}
{
\addtocounter{seqlevel}{\l\thecallevel}
\path
(\f\thecallevel)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (rf\thecallevel) {}
(\t\thecallevel.\threadbias)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (rt\thecallevel) {};
\draw[dashed,->,>=angle 60] ({rt\thecallevel}) -- (rf\thecallevel)
node[midway, above]{\returnvalue};
\drawthread{ct\thecallevel}{rt\thecallevel}
\addtocounter{callevel}{-1} % pop
}
% a function do not need call others
% Example:
% \begin{callself}[height]{caller}{function}{return}
% \end{callself}
\newenvironment{callself}[4][3]{
\stepcounter{seqlevel}
\stepcounter{callevel} % push
\stepcounter{callselflevel}
\path
(#2)+(\thecallselflevel*0.1-0.1,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (sc\thecallevel) {}
({sc\thecallevel}.east)+(0,-0.33*\unitfactor) node (scb\thecallevel) {};
\draw[->,>=triangle 60] ({sc\thecallevel}.east) -- ++(0.8,0)
node[near start, above right] {#3} -- ++(0,-0.33*\unitfactor)
-- (scb\thecallevel);
\def\l\thecallevel{#1}
\def\f\thecallevel{#2}
\def\returnvalue{#4}
\tikzstyle{threadstyle}+=[instcolor#2]
}{
\addtocounter{seqlevel}{\l\thecallevel}
\path (\f\thecallevel)+(\thecallselflevel*0.1-0.1,-\theseqlevel*\unitfactor-0.33*\unitfactor) node
(sct\thecallevel) {};
\draw[dashed,->,>=angle 60] ({sct\thecallevel}.east) node
(sce\thecallevel) {} -- ++(0.8,0) -- node[midway, right]{\returnvalue} ++(0,-0.33*\unitfactor) -- ++(-0.8,0);
\drawthread{scb\thecallevel}{sce\thecallevel}
\addtocounter{callevel}{-1} % pop
\addtocounter{callselflevel}{-1}
}
% message between threads
% Example:
% \mess{sender}{message content}{receiver}
\newcommand{\mess}[3]{
\stepcounter{seqlevel}
\path
(#1)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (messbeg) {}
(#3)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (messend) {};
\draw[->,>=angle 60] (messbeg) -- (messend) node[midway, above] {#2};
}
\newenvironment{messcall}[4][4]{
\stepcounter{seqlevel}
\stepcounter{callevel} % push
\path
(#2)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (cf\thecallevel) {}
(#4.\threadbias)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (ct\thecallevel) {};
\draw[->,>=angle 60] ({cf\thecallevel}) -- (ct\thecallevel)
node[midway, above] {#3};
\def\l\thecallevel{#1}
\def\f\thecallevel{#2}
\def\t\thecallevel{#4}
\tikzstyle{threadstyle}+=[instcolor#2]
}
{
\addtocounter{seqlevel}{\l\thecallevel}
\path
(\f\thecallevel)+(0,-\theseqlevel*\unitfactor-0.7*\unitfactor) node (rf\thecallevel) {}
(\t\thecallevel.\threadbias)+(0,-\theseqlevel*\unitfactor-0.3*\unitfactor) node (rt\thecallevel) {};
\drawthread{ct\thecallevel}{rt\thecallevel}
\addtocounter{callevel}{-1} % pop
}
% In the situation of multi-threads, some objects are called at the
% same time. Currently, we have to adjust the bias of thread line
% manually. Possible parameters are: center, west, east
\newcommand{\setthreadbias}[1]{\global\def\threadbias{#1}}
% In the situation of multi-threads, some events happen at the same
% time. Currently, we have to adjust the level(time) of events
% manually. This function makes the call earlier.
\newcommand{\prelevel}{\addtocounter{seqlevel}{-1}}
% a block box with caption
% \begin{sdblock}[caption background color]{caption}{comments}
% \end{sdblock}
\newenvironment{sdblock}[3][white]{
\stepcounter{seqlevel}
\stepcounter{blocklevel} % push
\coordinate (blockbeg\theblocklevel) at (0,-\theseqlevel*\unitfactor-\unitfactor);
\stepcounter{seqlevel}
\def\blockcolor\theblocklevel{#1}
\def\blockname\theblocklevel{#2}
\def\blockcomm\theblocklevel{#3}
\begin{pgfinterruptboundingbox}
}{
\coordinate (blockend) at (0,-\theseqlevel*\unitfactor-2*\unitfactor);
\path (current bounding box.east)+(0.2,0) node (boxeast) {}
(current bounding box.west |- {blockbeg\theblocklevel}) + (-0.2,0)
node (nw) {};
\path (boxeast |- blockend) node (se) {};
\draw (nw) rectangle (se);
% title
\node[blockstyle] (blocktitle) at (nw) {\blockname\theblocklevel};
\path (blocktitle.south east) + (0,0.2) node (set) {}
(blocktitle.south east) + (-0.2,0) node (seb) {}
(blocktitle.north east) + (0.2,0) node (comm) {};
\draw[fill=\blockcolor\theblocklevel] (blocktitle.north west) -- (blocktitle.north east) --
(set.center) -- (seb.center) -- (blocktitle.south west) -- cycle;
\node[blockstyle] (blocktitle) at (nw) {\blockname\theblocklevel};
\node[blockcommentstyle] (blockcomment) at (comm) {\blockcomm\theblocklevel};
\end{pgfinterruptboundingbox}
% add two points to keep the bounding box
\node[dot] (fnw) at (nw) {};
\node[dot] (fse) at (se) {};
\addtocounter{blocklevel}{-1} % pop
\stepcounter{seqlevel}
}
% the environment of sequence diagram
\newenvironment{sequencediagram}{
\begin{tikzpicture}
\setlength{\unitlength}{1cm}
\tikzstyle{sequence}=[coordinate]
\tikzstyle{inststyle}=[rectangle, draw, anchor=west, minimum
height=0.8cm, minimum width=1.6cm, fill=white,
drop shadow={opacity=1,fill=black}]
\ifpgfumlsdroundedcorners
\tikzstyle{inststyle}+=[rounded corners=3mm]
\fi
\tikzstyle{blockstyle}=[anchor=north west]
\tikzstyle{blockcommentstyle}=[anchor=north west, font=\small]
\tikzstyle{dot}=[inner sep=0pt,fill=black,circle,minimum size=0.2pt]
\global\def\unitfactor{0.6}
\global\def\threadbias{center}
% reset counters
\setcounter{preinst}{0}
\setcounter{instnum}{0}
\setcounter{threadnum}{0}
\setcounter{seqlevel}{0}
\setcounter{callevel}{0}
\setcounter{callselflevel}{0}
\setcounter{blocklevel}{0}
% origin
\node[coordinate] (inst0) {};
}
{
\begin{pgfonlayer}{background}
\ifnum\c@instnum > 0
\foreach \t [evaluate=\t] in {1,...,\theinstnum}{
\draw[dotted] (inst\t) -- ++(0,-\theseqlevel*\unitfactor-2.2*\unitfactor);
}
\fi
\ifnum\c@threadnum > 0
\foreach \t [evaluate=\t] in {1,...,\thethreadnum}{
\path (thread\t)+(0,-\theseqlevel*\unitfactor-0.1*\unitfactor) node (threadend) {};
\tikzstyle{threadstyle}+=[threadcolor\t]
\drawthread{thread\t}{threadend}
}
\fi
\end{pgfonlayer}
\end{tikzpicture}}
%%% End of pgf-umlsd.sty
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
我希望这些垂直虚线可以按照下面的说明进行配置。
例子。
当序列图的代码配置如下时:
\begin{sequencediagram}[]
序列竖线非常简单。
如果代码是:
\begin{sequencediagram}[dotted]
序列竖线为虚线。选项越粗,则竖线越粗,以此类推。
答案1
您可以更新环境以接受可选参数,其默认值为dotted
。在开头定义中,我将参数存储在样式中mygridstyle
,该样式在结尾定义中使用
\draw[mygridstyle] (inst\t) -- ...
这是必需的,因为环境的参数只能在打开时使用,而不能在关闭时使用。
\documentclass[border=3pt]{standalone}
\usepackage{pgf-umlsd}
\makeatletter
% renew the environment of sequence diagram
\renewenvironment{sequencediagram}[1][dotted]{%
% declare layers
\pgfdeclarelayer{umlsd@background}%
\pgfdeclarelayer{umlsd@threadlayer}%
\pgfsetlayers{umlsd@background,umlsd@threadlayer,main}%
\begin{tikzpicture}
\setlength{\unitlength}{1cm}
\tikzstyle{sequence}=[coordinate]
\tikzstyle{inststyle}=[rectangle, draw, anchor=west, minimum
height=0.8cm, minimum width=1.6cm, fill=white,
drop shadow={opacity=1,fill=black}]
\ifpgfumlsdroundedcorners%
\tikzstyle{inststyle}+=[rounded corners=3mm]
\fi
\tikzstyle{blockstyle}=[anchor=north west]
\tikzstyle{blockcommentstyle}=[anchor=north west, font=\small]
\tikzstyle{dot}=[inner sep=0pt,fill=black,circle,minimum size=0.2pt]
\tikzstyle{mygridstyle}=[#1]
\global\def\unitfactor{0.6}
\global\def\threadbias{center}
% reset counters
\setcounter{preinst}{0}
\setcounter{instnum}{0}
\setcounter{threadnum}{0}
\setcounter{seqlevel}{0}
\setcounter{callevel}{0}
\setcounter{callselflevel}{0}
\setcounter{blocklevel}{0}
% origin
\node[coordinate] (inst0) {};
}
{
\begin{pgfonlayer}{umlsd@background}
\ifnum\c@instnum > 0
\foreach \t [evaluate=\t] in {1,...,\theinstnum}{
\draw[mygridstyle] (inst\t) -- ++(0,-\theseqlevel*\unitfactor-2.2*\unitfactor);
}
\fi
\ifnum\c@threadnum > 0
\foreach \t [evaluate=\t] in {1,...,\thethreadnum}{
\path (thread\t)+(0,-\theseqlevel*\unitfactor-0.1*\unitfactor) node (threadend) {};
\tikzstyle{threadstyle}+=[threadcolor\t]
\drawthread{thread\t}{threadend}
}
\fi
\end{pgfonlayer}
\end{tikzpicture}}
\makeatother
\begin{document}
\begin{sequencediagram}[thick,dashed,blue]
\newthread{a}{:A}
\newinst{b}{:B}
\begin{call}{a}{getStuff()}{b}{}
\end{call}
\end{sequencediagram}
\end{document}