%    pgftree.tex
%    Version 1.2, 20 Apr 2012

%    Copyright 2009 by David Chiang

%    This program is free software; you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation; either version 2 of the License, or
%    (at your option) any later version.

%    This program is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.

%    You should have received a copy of the GNU General Public License along
%    with this program; if not, write to the Free Software Foundation, Inc.,
%    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

% New in version 1.2:
% - level-specific styles (thanks to Andrew Stacey)

% New in version 1.1:
% - major restructuring to not do arbitrary nesting of subpicture environments
% - sideways trees

% To do:
% - trees with all leaves at same level
% - if \nodename does not exist as desired, wrap inside a rectangle node
% - don't use pgfsubpic internals

\newdimen\levelsep \levelsep=30pt
\newdimen\subtreesep \subtreesep=2pt
\newdimen\smuggle@levelsep
\newdimen\smuggle@subtreesep
\newdimen\this@levelsep
\newdimen\this@subtreesep

\def\leveldirection{down}
\def\siblingdirection{right}

% definitions of growing directions
\def\pgftree@levelshift{\csname pgftree@levelshift@\leveldirection\endcsname}
\def\pgftree@parentanchor{\csname pgftree@parentanchor@\leveldirection\endcsname}
\def\pgftree@childanchor{\csname pgftree@childanchor@\leveldirection\endcsname}
% these assume that the current subpicture is the child
\def\pgftree@presiblingshift{\csname pgftree@presiblingshift@\siblingdirection\endcsname}
\def\pgftree@postsiblingshift{\csname pgftree@postsiblingshift@\siblingdirection\endcsname}

\def\pgftree@levelshift@down{\pgfpoint{0}{-\levelsep}}
\def\pgftree@parentanchor@down{south}
\def\pgftree@childanchor@down{north}

\def\pgftree@levelshift@up{\pgfpoint{0}{\levelsep}}
\def\pgftree@parentanchor@up{north}
\def\pgftree@childanchor@up{south}

\def\pgftree@levelshift@right{\pgfpoint{\levelsep}{0}}
\def\pgftree@parentanchor@right{east}
\def\pgftree@childanchor@right{west}

\def\pgftree@levelshift@left{\pgfpoint{-\levelsep}{0}}
\def\pgftree@parentanchor@left{west}
\def\pgftree@childanchor@left{east}

\def\pgftree@presiblingshift@right{\pgf@process{\pgf@x-\pgf@subpicminx \advance\pgf@x\subtreesep \pgf@y 0pt}}
\def\pgftree@postsiblingshift@right{\pgf@process{\pgf@x\pgf@subpicmaxx \pgf@y 0pt}}

\def\pgftree@presiblingshift@left{\pgf@process{\pgf@x-\pgf@subpicmaxx \advance\pgf@x-\subtreesep \pgf@y 0pt}}
\def\pgftree@postsiblingshift@left{\pgf@process{\pgf@x\pgf@subpicminx \pgf@y 0pt}}

\def\pgftree@presiblingshift@up{\pgf@process{\pgf@x 0pt \pgf@y-\pgf@subpicminy \advance\pgf@y\subtreesep}}
\def\pgftree@postsiblingshift@up{\pgf@process{\pgf@x 0pt \pgf@y\pgf@subpicmaxy}}

\def\pgftree@presiblingshift@down{\pgf@process{\pgf@x 0pt \pgf@y-\pgf@subpicmaxy \advance\pgf@y-\subtreesep}}
\def\pgftree@postsiblingshift@down{\pgf@process{\pgf@x 0pt \pgf@y\pgf@subpicminy}}

% for convenience if you are using \pgftree directly
\def\drawnode#1{\pgfnode{rectangle}{base}{#1}{\nodename}{\pgfusepath{discard}}}
\def\drawedge{%
\pgfpathmoveto{\pgfpointanchor{\parentnodename}{\pgftree@parentanchor}}%
\pgfpathlineto{\pgfpointanchor{\nodename}{\pgftree@childanchor}}%
\pgfusepath{stroke}}

% local variables that we need to assign to inside a \pgfforeach
\newdimen\pgftree@childx
\newdimen\pgftree@savechildx
\newdimen\pgftree@childy
\newdimen\pgftree@savechildy
\newcount\pgftree@childi
\newcount\pgftree@savechildi
\newcount\pgftree@level
\newdimen\pgftree@depth

%%% \pgftree{subtree}

\def\pgftree#1{%
\def\nodename{r}%
\pgftree@level=0\relax
\pgftree@depth=0pt\relax
#1%
\pgfplacesubpicture
}

%%% \pgfsubtree{root}{subtrees}
% The first argument draws the root node using PGF/TikZ commands.
% The node must be named \nodename.

% The second argument is a sequence of 3n tokens.
% Token 3n-2 draws the nth edge. It should draw an edge from \parentnodename to \nodename.
% Token 3n-1 is a hook that can change \levelsep or \subtreesep for child n only.
% Token 3n draws the nth subtree. Its root must be named \nodename.

\pgfnewsubpicture{children}
\newdimen\pgftree@lastchildx
\newdimen\pgftree@lastchildy

\def\pgfsubtree#1#2{%
\let\parentnodename\nodename
\pgftree@savechildx=\pgftree@childx
\pgftree@savechildy=\pgftree@childy
\pgftree@savechildi=\pgftree@childi
% Build subpicture with all the children and their subtrees
{\pgftree@childx=0pt%
\pgftree@childy=0pt%
\pgftree@childi=0%
\process@children #2}%
\begin{pgfsubpicture}%
% Create node
#1%
\ifnum\pgftree@childi>0%
% Place children
{% center so that parent is midway between origins of first and last children
\pgftransformshift{\pgfpointscale{-0.5}{\pgfqpoint{\the\pgftree@childx}{\the\pgftree@childy}}}%
\pgfplacesubpicture}%
% Draw the edges
{\pgftree@childi=0%
\process@edges #2}%
\fi
\end{pgfsubpicture}%
\global\pgftree@childi=\pgftree@savechildi
\global\pgftree@childx=\pgftree@savechildx
\global\pgftree@childy=\pgftree@savechildy
}

\def\process@children{%
\pgfutil@ifnextchar\egroup
{% No more children, step back to origin of last child
\global\pgftree@childx\pgftree@lastchildx
\global\pgftree@childy\pgftree@lastchildy
\global\pgftree@childi\pgftree@childi
\ifnum\pgftree@childi>0%
\pgfrestoresubpicture{children}% pass children back to caller
\fi
}%
{\@process@children}%
}
\def\@process@children#1#2#3{%
% #1 is the edge, #2 is the hook, #3 is the child
{% call hook to get \levelsep and \subtreesep
% and put them in \this@levelsep and \this@subtreesep
% to hide them from descendants
#2%
\global\smuggle@levelsep\levelsep
\global\smuggle@subtreesep\subtreesep}%
\this@levelsep\smuggle@levelsep
\this@subtreesep\smuggle@subtreesep
% Build the current child
{\edef\nodename{\parentnodename-\the\pgftree@childi}%
\advance\pgftree@level by 1\relax
\advance\pgftree@depth by \this@levelsep
#3}%
\begin{pgfsubpicture}%
% Place current child
{%
% The \levelsep and \subtreesep set in #2 apply only here
\levelsep\this@levelsep
\subtreesep\this@subtreesep
\ifnum\pgftree@childi>0% the first child is always at 0
\pgftree@presiblingshift \global\advance\pgftree@childx\pgf@x \global\advance\pgftree@childy\pgf@y
\fi
\pgftransformshift{\pgftree@levelshift}%
\pgftransformshift{\pgfqpoint{\the\pgftree@childx}{\the\pgftree@childy}}%
\pgfplacesubpicture
\global\pgftree@lastchildx\pgftree@childx
\global\pgftree@lastchildy\pgftree@childy
\pgftree@postsiblingshift \global\advance\pgftree@childx\pgf@x \global\advance\pgftree@childy\pgf@y
}%
% Save the augmented row of children back into "children"
\end{pgfsubpicture}
\ifnum\pgftree@childi>0%
\pgfmergesubpicture{children}
\else
\pgfsavesubpicture{children}%
\fi
\advance\pgftree@childi by 1%
\process@children
}

\def\process@edges{%
\pgfutil@ifnextchar\egroup
{}%
{\@process@edges}%
}
\def\@process@edges#1#2#3{%
\edef\nodename{\parentnodename-\the\pgftree@childi}%
#1%
\advance\pgftree@childi by 1%
\process@edges
}

\def\subtreeof#1{%
% the subpicture which contains a node also contains exactly its subtree
\csname pgf@sh@pi@#1\endcsname
}