[Tex/LaTex] Problem with automatic Chapters/Parts in List of Figures and List of Tables

table of contents

This is a follow up to "Include chapters in List of Figures with titletoc?". There appears to be a problem with the original solution when a float is placed at the top of the page following a new part/chapter. In the LoF, the figure caption is then above the inserted part/chapter title (see screenshot). If we change the float position to b or anything else, it works fine.

The code below is adapted to report class, but I've checked and exists in book/report/article and its KOMA equivalents.

\documentclass{scrreprt}

\usepackage{lipsum}

\usepackage{etoolbox}
\makeatletter
\def\thisparttitle{}\def\thispartnumber{}
\newtoggle{noFigs}

\apptocmd{\@part}%
  {\gdef\thisparttitle{#1}\gdef\thispartnumber{\thepart}%
    \global\toggletrue{noFigs}}{}{}

\AtBeginDocument{%
  \AtBeginEnvironment{figure}{%
    \iftoggle{noFigs}{
      \addtocontents{lof}{\protect\contentsline {part}%
        {\protect\numberline {\thispartnumber} {\thisparttitle}}{}{} }
      \global\togglefalse{noFigs}
    }{}
  }%
}

\makeatother

\begin{document}

\listoffigures

\part{Part 1}

\chapter{Hallo}

\lipsum

\section{Hallo}

\begin{figure}[t] % change placement to cbt and it works
\caption{Part 1 Fig}
  Test
\end{figure}


\end{document}

enter image description here


Edit

The suggested solution from Heiko below has a problem when several figures/tables are in different parts. For example:

\begin{document}

\listoftables\listoffigures

\part{Part 1}
\begin{table}\caption{Part 1 Tab}\end{table}

\part{Part 2}
\begin{table}\caption{Part 1 Tab}\end{table}
\begin{figure}\caption{Part 1 Fig}\end{figure}

\end{document}

enter image description here

Best Answer

The additional part contents line (in the list of figures) is added at the begin of macro \figure (\begin{figure}). There the float has not yet started and the write directive for the part line goes at the place of the figure in the source.

The float object will be created later in \@xfloat. \caption will then write its contents line inside the float object. But the float object can float to a location before the source code location, in your case with option t. Then the two contents lines get out of order.

This can be fixed by moving the part contents line inside the float box.

Instead of the very begin of the float environment, still outside the float box, the following example hooks into \@floatboxreset, which is automatically called at the begin of the float box. LaTeX remembers the type of the float object in \@captype and macro \ext@<captype> (<captype> ∈ {figure, table, ...}) contains the list type (\ext@figure -> lof). This way, also the other float types are supported automatically, if they follow the LaTeX conventions. For example, new floats, defined by package float will work.

A new float type only needs a new toggle and the toggle to be reset at the start of a new part. This is done by macro \AddFloatToggle in the example.

\documentclass{scrreprt}

\usepackage{etoolbox}

\makeatletter
% Initialize variables
\newcommand*{\ResetFloatToggles}{}% toggle reset list for \part
\newcommand*{\thisparttitle}{}
\newcommand*{\thispartnumber}{}

\newcommand*{\AddFloatToggle}[1]{%
  \newtoggle{no#1s}%
  \apptocmd{\ResetFloatToggles}{%
    \global\toggletrue{no#1s}%
  }{}{}%
}   
% Set variables and reset float toggles at the start of \part
\apptocmd{\@part}{%
  % Remember part title and part number
  \gdef\thisparttitle{#1}%
  \gdef\thispartnumber{\thepart}%
  \ResetFloatToggles
}{}{}
% Emit \addcontentsline at the begin of the float box
\apptocmd{\@floatboxreset}{%
  % Test, if toggle exists for this float type.
  % Since there isn't an official command for testing
  % toggle existence, the internal code for testing
  % is used, see the definition of \newtoggle.
  \ifcsdef{etb@tgl@no\@captype s}{%
    \iftoggle{no\@captype s}{%
      % \@captype is the type of float, e.g. "figure", "table", "program"
      % \ext@... (\ext@figure, \ext@table, \ext@program)
      % contains the type/extension for the list of the float type, e.g.
      % "lof", "lot", "lop".
      \addcontentsline{\csname ext@\@captype\endcsname}{part}{%
        \protect\numberline{\thispartnumber} {\thisparttitle}%
      }%
      \global\togglefalse{no\@captype s}%
    }{}%
  }{%
    % unsupported float type
    \typeout{Warning: there is no toggle for float type \@captype!}%
  }%
}{}{}
\makeatother

\usepackage{float}
\newfloat{program}{tbp}{lop}[chapter]

\AddFloatToggle{figure}
\AddFloatToggle{table}
\AddFloatToggle{program}

\begin{document}

\listoftables
\listoffigures
\listof{program}{List of Programs}

\part{Part 1}
\begin{table}\caption{Part 1 Tab}\end{table}
\begin{program}\caption{Part 1 Program}\end{program}

\part{Part 2}
\begin{table}\caption{Part 2 Tab}\end{table}
\begin{figure}\caption{Part 2 Fig}\end{figure}

\end{document}

List of Tables

List of Figures

List of Programs

Related Question