7

Objective

I'm trying to create a beamer presentation (in LyX) where frames conditionally display a headline containing section and subsection navigation depending on (a) whether a frame is in a section environment and (b) whether the section environment contains any subsections. Specifically, the following three conditions should apply:

  1. If frame outside section: do not display headline (e.g. title frame, toc frame)
  2. If frame inside section without any subsections: display for all frames in section only the portion of headline containing section navigation
  3. If frame inside section with subsections: display for all frames in section both the portion of headline containing section navigation and the portion containing subsection navigation

The following MWE should clarify the desired outcomes:

\documentclass{beamer}

% define colors
\definecolor{black}{RGB}{0,0,0}
\definecolor{darkblue}{RGB}{0,41,103}
\definecolor{lightblue}{RGB}{0,118,188}

\setbeamercolor*{section in head/foot}{fg=white, bg=lightblue}
\setbeamercolor*{section in head/foot shaded}{fg=white, bg=darkblue}
\setbeamercolor{subsection in head/foot}{fg=white, bg=darkblue}

% Create headline environment
\setbeamertemplate{headline}{%
\begin{beamercolorbox}[colsep=1.5pt]{upper separation line head}
\end{beamercolorbox}
\begin{beamercolorbox}{section in head/foot}
      \vskip2pt\insertsectionnavigationhorizontal{\paperwidth}{}{\hfill\hfill}\vskip2pt 
\end{beamercolorbox}%
\begin{beamercolorbox}[ht=10pt]{subsection in head/foot}%
       \vskip2pt\insertsubsectionnavigationhorizontal{\paperwidth}{}{\hfill\hfill}\vskip2pt
\end{beamercolorbox}%
\begin{beamercolorbox}[colsep=1.5pt]{lower separation line head}
\end{beamercolorbox}
}

\begin{document}

\frame{\frametitle{Frame outside section environment} 
This frame should display neither the section, nor the subsection portion of the headline 
}

\section{Section 1 (no subsections)}
\frame{\frametitle{Frame in section environment with no subsections} 
This frame should display the section portion of the headline, but not the subsection portion 
}

\section{Section 2 (with subsection)}
\subsection{Subsection 2.1}
\frame{\frametitle{Frame in section environment (post-subsection)} 
This frame should display both the section and subsection portions of the headline 
}

\section{Section 3 (with)}
\frame{\frametitle{Frame in section environment (pre-subsection)} 
This frame should display both the section and subsection portions of the headline 
}
\subsection{Subsection 3.1}

\section{Section 4 (with subsections)}
\frame{\frametitle{Frame in section environment pre-subsection} 
This frame should display both the section and subsection portions of the headline 
}
\subsection{Subsection 4.1}
\frame{\frametitle{Frame in section environment post-subsection} 
This frame should display both the section and subsection portions of the headline 
}
\subsection{Subsection 4.2}

\end{document}

Question(s)

How can I achieve this kind of complex conditionality?

I am aware that one can use \ifx to check whether a certain environment is defined or whether an element is positioned within a certain environment. For example, to check if one is in a section environment, one could use:

\ifx\insertsection\empty
    %do this if NOT in section environment%
\else
    %do this if in section environment%
\fi

Unfortunately, this only addresses the first of the three conditions stated above. The second two conditions effectively require code that "searches through" a section for defined subsections and evaluates to "true" if any are found and "false" if none are found. I have attempted to address this by playing around with the \pretocmd option of the etoolbox package and the approach used in the miniframes outer theme, but I fear my understanding of said approaches is so lacking that I am effectively just stumbling around in the dark.

I'm grateful for any guidance as to how this scenario may be resolved.

  • A quick hint might be to use the value of the section or rather subsection counters, using for example etoolbox command \ifnumequal{\number\value{subsection}}{0}}{do section stuff}{do subsection stuff} – user31729 Feb 25 '14 at 9:20
  • Thank you for the suggestion, @Christian. However, much like the \ifx\insertsection approach, this again only addresses the first conditional requirement and not the other two. That is, the expression \number\value{subsection} evaluates to 0 for any frame that is not currently in a subsection environment, even if that frame is in a section environment that contains subsections. – hendrikvanb Feb 25 '14 at 9:47
  • I already suspected your discovery, it was a bad idea of mine :( – user31729 Feb 25 '14 at 11:17
3

First things first: the \section instruction (in standard LaTeX) does not initiate an environment. But, you kind of forsaw that you would need to change the interface with respect to the last said. At least my solution needs sections to be grouped inside environments.

The conditional logic isn't that complex in the end. Say you have two conditionals \ifinsertsection and \ifinsertsubsection. Then they are simply nested inside the header setup like

\setbeamertemplate{headline}{%
  \ifinsertsection
    <do section headline>
    \ifinsertsubsection
      <do subsection headline>
    \fi
  \fi
}

Switching the toggles remains the actual work now. The first one is rather easy as it has be true when a section starts. For this you could say

\let\ltx@section\section
\def\section{\insertsectiontrue\ltx@section}

or with the environment approach:

\newenvironment{customsectionenv}[2][]{%
  \insertsectiontrue
  \section[#1]{#2}
}{}

The complete solution will use a version of this approach, not only because it is necessary to control the subsection toggle, but because it is possible to tell where a section ends.

Now, the subsection toggle will be in the same place as the section toggle, but it should only be toggled iff the section body contains at least one \subsection, as requested. For that you need to collect the body of the section environment, store it into a macro (the usecase of the environ package) and scan whether the replacement text of the environ \BODY contains any \subsection, which is solvable through this question which uses the substr package:

\IfSubStringInString{\detokenize{\subsection}}{\detokenize\expandafter{\BODY}}
    {\insertsubsectiontrue}{}

The complete code then would look like

\documentclass[handout]{beamer}

%Define colors
\definecolor{black}{RGB}{0,0,0}
\definecolor{darkblue}{RGB}{0,41,103}
\definecolor{lightblue}{RGB}{0,118,188}

\setbeamercolor*{section in head/foot}{fg=white, bg=lightblue}
\setbeamercolor*{section in head/foot shaded}{fg=white, bg=darkblue}
\setbeamercolor{subsection in head/foot}{fg=white, bg=darkblue}

\usepackage{environ,substr}% required for the solution

%Create headline environment
\newif\ifinsertsection
\newif\ifinsertsubsection

\NewEnviron{beamersection}[2][]{%
  \IfSubStringInString{\detokenize{\subsection}}{\detokenize\expandafter{\BODY}}
    {\insertsubsectiontrue}{}
  \insertsectiontrue
  \if\relax\detokenize{#1}\relax
    \section{#2}
  \else
    \section[#1]{#2}
  \fi
  \par\BODY
}

\setbeamertemplate{headline}{%
  \ifinsertsection
    \begin{beamercolorbox}[colsep=1.5pt]{upper separation line head}
    \end{beamercolorbox}
    \begin{beamercolorbox}{section in head/foot}
      \vskip2pt\insertsectionnavigationhorizontal{\paperwidth}{}{\hfill\hfill}\vskip2pt
    \end{beamercolorbox}%
    \ifinsertsubsection
      \begin{beamercolorbox}[ht=10pt]{subsection in head/foot}%
        \vskip2pt\insertsubsectionnavigationhorizontal{\paperwidth}{}{\hfill\hfill}\vskip2pt
      \end{beamercolorbox}%
      \begin{beamercolorbox}[colsep=1.5pt]{lower separation line head}
      \end{beamercolorbox}
    \fi
  \fi
  \vspace{20pt}
}

\begin{document}

\frame{%
  \frametitle{Frame outside section environment} 
  This frame should display neither the section, nor the subsection portion of the headline 
}

\begin{beamersection}{Section 1 (no subsections)}
\frame{%
  \frametitle{Frame in section environment with no subsections} 
  This frame should display the section portion of the headline, but not the subsection portion 
}
\end{beamersection}

\begin{beamersection}{Section 2 (with subsection)}
\subsection{Subsection 2.1}
\frame{%
  \frametitle{Frame in section environment (post-subsection)} 
  This frame should display both the section and subsection portions of the headline 
}
\end{beamersection}

\begin{beamersection}{Section 3 (with subsections)}
\frame{%
  \frametitle{Frame in section environment pre-subsection} 
  This frame should display both the section and subsection portions of the headline 
}
\subsection{Subsection 3.1}
\frame{%
  \frametitle{Frame in section environment post-subsection} 
  This frame should display both the section and subsection portions of the headline 
}
\end{beamersection}

\end{document}

A few notes:

  • I canceled out the fourth case/section. It was equivalent to the third one.
  • As mentioned above the user interface for sections changes when using this solution; sections would be coded as \begin{beamersection}[<opt. TOC title>]{<full title>} ... \end{beamersection}
  • The ouptut pic was produced with \usepackage{pgfpages}\pgfpagesuselayout{2 on 1}[letterpaper,border shrink=5mm]

output

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.