This looks scary but unless you have to rotate the nodes I'd go with this path picture
approach:
It allows a list of boxes, i.e.
4/gray, 4/pink
means four gray squares and four pink squares. (They are actually drawn as one rectangles to hide a few unlucky rendering artefacts.)
The rectangle is as high as register/height
and as wide as <number of boxes> * register/width
.
This allows you to change the size of the nodes without having to hard-coding them into the style.
There are three loops necessary:
- The
.list
one from the dim list
helper that evaluated how many boxes are needed and sets the minimum width
of the node accordingly.
- The first
\foreach
that steps through the user-given list.
- The second
\foreach
that draws the vertical lines.
(The \the\numexpr\registerNodeWidth-1\relax
makes it so that the last one that would fall on the right border of the node is not drawn. It would be under the border of the node anyway.)
The [style/.expand once=\Color]
with the \fill
command allows one to use arbitrary styles in the list, for example
{
1/red,
1/{left color=red, right color=blue!50},
1/{left color=blue!50, right color=green},
1/green,
1/{pattern=crosshatch, pattern color=gray}
}
and, of course, also your own.
The label
is not part of the register node
and will not be considered when you place the node via below=of …
or similars.
If you want the registers to be left-aligned, there are options for this, too, aside from just manually doing below=of ….south west, anchor=north west
, for example a \matrix
where all nodes are placed with anchor=west
.
Code
\documentclass[tikz, border=5pt, convert]{standalone}
\usetikzlibrary{patterns, shadings, positioning, ext.misc}
\pgfkeys{
/utils/dim list/.style={
/utils/exec=\def\registerNodeWidth{0},
/utils/@dim list/.list={#1}},
/utils/@dim list/.code args={#1/#2}%
{\edef\registerNodeWidth{\the\numexpr\registerNodeWidth+#1}}}
\tikzset{
draw,
register/width/.initial=1cm, register/height/.initial=1cm,
register/dotted/.style={dotted}, register/dashed/.style={dashed},
every register node/.style={draw, thick},
register node/.value required,
register node/.style 2 args={
shape=rectangle, every register node, /utils/dim list={#2},
minimum width=\registerNodeWidth*\pgfkeysvalueof{/tikz/register/width},
minimum height=\pgfkeysvalueof{/tikz/register/height},
path picture={
\foreach[
remember=\totalWidth as \lastTotalWidth (initially 0),
evaluate={\totalWidth=\lastTotalWidth+\Width;}]
\Width/\Color in {#2}
\fill[style/.expand once=\Color]
([xshift=\lastTotalWidth*\pgfkeysvalueof{/tikz/register/width}]%
path picture bounding box.south west)
rectangle ++(\Width*\pgfkeysvalueof{/tikz/register/width},
\pgfkeysvalueof{/tikz/register/height});
\foreach \cnt in {1,...,\the\numexpr\registerNodeWidth-1\relax}
\draw[every register node,
/utils/if={mod(\cnt,2)}{register/dotted},
/utils/if={mod(\cnt,4)==2}{register/dashed}]
([xshift=\cnt*\pgfkeysvalueof{/tikz/register/width}]%
path picture bounding box.south west)
-- ++ (up:\pgfkeysvalueof{/tikz/register/height});
},
label={[anchor=south west]north west:$#1$}}}
\begin{document}
\begin{tikzpicture}
\node [register node={R_1}{4/gray, 4/pink}] (A) {};
\node[below=of A] [register node={R_2}{3/gray, 2/pink, 3/magenta}] (B) {};
\node[below=of B] [register node={R_3}{
1/red,
1/{left color=red, right color=blue!50},
1/{left color=blue!50, right color=green},
1/green,
1/{pattern=crosshatch, pattern color=gray}
}] (C) {};
\end{tikzpicture}
\end{document}
Output

\newcommand{\Register}[1]
. Note where the braces are.\Register
will always be placed at the coordinates that are specified in the macro. You're going to need to use a transformation to have it move around. That said, I think you are looking for apic
which are almost like a macro but it can be placed like a node (where(0,0)
of the pic will be placed at the specified coordinate:\pic at (<coord>) {pic name};
) There are also ways to do that without a pic but it's the easiest way to do in TikZ.pic
solution: is that in fact a possibility? Or must I pass parameters to indicate coordinates into the macro? (I'm a bit worried about running out of parameters: I believe I can only have 9?) The Registers will be connected together with arrows to indicate a processing flow. Some Registers will be grouped together, probably by a surrounding rectangle.#
(there are ways around it but I don't think we need that here). It's better to use a different syntax or keys. Is it always dotted, dashed, dotted, solid, dotted, dashed, dotted, solid, …?