# Change and mix folder style in forest package when making trees

I have a question regarding the forest package. I would like to change the following tree to save some vertical space by changing the folder style at a certain level to be alternating or grow in a different direction. To that, I don't know why the first level is not aligned vertically.

Bonus Question: How is it possible to have alternating folder structure? Such as

            A
|-B
C-|
or even   E-|-D


What I would like to have is something like this.

Here is my MWE:

\documentclass[tikz,multi]{standalone}
\usepackage[edges]{forest}

\begin{document}
\begin{forest}
basic/.style = {draw, thin, drop shadow, font=\sffamily},
my root/.style = {basic, rounded corners=2pt, fill=black!2},
upper style/.style = {basic, rounded corners=6pt, fill=black!6, text width=10.5em},
lower style/.style = {basic, rounded corners=0pt,fill=black!10, text width=9em},
for tree={%
parent anchor=south,
child anchor=north,
edge path={
\noexpand\path [-{Stealth[]}, \forestoption{edge}, thin]
(!u.parent anchor) -- +(0,-5pt) -| (.child anchor)\forestoption{edge label};
},
/tikz/>=LaTeX,
},
where level=0{%
my root,
%for 1={%
for tree={%
if={level()<3}{%
upper style,
}{%
lower style,
},
if={level()<2}{%
if={isodd(n_children())}{%
calign=child edge,
calign primary child/.wrap pgfmath arg={#1}{int((n_children()+1)/2)},
}{%
calign=edge midpoint,
},
}{%
folder,
grow'=0,
},
},
}{},
[Alphabet
[First five letters, folder, grow'=0,
[A, lower style,]
[B, lower style,]
[C, lower style,]
[D, lower style,]
[E, lower style, text width=12em]
]
[More letters
[Two
[F]
[G]
]
[Nine
[H]
[I]
[J]
[K]
[L]
[M]
[N]
[O]
[And a longer box, text width=12em]
]
[Some more stuff
[to fill]
[this tree]
]
]
]
\end{forest}
\end{document}


The folder style is not really designed with changes of growth direction in mind, I don't think. Hence, it requires some manual adjustments after the fact. At least, I think the easiest way is just to move the relevant subtree before the tree is drawn.

\documentclass[border=10pt]{standalone}
\usepackage[edges]{forest}
\begin{document}
\begin{forest}
basic/.style = {draw, thin, drop shadow, font=\sffamily},
upper style/.style = {basic, rounded corners=6pt, edge+={-Stealth, thin}, fill=black!6, text width=10.5em},
lower style/.style = {basic, rounded corners=0pt, edge+={-, line width=.4pt}, fill=black!10, text width=9em},
where level<=2{%
upper style,
edge path'={
(!u.parent anchor) -- +(0,-5pt) -| (.child anchor)
},
}{%
lower style,
},
where level<=1{%
parent anchor=children,
child anchor=parent,
if={isodd(n_children())}{%
calign=child edge,
calign primary child/.process={
O+nw+n{n children}{(#1+1)/2}
},
}{%
calign=edge midpoint,
},
}{
folder,
grow'=0,
},
[Alphabet
[First five letters, folder, grow'=0, for children={lower style},
before drawing tree={
tempdima/.option=!r2.max y,
tempdima-/.option=max y,
for tree={
y+/.register=tempdima,
},
}
[A]
[B]
[C]
[D]
[E, text width=12em]
]
[More letters
[Two
[F]
[G]
]
[Nine
[H]
[I]
[J]
[K]
[L]
[M]
[N]
[O]
[And a longer box, text width=12em]
]
[Some more stuff
[to fill]
[this tree]
]
]
]
\end{forest}
\end{document}


The further desiderata is not, I think, possible with Forest without changing the structure of the tree. That is, you could fake it, but you can't put some children one way and some another, without manually moving one set or t'other, at which point, it is probably easier to abandon Forest and use TikZ to place everything directly.

If you are prepared to change the structure of the tree (which you could even do automatically, although I wouldn't bother unless you have very many with just this pattern), you could use a coordinate node to change the direction of growth i.e. some of the children would become grandchildren of their current parent and you'd have a coordinate as their parent. You'd then need to insert another set of three coordinates, making the original children great-grandchildren of their original parent. I doubt it is worth the additional complexity of the code, but here's an example.

\begin{forest}
basic/.style = {draw, thin, drop shadow, font=\sffamily},
upper style/.style = {basic, rounded corners=6pt, edge+={-Stealth, thin}, fill=black!6, text width=10.5em},
lower style/.style = {basic, rounded corners=0pt, edge+={-, line width=.4pt}, fill=black!10, text width=9em},
where level<=2{%
upper style,
edge path'={
(!u.parent anchor) -- +(0,-5pt) -| (.child anchor)
},
}{%
lower style,
},
where level<=1{%
parent anchor=children,
child anchor=parent,
if={isodd(n_children())}{%
calign=child edge,
calign primary child/.process={
O+nw+n{n children}{(#1+1)/2}
},
}{%
calign=edge midpoint,
},
}{
folder,
grow'=0,
},
[Alphabet
[First five letters, folder, grow'=0, for children={lower style},
before drawing tree={
tempdima/.option=!r2.max y,
tempdima-/.option=max y,
for tree={
y+/.register=tempdima,
},
}
[A]
[B]
[C]
[D]
[E, text width=12em]
]
[More letters
[Two
[F]
[G]
]
[Nine
[H]
[I]
[J]
[K]
[, coordinate, grow'=-90, for descendants={edge path'={(!u.parent anchor) |- (.child anchor)}}, before packing={calign primary child=2}
[, coordinate
[And a longer box, text width=12em]
]
[, coordinate
[N]
[O]
]
[, coordinate
[L]
[M]
]
]
]
[Some more stuff
[to fill]
[this tree]
]
]
]
\end{forest}


Why, by the way, do you want some edges to be regular width and some thin? Although I've preserved it here, I think it a weird idea.

• Thank you for this solution! To be honest, I didn't realized I was mixing line styles. However by looking at this tree I also don't know if I should save the space for the price of awkward layout. However, I think there is a lot to learn here. Can you give some explanation on these parts? if={isodd(n_children())}{% calign=child edge, calign primary child/.process={ O+nw+n{n children}{(#1+1)/2} }, before drawing tree={ tempdima/.option=!r2.max y, tempdima-/.option=max y, for tree={ y+/.register=tempdima, }, Apr 19 '17 at 11:53
• @Bernte if={isodd(n_children())}{% calign=child edge, calign primary child/.process={ O+nw+n{n children}{(#1+1)/2} }, is just equivalent to if={isodd(n_children())}{ calign=child edge, calign primary child/.wrap pgfmath arg={#1}{int((n_children()+1)/2)}, } which is in your original code. .process is a faster alternative to .pgfmath, roughly speaking. before drawing tree={ tempdima/.option=!r2.max y, tempdima-/.option=max y, for tree={ y+/.register=tempdima, }, is just getting the vertical position of the root's second child in order to adjust the first child's tree.
– cfr
Apr 19 '17 at 15:11