package gutenberg.itext;
import com.itextpdf.text.Document;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import gutenberg.util.RomanNumeral;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author <a href="http://twitter.com/aloyer">@aloyer</a>
*/
public class PageNumber extends PdfPageEventHelper {
private Sequence pnMainMatter = new Sequence();
private Sequence pnFrontMatter = new Sequence(0, true);
private PageInfos.Matter currentMatter = PageInfos.Matter.Front;
private Sequence pnCurrent = pnFrontMatter;
private int pageNumber;
private List<PageInfos> emittedPageInfos = new ArrayList<PageInfos>();
private String[] sectionTitles = new String[10];
public void notifyPageChange() {
pageNumber++;
pnCurrent = pnCurrent.next();
}
@Override
public void onChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title) {
Arrays.fill(sectionTitles, 1, sectionTitles.length, null);
sectionTitles[1] = title.getContent();
}
@Override
public void onSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title) {
Arrays.fill(sectionTitles, depth, sectionTitles.length, null);
sectionTitles[depth] = title.getContent();
}
@Override
public void onStartPage(PdfWriter writer, Document document) {
notifyPageChange();
}
public PageInfos pageInfos() {
PageInfos pageInfos = new PageInfos(
pageNumber,
pnCurrent.formatPageNumber(),
currentMatter,
Arrays.copyOf(sectionTitles, sectionTitles.length));
if (!emittedPageInfos.contains(pageInfos))
emittedPageInfos.add(pageInfos);
return pageInfos;
}
private List<PageInfos> emittedPageInfos() {
return emittedPageInfos;
}
public void continueFrontMatter() {
currentMatter = PageInfos.Matter.Front;
PageInfos pageInfos = lastFrontMatterInfos();
if (pageInfos != null) {
sectionTitles = Arrays.copyOf(pageInfos.sectionTitles(), sectionTitles.length);
} else {
resetText();
}
pnCurrent.next = pnFrontMatter;
}
private void resetText() {
Arrays.fill(sectionTitles, 0, sectionTitles.length, null);
}
public void startFrontMatter() {
currentMatter = PageInfos.Matter.Front;
resetText();
pnFrontMatter = new Sequence(0, true);
pnCurrent = pnFrontMatter;
}
public void startMainMatter() {
currentMatter = PageInfos.Matter.Main;
resetText();
pnMainMatter = new Sequence();
pnCurrent = pnMainMatter;
}
private PageInfos lastFrontMatterInfos() {
PageInfos found = null;
for (PageInfos pageInfos : emittedPageInfos()) {
if (!pageInfos.is(PageInfos.Matter.Front))
break;
found = pageInfos;
}
return found;
}
public int lookupFrontMatterLastPage() {
PageInfos pageInfos = lastFrontMatterInfos();
if (pageInfos == null)
return -1;
else
return pageInfos.getRawPageNumber();
}
private static class Sequence {
int count = 1;
Sequence next;
boolean isRoman;
public Sequence(int start, boolean isRoman) {
this.count = start;
this.isRoman = isRoman;
}
public Sequence() {
this(1, false);
}
public String formatPageNumber() {
if (count == 0)
count++;
if (isRoman)
return new RomanNumeral().format(count);
else
return String.valueOf(count);
}
public Sequence next() {
count++;
if (next != null) {
Sequence tmp = next;
next = null;
return tmp;
}
return this;
}
}
}