From f7b8cebe4234d038a27c86871568c9cab1b23820 Mon Sep 17 00:00:00 2001 From: Nikolay Pultsin Date: Sat, 11 Apr 2009 09:34:48 +0000 Subject: [PATCH] smooth scrolling git-svn-id: https://only.mawhrin.net/repos/FBReaderJ/trunk@921 6a642e6f-84f6-412e-ac94-c4a38d5a04b0 --- .../android/fbreader/TOCActivity.java | 2 +- .../core/sqliteconfig/ZLSQLiteConfig.java | 11 +- .../ui/android/view/ZLAndroidWidget.java | 60 ++- .../fbreader/fbreader/BookTextView.java | 25 +- .../fbreader/fbreader/FBView.java | 49 ++- .../zlibrary/core/view/ZLView.java | 1 + .../text/view/impl/PaintStateEnum.java | 29 ++ .../zlibrary/text/view/impl/ZLTextPage.java | 144 ++++++ .../text/view/impl/ZLTextParagraphCursor.java | 2 +- .../text/view/impl/ZLTextViewImpl.java | 416 +++++++++--------- .../text/view/style/ZLTextBaseStyle.java | 4 +- 11 files changed, 477 insertions(+), 266 deletions(-) create mode 100644 src/org/geometerplus/zlibrary/text/view/impl/PaintStateEnum.java create mode 100644 src/org/geometerplus/zlibrary/text/view/impl/ZLTextPage.java diff --git a/platform/android/src/org/geometerplus/android/fbreader/TOCActivity.java b/platform/android/src/org/geometerplus/android/fbreader/TOCActivity.java index 316a5e825..8cd55038d 100644 --- a/platform/android/src/org/geometerplus/android/fbreader/TOCActivity.java +++ b/platform/android/src/org/geometerplus/android/fbreader/TOCActivity.java @@ -48,7 +48,7 @@ public class TOCActivity extends ListActivity { final FBReader fbreader = (FBReader)ZLApplication.Instance(); final TOCTree root = fbreader.Model.TOCTree; myAdapter = new TOCAdapter(root); - final ZLTextWordCursor cursor = fbreader.BookTextView.StartCursor; + final ZLTextWordCursor cursor = fbreader.BookTextView.getStartCursor(); int index = cursor.getParagraphCursor().Index; if (cursor.isEndOfParagraph()) { ++index; diff --git a/platform/android/src/org/geometerplus/zlibrary/core/sqliteconfig/ZLSQLiteConfig.java b/platform/android/src/org/geometerplus/zlibrary/core/sqliteconfig/ZLSQLiteConfig.java index babc67c61..c411dc04e 100644 --- a/platform/android/src/org/geometerplus/zlibrary/core/sqliteconfig/ZLSQLiteConfig.java +++ b/platform/android/src/org/geometerplus/zlibrary/core/sqliteconfig/ZLSQLiteConfig.java @@ -45,7 +45,7 @@ public final class ZLSQLiteConfig extends ZLConfig { myDeleteGroupStatement = myDatabase.compileStatement("DELETE FROM config WHERE groupName = ?"); } - public void executeAsATransaction(Runnable actions) { + synchronized public void executeAsATransaction(Runnable actions) { myDatabase.beginTransaction(); try { actions.run(); @@ -55,7 +55,7 @@ public final class ZLSQLiteConfig extends ZLConfig { } } - public void removeGroup(String name) { + synchronized public void removeGroup(String name) { myDeleteGroupStatement.bindString(1, name); try { myDeleteGroupStatement.execute(); @@ -63,7 +63,7 @@ public final class ZLSQLiteConfig extends ZLConfig { } } - public String getValue(String group, String name, String defaultValue) { + synchronized public String getValue(String group, String name, String defaultValue) { String answer = defaultValue; myGetValueStatement.bindString(1, group); myGetValueStatement.bindString(2, name); @@ -74,7 +74,8 @@ public final class ZLSQLiteConfig extends ZLConfig { return answer; } - public void setValue(String group, String name, String value) { + synchronized public void setValue(String group, String name, String value) { + //System.err.println("g/n/v:" + group + ':' + name + ':' + value); mySetValueStatement.bindString(1, group); mySetValueStatement.bindString(2, name); mySetValueStatement.bindString(3, value); @@ -84,7 +85,7 @@ public final class ZLSQLiteConfig extends ZLConfig { } } - public void unsetValue(String group, String name) { + synchronized public void unsetValue(String group, String name) { myUnsetValueStatement.bindString(1, group); myUnsetValueStatement.bindString(2, name); try { diff --git a/platform/android/src/org/geometerplus/zlibrary/ui/android/view/ZLAndroidWidget.java b/platform/android/src/org/geometerplus/zlibrary/ui/android/view/ZLAndroidWidget.java index 70ce72f50..d876a3a25 100644 --- a/platform/android/src/org/geometerplus/zlibrary/ui/android/view/ZLAndroidWidget.java +++ b/platform/android/src/org/geometerplus/zlibrary/ui/android/view/ZLAndroidWidget.java @@ -63,9 +63,34 @@ public class ZLAndroidWidget extends View { myViewWidget = viewWidget; } - public void onDraw(final Canvas canvas) { + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + if (myScreenIsTouched) { + final ZLView view = ZLApplication.Instance().getCurrentView(); + view.onStylusRelease(myTouchX, myTouchY); + myScrollingInProgress = false; + myScrollingShift = 0; + myScreenIsTouched = false; + } + } + + @Override + protected void onDraw(final Canvas canvas) { super.onDraw(canvas); + final int w = getWidth(); + final int h = getHeight(); + + if ((myMainBitmap != null) && ((myMainBitmap.getWidth() != w) || (myMainBitmap.getHeight() != h))) { + myMainBitmap = null; + } + if (myMainBitmap == null) { + myMainBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + mySecondaryBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + mySecondaryBitmapIsUpToDate = false; + drawOnBitmap(myMainBitmap); + } + if (myScrollingInProgress || (myScrollingShift != 0)) { onDrawInScrolling(canvas); } else { @@ -102,14 +127,16 @@ public class ZLAndroidWidget extends View { Bitmap swap = myMainBitmap; myMainBitmap = mySecondaryBitmap; mySecondaryBitmap = swap; + mySecondaryBitmapIsUpToDate = false; + ZLApplication.Instance().getCurrentView().onScrollingFinished(0, (myScrollingBound < 0) ? 1 : -1); } - mySecondaryBitmapIsUpToDate = false; myScrollingInProgress = false; myScrollingShift = 0; } else { if (shift < 0) { shift += h; } + // TODO: set color canvas.drawLine(0, shift, w, shift, context.Paint); if (myScrollingInProgress) { postInvalidate(); @@ -121,8 +148,12 @@ public class ZLAndroidWidget extends View { if (myMainBitmap == null) { return; } - drawOnBitmap(mySecondaryBitmap); + if (((shift > 0) && (myScrollingShift <= 0)) || + ((shift < 0) && (myScrollingShift >= 0))) { + mySecondaryBitmapIsUpToDate = false; + } myScrollingShift = shift; + drawOnBitmap(mySecondaryBitmap); postInvalidate(); } @@ -179,31 +210,26 @@ public class ZLAndroidWidget extends View { canvas.rotate(90, w / 2, w / 2); break; } - int dy = (bitmap == myMainBitmap) ? 0 : ((myScrollingShift > 0) ? 1 : 0); + int dy = (bitmap == myMainBitmap) ? 0 : ((myScrollingShift > 0) ? -1 : 1); view.paint(0, dy); context.endPaint(); } private void onDrawStatic(Canvas canvas) { - final int w = getWidth(); - final int h = getHeight(); - - if ((myMainBitmap != null) && ((myMainBitmap.getWidth() != w) || (myMainBitmap.getHeight() != h))) { - myMainBitmap = null; - } - if (myMainBitmap == null) { - myMainBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - mySecondaryBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - } drawOnBitmap(myMainBitmap); canvas.drawBitmap(myMainBitmap, 0, 0, ZLAndroidPaintContext.Instance().Paint); } + @Override public boolean onTrackballEvent(MotionEvent event) { ZLApplication.Instance().getCurrentView().onTrackballRotated((int)(10 * event.getX()), (int)(10 * event.getY())); return true; } + private boolean myScreenIsTouched; + private int myTouchX; + private int myTouchY; + @Override public boolean onTouchEvent(MotionEvent event) { int x = (int)event.getX(); int y = (int)event.getY(); @@ -231,14 +257,18 @@ public class ZLAndroidWidget extends View { break; } } + myTouchX = x; + myTouchY = y; - ZLView view = ZLApplication.Instance().getCurrentView(); + final ZLView view = ZLApplication.Instance().getCurrentView(); switch (event.getAction()) { case MotionEvent.ACTION_UP: view.onStylusRelease(x, y); + myScreenIsTouched = false; break; case MotionEvent.ACTION_DOWN: view.onStylusPress(x, y); + myScreenIsTouched = true; break; case MotionEvent.ACTION_MOVE: view.onStylusMovePressed(x, y); diff --git a/src/org/geometerplus/fbreader/fbreader/BookTextView.java b/src/org/geometerplus/fbreader/fbreader/BookTextView.java index d8ece5d8c..c2890255a 100644 --- a/src/org/geometerplus/fbreader/fbreader/BookTextView.java +++ b/src/org/geometerplus/fbreader/fbreader/BookTextView.java @@ -96,12 +96,11 @@ public class BookTextView extends FBView { } } - protected synchronized void preparePaintInfo() { - super.preparePaintInfo(); + protected void onPreparePaintInfo() { if (myPositionStack.isEmpty()) { - myPositionStack.add(new Position(myCurrentModelIndex, StartCursor)); + myPositionStack.add(new Position(myCurrentModelIndex, getStartCursor())); } else { - ((Position)myPositionStack.get(myCurrentPointInStack)).set(StartCursor); + ((Position)myPositionStack.get(myCurrentPointInStack)).set(getStartCursor()); ((Position)myPositionStack.get(myCurrentPointInStack)).ModelIndex = myCurrentModelIndex; // Position position = (Position)myPositionStack.get(myCurrentPointInStack); @@ -110,7 +109,7 @@ public class BookTextView extends FBView { } void scrollToHome() { - final ZLTextWordCursor cursor = StartCursor; + final ZLTextWordCursor cursor = getStartCursor(); if (!cursor.isNull() && cursor.isStartOfParagraph() && cursor.getParagraphCursor().Index == 0 && myCurrentModelIndex == 0) { return; @@ -121,7 +120,7 @@ public class BookTextView extends FBView { gotoParagraph(0, false); gotoPosition(0, 0, 0); preparePaintInfo(); - savePosition(position, 0, StartCursor); + savePosition(position, 0, getStartCursor()); ZLApplication.Instance().refreshWindow(); } @@ -129,12 +128,12 @@ public class BookTextView extends FBView { void gotoParagraphSafe(int paragraphIndex) { // gotoParagraphSafe(paragraphIndex, myCurrentModelIndex); preparePaintInfo(); - final ZLTextWordCursor cursor = StartCursor; - if (cursor != null) { + final ZLTextWordCursor cursor = getStartCursor(); + if (!cursor.isNull()) { final Position position = new Position(myCurrentModelIndex, cursor); gotoParagraph(paragraphIndex, false); preparePaintInfo(); - savePosition(position, myCurrentModelIndex, StartCursor); + savePosition(position, myCurrentModelIndex, getStartCursor()); } } @@ -144,13 +143,13 @@ public class BookTextView extends FBView { void gotoParagraphSafe(int modelIndex, int paragraphIndex) { preparePaintInfo(); - final ZLTextWordCursor cursor = StartCursor; - if (cursor != null) { + final ZLTextWordCursor cursor = getStartCursor(); + if (!cursor.isNull()) { final Position position = new Position(myCurrentModelIndex, cursor); setModelIndex(modelIndex); gotoParagraph(paragraphIndex, false); preparePaintInfo(); - savePosition(position, modelIndex, StartCursor); + savePosition(position, modelIndex, getStartCursor()); } } @@ -164,7 +163,7 @@ public class BookTextView extends FBView { ZLTextElement element = area.Element; if ((element instanceof ZLTextImageElement) || (element instanceof ZLTextWord)) { - final ZLTextWordCursor cursor = new ZLTextWordCursor(StartCursor); + final ZLTextWordCursor cursor = new ZLTextWordCursor(getStartCursor()); cursor.moveToParagraph(area.ParagraphIndex); cursor.moveToParagraphStart(); final int elementIndex = area.TextElementIndex; diff --git a/src/org/geometerplus/fbreader/fbreader/FBView.java b/src/org/geometerplus/fbreader/fbreader/FBView.java index 9e976c582..3957103e2 100644 --- a/src/org/geometerplus/fbreader/fbreader/FBView.java +++ b/src/org/geometerplus/fbreader/fbreader/FBView.java @@ -47,7 +47,7 @@ public abstract class FBView extends ZLTextViewImpl { private int myStartX; private int myStartY; - private boolean myTouchIsProcessed; + private boolean myScrollingIsActive; public boolean onStylusPress(int x, int y) { if (super.onStylusPress(x, y)) { @@ -56,38 +56,65 @@ public abstract class FBView extends ZLTextViewImpl { myStartX = x; myStartY = y; - myTouchIsProcessed = false; + myScrollingIsActive = true; //activateSelection(x, y); return true; } public boolean onStylusMovePressed(int x, int y) { - if (super.onStylusMovePressed(x, y) || myTouchIsProcessed) { + if (super.onStylusMovePressed(x, y)) { return true; } - final int diffY = y - myStartY; - if (Math.abs(diffY) * 5 >= Context.getHeight()) { + if (myScrollingIsActive) { + final int diffY = y - myStartY; + boolean doScroll = true; if (diffY > 0) { - ZLApplication.Instance().doAction(ActionCode.TOUCH_SCROLL_BACKWARD); - } else { - ZLApplication.Instance().doAction(ActionCode.TOUCH_SCROLL_FORWARD); + ZLTextWordCursor cursor = getStartCursor(); + doScroll = !cursor.isStartOfParagraph() || !cursor.getParagraphCursor().isFirst(); + } else if (diffY < 0) { + ZLTextWordCursor cursor = getEndCursor(); + doScroll = !cursor.isEndOfParagraph() || !cursor.getParagraphCursor().isLast(); + } + if (doScroll) { + scrollTo(diffY); + return true; } - myTouchIsProcessed = true; - return true; } return false; } public boolean onStylusRelease(int x, int y) { + boolean scrollingWasActive = myScrollingIsActive; + myScrollingIsActive = false; + if (super.onStylusRelease(x, y)) { return true; } + if (scrollingWasActive) { + final int diffY = y - myStartY; + boolean doScroll = false; + if (diffY > 0) { + ZLTextWordCursor cursor = getStartCursor(); + doScroll = !cursor.isStartOfParagraph() || !cursor.getParagraphCursor().isFirst(); + } else if (diffY < 0) { + ZLTextWordCursor cursor = getEndCursor(); + doScroll = !cursor.isEndOfParagraph() || !cursor.getParagraphCursor().isLast(); + } + if (doScroll) { + final int h = Context.getHeight(); + final int w = Context.getWidth(); + final int minDiff = (h > w) ? h / 4 : h / 3; + startAutoScrolling(Math.abs(diffY) >= minDiff); + return true; + } + } + //activateSelection(x, y); - return myTouchIsProcessed; + return false; } public boolean onTrackballRotated(int diffX, int diffY) { diff --git a/src/org/geometerplus/zlibrary/core/view/ZLView.java b/src/org/geometerplus/zlibrary/core/view/ZLView.java index 257b450a5..e6a47875d 100644 --- a/src/org/geometerplus/zlibrary/core/view/ZLView.java +++ b/src/org/geometerplus/zlibrary/core/view/ZLView.java @@ -31,6 +31,7 @@ abstract public class ZLView { abstract public String getCaption(); abstract public void paint(int dx, int dy); + abstract public void onScrollingFinished(int dx, int dy); public boolean onStylusPress(int x, int y) { return false; diff --git a/src/org/geometerplus/zlibrary/text/view/impl/PaintStateEnum.java b/src/org/geometerplus/zlibrary/text/view/impl/PaintStateEnum.java new file mode 100644 index 000000000..4f52acd58 --- /dev/null +++ b/src/org/geometerplus/zlibrary/text/view/impl/PaintStateEnum.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007-2009 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package org.geometerplus.zlibrary.text.view.impl; + +interface PaintStateEnum { + int NOTHING_TO_PAINT = 0; + int READY = 1; + int START_IS_KNOWN = 2; + int END_IS_KNOWN = 3; + int TO_SCROLL_FORWARD = 4; + int TO_SCROLL_BACKWARD = 5; +}; diff --git a/src/org/geometerplus/zlibrary/text/view/impl/ZLTextPage.java b/src/org/geometerplus/zlibrary/text/view/impl/ZLTextPage.java new file mode 100644 index 000000000..12ea768e2 --- /dev/null +++ b/src/org/geometerplus/zlibrary/text/view/impl/ZLTextPage.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2007-2009 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package org.geometerplus.zlibrary.text.view.impl; + +import java.util.ArrayList; + +final class ZLTextPage { + final ZLTextWordCursor StartCursor = new ZLTextWordCursor(); + final ZLTextWordCursor EndCursor = new ZLTextWordCursor(); + final ArrayList LineInfos = new ArrayList(); + int PaintState = PaintStateEnum.NOTHING_TO_PAINT; + + int OldWidth; + int OldHeight; + + void reset() { + StartCursor.reset(); + EndCursor.reset(); + LineInfos.clear(); + PaintState = PaintStateEnum.NOTHING_TO_PAINT; + } + + void moveStartCursor(ZLTextParagraphCursor cursor) { + StartCursor.setCursor(cursor); + EndCursor.reset(); + LineInfos.clear(); + PaintState = PaintStateEnum.START_IS_KNOWN; + } + + void moveStartCursor(int paragraphIndex, int wordIndex, int charIndex) { + if (StartCursor.isNull()) { + StartCursor.setCursor(EndCursor); + } + StartCursor.moveToParagraph(paragraphIndex); + StartCursor.moveTo(wordIndex, charIndex); + EndCursor.reset(); + LineInfos.clear(); + PaintState = PaintStateEnum.START_IS_KNOWN; + } + + void moveEndCursor(int paragraphIndex, int wordIndex, int charIndex) { + if (EndCursor.isNull()) { + EndCursor.setCursor(StartCursor); + } + EndCursor.moveToParagraph(paragraphIndex); + if ((paragraphIndex > 0) && (wordIndex == 0) && (charIndex == 0)) { + EndCursor.previousParagraph(); + EndCursor.moveToParagraphEnd(); + } else { + EndCursor.moveTo(wordIndex, charIndex); + } + StartCursor.reset(); + LineInfos.clear(); + PaintState = PaintStateEnum.END_IS_KNOWN; + } + + boolean isEmptyPage() { + for (ZLTextLineInfo info : LineInfos) { + if (info.IsVisible) { + return false; + } + } + return true; + } + + void findLineFromStart(ZLTextWordCursor cursor, int overlappingValue) { + if (LineInfos.isEmpty() || (overlappingValue == 0)) { + cursor.reset(); + return; + } + ZLTextLineInfo info = null; + for (ZLTextLineInfo i : LineInfos) { + info = i; + if (info.IsVisible) { + --overlappingValue; + if (overlappingValue == 0) { + break; + } + } + } + cursor.setCursor(info.ParagraphCursor); + cursor.moveTo(info.EndWordIndex, info.EndCharIndex); + } + + void findLineFromEnd(ZLTextWordCursor cursor, int overlappingValue) { + if (LineInfos.isEmpty() || (overlappingValue == 0)) { + cursor.reset(); + return; + } + final ArrayList infos = LineInfos; + final int size = infos.size(); + ZLTextLineInfo info = null; + for (int i = size - 1; i >= 0; --i) { + info = infos.get(i); + if (info.IsVisible) { + --overlappingValue; + if (overlappingValue == 0) { + break; + } + } + } + cursor.setCursor(info.ParagraphCursor); + cursor.moveTo(info.StartWordIndex, info.StartCharIndex); + } + + void findPercentFromStart(ZLTextWordCursor cursor, int areaHeight, int percent) { + if (LineInfos.isEmpty()) { + cursor.reset(); + return; + } + int height = areaHeight * percent / 100; + boolean visibleLineOccured = false; + ZLTextLineInfo info = null; + for (ZLTextLineInfo i : LineInfos) { + info = i; + if (info.IsVisible) { + visibleLineOccured = true; + } + height -= info.Height + info.Descent + info.VSpaceAfter; + if (visibleLineOccured && (height <= 0)) { + break; + } + } + cursor.setCursor(info.ParagraphCursor); + cursor.moveTo(info.EndWordIndex, info.EndCharIndex); + } +} diff --git a/src/org/geometerplus/zlibrary/text/view/impl/ZLTextParagraphCursor.java b/src/org/geometerplus/zlibrary/text/view/impl/ZLTextParagraphCursor.java index b50331631..e9e5b52b9 100644 --- a/src/org/geometerplus/zlibrary/text/view/impl/ZLTextParagraphCursor.java +++ b/src/org/geometerplus/zlibrary/text/view/impl/ZLTextParagraphCursor.java @@ -163,7 +163,7 @@ public final class ZLTextParagraphCursor { myElements.clear(); } - boolean isFirst() { + public boolean isFirst() { return Index == 0; } diff --git a/src/org/geometerplus/zlibrary/text/view/impl/ZLTextViewImpl.java b/src/org/geometerplus/zlibrary/text/view/impl/ZLTextViewImpl.java index d4fa7caa3..ac1d6674f 100644 --- a/src/org/geometerplus/zlibrary/text/view/impl/ZLTextViewImpl.java +++ b/src/org/geometerplus/zlibrary/text/view/impl/ZLTextViewImpl.java @@ -30,10 +30,6 @@ import org.geometerplus.zlibrary.text.view.*; import org.geometerplus.zlibrary.text.view.style.*; public abstract class ZLTextViewImpl extends ZLTextView { - private static final int PREVIOUS_PAGE = -1; - private static final int CURRENT_PAGE = 0; - private static final int NEXT_PAGE = 1; - private ZLTextModel myModel; protected int myCurrentModelIndex; private ArrayList myModelList; @@ -77,25 +73,13 @@ public abstract class ZLTextViewImpl extends ZLTextView { int PIXEL_UNIT = 0; int LINE_UNIT = 1; }; - private interface PaintState { - int NOTHING_TO_PAINT = 0; - int READY = 1; - int START_IS_KNOWN = 2; - int END_IS_KNOWN = 3; - int TO_SCROLL_FORWARD = 4; - int TO_SCROLL_BACKWARD = 5; - }; - private int myPaintState = PaintState.NOTHING_TO_PAINT; private int myScrollingMode; private int myOverlappingValue; - private int myOldWidth; - private int myOldHeight; + private ZLTextPage myPreviousPage = new ZLTextPage(); + private ZLTextPage myCurrentPage = new ZLTextPage(); + private ZLTextPage myNextPage = new ZLTextPage(); - public final ZLTextWordCursor StartCursor = new ZLTextWordCursor(); - private final ZLTextWordCursor EndCursor = new ZLTextWordCursor(); - - private final ArrayList myLineInfos = new ArrayList(); private final HashMap myLineInfoCache = new HashMap(); private int[] myTextSize; @@ -130,9 +114,9 @@ public abstract class ZLTextViewImpl extends ZLTextView { for (int i = 0; i < paragraphsNumber; ++i) { myTextSize[i + 1] = myTextSize[i] + myModel.getParagraphTextLength(i); } - StartCursor.setCursor(ZLTextParagraphCursor.cursor(myModel, 0)); - EndCursor.reset(); - myPaintState = PaintState.START_IS_KNOWN; + myCurrentPage.moveStartCursor(ZLTextParagraphCursor.cursor(myModel, 0)); + myPreviousPage.reset(); + myNextPage.reset(); } } } @@ -157,7 +141,7 @@ public abstract class ZLTextViewImpl extends ZLTextView { public void highlightParagraph(int paragraphIndex) { myModel.selectParagraph(paragraphIndex); - rebuildPaintInfo(true); + rebuildPaintInfo(); } void setTextStyle(ZLTextStyle style) { @@ -274,17 +258,9 @@ public abstract class ZLTextViewImpl extends ZLTextView { } private void moveStartCursor(int paragraphIndex, int wordIndex, int charIndex) { - if (myPaintState == PaintState.NOTHING_TO_PAINT) { - return; - } - if (StartCursor.isNull()) { - StartCursor.setCursor(EndCursor); - } - StartCursor.moveToParagraph(paragraphIndex); - StartCursor.moveTo(wordIndex, charIndex); - EndCursor.reset(); - myLineInfos.clear(); - myPaintState = PaintState.START_IS_KNOWN; + myCurrentPage.moveStartCursor(paragraphIndex, wordIndex, charIndex); + myPreviousPage.reset(); + myNextPage.reset(); } private void moveEndCursor(int paragraphIndex) { @@ -292,59 +268,62 @@ public abstract class ZLTextViewImpl extends ZLTextView { } private void moveEndCursor(int paragraphIndex, int wordIndex, int charIndex) { - if (myPaintState == PaintState.NOTHING_TO_PAINT) { - return; + myCurrentPage.moveEndCursor(paragraphIndex, wordIndex, charIndex); + myPreviousPage.reset(); + myNextPage.reset(); + } + + public ZLTextWordCursor getStartCursor() { + if (myCurrentPage.StartCursor.isNull()) { + preparePaintInfo(myCurrentPage); } - if (EndCursor.isNull()) { - EndCursor.setCursor(StartCursor); + return myCurrentPage.StartCursor; + } + + public ZLTextWordCursor getEndCursor() { + if (myCurrentPage.EndCursor.isNull()) { + preparePaintInfo(myCurrentPage); } - EndCursor.moveToParagraph(paragraphIndex); - if ((paragraphIndex > 0) && (wordIndex == 0) && (charIndex == 0)) { - EndCursor.previousParagraph(); - EndCursor.moveToParagraphEnd(); - } else { - EndCursor.moveTo(wordIndex, charIndex); - } - StartCursor.reset(); - myLineInfos.clear(); - myPaintState = PaintState.END_IS_KNOWN; + return myCurrentPage.EndCursor; } public void gotoMark(ZLTextMark mark) { + myPreviousPage.reset(); + myNextPage.reset(); if (mark.ParagraphIndex < 0) { return; } boolean doRepaint = false; - if (StartCursor.isNull()) { + if (myCurrentPage.StartCursor.isNull()) { doRepaint = true; - preparePaintInfo(); + preparePaintInfo(myCurrentPage); } - if (StartCursor.isNull()) { + if (myCurrentPage.StartCursor.isNull()) { return; } - final Position position = new Position(myCurrentModelIndex, StartCursor); - if ((StartCursor.getParagraphCursor().Index != mark.ParagraphIndex) || (StartCursor.getPosition().compareTo(mark) > 0)) { + final Position position = new Position(myCurrentModelIndex, myCurrentPage.StartCursor); + if ((myCurrentPage.StartCursor.getParagraphCursor().Index != mark.ParagraphIndex) || (myCurrentPage.StartCursor.getPosition().compareTo(mark) > 0)) { doRepaint = true; gotoParagraph(mark.ParagraphIndex, false); - preparePaintInfo(); + preparePaintInfo(myCurrentPage); } - if (EndCursor.isNull()) { - preparePaintInfo(); + if (myCurrentPage.EndCursor.isNull()) { + preparePaintInfo(myCurrentPage); } - while (mark.compareTo(EndCursor.getPosition()) > 0) { + while (mark.compareTo(myCurrentPage.EndCursor.getPosition()) > 0) { doRepaint = true; scrollPage(true, ScrollingMode.NO_OVERLAPPING, 0); - preparePaintInfo(); + preparePaintInfo(myCurrentPage); } if (doRepaint) { - if (StartCursor.isNull()) { - preparePaintInfo(); + if (myCurrentPage.StartCursor.isNull()) { + preparePaintInfo(myCurrentPage); } - /* if (!position.equalsToCursor(StartCursor)) { + /* if (!position.equalsToCursor(myCurrentPage.StartCursor)) { savePosition(position); } */ - savePosition(position, myCurrentModelIndex, StartCursor); + savePosition(position, myCurrentModelIndex, myCurrentPage.StartCursor); ZLApplication.Instance().refreshWindow(); } } @@ -370,9 +349,11 @@ public abstract class ZLTextViewImpl extends ZLTextView { //To be written } myModel.search(text, startIndex, endIndex, ignoreCase); - if (!StartCursor.isNull()) { - rebuildPaintInfo(true); - ZLTextMark position = StartCursor.getPosition(); + myPreviousPage.reset(); + myNextPage.reset(); + if (!myCurrentPage.StartCursor.isNull()) { + rebuildPaintInfo(); + ZLTextMark position = myCurrentPage.StartCursor.getPosition(); gotoMark(wholeText ? (backward ? myModel.getLastMark() : myModel.getFirstMark()) : (backward ? myModel.getPreviousMark(position) : myModel.getNextMark(position))); @@ -381,26 +362,57 @@ public abstract class ZLTextViewImpl extends ZLTextView { } public boolean canFindNext() { - return !EndCursor.isNull() && (myModel != null) && (myModel.getNextMark(EndCursor.getPosition()).ParagraphIndex > -1); + final ZLTextWordCursor end = myCurrentPage.EndCursor; + return !end.isNull() && (myModel != null) && (myModel.getNextMark(end.getPosition()).ParagraphIndex > -1); } public void findNext() { - if (!EndCursor.isNull()) { - gotoMark(myModel.getNextMark(EndCursor.getPosition())); + final ZLTextWordCursor end = myCurrentPage.EndCursor; + if (!end.isNull()) { + gotoMark(myModel.getNextMark(end.getPosition())); } } public boolean canFindPrevious() { - return !StartCursor.isNull() && (myModel != null) && (myModel.getPreviousMark(StartCursor.getPosition()).ParagraphIndex > -1); + final ZLTextWordCursor start = myCurrentPage.StartCursor; + return !start.isNull() && (myModel != null) && (myModel.getPreviousMark(start.getPosition()).ParagraphIndex > -1); } public void findPrevious() { - if (!StartCursor.isNull()) { - gotoMark(myModel.getPreviousMark(StartCursor.getPosition())); + final ZLTextWordCursor start = myCurrentPage.StartCursor; + if (!start.isNull()) { + gotoMark(myModel.getPreviousMark(start.getPosition())); + } + } + + public synchronized void onScrollingFinished(int dx, int dy) { + if ((dx < 0) || (dy < 0)) { + ZLTextPage swap = myNextPage; + myNextPage = myCurrentPage; + myCurrentPage = myPreviousPage; + myPreviousPage = swap; + myPreviousPage.reset(); + if (myCurrentPage.PaintState == PaintStateEnum.NOTHING_TO_PAINT) { + preparePaintInfo(myNextPage); + myCurrentPage.EndCursor.setCursor(myNextPage.StartCursor); + myCurrentPage.PaintState = PaintStateEnum.START_IS_KNOWN; + } + } else if ((dx > 0) || (dy > 0)) { + ZLTextPage swap = myPreviousPage; + myPreviousPage = myCurrentPage; + myCurrentPage = myNextPage; + myNextPage = swap; + myNextPage.reset(); + if (myCurrentPage.PaintState == PaintStateEnum.NOTHING_TO_PAINT) { + preparePaintInfo(myPreviousPage); + myCurrentPage.StartCursor.setCursor(myPreviousPage.EndCursor); + myCurrentPage.PaintState = PaintStateEnum.END_IS_KNOWN; + } } } public synchronized void paint(int dx, int dy) { + System.err.println("paint " + dx + ' ' + dy); myTextElementMap.clear(); final ZLTextBaseStyle baseStyle = ZLTextStyleCollection.getInstance().getBaseStyle(); @@ -411,16 +423,35 @@ public abstract class ZLTextViewImpl extends ZLTextView { return; } - preparePaintInfo(); + ZLTextPage page; + if ((dx < 0) || (dy < 0)) { + page = myPreviousPage; + if (myPreviousPage.PaintState == PaintStateEnum.NOTHING_TO_PAINT) { + preparePaintInfo(myCurrentPage); + myPreviousPage.EndCursor.setCursor(myCurrentPage.StartCursor); + myPreviousPage.PaintState = PaintStateEnum.END_IS_KNOWN; + } + } else if ((dx > 0) || (dy > 0)) { + page = myNextPage; + if (myNextPage.PaintState == PaintStateEnum.NOTHING_TO_PAINT) { + preparePaintInfo(myCurrentPage); + myNextPage.StartCursor.setCursor(myCurrentPage.EndCursor); + myNextPage.PaintState = PaintStateEnum.START_IS_KNOWN; + } + } else { + page = myCurrentPage; + } - if (StartCursor.isNull() || EndCursor.isNull()) { + preparePaintInfo(page); + + if (page.StartCursor.isNull() || page.EndCursor.isNull()) { return; } { final int fullScrollBarSize = myTextSize[myTextSize.length - 1]; - final int scrollBarStart = sizeOfTextBeforeCursor(StartCursor); - final int scrollBarEnd = sizeOfTextBeforeCursor(EndCursor); + final int scrollBarStart = sizeOfTextBeforeCursor(page.StartCursor); + final int scrollBarEnd = sizeOfTextBeforeCursor(page.EndCursor); setVerticalScrollbarParameters( fullScrollBarSize, scrollBarStart, @@ -428,7 +459,7 @@ public abstract class ZLTextViewImpl extends ZLTextView { ); } - final ArrayList lineInfos = myLineInfos; + final ArrayList lineInfos = page.LineInfos; final int[] labels = new int[lineInfos.size() + 1]; context.moveYTo(getTopMargin()); int index = 0; @@ -665,11 +696,11 @@ public abstract class ZLTextViewImpl extends ZLTextView { } } - private void buildInfos(final ZLTextWordCursor start, final ZLTextWordCursor result) { + private void buildInfos(ZLTextPage page, ZLTextWordCursor start, ZLTextWordCursor result) { result.setCursor(start); final ZLPaintContext context = Context; int textAreaHeight = getTextAreaHeight(); - myLineInfos.clear(); + page.LineInfos.clear(); int counter = 0; do { resetTextStyle(); @@ -686,7 +717,7 @@ public abstract class ZLTextViewImpl extends ZLTextView { } textAreaHeight -= info.VSpaceAfter; result.moveTo(info.EndWordIndex, info.EndCharIndex); - myLineInfos.add(info); + page.LineInfos.add(info); if (textAreaHeight < 0) { break; } @@ -957,9 +988,11 @@ public abstract class ZLTextViewImpl extends ZLTextView { } public void scrollPage(boolean forward, int scrollingMode, int value) { - preparePaintInfo(); - if (myPaintState == PaintState.READY) { - myPaintState = forward ? PaintState.TO_SCROLL_FORWARD : PaintState.TO_SCROLL_BACKWARD; + preparePaintInfo(myCurrentPage); + myPreviousPage.reset(); + myNextPage.reset(); + if (myCurrentPage.PaintState == PaintStateEnum.READY) { + myCurrentPage.PaintState = forward ? PaintStateEnum.TO_SCROLL_FORWARD : PaintStateEnum.TO_SCROLL_BACKWARD; myScrollingMode = scrollingMode; myOverlappingValue = value; } @@ -977,10 +1010,9 @@ public abstract class ZLTextViewImpl extends ZLTextView { if (paragraphIndex < 0) { paragraphIndex = 0; } - StartCursor.setCursor(ZLTextParagraphCursor.cursor(myModel, paragraphIndex)); - StartCursor.moveTo(wordIndex, charIndex); - EndCursor.reset(); - myPaintState = PaintState.START_IS_KNOWN; + myCurrentPage.moveStartCursor(paragraphIndex, wordIndex, charIndex); + myPreviousPage.reset(); + myNextPage.reset(); } public final void gotoPosition(int modelIndex, int paragraphIndex, int wordIndex, int charIndex) { @@ -1008,216 +1040,164 @@ public abstract class ZLTextViewImpl extends ZLTextView { return Math.max(Context.getWidth() - getLeftMargin() - getRightMargin(), 1); } - protected synchronized void preparePaintInfo(/*int page*/) { + protected synchronized void preparePaintInfo() { + myPreviousPage.reset(); + myNextPage.reset(); + preparePaintInfo(myCurrentPage); + } + + private synchronized void preparePaintInfo(ZLTextPage page) { int newWidth = getViewWidth(); int newHeight = getTextAreaHeight(); - if ((newWidth != myOldWidth) || (newHeight != myOldHeight)) { - myOldWidth = newWidth; - myOldHeight = newHeight; - rebuildPaintInfo(false); + if ((newWidth != page.OldWidth) || (newHeight != page.OldHeight)) { + page.OldWidth = newWidth; + page.OldHeight = newHeight; + if (page.PaintState != PaintStateEnum.NOTHING_TO_PAINT) { + page.LineInfos.clear(); + if (!page.StartCursor.isNull()) { + page.EndCursor.reset(); + page.PaintState = PaintStateEnum.START_IS_KNOWN; + } else if (!page.EndCursor.isNull()) { + page.StartCursor.reset(); + page.PaintState = PaintStateEnum.END_IS_KNOWN; + } + } } - if ((myPaintState == PaintState.NOTHING_TO_PAINT) || (myPaintState == PaintState.READY)) { + if ((page.PaintState == PaintStateEnum.NOTHING_TO_PAINT) || (page.PaintState == PaintStateEnum.READY)) { return; } final HashMap cache = myLineInfoCache; - for (ZLTextLineInfo info : myLineInfos) { + for (ZLTextLineInfo info : page.LineInfos) { cache.put(info, info); } - switch (myPaintState) { + switch (page.PaintState) { default: break; - case PaintState.TO_SCROLL_FORWARD: - if (!EndCursor.getParagraphCursor().isLast() || !EndCursor.isEndOfParagraph()) { + case PaintStateEnum.TO_SCROLL_FORWARD: + if (!page.EndCursor.getParagraphCursor().isLast() || !page.EndCursor.isEndOfParagraph()) { final ZLTextWordCursor startCursor = new ZLTextWordCursor(); switch (myScrollingMode) { case ScrollingMode.NO_OVERLAPPING: break; case ScrollingMode.KEEP_LINES: - findLineFromEnd(startCursor, myOverlappingValue); + page.findLineFromEnd(startCursor, myOverlappingValue); break; case ScrollingMode.SCROLL_LINES: - findLineFromStart(startCursor, myOverlappingValue); + page.findLineFromStart(startCursor, myOverlappingValue); if (startCursor.isEndOfParagraph()) { startCursor.nextParagraph(); } break; case ScrollingMode.SCROLL_PERCENTAGE: - findPercentFromStart(startCursor, myOverlappingValue); + page.findPercentFromStart(startCursor, getTextAreaHeight(), myOverlappingValue); break; } - if (!startCursor.isNull() && startCursor.equalsToCursor(StartCursor)) { - findLineFromStart(startCursor, 1); + if (!startCursor.isNull() && startCursor.equalsToCursor(page.StartCursor)) { + page.findLineFromStart(startCursor, 1); } if (!startCursor.isNull()) { final ZLTextWordCursor endCursor = new ZLTextWordCursor(); - buildInfos(startCursor, endCursor); - if (!pageIsEmpty() && ((myScrollingMode != ScrollingMode.KEEP_LINES) || (!endCursor.equalsToCursor(EndCursor)))) { - StartCursor.setCursor(startCursor); - EndCursor.setCursor(endCursor); + buildInfos(page, startCursor, endCursor); + if (!page.isEmptyPage() && ((myScrollingMode != ScrollingMode.KEEP_LINES) || (!endCursor.equalsToCursor(page.EndCursor)))) { + page.StartCursor.setCursor(startCursor); + page.EndCursor.setCursor(endCursor); break; } } - StartCursor.setCursor(EndCursor); - buildInfos(StartCursor, EndCursor); + page.StartCursor.setCursor(page.EndCursor); + buildInfos(page, page.StartCursor, page.EndCursor); } break; - case PaintState.TO_SCROLL_BACKWARD: - if (!StartCursor.getParagraphCursor().isFirst() || !StartCursor.isStartOfParagraph()) { + case PaintStateEnum.TO_SCROLL_BACKWARD: + if (!page.StartCursor.getParagraphCursor().isFirst() || !page.StartCursor.isStartOfParagraph()) { switch (myScrollingMode) { case ScrollingMode.NO_OVERLAPPING: - StartCursor.setCursor(findStart(StartCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight())); + page.StartCursor.setCursor(findStart(page.StartCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight())); break; case ScrollingMode.KEEP_LINES: { ZLTextWordCursor endCursor = new ZLTextWordCursor(); - findLineFromStart(endCursor, myOverlappingValue); - if (!endCursor.isNull() && endCursor.equalsToCursor(EndCursor)) { - findLineFromEnd(endCursor, 1); + page.findLineFromStart(endCursor, myOverlappingValue); + if (!endCursor.isNull() && endCursor.equalsToCursor(page.EndCursor)) { + page.findLineFromEnd(endCursor, 1); } if (!endCursor.isNull()) { ZLTextWordCursor startCursor = findStart(endCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight()); - if (startCursor.equalsToCursor(StartCursor)) { - StartCursor.setCursor(findStart(StartCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight())); + if (startCursor.equalsToCursor(page.StartCursor)) { + page.StartCursor.setCursor(findStart(page.StartCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight())); } else { - StartCursor.setCursor(startCursor); + page.StartCursor.setCursor(startCursor); } } else { - StartCursor.setCursor(findStart(StartCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight())); + page.StartCursor.setCursor(findStart(page.StartCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight())); } break; } case ScrollingMode.SCROLL_LINES: - StartCursor.setCursor(findStart(StartCursor, SizeUnit.LINE_UNIT, myOverlappingValue)); + page.StartCursor.setCursor(findStart(page.StartCursor, SizeUnit.LINE_UNIT, myOverlappingValue)); break; case ScrollingMode.SCROLL_PERCENTAGE: - StartCursor.setCursor(findStart(StartCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight() * myOverlappingValue / 100)); + page.StartCursor.setCursor(findStart(page.StartCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight() * myOverlappingValue / 100)); break; } - buildInfos(StartCursor, EndCursor); - if (pageIsEmpty()) { - StartCursor.setCursor(findStart(StartCursor, SizeUnit.LINE_UNIT, 1)); - buildInfos(StartCursor, EndCursor); + buildInfos(page, page.StartCursor, page.EndCursor); + if (page.isEmptyPage()) { + page.StartCursor.setCursor(findStart(page.StartCursor, SizeUnit.LINE_UNIT, 1)); + buildInfos(page, page.StartCursor, page.EndCursor); } } break; - case PaintState.START_IS_KNOWN: - buildInfos(StartCursor, EndCursor); + case PaintStateEnum.START_IS_KNOWN: + buildInfos(page, page.StartCursor, page.EndCursor); break; - case PaintState.END_IS_KNOWN: - StartCursor.setCursor(findStart(EndCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight())); - buildInfos(StartCursor, EndCursor); + case PaintStateEnum.END_IS_KNOWN: + page.StartCursor.setCursor(findStart(page.EndCursor, SizeUnit.PIXEL_UNIT, getTextAreaHeight())); + buildInfos(page, page.StartCursor, page.EndCursor); break; } - myPaintState = PaintState.READY; + page.PaintState = PaintStateEnum.READY; + // TODO: cache? myLineInfoCache.clear(); - } - boolean pageIsEmpty() { - for (ZLTextLineInfo info : myLineInfos) { - if (info.IsVisible) { - return false; - } - } - return true; - } - - private void findLineFromStart(ZLTextWordCursor cursor, int overlappingValue) { - if (myLineInfos.isEmpty() || (overlappingValue == 0)) { - cursor.reset(); - } else { - ZLTextLineInfo info = null; - for (ZLTextLineInfo i : myLineInfos) { - info = i; - if (info.IsVisible) { - --overlappingValue; - if (overlappingValue == 0) { - break; - } - } - } - cursor.setCursor(info.ParagraphCursor); - cursor.moveTo(info.EndWordIndex, info.EndCharIndex); + if (page == myCurrentPage) { + myPreviousPage.reset(); + myNextPage.reset(); + onPreparePaintInfo(); } } - void findLineFromEnd(ZLTextWordCursor cursor, int overlappingValue) { - if (myLineInfos.isEmpty() || (overlappingValue == 0)) { - cursor.reset(); - } else { - final ArrayList infos = myLineInfos; - final int size = infos.size(); - ZLTextLineInfo info = null; - for (int i = size - 1; i >= 0; --i) { - info = infos.get(i); - if (info.IsVisible) { - --overlappingValue; - if (overlappingValue == 0) { - break; - } - } - } - cursor.setCursor(info.ParagraphCursor); - cursor.moveTo(info.StartWordIndex, info.StartCharIndex); - } - } - - private void findPercentFromStart(ZLTextWordCursor cursor, int percent) { - if (myLineInfos.isEmpty()) { - cursor.reset(); - } else { - int height = getTextAreaHeight() * percent / 100; - boolean visibleLineOccured = false; - ZLTextLineInfo info = null; - for (ZLTextLineInfo i : myLineInfos) { - info = i; - if (info.IsVisible) { - visibleLineOccured = true; - } - height -= info.Height + info.Descent + info.VSpaceAfter; - if (visibleLineOccured && (height <= 0)) { - break; - } - } - cursor.setCursor(info.ParagraphCursor); - cursor.moveTo(info.EndWordIndex, info.EndCharIndex); - } + protected void onPreparePaintInfo() { } public void clearCaches() { - rebuildPaintInfo(true); + rebuildPaintInfo(); } - protected void rebuildPaintInfo(boolean strong) { - if (strong) { - ZLTextParagraphCursorCache.clear(); - } + protected void rebuildPaintInfo() { + myPreviousPage.reset(); + myNextPage.reset(); + ZLTextParagraphCursorCache.clear(); - if (myPaintState != PaintState.NOTHING_TO_PAINT) { - myLineInfos.clear(); - if (!StartCursor.isNull()) { - if (strong) { - StartCursor.rebuild(); - } - EndCursor.reset(); - myPaintState = PaintState.START_IS_KNOWN; - } else if (!EndCursor.isNull()) { - if (strong) { - EndCursor.rebuild(); - } - StartCursor.reset(); - myPaintState = PaintState.END_IS_KNOWN; + if (myCurrentPage.PaintState != PaintStateEnum.NOTHING_TO_PAINT) { + myCurrentPage.LineInfos.clear(); + if (!myCurrentPage.StartCursor.isNull()) { + myCurrentPage.StartCursor.rebuild(); + myCurrentPage.EndCursor.reset(); + myCurrentPage.PaintState = PaintStateEnum.START_IS_KNOWN; + } else if (!myCurrentPage.EndCursor.isNull()) { + myCurrentPage.EndCursor.rebuild(); + myCurrentPage.StartCursor.reset(); + myCurrentPage.PaintState = PaintStateEnum.END_IS_KNOWN; } } - if (strong) { - myLineInfoCache.clear(); - } + myLineInfoCache.clear(); } private int infoSize(ZLTextLineInfo info, int unit) { diff --git a/src/org/geometerplus/zlibrary/text/view/style/ZLTextBaseStyle.java b/src/org/geometerplus/zlibrary/text/view/style/ZLTextBaseStyle.java index 44b8d0cec..85dd9baa3 100644 --- a/src/org/geometerplus/zlibrary/text/view/style/ZLTextBaseStyle.java +++ b/src/org/geometerplus/zlibrary/text/view/style/ZLTextBaseStyle.java @@ -39,9 +39,9 @@ public class ZLTextBaseStyle implements ZLTextStyle { public final ZLColorOption RegularTextColorOption = new ZLColorOption(COLORS, "Text", new ZLColor(0, 0, 0)); public final ZLColorOption InternalHyperlinkTextColorOption = - new ZLColorOption(COLORS, "Hyperlink", new ZLColor(33, 96, 180)); + new ZLColorOption(COLORS, "Hyperlink", new ZLColor(60, 139, 255)); public final ZLColorOption ExternalHyperlinkTextColorOption = - new ZLColorOption(COLORS, "ExternalHyperlink", new ZLColor(98, 174, 26)); + new ZLColorOption(COLORS, "ExternalHyperlink", new ZLColor(33, 96, 180)); public final ZLBooleanOption AutoHyphenationOption = new ZLBooleanOption(OPTIONS, "AutoHyphenation", true);