# Absolute positioning of a forest tree (with overlay-specifications) in beamer

I'm trying to position a forest tree at the center of a beamer frame with the following code. In particular, the tree contains a beamer-overlay specification. This makes \sbox or similar "externalization" methods less desirable.

# MWE

\documentclass{beamer}
\usepackage{forest}
\forestset{
os/.code args={<#1>#2}{\only<#1>{\pgfkeysalso{#2}}} % 'os' short for 'onslide'
}

\begin{document}
\begin{frame}{xx}
\begin{itemize}
\item text text
\item text text
\item text text
\item text text
\item text text
\item text text
\end{itemize}

\begin{tikzpicture}[remember picture,overlay]
\node(n)[draw=red,at=(current page.center)]{center}; % just for reference
\node[draw]at(current page.center){
\begin{forest}
[x[x[x][x]][x,os=<2->red]]
\end{forest}
};
\end{tikzpicture}
\end{frame}
\end{document}


This is what it looks like after the first compilation

So far so good. But when I compile again, the tree expands...

Compile again, it expands further...

As @cfr's comment suggests, this is likely due to the fact that I'm nesting a forest in a tikzpicture.

I'm hoping someone would provide a solution that allows both absolute positioning of a forest tree and beamer-overlay specifications in the tree.

• In general, nesting tikzpictures is a Bad Idea. So, yes, it is probably due to the fact that you are doing this. ;) This appears to answer your question ?
– cfr
Apr 1 '16 at 23:55
• Also, you are overlaying an overlay and I'm not even sure you can apply overlay to particular nodes.... (But maybe you can.)
– cfr
Apr 2 '16 at 0:00

Nesting tikzpictures is generally A Very Bad Idea and Something Best Avoided. In very simple cases, it may work, but it is unpredictable and liable to break in various weird and wonderful ways. The general advice is: do not do it.

If you just want to centre a tree or do not need to use overlay specifications, please see Simple Cases below for two more straightforward approaches. (One centres the tree using columns. The other overlays the tree, placing it at the frame's centre regardless of other content but cannot be used with overlay specifications.)

# Complex Case

Use this approach only if you need a tree which uses overlay specifications to be overlaid on the frame, regardless of other content. This method works in my extremely minimal testing.

## Caveat emptor...

As shown below, saving a tree into a box allows it to be used within a TikZ node and, hence, to be overlaid on the frame at an absolute position. However, this doesn't work well with overlay specifications because the whole point is to save the box 'as is' at the time it is defined.

We can, however, emulate this effect by modifying the way Forest draws the tree. That is, we can have Forest save the drawn tree into a box and then typeset that box as the contents of a TikZ node. Because this is done on-the-fly as the tree is typeset, this allows us to use overlay specifications within the tree in the normal way. Effectively, Forest saves the current tree to the box and then puts the box in the node for each slide on which it is asked to do so.

To achieve this, we define a new style centre tree which we can use when we want a tree treated in this fashion.

  centre tree/.code={%


This style modifies draw tree stage, overriding Forest's default.

    \forestset{%
draw tree stage/.style={
for root'={


Before drawing the tree, we specify a box we want Forest to draw the tree into.

          draw tree box=0,


Now we draw the tree - but this won't typeset anything. Instead, it will save the tree into the box.

          draw tree,


Now we actually typeset the tree by unboxing our box into a suitably defined TikZ node.

          TeX={
\tikz[overlay,remember picture]{\node [anchor=center] at (current page.center) {\box0};}
},
},
},
}%
},


Now we can use this new style when we want a tree overlaid and centred. For example, here are 3 slides within a modified version of the frame included in the question:

  \begin{forest}
centre tree
[x
[x, visible on=<2->
[x]
[x]
]
[x, visible on=<3->]
]
\end{forest}


This produces the desired 3 slides as the tree is incrementally uncovered at the frame's centre:

Complete code:

\documentclass{beamer}
\usepackage{forest}
\tikzset{% set up for transitions using tikz with beamer overlays - developed by Daniel (http://tex.stackexchange.com/a/55849/) and, in earlier form, by Matthew Leingang (http://tex.stackexchange.com/a/6155/) and modified for this use, I think by Qrrbrbirlbel (http://tex.stackexchange.com/a/112471/)
invisible/.style={opacity=0,text opacity=0},
visible on/.style={alt=#1{}{invisible}},
alt/.code args={<#1>#2#3}{%
\alt<#1>{\pgfkeysalso{#2}}{\pgfkeysalso{#3}} % \pgfkeysalso doesn't change the path
},
}
\forestset{%
visible on/.style={% developed by Qrrbrbirlbel (http://tex.stackexchange.com/a/112471/)
for tree={%
/tikz/visible on={#1},
edge={/tikz/visible on={#1}},
},
},
centre tree/.code={%
\forestset{%
draw tree stage/.style={
for root'={
draw tree box=0,
draw tree,
TeX={
\tikz[overlay,remember picture]{\node [anchor=center] at (current page.center) {\box0};}
},
},
},
}%
},
}
\begin{document}
\begin{frame}{xx}
\begin{itemize}
\item text text
\item text text
\item text text
\item text text
\item text text
\item text text
\end{itemize}
\begin{forest}
centre tree
[x
[x, visible on=<2->
[x]
[x]
]
[x, visible on=<3->]
]
\end{forest}
\end{frame}
\end{document}


# Simple Cases

If you just want to centre things, why not just use one of the usual Beamer strategies? For example:

\documentclass{beamer}
\usepackage{forest}

\begin{document}
\begin{frame}{xx}
\begin{columns}
\begin{column}{.5\textwidth}
\begin{itemize}
\item text text
\item text text
\item text text
\item text text
\item text text
\item text text
\end{itemize}
\end{column}%
\begin{column}{.5\textwidth}
\begin{forest}
[x[x[x][x]][x]]
\end{forest}
\end{column}
\end{columns}
\end{frame}
\end{document}


If you really need it centred on the frame and overlaying the other content, then the easiest way is probably to save the tree in a box and then place the box. For example:

\documentclass{beamer}
\usepackage{forest}

\begin{document}
\newsavebox\myforest
\sbox\myforest{%
\begin{forest}
[x[x[x][x]][x]]
\end{forest}%
}
\begin{frame}{xx}
\begin{itemize}
\item text text
\item text text
\item text text
\item text text
\item text text
\item text text
\end{itemize}
\tikz[overlay,remember picture]{\node [anchor=center] at (current page.center) {\usebox{\myforest}};}
\end{frame}
\end{document}


Or wait for Sašo Živanović to provide a slicker solution ;).

• Thanks for the answer @cfr ! I do need to position a tree in an absolute fashion. Moreover, I want to be able to uncover parts of the tree frame by frame a la this style. This is why I'm not using \sbox or similar methods. I'll revise my question to better reflect my full intention when I get on my computer at home. Apr 2 '16 at 3:14
• One or the other is straightforward. Both I think will be rather more difficult. Even if you change the way Forest draws the tree (which isn't necessary for incremental uncovering), it isn't obvious how to get absolute positioning. even changing x and y before drawing tree doesn't change the absolute position. It is still relative. I'm not sure generally how you can use overlay specifications for overlaid stuff except by splitting that stuff up. Obviously you can do that here, but it would be a pain. Probably you might persuade Forest into several save boxes?
– cfr
Apr 2 '16 at 3:36
• I use something somewhat similar for overlay specs in TikZ and in Forest. But you want to combine that with overlay and I don't see how that can work.
– cfr
Apr 2 '16 at 3:38
• Yeah, both beamer-overlay effect and absolute positioning is what I'm hoping to achieve. If it's difficult to combine beamer-overlay with TikZ-overlay, perhaps textpos could be an alternative to TikZ-overlay? Apr 2 '16 at 3:45
• @HerrK. Please see edit above.
– cfr
Apr 3 '16 at 0:34

I managed to achieve absolute positioning with the textpos package, and this method also seems to accommodate beamer-overlay effects applied in the Forest tree. Admittedly, this solution is somewhat clumsy, so I'd appreciate if anyone can come up with better solutions.

# MWE

\documentclass{beamer}
\usepackage{forest}
\forestset{
os/.code args={<#1>#2}{\only<#1>{\pgfkeysalso{#2}}} % 'os' short for 'onslide'
}
\usepackage[absolute,overlay]{textpos}
\setlength{\TPHorizModule}{\paperwidth}
\setlength{\TPVertModule}{\paperheight}

\begin{document}
\begin{frame}{xx}
\begin{itemize}
\item text text
\item text text
\end{itemize}

\begin{textblock}{1}(0,0)
\centering