[Tex/LaTex] Create references with part number and frame number

beamercross-referencingparts

I created a beamer theme which uses parts (for lecture slides) and where the slides are numbered using the part number and the frame number. The frame number is reset at the beginning of each part.

The problem is, when I create a reference with \ref, only the frame number is shown.

How can I show both the part number and the frame number?

Here is a minimal example:

\documentclass{beamer}
\AtBeginPart{\setcounter{framenumber}{0}}
\makeatletter
\newcommand{\slidenumber}
{slide \ifnum\c@part=0
\insertframenumber
\else
\insertpartnumber-\insertframenumber
\fi}
\makeatother
\begin{document}
\frame{\slidenumber, ref: \ref{one-two}}
\frame{\slidenumber}
\part{one}
\frame{\slidenumber}
\frame[label=one-two]{\slidenumber}
\part{two}
\frame{\slidenumber}
\frame{\slidenumber}
\end{document}

This example shows "ref: 2" on the first slide, but I would like it to show "ref: 1-2".

I guess I'll have to somehow redefine \label and/or \ref, but sadly, this is way beyond my TeX/LaTeX skills.

Best Answer

Here's one possible solution:

\documentclass{beamer}
\usepackage{etoolbox}

\AtBeginPart{\setcounter{framenumber}{0}}
\makeatletter
\newcommand{\slidenumber}{%
slide \ifnum\c@part=0\relax
  \insertframenumber
\else
  \insertpartnumber-\insertframenumber
\fi}
\def\mynumberwithin#1#2{\@ifundefined{c@#1}{\@nocounterr{#1}}{%
  \@ifundefined{c@#2}{\@nocnterr{#2}}{%
  \@addtoreset{#1}{#2}%
  \toks@\expandafter\expandafter\expandafter{\csname the#1\endcsname}%
  \expandafter\xdef\csname the#1\endcsname
    {\expandafter\noexpand\csname the#2\endcsname
     -\the\toks@}}}}
\pretocmd{\part}{%
\ifnum\c@part=0\relax
  \mynumberwithin{framenumber}{part}
\fi%
}{}{}

\makeatother

\begin{document}

\frame{\slidenumber, ref~\ref{two}, ref~\ref{one-two} and ref~\ref{two-two}}
\frame[label=two]{\slidenumber}

\part{one}
\frame{\slidenumber}
\frame[label=one-two]{\slidenumber}

\part{two}
\frame{\slidenumber}
\frame[label=two-two]{\slidenumber}

\end{document}

An image showing the produced cross-references:

enter image description here

The idea is simply to set the framenumber counter to be prepended by the part counter. I used a similar mechanism as the used by amstex's \numberwithin, but with a variation to use a hyphen instead of a dot. Provision was made to make this change just after a \part command has been actually used so eventual references to frames before the first part will produce just the frame number.

Notice that with these settings, there's no need for your \slidenumber command, since now you can simply use \theframenumber:

\documentclass{beamer}
\usepackage{etoolbox}

\AtBeginPart{\setcounter{framenumber}{0}}
\makeatletter
\def\mynumberwithin#1#2{\@ifundefined{c@#1}{\@nocounterr{#1}}{%
  \@ifundefined{c@#2}{\@nocnterr{#2}}{%
  \@addtoreset{#1}{#2}%
  \toks@\expandafter\expandafter\expandafter{\csname the#1\endcsname}%
  \expandafter\xdef\csname the#1\endcsname
    {\expandafter\noexpand\csname the#2\endcsname
     -\the\toks@}}}}
\pretocmd{\part}{%
\ifnum\c@part=0\relax
  \mynumberwithin{framenumber}{part}
\fi%
}{}{}

\makeatother

\begin{document}

\frame{\theframenumber, ref~\ref{two}, ref~\ref{one-two} and ref~\ref{two-two}}
\frame[label=two]{\theframenumber}

\part{one}
\frame{\theframenumber}
\frame[label=one-two]{\theframenumber}

\part{two}
\frame{\theframenumber}
\frame[label=two-two]{\theframenumber}

\end{document}

enter image description here