[Tex/LaTex] List of Figures + Beamer

beamertable of contents

I want to have a List of Figures in my Beamer presentation.

I spent some time searching the web for a solution and only found desperate people telling others that it's not possible, i.e. here or here (german).

I also made some experiments on my own, i.e. "abuse" tocloft to do the job. However, even \usepackage{tocloft} causes pdflatex to fail with ! LaTeX Error: \l@section undefined. (and lying to tocloft by defining the command as empty beforehand doesn't to any good either).

I can't really see why it should be that difficult to make a List of Figures in beamer, since \tableofcontents works flawlessly.

I'm not afraid of doing some coding on my own, but I'm not deep enough into TeX to really understand the magic behind the "List of Figures", "Table of Contents" and alike.

Is anyone out there having suggestions or links that might help me figure this out?

\documentclass{beamer}

% uncomment the following line
% to get the error message
% `! LaTeX Error: \l@section undefined.`

%\usepackage{tocloft} 

% uncomment the following lines INSTEAD
% to lie to tocloft
% and get the next error message

%\makeatletter
%\newcommand\l@section{}
%\makeatother
%\usepackage{tocloft}

\begin{document}

\begin{frame}{A frame}
\begin{figure}
\mbox{A}
\caption{An 'A'}
\end{figure}
\end{frame}

\begin{frame}{List of Figures}
\listoffigures
\end{frame}

\end{document}

EDIT: Solution

Starting from Marco Daniels answer to my question, I modified his code to reflect my needs. Here is what I came up with. Please feel free to comment, improve and reuse this.

\RequirePackage{ifthen}

\makeatletter

\AtEndDocument{%
  \clearpage
  \beamer@tempcount=\c@page\advance\beamer@tempcount by -1%
  \if@filesw
  \newwrite\tf@lof
  \immediate\openout\tf@lof\jobname.lof\relax
  \newwrite\tf@lot
  \immediate\openout\tf@lot\jobname.lot\relax
  \fi
}

\long\def\beamer@makecaption#1#2#3#4{%
  \def\insertcaptionname{\csname#1name\endcsname}%
  \def\insertcaptionnumber{\csname the#1\endcsname}%
  \edef\insertframenumber{\theframenumber}%
  \ifthenelse{\equal{#3}{\empty}}{%  
    \def\insertlistcaption{#2}%
  }{%
    \def\insertlistcaption{#3}%
  }
  \def\insertsource{#4}%
  \def\insertcaption{#2}%
  \ifthenelse{\equal{#1}{figure}}{%  
    \addtocontents{lof}{\protect\listoffigureformat{\insertcaptionnumber}{\insertlistcaption}{\insertframenumber}{\insertsource}}{}{}%
  }{}
  \ifthenelse{\equal{#1}{table}}{%  
    \addtocontents{lot}{\protect\listoftableformat{\insertcaptionnumber}{\insertlistcaption}{\insertframenumber}}{}{}%
  }{}
  \nobreak\vskip\abovecaptionskip\nobreak
  \sbox\@tempboxa{\usebeamertemplate**{caption}}%
  \ifdim \wd\@tempboxa >\hsize
  \usebeamertemplate**{caption}\par
  \else
  \global \@minipagefalse
  \hb@xt@\hsize{\hfil\box\@tempboxa\hfil}%
  \fi
  \nobreak\vskip\belowcaptionskip\nobreak%
}

\def\listoffigureformat#1#2#3#4{%
  \makebox[2ex][r]{#1}%
  \hspace{1ex}%
  {\usebeamercolor[fg]{bibliography entry author} #2}%
  \ifthenelse{\equal{#4}{\empty}}{}{ -- #4}%
  \dotfill%
  \makebox[2ex][r]{#3}\par%
}
\def\listoffigures{%
  \setlength{\leftskip}{3ex}
  \setlength{\parindent}{-3ex}
  \@starttoc{lof}%
}
\def\listoftableformat#1#2#3{\makebox[2ex][r]{#1}\hspace{1ex}#2\dotfill\makebox[2ex][r]{#3}\par}
\def\listoftables{%
  \setlength{\leftskip}{3ex}
  \setlength{\parindent}{-3ex}
  \@starttoc{lot}%
}

\long\def\@caption#1[#2]#3{
  \par\nobreak
  \begingroup
    \@parboxrestore
    \if@minipage
      \@setminipage
    \fi
    \beamer@makecaption{#1}{\ignorespaces #3}{\ignorespaces #3}{\ignorespaces #2}\par\nobreak
    \endgroup}

\makeatother

Best Answer

The following code is a starting point and can be modified for the personal settings.

First some explanation. To provide a list of figures or tables you need an extra file to save the captions. That's equal to the toc file which is need by tableofcontents. beamer uses a special way to create the toc. The reason is very simple -- It's the only way to setup so many user options. However the following part is only a basic. A full implementation with all beamer features leads to a new package. Up to know I think it's not useful to have a list of figures or so.


First of all we make sure that beamer opens a file to save all entries of caption separated by list of figures (lof) and by list of tables (lot).

\AtEndDocument{%
  \clearpage
  \beamer@tempcount=\c@page\advance\beamer@tempcount by -1%
  \if@filesw
      \immediate\write\@auxout{\string\@writefile{lof}%
        {\noexpand\headcommand{\noexpand\beamer@partpages{\the\beamer@partstartpage}{\the\beamer@tempcount}}}}%
      \newwrite\tf@lof
      \immediate\openout\tf@lof\jobname.lof\relax
      \immediate\write\@auxout{\string\@writefile{lot}%
        {\noexpand\headcommand{\noexpand\beamer@partpages{\the\beamer@partstartpage}{\the\beamer@tempcount}}}}%
      \newwrite\tf@lot
      \immediate\openout\tf@lot\jobname.lof\relax
    \fi
}

Next step is to tell beamer that all captions must be written in the lof or lot file. Therefor the internal command \beamer@makecaption must be changed. The new part is:

  \def\@tempa{#1}
  \def\@tempb{figure}
   \ifx\@tempa\@tempb
      \addtocontents{lof}{\protect\listoffigureformat{\insertcaptionnumber}{\insertcaption}}{}{}%
  \else
       \addtocontents{lot}{\protect\listoffigureformat{\insertcaptionnumber}{\insertcaption}}{}{}%
  \fi%

Here is a simple test which test whether the input is a figure or something else. Of course this test can be more clearer to test other types too.

The complete redefinition looks as follows:

\long\def\beamer@makecaption#1#2{%
  \def\insertcaptionname{\csname#1name\endcsname}%
  \def\insertcaptionnumber{\csname the#1\endcsname}%
  \def\insertcaption{#2}%
  \def\@tempa{#1}
  \def\@tempb{figure}
   \ifx\@tempa\@tempb
      \addtocontents{lof}{\protect\listoffigureformat{\insertcaptionnumber}{\insertcaption}}{}{}%
  \else
       \addtocontents{lot}{\protect\listoffigureformat{\insertcaptionnumber}{\insertcaption}}{}{}%
  \fi%
  \nobreak\vskip\abovecaptionskip\nobreak
  \sbox\@tempboxa{\usebeamertemplate**{caption}}%
  \ifdim \wd\@tempboxa >\hsize
    \usebeamertemplate**{caption}\par
  \else
    \global \@minipagefalse
    \hb@xt@\hsize{\hfil\box\@tempboxa\hfil}%
  \fi
  \nobreak\vskip\belowcaptionskip\nobreak}

Now the contents will be write in the external file with the command

\addtocontents{lot}{\protect\listoffigureformat{\insertcaptionnumber}{\insertcaption}}{}{}%

whereby the command \listoffigureformat is currently undefined. So I defined the command to format the output of listoffigures:

\def\listoffigureformat#1#2{#1:~#2\par}

You see it's very simple.

The last step is the definition of \listoffigures whereby the internal command \@starttoc is used to read the file \jobname.lof.

\def\listoffigures{%
  \frame{
    \frametitle{List of Figures}
    \@starttoc{lof}%
  }
}

Now the complete example.

\documentclass{beamer}

\makeatletter

\AtEndDocument{%
  \clearpage
  \beamer@tempcount=\c@page\advance\beamer@tempcount by -1%
  \if@filesw
      \immediate\write\@auxout{\string\@writefile{lof}%
        {\noexpand\headcommand{\noexpand\beamer@partpages{\the\beamer@partstartpage}{\the\beamer@tempcount}}}}%
      \newwrite\tf@lof
      \immediate\openout\tf@lof\jobname.lof\relax
      \immediate\write\@auxout{\string\@writefile{lot}%
        {\noexpand\headcommand{\noexpand\beamer@partpages{\the\beamer@partstartpage}{\the\beamer@tempcount}}}}%
      \newwrite\tf@lot
      \immediate\openout\tf@lot\jobname.lof\relax
    \fi
}

\long\def\beamer@makecaption#1#2{%
  \def\insertcaptionname{\csname#1name\endcsname}%
  \def\insertcaptionnumber{\csname the#1\endcsname}%
  \def\insertcaption{#2}%
  \def\@tempa{#1}
  \def\@tempb{figure}
   \ifx\@tempa\@tempb
      \addtocontents{lof}{\protect\listoffigureformat{\insertcaptionnumber}{\insertcaption}}{}{}%
  \else
       \addtocontents{lot}{\protect\listoffigureformat{\insertcaptionnumber}{\insertcaption}}{}{}%
  \fi%
  \nobreak\vskip\abovecaptionskip\nobreak
  \sbox\@tempboxa{\usebeamertemplate**{caption}}%
  \ifdim \wd\@tempboxa >\hsize
    \usebeamertemplate**{caption}\par
  \else
    \global \@minipagefalse
    \hb@xt@\hsize{\hfil\box\@tempboxa\hfil}%
  \fi
  \nobreak\vskip\belowcaptionskip\nobreak}

\def\listoffigureformat#1#2{#1:~#2\par}
\def\listoffigures{%
\frame{\frametitle{List of Figures}
 \@starttoc{lof}%
}
}
\makeatother


\begin{document}

\listoffigures


\begin{frame}
\color{blue}
\begin{figure}
\rule{3cm}{3cm}
\caption{fig 1}
\end{figure}
\end{frame}

\begin{frame}
\begin{figure}
\color{green}
\rule{3cm}{3cm}
\caption{fig 2}
\end{figure}
\end{frame}

\begin{frame}
\begin{figure}
\color{blue}
\rule{3cm}{3cm}
\caption{fig 3}
\end{figure}
\end{frame}

\begin{frame}
\begin{figure}
\color{yellow}
\rule{3cm}{3cm}
\caption{fig 4}
\end{figure}
\end{frame}
\end{document}

Related Question