6

Background

Looking to draw a horizontal "progress bar" along the bottom of each page. The first page should have no line above the page number (or very, very short) and the last page should have a line \textwidth in length.

Code

The following code works in some but not all situations:

% Calculate the percentage complete for a progress meter.
\define\PercentComplete{\the\dimexpr\textwidth*\currentpage/\lastpage\relax}

%
\define\PageNumber{%
  \inframed[
    frame=off,
    bottomframe=on,
    width=\PercentComplete,
    framecolor=ProgressBar,
  ]{\currentpage\ of \lastpage}
}

\startsetups[FooterLeft]
  \midaligned{\FontFooter \PageNumber}
\stopsetups

\startsetups[FooterRight]
  \midaligned{\FontFooter \PageNumber}
\stopsetups

Example Output

Here are some examples that work using the above code:

Page 4 of 145

Page 61 of 145

Page 144 of 145

Other documents, unfortunately, fail with an arithmetic error (probably divide by zero).

Question

What is the correct way to calculate the percentage complete so that if \lastpage isn't valid (i.e., first pass of multiple passes), then the calculation is postponed until \lastpage has a known value?

  • \ifnum\lastpage=0 \else .. \fi? – Manuel Apr 17 '17 at 6:13
  • 1
    If you want much fancier "progress bars", see my visualcounter module. – Aditya Apr 20 '17 at 1:14
7

The macro \lastpage is 0 during the first pass because the document's last page is unknown. This allows setting the percentage to 0pt for the first pass and to the desired dimension for all other passes. Also, measures provide a higher-level interface to adaptive dimensions.

\doifelse{\lastpage}{0}{
  \definemeasure
    [percent complete]
    [0pt]
}{
  \definemeasure
    [percent complete]
    [\textwidth*\currentpage/\lastpage]
}

\define\PageNumber{%
  \inframed[
    frame=off,
    bottomframe=on,
    width=\measure{percent complete},
    framecolor=ProgressBar,
  ]{\currentpage\ of \lastpage}
}

\def\FontFooter{\ss}

\startsetups[FooterLeft]
  \midaligned{\FontFooter \PageNumber}
\stopsetups

\startsetups[FooterRight]
  \midaligned{\FontFooter \PageNumber}
\stopsetups

\setupfootertexts[\setups{FooterLeft}][\setups{FooterRight}]

\starttext

\dorecurse{10}{\input knuth\relax}

\stoptext
| improve this answer | |
  • For some reason, this only works if the .tuc file is deleted prior to running context. If the .tuc file remains, the measure is only set once: to \zeropoint. – Dave Jarvis Apr 19 '17 at 5:56
  • @DaveJarvis You are right. Apparently, the mode *first is always active when you run ConTeXt and is only disabled when ConTeXt itself decides to run multiple passes. – Henri Menke Apr 20 '17 at 1:09

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.