# How could I center the text in a rectangle split node?

I use TikZ to create pictures in LaTeX. My picture consists of a rectangle with nine split parts. Every part has its own text inside the node, for example, "local variables, and temporaries":

\nodepart{eight} \structtwenty Saved registers, local variables, and temporaries


My problem is the text is not centered in the node, but on top and bottom of the node, can any help, below is the whole TeX file:

\documentclass{article}
\usepackage{tikz}

\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathreplacing}

\usetikzlibrary{shapes,arrows,positioning}
\def\structforty{\vrule depth 4cm width 0pt}
\def\structsix{\vrule depth 0.14cm width 0pt}
\def\struceleven{\vrule depth 1.1cm width 0pt}
\def\strucfourteen{\vrule depth 1.1cm width 0pt}
\def\structtwenty{\vrule depth 1.9cm width 0pt}

\begin{document}

\begin{tikzpicture}[auto,
rect/.style={
rectangle split, rectangle split parts=9,
draw,rectangle split part align=center,draw, thick,
text width=3cm,
text centered, %minimum height=26em,
% font=\ttfamily,
align=center, rectangle split part align={center,left},
rectangle split part align=midway,
rectangle split part fill={gray!30, blue!20, blue!15, blue!20,blue!15,blue!15,green!15,green!20,green!30}
}]

\node (stack) [rect] {
\nodepart {one}\structforty $\vdots$
\nodepart {two}\struceleven $\vdots$

\nodepart{three}\structsix Argument n
\nodepart{four} \struceleven $\vdots$
\nodepart{five} \structsix Argument 1
\nodepart{seven} \structsix Saved \%ebp
\nodepart{eight} \structtwenty Saved registers, local variables, and temporaries
\nodepart{nine} \strucfourteen Argument build area
};

\end{tikzpicture}
\end{document}

• First of all, welcome. Did you really need \struct...? If you remove them, it will work. You can define the vertical spacing with inner ysep=. – cacamailg May 5 '13 at 17:54
• @cacamailg wouldn't inner ysep apply to all parts of the node? Apparently the OP wants to have each part with a different vertical spacing between the border and the contents. – Gonzalo Medina May 5 '13 at 22:30
• @GonzaloMedina inner sep applies to all. I said that because I didn't understand that @vampire wanted different vertical spacing. – cacamailg May 5 '13 at 23:20

In the node content, you can use a \parbox with centered alignment and predefined width and height; the \Textbox command receives two arguments:

\Textbox{<length>}{<text>}


where <lenght> is any valid length that lets you specify the height for the box, and <text> is the content for the box:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathreplacing}
\usetikzlibrary{shapes,arrows,positioning}

\newlength\Textwd
\setlength\Textwd{3cm}
\newcommand\Textbox[2]{%
\parbox[c][#1][c]{\Textwd}{\centering#2}}

\makeatletter
\DeclareRobustCommand{\rvdots}{%
\vbox{
\baselineskip4\p@\lineskiplimit\z@
\kern-\p@
\hbox{.}\hbox{.}\hbox{.}
}}
\makeatother

\begin{document}

\begin{tikzpicture}[auto,
rect/.style={
rectangle split, rectangle split parts=9,
draw, thick,
text width=3cm,
text centered,
rectangle split part fill={gray!30, blue!20, blue!15, blue!20,blue!15,blue!15,green!15,green!20,green!30}
}]

\node (stack) [rect] {
\nodepart {one} \Textbox{1cm}{$\rvdots$}
\nodepart {two} \Textbox{1cm}{$\rvdots$}
\nodepart{three} \Textbox{1.5cm}{Argument n}
\nodepart{four} \Textbox{1cm}{$\rvdots$}
\nodepart{five} \Textbox{1.5cm}{Argument 1}
\nodepart{seven} \Textbox{1cm}{Saved \%ebp}
\nodepart{eight} \Textbox{3cm}{Saved registers, local variables, and temporaries}
\nodepart{nine} \Textbox{2cm}{Argument build area}
};
\end{tikzpicture}

\end{document}


Instead of the standard \vdots command, I used the version \rvdots from the answer to How to vertically center the \vdots in this node? to avoid some additional spacing at the top included by default in \vdots.

• The \rvdots macro from How to vertically center the \vdots in this node? might come in handy. – Qrrbrbirlbel May 5 '13 at 20:57
• @Qrrbrbirlbel indeed! I've added it to my answer. Thanks. – Gonzalo Medina May 5 '13 at 22:31
• @GonzaloMedina You can redefine the \textbox command to set a default width. – cacamailg May 5 '13 at 23:22
• Other way to have centralized vertical dots is to use the ellipsis package and add in the preamble \newcommand\rvdots{\rotatebox{90}{\dots}}. – cacamailg May 5 '13 at 23:32
• @cacamailg I don't understand your first comment; \textbox has a fixed width that can be changed using \Textwd. – Gonzalo Medina May 5 '13 at 23:54

A TikZ-only alternative of Gonzalo Medina’s answer that uses the internal (with text width set already present) \pgfutil@minipage which is—in LaTeX—simply let to \minipage and therefore similar to \parbox.

There also did exist an alternative that adds a \vrule to \tikz@textfont (which is set by the /tikz/font key). That worked well for one-liners but not for the nodes with more than one line because the internal minipage is top-aligned so a fix that uses c has been needed anyway. In addition to that, the first node part (one or text) seemed a little bit reluctant to the vertical alignment (I lost track because the original \vdots macro also messes with the vertical spacing).

There also exists a heights key so the heights can be set in advance.

## Code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes}
\makeatletter
\DeclareRobustCommand{\rvdots}{%
\vbox{
\baselineskip4\p@\lineskiplimit\z@
\kern-\p@
\hbox{.}\hbox{.}\hbox{.}}}
\tikzset{
heights/.code={
\def\pgf@tempb{}%
\foreach \qrr@tikz@rs@height[count=\qrr@tikz@count from 1] in {#1}{
\edef\pgf@tempa{\noexpand\pgfkeysalso{/tikz/every \pgf@lib@sh@toalpha\qrr@tikz@count\space node part/.append style={height={\qrr@tikz@rs@height}}}}%
\ifnum\qrr@tikz@count=1\relax % allows to use \nodepart{text} (or not at all for the first part)
\edef\pgf@tempa{\unexpanded\expandafter{\pgf@tempa}\noexpand\pgfkeysalso{/tikz/every text node part/.append style={height={\qrr@tikz@rs@height}}}}%
\fi
}
\pgf@tempb
},
height/.code={%
\expandafter\def\expandafter\pgfutil@minipage\expandafter[\expandafter##\expandafter 1\expandafter]\expandafter{\pgfutil@minipage[][#1][c]}% LaTeX only!
}
}
\makeatother
\tikzset{rect/.style={
draw,
rectangle split,
rectangle split parts=9,
rectangle split part align=center,
draw,
font=\ttfamily, % still works
thick,
text width=3cm,
align=center,
rectangle split part align={center,left,right},
rectangle split part fill={gray!30, blue!20, blue!15, blue!20,blue!15,blue!15,green!15,green!20,green!30},
}}
\begin{document}
\begin{tikzpicture}[auto]
\node (stack) [rect] {
\nodepart[height=1cm]{one}     $\rvdots$
\nodepart[height=1cm]{two}     $\rvdots$
\nodepart[height=1.5cm]{three} Argument n
\nodepart[height=1cm]{four}    $\rvdots$
\nodepart[height=1.5cm]{five}  Argument 1
\nodepart[height=1cm]{seven}   Saved \%ebp
\nodepart[height=3cm]{eight}   Saved registers, local variables, and temporaries
\nodepart[height=2cm]{nine}    Argument build area
};
\end{tikzpicture}
\begin{tikzpicture}[auto,rect/.append style={heights={1cm,1cm,1.5cm,1cm,1.5cm,1cm,1cm,3cm,2cm}}]
\node (stack) [rect] {
%    \nodepart{text}
$\rvdots$
\nodepart{two}  $\rvdots$
\nodepart{three} Argument n
\nodepart{four}  $\rvdots$
\nodepart{five}  Argument 1

• @vampire The standalone class is not needed for the answer. I have updated the answer with the stand article class. – Qrrbrbirlbel May 6 '13 at 16:17