mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-05 02:39:23 +02:00
Navigation implementation
git-svn-id: https://only.mawhrin.net/repos/FBReaderJ/trunk@1511 6a642e6f-84f6-412e-ac94-c4a38d5a04b0
This commit is contained in:
parent
3febb4c53f
commit
c232934e75
6 changed files with 221 additions and 16 deletions
|
@ -214,16 +214,16 @@ public final class FBReader extends ZLAndroidActivity {
|
||||||
private boolean myInTouch;
|
private boolean myInTouch;
|
||||||
|
|
||||||
private void gotoPage(int page) {
|
private void gotoPage(int page) {
|
||||||
/*final ZLView view = ZLApplication.Instance().getCurrentView();
|
final ZLView view = ZLApplication.Instance().getCurrentView();
|
||||||
if (view instanceof ZLTextView) {
|
if (view instanceof ZLTextView) {
|
||||||
ZLTextView textView = (ZLTextView) view;
|
ZLTextView textView = (ZLTextView) view;
|
||||||
textView.gotoPage(page);
|
textView.gotoPage(page);
|
||||||
}*/
|
ZLApplication.Instance().repaintView();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
gotoPage(seekBar.getProgress() + 1);
|
gotoPage(seekBar.getProgress() + 1);
|
||||||
//updateEpdView(0);
|
|
||||||
myInTouch = false;
|
myInTouch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +238,6 @@ public final class FBReader extends ZLAndroidActivity {
|
||||||
myNavigateDialog.setTitle(makeNavigationTitle(page, pagesNumber));
|
myNavigateDialog.setTitle(makeNavigationTitle(page, pagesNumber));
|
||||||
if (!myInTouch) {
|
if (!myInTouch) {
|
||||||
gotoPage(page);
|
gotoPage(page);
|
||||||
//updateEpdView(250);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,14 +251,11 @@ public final class FBReader extends ZLAndroidActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateNavigation() {
|
private void updateNavigation() {
|
||||||
/*final org.geometerplus.fbreader.fbreader.FBReader fbreader =
|
final org.geometerplus.fbreader.fbreader.FBReader fbreader =
|
||||||
(org.geometerplus.fbreader.fbreader.FBReader)ZLApplication.Instance();
|
(org.geometerplus.fbreader.fbreader.FBReader)ZLApplication.Instance();
|
||||||
final ZLTextView textView = (ZLTextView) fbreader.getCurrentView();
|
final ZLTextView textView = (ZLTextView) fbreader.getCurrentView();
|
||||||
final int page = textView.computeCurrentPage();
|
final int page = textView.computeCurrentPage();
|
||||||
final int pagesNumber = textView.computePageNumber();*/
|
final int pagesNumber = textView.computePageNumber();
|
||||||
|
|
||||||
final int page = 1;
|
|
||||||
final int pagesNumber = 100;
|
|
||||||
|
|
||||||
final SeekBar slider = (SeekBar) myNavigateDialog.findViewById(R.id.book_position_slider);
|
final SeekBar slider = (SeekBar) myNavigateDialog.findViewById(R.id.book_position_slider);
|
||||||
slider.setMax(pagesNumber - 1);
|
slider.setMax(pagesNumber - 1);
|
||||||
|
|
|
@ -38,6 +38,7 @@ public interface ZLTextModel {
|
||||||
|
|
||||||
// text length for paragraphs from 0 to index
|
// text length for paragraphs from 0 to index
|
||||||
int getTextLength(int index);
|
int getTextLength(int index);
|
||||||
|
int findParagraphByTextLength(int length);
|
||||||
|
|
||||||
int search(final String text, int startIndex, int endIndex, boolean ignoreCase);
|
int search(final String text, int startIndex, int endIndex, boolean ignoreCase);
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,4 +305,30 @@ public class ZLTextPlainModel implements ZLTextModel {
|
||||||
public final int getTextLength(int index) {
|
public final int getTextLength(int index) {
|
||||||
return myTextSizes[Math.max(Math.min(index, myParagraphsNumber - 1), 0)];
|
return myTextSizes[Math.max(Math.min(index, myParagraphsNumber - 1), 0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int binarySearch(int[] array, int length, int value) {
|
||||||
|
int lowIndex = 0;
|
||||||
|
int highIndex = length - 1;
|
||||||
|
|
||||||
|
while (lowIndex <= highIndex) {
|
||||||
|
int midIndex = (lowIndex + highIndex) >>> 1;
|
||||||
|
int midValue = array[midIndex];
|
||||||
|
if (midValue > value) {
|
||||||
|
highIndex = midIndex - 1;
|
||||||
|
} else if (midValue < value) {
|
||||||
|
lowIndex = midIndex + 1;
|
||||||
|
} else {
|
||||||
|
return midIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -lowIndex - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int findParagraphByTextLength(int length) {
|
||||||
|
int index = binarySearch(myTextSizes, myParagraphsNumber, length);
|
||||||
|
if (index >= 0) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
return Math.min(-index - 1, myParagraphsNumber - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,6 @@ final class ZLTextPage {
|
||||||
PaintState = PaintStateEnum.START_IS_KNOWN;
|
PaintState = PaintStateEnum.START_IS_KNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
void moveEndCursor(int paragraphIndex, int wordIndex, int charIndex) {
|
void moveEndCursor(int paragraphIndex, int wordIndex, int charIndex) {
|
||||||
if (EndCursor.isNull()) {
|
if (EndCursor.isNull()) {
|
||||||
EndCursor.setCursor(StartCursor);
|
EndCursor.setCursor(StartCursor);
|
||||||
|
@ -73,7 +72,6 @@ final class ZLTextPage {
|
||||||
LineInfos.clear();
|
LineInfos.clear();
|
||||||
PaintState = PaintStateEnum.END_IS_KNOWN;
|
PaintState = PaintStateEnum.END_IS_KNOWN;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
boolean isEmptyPage() {
|
boolean isEmptyPage() {
|
||||||
for (ZLTextLineInfo info : LineInfos) {
|
for (ZLTextLineInfo info : LineInfos) {
|
||||||
|
|
|
@ -398,6 +398,174 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
||||||
return sizeOfText;
|
return sizeOfText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Can be called only when (myModel.getParagraphsNumber() != 0)
|
||||||
|
private synchronized float computeCharsPerPage() {
|
||||||
|
setTextStyle(ZLTextStyleCollection.Instance().getBaseStyle());
|
||||||
|
|
||||||
|
final int textWidth = getTextAreaWidth();
|
||||||
|
final int textHeight = getTextAreaHeight();
|
||||||
|
|
||||||
|
final int num = myModel.getParagraphsNumber();
|
||||||
|
final int totalTextSize = myModel.getTextLength(num - 1);
|
||||||
|
final float charsPerParagraph = ((float) totalTextSize) / num;
|
||||||
|
|
||||||
|
final float charWidth = computeCharWidth();
|
||||||
|
|
||||||
|
final int indentWidth = getElementWidth(ZLTextElement.IndentElement, 0);
|
||||||
|
final float effectiveWidth = textWidth - (indentWidth + 0.5f * textWidth) / charsPerParagraph;
|
||||||
|
float charsPerLine = Math.min(effectiveWidth / charWidth,
|
||||||
|
charsPerParagraph * 1.2f);
|
||||||
|
|
||||||
|
final int strHeight = getWordHeight() + Context.getDescent();
|
||||||
|
final int effectiveHeight = (int) (textHeight - (getTextStyle().getSpaceBefore()
|
||||||
|
+ getTextStyle().getSpaceAfter()) / charsPerParagraph);
|
||||||
|
final int linesPerPage = effectiveHeight / strHeight;
|
||||||
|
|
||||||
|
/*System.err.println("PAGE: textWidth = " + textWidth);
|
||||||
|
System.err.println("PAGE: textHeight = " + textHeight);
|
||||||
|
System.err.println("PAGE: indentWidth = " + indentWidth);
|
||||||
|
System.err.println("PAGE: strHeight = " + strHeight);
|
||||||
|
System.err.println("PAGE: lang = " + getLanguage());
|
||||||
|
System.err.println("PAGE: charWidth = " + charWidth);
|
||||||
|
System.err.println("PAGE: effectiveWidth = " + effectiveWidth);
|
||||||
|
System.err.println("PAGE: effectiveHeight = " + effectiveHeight);
|
||||||
|
System.err.println("PAGE: linesPerPage = " + linesPerPage);
|
||||||
|
System.err.println("PAGE: charsPerParagraph = " + charsPerParagraph + " (factor = " + 1.0f / charsPerParagraph + ")");
|
||||||
|
System.err.println("PAGE: charsPerLine = " + charsPerLine);*/
|
||||||
|
|
||||||
|
return charsPerLine * linesPerPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized int computeTextPageNumber(int textSize) {
|
||||||
|
if (myModel == null || myModel.getParagraphsNumber() == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// System.err.println(">------------------------------------------->");
|
||||||
|
|
||||||
|
final float factor = 1.0f / computeCharsPerPage();
|
||||||
|
final float pages = textSize * factor;
|
||||||
|
int result = Math.max((int) (pages + 1.0f - 0.5f * factor), 1);
|
||||||
|
|
||||||
|
/*System.err.println("PAGE: textSize = " + textSize);
|
||||||
|
System.err.println("PAGE: factor = " + factor);
|
||||||
|
System.err.println("PAGE: pages = " + pages);
|
||||||
|
System.err.println("PAGE: result = " + result);
|
||||||
|
System.err.println("<-------------------------------------------<");*/
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final char[] ourDefaultLetters = "System developers have used modeling languages for decades to specify, visualize, construct, and document systems. The Unified Modeling Language (UML) is one of those languages. UML makes it possible for team members to collaborate by providing a common language that applies to a multitude of different systems. Essentially, it enables you to communicate solutions in a consistent, tool-supported language.".toCharArray();
|
||||||
|
|
||||||
|
private final char[] myLettersBuffer = new char[512];
|
||||||
|
private int myLettersBufferLength = 0;
|
||||||
|
private ZLTextModel myLettersModel = null;
|
||||||
|
|
||||||
|
private final float computeCharWidth() {
|
||||||
|
if (myLettersModel != myModel) {
|
||||||
|
myLettersModel = myModel;
|
||||||
|
myLettersBufferLength = 0;
|
||||||
|
|
||||||
|
int paragraph = 0;
|
||||||
|
final int textSize = myModel.getTextLength(myModel.getParagraphsNumber() - 1);
|
||||||
|
if (textSize > myLettersBuffer.length) {
|
||||||
|
paragraph = myModel.findParagraphByTextLength((textSize - myLettersBuffer.length) / 2);
|
||||||
|
}
|
||||||
|
while (paragraph < myModel.getParagraphsNumber()
|
||||||
|
&& myLettersBufferLength < myLettersBuffer.length) {
|
||||||
|
ZLTextParagraph.EntryIterator it = myModel.getParagraph(paragraph++).iterator();
|
||||||
|
while (it.hasNext()
|
||||||
|
&& myLettersBufferLength < myLettersBuffer.length) {
|
||||||
|
it.next();
|
||||||
|
if (it.getType() == ZLTextParagraph.Entry.TEXT) {
|
||||||
|
final int len = Math.min(it.getTextLength(),
|
||||||
|
myLettersBuffer.length - myLettersBufferLength);
|
||||||
|
System.arraycopy(it.getTextData(), it.getTextOffset(),
|
||||||
|
myLettersBuffer, myLettersBufferLength, len);
|
||||||
|
myLettersBufferLength += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myLettersBufferLength == 0) {
|
||||||
|
myLettersBufferLength = Math.min(myLettersBuffer.length, ourDefaultLetters.length);
|
||||||
|
System.arraycopy(ourDefaultLetters, 0, myLettersBuffer, 0, myLettersBufferLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final float charWidth = computeCharWidth(myLettersBuffer, myLettersBufferLength);
|
||||||
|
System.err.println("CHARWIDTH: charWidth = " + charWidth);
|
||||||
|
return charWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final float computeCharWidth(char[] pattern, int length) {
|
||||||
|
return Context.getStringWidth(pattern, 0, length) / ((float) length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final synchronized int computePageNumber() {
|
||||||
|
return computeTextPageNumber(getScrollbarFullSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final synchronized int computeCurrentPage() {
|
||||||
|
return computeTextPageNumber(
|
||||||
|
getScrollbarThumbPosition(PAGE_CENTRAL)
|
||||||
|
+ getScrollbarThumbLength(PAGE_CENTRAL)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final synchronized void gotoPage(int page) {
|
||||||
|
if (myModel == null || myModel.getParagraphsNumber() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final float factor = computeCharsPerPage();
|
||||||
|
final float textSize = page * factor;
|
||||||
|
|
||||||
|
/*System.err.println(">------------------------------------------->");
|
||||||
|
System.err.println("SETPAGE: page = " + page);
|
||||||
|
System.err.println("SETPAGE: factor = " + factor);
|
||||||
|
System.err.println("SETPAGE: textSize = " + textSize);*/
|
||||||
|
|
||||||
|
int intTextSize = (int) textSize;
|
||||||
|
int paragraphIndex = myModel.findParagraphByTextLength(intTextSize);
|
||||||
|
|
||||||
|
if (paragraphIndex > 0 && myModel.getTextLength(paragraphIndex) > intTextSize) {
|
||||||
|
/*System.err.println("SETPAGE: drop overlength paragraph: " + paragraphIndex + " (" + myModel.getTextLength(paragraphIndex) + ")");*/
|
||||||
|
--paragraphIndex;
|
||||||
|
}
|
||||||
|
intTextSize = myModel.getTextLength(paragraphIndex);
|
||||||
|
|
||||||
|
int sizeOfTextBefore = myModel.getTextLength(paragraphIndex - 1);
|
||||||
|
while (paragraphIndex > 0 && intTextSize == sizeOfTextBefore) {
|
||||||
|
/*System.err.println("SETPAGE: drop empty paragraph: " + paragraphIndex);*/
|
||||||
|
--paragraphIndex;
|
||||||
|
intTextSize = sizeOfTextBefore;
|
||||||
|
sizeOfTextBefore = myModel.getTextLength(paragraphIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int paragraphLength = intTextSize - sizeOfTextBefore;
|
||||||
|
|
||||||
|
/*System.err.println("SETPAGE: paragraphIndex = " + paragraphIndex);
|
||||||
|
System.err.println("SETPAGE: intTextSize = " + intTextSize);
|
||||||
|
System.err.println("SETPAGE: sizeOfTextBefore = " + sizeOfTextBefore);
|
||||||
|
System.err.println("SETPAGE: paragraphLength = " + paragraphLength);*/
|
||||||
|
|
||||||
|
final int wordIndex;
|
||||||
|
if (paragraphLength == 0) {
|
||||||
|
wordIndex = 0;
|
||||||
|
} else {
|
||||||
|
preparePaintInfo(myCurrentPage);
|
||||||
|
final ZLTextWordCursor cursor = new ZLTextWordCursor(myCurrentPage.EndCursor);
|
||||||
|
cursor.moveToParagraph(paragraphIndex);
|
||||||
|
wordIndex = cursor.getParagraphCursor().getParagraphLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*System.err.println("SETPAGE: wordIndex = " + wordIndex);
|
||||||
|
System.err.println("<-------------------------------------------<");*/
|
||||||
|
|
||||||
|
gotoPositionByEnd(paragraphIndex, wordIndex, 0);
|
||||||
|
}
|
||||||
|
|
||||||
private static final char[] SPACE = new char[] { ' ' };
|
private static final char[] SPACE = new char[] { ' ' };
|
||||||
private void drawTextLine(ZLTextPage page, ZLTextLineInfo info, int from, int to, int y) {
|
private void drawTextLine(ZLTextPage page, ZLTextLineInfo info, int from, int to, int y) {
|
||||||
final ZLTextParagraphCursor paragraph = info.ParagraphCursor;
|
final ZLTextParagraphCursor paragraph = info.ParagraphCursor;
|
||||||
|
@ -841,6 +1009,18 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final synchronized void gotoPositionByEnd(int paragraphIndex, int wordIndex, int charIndex) {
|
||||||
|
if (myModel != null && myModel.getParagraphsNumber() > 0) {
|
||||||
|
myCurrentPage.moveEndCursor(paragraphIndex, wordIndex, charIndex);
|
||||||
|
myPreviousPage.reset();
|
||||||
|
myNextPage.reset();
|
||||||
|
preparePaintInfo(myCurrentPage);
|
||||||
|
if (myCurrentPage.isEmptyPage()) {
|
||||||
|
scrollPage(false, ScrollingMode.NO_OVERLAPPING, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected synchronized void preparePaintInfo() {
|
protected synchronized void preparePaintInfo() {
|
||||||
myPreviousPage.reset();
|
myPreviousPage.reset();
|
||||||
myNextPage.reset();
|
myNextPage.reset();
|
||||||
|
|
|
@ -35,6 +35,14 @@ abstract class ZLTextViewBase extends ZLView {
|
||||||
resetTextStyle();
|
resetTextStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int getWordHeight() {
|
||||||
|
if (myWordHeight == -1) {
|
||||||
|
final ZLTextStyle textStyle = myTextStyle;
|
||||||
|
myWordHeight = (int)(Context.getStringHeight() * textStyle.getLineSpacePercent() / 100) + textStyle.getVerticalShift();
|
||||||
|
}
|
||||||
|
return myWordHeight;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract int getLeftMargin();
|
public abstract int getLeftMargin();
|
||||||
public abstract int getRightMargin();
|
public abstract int getRightMargin();
|
||||||
public abstract int getTopMargin();
|
public abstract int getTopMargin();
|
||||||
|
@ -114,11 +122,7 @@ abstract class ZLTextViewBase extends ZLView {
|
||||||
|
|
||||||
final int getElementHeight(ZLTextElement element) {
|
final int getElementHeight(ZLTextElement element) {
|
||||||
if (element instanceof ZLTextWord) {
|
if (element instanceof ZLTextWord) {
|
||||||
if (myWordHeight == -1) {
|
return getWordHeight();
|
||||||
final ZLTextStyle textStyle = myTextStyle;
|
|
||||||
myWordHeight = (int)(Context.getStringHeight() * textStyle.getLineSpacePercent() / 100) + textStyle.getVerticalShift();
|
|
||||||
}
|
|
||||||
return myWordHeight;
|
|
||||||
} else if (element instanceof ZLTextImageElement) {
|
} else if (element instanceof ZLTextImageElement) {
|
||||||
final ZLPaintContext context = Context;
|
final ZLPaintContext context = Context;
|
||||||
return context.imageHeight(((ZLTextImageElement)element).ImageData) +
|
return context.imageHeight(((ZLTextImageElement)element).ImageData) +
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue