Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I would like to define a macro, which would take a list of node definitions, like this

\mymacro[boxes={{\node[rectangle] {foo};},
                {\node[rectangle] {bar};},
                {\node[circle] {baz};},
                alignment=stacked]{ ... }

and place the nodes vertically, i.e. stacked on top of each other.

[ ]
[ ]
( )

Or like this:

\mymacro[boxes={{\node[rectangle] {foo};},
                {\node[rectangle] {bar};},
                {\node[circle] {baz};},
                alignment=listed]{ ... }

[ ] , [ ] , ( )

to place them besides each other, interspersed with another node (containing a comma in this case).

I know how to handle a list option with pgfkeys, but have no idea where to start on the stacking or listing bit.

share|improve this question

1 Answer 1

up vote 3 down vote accepted

I would use styles instead of a macro for this: The vertical and horizontal placement can be accomplished by using chains, the comma between the horizontal nodes can be placed using a decoration.

I've used two styles here: nodelist defines all nodes to be drawn and to be part of a chain, and calls a second style called nodelist direction, which actually starts the chain, defines the direction the chain will grow in, and in the case of nodelist direction=horizontal sets up the decoration that will replace the joins of the chain with nodes containing commas.

You can then just enclose the nodes in a scope with the nodelist style, and everything will be set up:

\begin{scope}[nodelist]
\node {A};
\node [circle] {B};
\node [star] {C};
\end{scope}

\begin{scope}[xshift=6cm,nodelist=vertical]
\node {A};
\node [circle] {B};
\node [star] {C};
\end{scope}

will lead to

chains!

And here's the complete code:

\documentclass{article}
\usepackage{tikz} 
\usetikzlibrary{calc,shapes,chains,decorations.markings}  
\begin{document}

\tikzset{
    nodelist direction/.is choice,
    nodelist direction/.default=horizontal,
    nodelist direction/horizontal/.style={
        start chain=going right,
        every node/.style=join,
        decoration={
            markings, % switch on markings
            mark=at position 0.5 with {
                \tikzset{every node/.style={}} % Reset the style locally
                \node {,}; % Create a node that holds a comma
            }
        },
        every join/.style={
            decorate    % Decorate every join with the decoration defined above
        }
    },
    nodelist direction/vertical/.style={
        start chain=going below, % Much simpler, just go down, no decorations, no joins
    },
    nodelist/.style={ % Options common to horizontal and vertical
        nodelist direction=#1,
        every node/.append style={
            on chain,
            draw
        },
    }
}

\begin{tikzpicture}

\begin{scope}[nodelist]
\node {A};
\node [circle] {B};
\node [star] {C};
\end{scope}

\begin{scope}[xshift=6cm,nodelist=vertical]
\node {A};
\node [circle] {B};
\node [star] {C};
\end{scope}
\end{tikzpicture} 


\end{document} 
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.