/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.albite.book.view;
import java.util.Vector;
import org.albite.albite.AlbiteMIDlet;
import org.albite.book.model.book.Chapter;
import org.albite.book.model.parser.TextParser;
import org.albite.font.AlbiteFont;
import org.albite.util.archive.Archive;
//#if !(TinyMode || TinyModeExport || LightMode || LightModeExport)
import org.geometerplus.zlibrary.text.hyphenation.ZLTextTeXHyphenator;
//#endif
/**
* This class is non-mutable with the exception that the ColorProfile can be
* changed if desired for no reflow is required when changing colours.
*
* @author albus
*/
public class Booklet {
final Archive bookArchive;
final Chapter chapter;
final int width;
final int height;
final AlbiteFont fontPlain;
final AlbiteFont fontItalic;
//#if !(TinyMode || TinyModeExport || LightMode || LightModeExport)
final ZLTextTeXHyphenator hyphenator;
//#endif
final boolean renderImages;
final int fontHeight;
final int fontIndent;
final byte defaultAlign = StylingConstants.JUSTIFY;
private final Vector pages; //Page elements
private Page currentPage;
private int currentPageIndex;
private Page prevPage;
private Page nextPage;
/* this inverts the direction of pages */
private boolean inverted;
public Booklet(
final int width,
final int height,
final boolean inverted,
final Chapter chapter,
final Archive bookArchive,
final AlbiteFont fontPlain,
final AlbiteFont fontItalic,
final int lineSpacing,
final boolean renderImages,
//#if !(TinyMode || TinyModeExport || LightMode || LightModeExport)
final ZLTextTeXHyphenator hyphenator,
//#endif
final TextParser parser) {
this.width = width;
this.height = height;
this.inverted = inverted;
this.chapter = chapter;
this.bookArchive = bookArchive;
this.fontPlain = fontPlain;
this.fontItalic = fontItalic;
//#if !(TinyMode || TinyModeExport || LightMode || LightModeExport)
this.hyphenator = hyphenator;
//#endif
this.renderImages = renderImages;
fontHeight = fontPlain.getLineHeight() + lineSpacing;
fontIndent = fontPlain.charWidth(' ') * 3;
/*
* Typically ~60-100 pages per chapter, so 200 is quite enough
*/
Vector pagesTemp = new Vector(200);
/*
* Reserve the position of the first dummy page
*/
pagesTemp.addElement(null);
PageState ps = new PageState(parser);
//#debug
int i = 0;
try {
/*
* Real pages
*/
TextPage current;
while (!ps.finishedReading()) {
//#debug
AlbiteMIDlet.LOGGER.log("New page #" + (i++));
current = new TextPage(this, ps);
if (!current.isEmpty()) {
/*
* page with content to render
*/
pagesTemp.addElement(current);
}
}
//#debug
AlbiteMIDlet.LOGGER.log("pages done!");
} catch (OutOfMemoryError e) {
//#debug
AlbiteMIDlet.LOGGER.log(e);
pagesTemp = new Vector(3);
/*
* Reserve the position of the first dummy page
*/
pagesTemp.addElement(null);
/*
* Add a warning message
*/
pagesTemp.addElement(
new DummyPage(this, DummyPage.TYPE_CHAPTER_TOO_BIG));
} catch (Exception e) {
//#debug
AlbiteMIDlet.LOGGER.log(e);
pagesTemp = new Vector(3);
/*
* Reserve the position of the first dummy page
*/
pagesTemp.addElement(null);
/*
* Add a warning message
*/
pagesTemp.addElement(
new DummyPage(this, DummyPage.TYPE_CHAPTER_ERROR));
}
/*
* Don't forget to set the final field
*/
pages = pagesTemp;
if (pages.size() == 1) {
/*
* No TextPages have been added; == 1 because of the reserved
* position of the first dummy page
*/
pages.addElement(new DummyPage(this, DummyPage.TYPE_EMPTY_CHAPTER));
}
/*
* First dummy page (transition to prev chapter or opening of book)
*/
if (chapter.getPrevChapter() == null) {
pages.setElementAt(
new DummyPage(this, DummyPage.TYPE_BOOK_START), 0);
} else {
pages.setElementAt(
new DummyPage(this, DummyPage.TYPE_CHAPTER_PREV), 0);
}
/*
* Last dummy page (transition to next chapter or end of book)
*/
if (chapter.getNextChapter() == null) {
pages.addElement(new DummyPage(this, DummyPage.TYPE_BOOK_END));
} else {
pages.addElement(new DummyPage(this, DummyPage.TYPE_CHAPTER_NEXT));
}
goToFirstPage();
}
public final Page getCurrentPage() {
return currentPage;
}
public final Page getNextPage() {
return nextPage;
}
public final Page getPrevPage() {
return prevPage;
}
public final boolean goToPrevPage() {
if (inverted) {
return incrementPage();
} else {
return decrementPage();
}
}
private boolean decrementPage() {
int index = currentPageIndex - 1;
if (index < 0) {
return false;
}
currentPageIndex = index;
setPages();
return true;
}
public final boolean goToNextPage() {
if (inverted) {
return decrementPage();
} else {
return incrementPage();
}
}
private boolean incrementPage() {
int index = currentPageIndex + 1;
if (index == pages.size()) {
return false;
}
currentPageIndex = index;
setPages();
return true;
}
public final void goToFirstPage() {
currentPageIndex = 1;
setPages();
}
public final void goToLastPage() {
currentPageIndex = pages.size() - 2;
setPages();
}
public final void goToPosition(final int position) {
if (position <= 0) {
goToFirstPage();
return;
}
if (position >= chapter.getTextBuffer().length) {
goToLastPage();
return;
}
Page foundPage;
final int pagesSize = pages.size();
for (int i = 0; i < pagesSize; i++) {
foundPage = (Page) pages.elementAt(i);
if (foundPage.contains(position)) {
goToPage(i);
return;
}
}
goToFirstPage();
}
public void goToPage(final int page) {
if (page <= 0) {
goToFirstPage();
return;
}
if (page >= pages.size() - 1) {
goToLastPage();
return;
}
currentPageIndex = page;
setPages();
}
private void setPages() {
/* there are always at least three Pages in a booklet! */
currentPage = (Page)(pages.elementAt(currentPageIndex));
if (inverted) {
prevPage = chooseNextPage();
nextPage = choosePrevPage();
} else {
prevPage = choosePrevPage();
nextPage = chooseNextPage();
}
chapter.setCurrentPosition(currentPage.getStart());
}
public void setInverted(final boolean inverted) {
//#debug
AlbiteMIDlet.LOGGER.log("setting inverted: " + inverted);
this.inverted = inverted;
setPages();
}
private Page choosePrevPage() {
int index = currentPageIndex -1;
if (index < 0) {
return null;
} else {
return (Page)(pages.elementAt(index));
}
}
private Page chooseNextPage() {
int index = currentPageIndex +1;
if (index == pages.size()) {
return null;
} else {
return (Page)(pages.elementAt(index));
}
}
public final int getCurrentPageIndex() {
return currentPageIndex;
}
public final int getPagesCount() {
return pages.size();
}
public final char[] getTextBuffer() {
return chapter.getTextBuffer();
}
public final Chapter getChapter() {
return chapter;
}
}