%D \module %D [ file=t-gantt-tikz, %D version=2011.09.11, %D title=\CONTEXT\ User Module, %D subtitle=Drawing Gantt charts, %D author=Adam Reviczky, %D date=\currentdate, %D copyright=Adam Reviczky, %D license=Public Domain] %D Some macros for drawing Gantt charts using TikZ. \writestatus{loading}{ConTeXt User Module / tikz gantt chart} \startmodule[gantt-s-tikz] \unprotect \def\????gantt-tikz{@@@@gantt-tikz} \usemodule[tikz,pgffor] \usetikzlibrary[arrows,patterns] \definesystemvariable{gantt} \newcount\ganttnum \newcount\gantttitlenum \newcount\ganttwidth \newdimen\ganttlastx \ganttlastx = 0cm \newdimen\nextganttlastx \newdimen\titleunitlength \titleunitlength = 1cm \newdimen\ganttunitlength \ganttunitlength = 1cm \newdimen\gantttmpa \newdimen\gantttmpb \def\setupgantt {\bgroup \catcode`\#=\@@other \dosingleempty \dosetupgantt} \def\dosetupgantt[#1]% {\egroup \getparameters[\??gantt][#1]} \setupgantt [xunitlength=1cm, fontsize=\tf, titlefontsize=\tfx, drawledgerline=false] \def\setupganttbar {\bgroup \catcode`\#=\@@other \dosingleempty \dosetupganttbar} \def\dosetupganttbar[#1]% {\egroup \getparameters[\??gantt][#1]} \setupganttbar [pattern=north east lines, color=black] % The gantt environment draws the canvas of a gantt figure (realized as tikzpicture) % The usage is \startgantt[...]{no of Tasks to plot}{no of time slots} % The optional argument [...] can be filled in a key=value syntax, using one or more of the following keys: % % xunitlength - length of one time slot (default: 1 cm) % fontsize - fontsize of labels (default: \tf) % titlefontsize - fontsize of title section (default: \tfx) % drawledgerline - Switch to enable/disable the drawing of horizontal ledger lines (default value: false) \long\def\dostartgantt[#1]#2#3% {\getparameters[\??gantt][#1]% \gdef\v!ganttunitlength{\getvalue{@@ganttxunitlength}} \gdef\v!fontsize{\getvalue{@@ganttfontsize}} \gdef\v!titlefontsize{\getvalue{@@gantttitlefontsize}} \gdef\v!drawledgerline{\@@ganttdrawledgerline} \bgroup \tikzstyle{time}=[coordinate] \newcount\ganttx \ganttx=0 \newcount\ganttheight \def\ganttxstringtop{} \def\ganttxstringbottom{} \global\ganttwidth=#3 \global\ganttnum=0 \ganttheight=#2 \advance\ganttheight by 1; \draw (0,0.5) node[above] {\ganttxstringtop} -- (0,1.4-\ganttheight) node[below] {\ganttxstringbottom}; \draw (\ganttwidth*\v!ganttunitlength,0.5) node[above] {\ganttxstringtop} -- (\ganttwidth*\v!ganttunitlength,1.4-\ganttheight) node[below] {\ganttxstringbottom}; % draw grid \foreach \!!t in {1,2,...,\ganttwidth}{ \draw[dotted] (\v!ganttunitlength*\!!t,-0.5) node[above] {\ganttxstringtop} -- (\v!ganttunitlength*\!!t,1.4-\ganttheight) node[below] {\ganttxstringbottom}; } % draw x axis \draw[] (0,-#2+0.4) -- (\ganttwidth*\v!ganttunitlength,-#2+0.4); \egroup } \def\startgantt% {\starttikzpicture[draw=black,yscale=.7,xscale=1] \dosingleempty\dostartgantt} \def\stopgantt% {\stoptikzpicture} % ganttitle is the environment for drawing the title section \definestartstop[ganttitle][ before={ \ganttlastx = 0cm }, after={ \ganttlastx = 0cm \doglobal\decrement\ganttnum } ] % \titleelement draws one element of the title % usage: \titleelement{label}{length} \long\def\dotitleelement#1#2% {\gantttmpa=\dimexpr\v!ganttunitlength*#2\relax \divide\gantttmpa by 2; \def\!!xoffset{1.5} \draw (\ganttlastx,\ganttnum) rectangle (\ganttlastx+#2*\v!ganttunitlength,\ganttnum+0.6); \node [text height=1.5ex,text depth=0.7ex] at (\ganttlastx+\gantttmpa-\!!xoffset,\ganttnum+0.25) {% \getvalue{v!titlefontsize} #1% }; \ganttlastx=\dimexpr\ganttlastx+\v!ganttunitlength*#2\relax } \def\titleelement% {\dotitleelement} % \numtitle draws a numbered sequence of title elements % usage: \numtitle{start number}{increment}{end number}{length of each title element} \long\def\donumtitle#1#2#3#4% {\gantttitlenum=#1 \dostepwiserecurse{#1}{#3}{#2}{ \titleelement{\the\gantttitlenum}{#4} \advance\gantttitlenum by #2; } } \def\numtitle% {\donumtitle} % \ganttbar draws a single, unconnected bar for representing a task % usage: \ganttbar[pattern=,color=]{label}{start}{length} % where the optional comma separated arguments are: % pattern - is a tikz pattern (e.g. north east lines (default), north west lines, crosshatch, crosshatch dots, grid, ...) % color - a tikz color of the pattern (e.g. red, green blue gray, dark gray) % for more information see the tikz documentation \long\def\doganttbar[#1]#2#3#4% {\bgroup \getparameters[\??gantt][#1]% \edef\v!pattern{\@@ganttpattern} \edef\v!color{\@@ganttcolor} \gantttmpa=\dimexpr\v!ganttunitlength*#3\relax \gantttmpb=\dimexpr\v!ganttunitlength*#4+\gantttmpa\relax \doif{\v!drawledgerline}{true}{ \draw[dotted] (0,\ganttnum-0.2) -- (\ganttwidth*\v!ganttunitlength,\ganttnum-0.2); } \node at (0,\ganttnum) [anchor=base east] {% \getvalue{v!fontsize} #2% }; \draw[pattern=\v!pattern,pattern color=\v!color] (\gantttmpa,\ganttnum+0.1) rectangle (\gantttmpb,\ganttnum+0.5); \global\ganttlastx=\gantttmpb \doglobal\decrement\ganttnum \egroup } \def\ganttbar {\dosingleempty\doganttbar} % \ganttcon draws an arrow between to bars with specified coordinates % usage: \ganttcon{startx}{starty}{endx}{endy} \long\def\doganttcon#1#2#3#4% {\bgroup \draw[-latex,rounded corners=1pt] (#1*\v!ganttunitlength,-#2+0.1+0.2) -- (#1*\v!ganttunitlength+0.4*\v!ganttunitlength,-#2+0.1+0.2) -- (#1*\v!ganttunitlength+0.4*\v!ganttunitlength,-#2-0.4+0.2) -- (#1*\v!ganttunitlength-0.4*\v!ganttunitlength,-#2-0.4+0.2) -- (#1*\v!ganttunitlength-0.4*\v!ganttunitlength,-#4+0.1+0.2) -- (#3*\v!ganttunitlength,-#4+0.1+0.2); \egroup } \def\ganttcon {\doganttcon} % \ganttbarcon draws a single bar *and* connects the bar with the previous bar for % consecutive tasks % usage: \ganttbarcon[pattern=,color=]{label}{start}{length} % where the optional pattern argument are the same as for \ganttbar \long\def\doganttbarcon[#1]#2#3#4% {\bgroup \getparameters[\??gantt][#1]% \edef\v!pattern{\@@ganttpattern} \edef\v!color{\@@ganttcolor} \nextganttlastx = \dimexpr\ganttlastx+\ganttunitlength*1\relax \ifdim\nextganttlastx>\dimexpr\v!ganttunitlength*#3\relax \draw[-latex,rounded corners=1pt] (\ganttlastx,\ganttnum+1.1+0.2) -- (\ganttlastx+0.4*\v!ganttunitlength,\ganttnum+1.1+0.2) -- (\ganttlastx+0.4*\v!ganttunitlength,\ganttnum+0.6+0.2) -- (\ganttlastx-0.4*\v!ganttunitlength,\ganttnum+0.6+0.2) -- (\ganttlastx-0.4*\v!ganttunitlength,\ganttnum+0.1+0.2) -- (#3*\v!ganttunitlength,\ganttnum+0.1+0.2); \else \draw[-latex,rounded corners=1pt] (\ganttlastx,\ganttnum+1.1+0.2) -- (\ganttlastx+0.4*\v!ganttunitlength,\ganttnum+1.1+0.2) -- (\ganttlastx+0.4*\v!ganttunitlength,\ganttnum+0.1+0.2) -- (#3*\v!ganttunitlength,\ganttnum+0.1+0.2); \fi %hbox overfull! \ganttbar[#1]{#2}{#3}{#4} \egroup } \def\ganttbarcon {\dosingleempty\doganttbarcon} % \ganttgroup draws a bar to group tasks % usage: \ganttgroup{label}{start}{length} \long\def\doganttgroup#1#2#3% {\bgroup \gantttmpa=\dimexpr\v!ganttunitlength*#2\relax \gantttmpb=\dimexpr\v!ganttunitlength*#3+\gantttmpa\relax \doif{\v!drawledgerline}{true}{ \draw[dotted] (0,\ganttnum-0.2) -- (\ganttwidth*\v!ganttunitlength,\ganttnum-0.2); } \node at (0,\ganttnum) [anchor=base east] {% \getvalue{v!fontsize}\bf #1% }; \fill[black] (\gantttmpa-0.14cm,\ganttnum+0.2) rectangle (\gantttmpb+0.14cm,\ganttnum+0.4); \draw[diamond-diamond] (\gantttmpa-0.14cm,\ganttnum+0.2) -- (\gantttmpb+0.14cm,\ganttnum+0.2); \global\ganttlastx=\gantttmpb \doglobal\decrement\ganttnum \egroup } \def\ganttgroup {\doganttgroup} % \ganttmilestone, draw a diamond to represent a milestone % usage: \ganttmilestone[color=]{label}{start} % color - a tikz color of the pattern (e.g. red, green blue gray, dark gray) % for more information see the tikz documentation % Declaring layers to abvoid superposition when you connect a \ganttmileston with a task \pgfdeclarelayer{background} \pgfdeclarelayer{foreground} \pgfsetlayers{background,main,foreground} \long\def\doganttmilestone[#1]#2#3% {\bgroup \getparameters[\??gantt][#1]% \edef\v!color{\@@ganttcolor} \gantttmpa=\dimexpr\v!ganttunitlength*#3\relax \gantttmpb=\dimexpr\v!ganttunitlength*0+\gantttmpa\relax \doif{\v!drawledgerline}{true}{ \draw[dotted] (0,\ganttnum-0.2) -- (\ganttwidth*\v!ganttunitlength,\ganttnum-0.2); } \node at (0,\ganttnum) [anchor=base east] {% \getvalue{v!fontsize} #2% }; \pgfonlayer{foreground} \draw[diamond-, color=\v!color] (\gantttmpa,\ganttnum+0.1) -- (\gantttmpb,\ganttnum+0.4); \endpgfonlayer \global\ganttlastx=\gantttmpb \doglobal\decrement\ganttnum \egroup } \def\ganttmilestone {\dosingleempty\doganttmilestone} % \ganttmilestonecon draws a single diamond *and* connects the diamond with the previous task % usage: \ganttmilestonecon[color=]{label}{start} % where the optional color argument are the same as for \ganttbar and \ganttmilestone \long\def\doganttmilestonecon[#1]#2#3% {\bgroup \getparameters[\??gantt][#1]% \edef\v!color{\@@ganttcolor} \nextganttlastx = \dimexpr\ganttlastx+\ganttunitlength*1\relax \ifdim\nextganttlastx>\dimexpr\v!ganttunitlength*#3\relax \draw[-latex,rounded corners=1pt] (\ganttlastx,\ganttnum+1.1+0.2) -- (\ganttlastx+0.4*\v!ganttunitlength,\ganttnum+1.1+0.2) -- (\ganttlastx+0.4*\v!ganttunitlength,\ganttnum+0.6+0.2) -- (\ganttlastx-0.4*\v!ganttunitlength-1.8,\ganttnum+0.6+0.2) -- (\ganttlastx-0.4*\v!ganttunitlength-1.8,\ganttnum+0.1+0.2) -- (#3*\v!ganttunitlength-1.8,\ganttnum+0.1+0.2); \else \draw[-latex,rounded corners=1pt] (\ganttlastx,\ganttnum+1.1+0.2) -- (\ganttlastx+0.4*\v!ganttunitlength,\ganttnum+1.1+0.2) -- (\ganttlastx+0.4*\v!ganttunitlength,\ganttnum+0.1+0.2) -- (#3*\v!ganttunitlength-1.8,\ganttnum+0.1+0.2); \fi \ganttmilestone[#1]{#2}{#3} \egroup } \def\ganttmilestonecon {\dosingleempty\doganttmilestonecon} \protect \stopmodule