mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-05 19:42:17 +02:00
smooth scrolling
git-svn-id: https://only.mawhrin.net/repos/FBReaderJ/trunk@921 6a642e6f-84f6-412e-ac94-c4a38d5a04b0
This commit is contained in:
parent
6596404a5e
commit
f7b8cebe42
11 changed files with 477 additions and 266 deletions
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* 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;
|
||||
};
|
144
src/org/geometerplus/zlibrary/text/view/impl/ZLTextPage.java
Normal file
144
src/org/geometerplus/zlibrary/text/view/impl/ZLTextPage.java
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* 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<ZLTextLineInfo> LineInfos = new ArrayList<ZLTextLineInfo>();
|
||||
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<ZLTextLineInfo> 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);
|
||||
}
|
||||
}
|
|
@ -163,7 +163,7 @@ public final class ZLTextParagraphCursor {
|
|||
myElements.clear();
|
||||
}
|
||||
|
||||
boolean isFirst() {
|
||||
public boolean isFirst() {
|
||||
return Index == 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<ZLTextModel> 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<ZLTextLineInfo> myLineInfos = new ArrayList<ZLTextLineInfo>();
|
||||
private final HashMap<ZLTextLineInfo,ZLTextLineInfo> myLineInfoCache = new HashMap<ZLTextLineInfo,ZLTextLineInfo>();
|
||||
|
||||
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<ZLTextLineInfo> lineInfos = myLineInfos;
|
||||
final ArrayList<ZLTextLineInfo> 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<ZLTextLineInfo,ZLTextLineInfo> 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<ZLTextLineInfo> 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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue