9

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

1 Answer 1

10

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).

5
  • But the children of Foobarish are still not aligned with the children of Bar so this only solves the part of the problem relating to drawing the paths. I think that to align all the children and grandchildren one would need to adjust things a bit deeper. Trees are drawn by transforming first to the centre of the parent node. This is what would need changing, I think. Jan 4, 2013 at 10:06
  • @Jake Just come to the same conclusion ... Jan 4, 2013 at 10:13
  • @AndrewStacey and Jake, thank you for pointing at that issue and providing a solution. I updated the answer.
    – JLDiaz
    Jan 4, 2013 at 10:17
  • @JLDiaz: As you did change the anchor usage: Actually, I had added these to Andrew’s answer, and I did it only by try & error. Your new approach breaks in my real case (that also was the reason for contributing to Andrew’s answer). My first try here was to add an x-shift also to every child node/.style, this would work, but it is really complicated to fiddle out good values for both xshifts, then. I at last decided to change all parent anchors to south. In my case now the vertical lines are still almost aligned, because the nodes are almost the same length.
    – Speravir
    Jan 6, 2013 at 0:50
  • @JLDiaz: The best, I think, would be something like anchor=1em right of south west. BTW please add a remark in the code, that the value of xshift can be and perhaps should be adjusted to one’s own needs.
    – Speravir
    Jan 6, 2013 at 0:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .