[Tex/LaTex] Changing the indentation of a Tikz tree

tikz-pgftikz-trees

I've drawn a directory listing style tree using code similar to that found in Drawing a directory listing a la the tree command in TikZ. I'll repeat it here for clarity

            \documentclass[border=10]{standalone}   
            \usepackage{tikz}

            \makeatletter
            \newcount\dirtree@lvl
            \newcount\dirtree@plvl
            \newcount\dirtree@clvl
            \def\dirtree@growth{%
              \ifnum\tikznumberofcurrentchild=1\relax
              \global\advance\dirtree@plvl by 1
              \expandafter\xdef\csname dirtree@p@\the\dirtree@plvl\endcsname{\the\dirtree@lvl}
              \fi
              \global\advance\dirtree@lvl by 1\relax
              \dirtree@clvl=\dirtree@lvl
              \advance\dirtree@clvl by -\csname dirtree@p@\the\dirtree@plvl\endcsname
              \pgf@xa=1cm\relax
              \pgf@ya=-1cm\relax
              \pgf@ya=\dirtree@clvl\pgf@ya
              \pgftransformshift{\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
              \ifnum\tikznumberofcurrentchild=\tikznumberofchildren
              \global\advance\dirtree@plvl by -1
              \fi
            }

            \tikzset{
              dirtree/.style={
                growth function=\dirtree@growth,
                every node/.style={anchor=north},
                every child node/.style={anchor=west},
                edge from parent path={(\tikzparentnode\tikzparentanchor) |- (\tikzchildnode\tikzchildanchor)}
              }
            }
            \makeatother
            \begin{document}
            \begin{tikzpicture}[dirtree]
            \node {toplevel} 
                child { node {Foo}
                        child { node {foo} }
                        child { node {bar} }
                        child { node {baz} }
                }
                child { node {Bar}
                    child { node {foo} }
                    child { node {foo} }
                    child { node {foo} }
                    child { node {foo} }
                    child { node {bar} }
                    child { node {baz} }
                }
                child { node {Baz}
                    child { node {foo} }
                    child { node {bar} }
                    child { node {baz} }
                };
            \end{tikzpicture}
            \end{document}

My question is: how can I reduce the indentation of the child nodes?

Currently the anchor point comes from the south of the parent node which means the tree becomes large horizontally very quickly. I do not wish to use the parents' west as the anchor point. Ideally a point between the two would be better so the output looks like:

                            Root
                            |___ First Parent
                                    |__First Child
                                        |_ Grand Child

Rather than

                            Root
                            |___ First Parent
                                      |__First Child
                                               |_ Grand Child

Any thoughts much appreciated

Best Answer

Let's provide a different example which shows better your problem:

% Assumming preamble as provided in the question
    \tikzset{
    dirtree/.style={
      growth function=\dirtree@growth,
      every node/.style={anchor=north},
      every child node/.style={anchor=west},
      edge from parent path={(\tikzparentnode\tikzparentanchor) |- (\tikzchildnode\tikzchildanchor)}
  }
}
\makeatother
\begin{document}
\begin{tikzpicture}[dirtree]
\node {toplevel} 
    child { node {Foobarish}
            child { node  {foobar} 
                    child { node {foo}} 
                  }
            child { node  {foo} 
                    child {node {foo} } 
                  }
            child { node  {bar} }
    }
    child { node {Bar}
        child { node {foo} }
        child { node {foo} }
    };
\end{tikzpicture}

The output is:

Output

This shows not only the issue you mention, but also that the vertical stems in each branch are not aligned (the branch from Foobarish is not aligned with the branch from Bar). This problem will be also solved with a proper parent anchor (and growth parent anchor) which does not depend on the size of the parent. In this case south west is the best choice.

The following style solves all these issues, and provides a very compact version of the tree.

\tikzset{
  dirtree/.style={
    growth function=\dirtree@growth,
    growth parent anchor=south west,
    parent anchor=south west,
    every child node/.style={anchor=west},
    edge from parent path={([xshift=2ex] \tikzparentnode\tikzparentanchor) 
                           |- (\tikzchildnode\tikzchildanchor)}
  }
}

Final result

Thanks to Andrew Stacey and Jake for their useful comments about the need to set also growth parent anchor (their comments below refer to an early version of this answer).

Related Question