mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-03 09:49:19 +02:00
new style selection & selection cursors
This commit is contained in:
parent
ad6faeb64f
commit
943b01dc5d
23 changed files with 696 additions and 436 deletions
|
@ -8,6 +8,7 @@
|
|||
* ComicBook plugin icon
|
||||
* Updated Armenian localisation (by Yavruhrat, Marat Yavrumyan)
|
||||
* Added Korean intro text
|
||||
* New style selection rendering
|
||||
|
||||
===== 2.4.7 (May 20, 2015) =====
|
||||
* Added Korean localisation
|
||||
|
|
|
@ -151,8 +151,17 @@ class ProcessHyperlinkAction extends FBAndroidAction {
|
|||
}
|
||||
}
|
||||
} else if (soul instanceof ZLTextWordRegionSoul) {
|
||||
DictionaryUtil.openWordInDictionary(
|
||||
BaseActivity, ((ZLTextWordRegionSoul)soul).Word, region
|
||||
DictionaryUtil.openTextInDictionary(
|
||||
BaseActivity,
|
||||
((ZLTextWordRegionSoul)soul).Word.getString(),
|
||||
true,
|
||||
region.getTop(),
|
||||
region.getBottom(),
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
BaseActivity.outlineRegion(soul);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,7 @@
|
|||
|
||||
package org.geometerplus.android.fbreader;
|
||||
|
||||
import org.geometerplus.fbreader.fbreader.FBReaderApp;
|
||||
import org.geometerplus.fbreader.fbreader.FBView;
|
||||
import org.geometerplus.fbreader.fbreader.*;
|
||||
import org.geometerplus.android.fbreader.dict.DictionaryUtil;
|
||||
|
||||
public class SelectionTranslateAction extends FBAndroidAction {
|
||||
|
@ -31,13 +30,19 @@ public class SelectionTranslateAction extends FBAndroidAction {
|
|||
@Override
|
||||
protected void run(Object ... params) {
|
||||
final FBView fbview = Reader.getTextView();
|
||||
final DictionaryHighlighting dictionaryHilite = new DictionaryHighlighting(fbview);
|
||||
DictionaryUtil.openTextInDictionary(
|
||||
BaseActivity,
|
||||
fbview.getSelectedSnippet().getText(),
|
||||
fbview.getCountOfSelectedWords() == 1,
|
||||
fbview.getSelectionStartY(),
|
||||
fbview.getSelectionEndY(),
|
||||
fbview.getSelectionSoul()
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
fbview.addHighlighting(dictionaryHilite);
|
||||
Reader.getViewWidget().repaint();
|
||||
}
|
||||
}
|
||||
);
|
||||
fbview.clearSelection();
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ import org.geometerplus.zlibrary.core.options.ZLStringOption;
|
|||
import org.geometerplus.zlibrary.core.resources.ZLResource;
|
||||
import org.geometerplus.zlibrary.core.util.XmlUtil;
|
||||
|
||||
import org.geometerplus.zlibrary.text.view.ZLTextRegion;
|
||||
import org.geometerplus.zlibrary.text.view.ZLTextWord;
|
||||
|
||||
import org.geometerplus.zlibrary.ui.android.library.ZLAndroidLibrary;
|
||||
|
@ -122,7 +121,7 @@ public abstract class DictionaryUtil {
|
|||
}
|
||||
}
|
||||
|
||||
abstract void open(String text, ZLTextRegion.Soul soulToSelect, FBReader fbreader, PopupFrameMetric frameMetrics);
|
||||
abstract void open(String text, Runnable outliner, FBReader fbreader, PopupFrameMetric frameMetrics);
|
||||
}
|
||||
|
||||
private static class PlainPackageInfo extends PackageInfo {
|
||||
|
@ -131,7 +130,7 @@ public abstract class DictionaryUtil {
|
|||
}
|
||||
|
||||
@Override
|
||||
void open(String text, ZLTextRegion.Soul soulToSelect, FBReader fbreader, PopupFrameMetric frameMetrics) {
|
||||
void open(String text, Runnable outliner, FBReader fbreader, PopupFrameMetric frameMetrics) {
|
||||
final Intent intent = getDictionaryIntent(text);
|
||||
try {
|
||||
final String id = getId();
|
||||
|
@ -167,7 +166,7 @@ public abstract class DictionaryUtil {
|
|||
}
|
||||
|
||||
@Override
|
||||
void open(String text, ZLTextRegion.Soul soulToSelect, FBReader fbreader, PopupFrameMetric frameMetrics) {
|
||||
void open(String text, Runnable outliner, FBReader fbreader, PopupFrameMetric frameMetrics) {
|
||||
final Intent intent = getDictionaryIntent(text);
|
||||
try {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||
|
@ -176,7 +175,9 @@ public abstract class DictionaryUtil {
|
|||
intent.putExtra("article.text.size.max", MAX_LENGTH_FOR_TOAST);
|
||||
fbreader.startActivityForResult(intent, FBReader.REQUEST_DICTIONARY);
|
||||
fbreader.overridePendingTransition(0, 0);
|
||||
fbreader.outlineRegion(soulToSelect);
|
||||
if (outliner != null) {
|
||||
outliner.run();
|
||||
}
|
||||
} catch (ActivityNotFoundException e) {
|
||||
fbreader.hideOutline();
|
||||
installDictionaryIfNotInstalled(fbreader, this);
|
||||
|
@ -199,7 +200,7 @@ public abstract class DictionaryUtil {
|
|||
}
|
||||
|
||||
@Override
|
||||
void open(String text, ZLTextRegion.Soul soulToSelect, FBReader fbreader, PopupFrameMetric frameMetrics) {
|
||||
void open(String text, Runnable outliner, FBReader fbreader, PopupFrameMetric frameMetrics) {
|
||||
Flyout.showTranslation(fbreader, text, frameMetrics);
|
||||
}
|
||||
}
|
||||
|
@ -455,7 +456,7 @@ public abstract class DictionaryUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static void openTextInDictionary(final FBReader fbreader, String text, boolean singleWord, int selectionTop, int selectionBottom, final ZLTextRegion.Soul soulToSelect) {
|
||||
public static void openTextInDictionary(final FBReader fbreader, String text, boolean singleWord, int selectionTop, int selectionBottom, final Runnable outliner) {
|
||||
final String textToTranslate;
|
||||
if (singleWord) {
|
||||
int start = 0;
|
||||
|
@ -478,17 +479,11 @@ public abstract class DictionaryUtil {
|
|||
final PackageInfo info = getCurrentDictionaryInfo(singleWord);
|
||||
fbreader.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
info.open(textToTranslate, soulToSelect, fbreader, frameMetrics);
|
||||
info.open(textToTranslate, outliner, fbreader, frameMetrics);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void openWordInDictionary(FBReader fbreader, ZLTextWord word, ZLTextRegion region) {
|
||||
openTextInDictionary(
|
||||
fbreader, word.toString(), true, region.getTop(), region.getBottom(), region.getSoul()
|
||||
);
|
||||
}
|
||||
|
||||
public static void installDictionaryIfNotInstalled(final Activity activity, final PackageInfo info) {
|
||||
if (PackageUtil.canBeStarted(activity, info.getDictionaryIntent("test"), false)) {
|
||||
return;
|
||||
|
|
|
@ -59,4 +59,9 @@ public final class BookmarkHighlighting extends ZLTextSimpleHighlighting {
|
|||
final HighlightingStyle bmStyle = Collection.getHighlightingStyle(Bookmark.getStyleId());
|
||||
return bmStyle != null ? bmStyle.getForegroundColor() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZLColor getOutlineColor() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2015 FBReader.ORG Limited <contact@fbreader.org>
|
||||
*
|
||||
* 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.fbreader.fbreader;
|
||||
|
||||
import org.geometerplus.zlibrary.core.util.ZLColor;
|
||||
import org.geometerplus.zlibrary.text.view.*;
|
||||
|
||||
public final class DictionaryHighlighting extends ZLTextSimpleHighlighting {
|
||||
public DictionaryHighlighting(ZLTextView view) {
|
||||
this(view, view.getSelectionHighlighting());
|
||||
}
|
||||
|
||||
private DictionaryHighlighting(ZLTextView view, ZLTextHighlighting selection) {
|
||||
super(view, selection.getStartPosition(), selection.getEndPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZLColor getBackgroundColor() {
|
||||
return View.getSelectionBackgroundColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZLColor getForegroundColor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZLColor getOutlineColor() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import org.geometerplus.zlibrary.core.filesystem.ZLResourceFile;
|
|||
import org.geometerplus.zlibrary.core.fonts.FontEntry;
|
||||
import org.geometerplus.zlibrary.core.library.ZLibrary;
|
||||
import org.geometerplus.zlibrary.core.util.ZLColor;
|
||||
import org.geometerplus.zlibrary.core.view.SelectionCursor;
|
||||
import org.geometerplus.zlibrary.core.view.ZLPaintContext;
|
||||
|
||||
import org.geometerplus.zlibrary.text.model.ZLTextModel;
|
||||
|
@ -158,10 +159,10 @@ public final class FBView extends ZLTextView {
|
|||
return true;
|
||||
}
|
||||
|
||||
final ZLTextSelectionCursor cursor = findSelectionCursor(x, y, maxSelectionDistance());
|
||||
if (cursor != ZLTextSelectionCursor.None) {
|
||||
final SelectionCursor.Which cursor = findSelectionCursor(x, y, maxSelectionDistance());
|
||||
if (cursor != null) {
|
||||
myReader.runAction(ActionCode.SELECTION_HIDE_PANEL);
|
||||
moveSelectionCursorTo(cursor, x, y, true);
|
||||
moveSelectionCursorTo(cursor, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -199,9 +200,9 @@ public final class FBView extends ZLTextView {
|
|||
return true;
|
||||
}
|
||||
|
||||
final ZLTextSelectionCursor cursor = getSelectionCursorInMovement();
|
||||
if (cursor != ZLTextSelectionCursor.None) {
|
||||
moveSelectionCursorTo(cursor, x, y, true);
|
||||
final SelectionCursor.Which cursor = getSelectionCursorInMovement();
|
||||
if (cursor != null) {
|
||||
moveSelectionCursorTo(cursor, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -229,8 +230,8 @@ public final class FBView extends ZLTextView {
|
|||
return true;
|
||||
}
|
||||
|
||||
final ZLTextSelectionCursor cursor = getSelectionCursorInMovement();
|
||||
if (cursor != ZLTextSelectionCursor.None) {
|
||||
final SelectionCursor.Which cursor = getSelectionCursorInMovement();
|
||||
if (cursor != null) {
|
||||
releaseSelectionCursor();
|
||||
return true;
|
||||
}
|
||||
|
@ -266,9 +267,9 @@ public final class FBView extends ZLTextView {
|
|||
case startSelecting:
|
||||
myReader.runAction(ActionCode.SELECTION_HIDE_PANEL);
|
||||
initSelection(x, y);
|
||||
final ZLTextSelectionCursor cursor = findSelectionCursor(x, y);
|
||||
if (cursor != ZLTextSelectionCursor.None) {
|
||||
moveSelectionCursorTo(cursor, x, y, false);
|
||||
final SelectionCursor.Which cursor = findSelectionCursor(x, y);
|
||||
if (cursor != null) {
|
||||
moveSelectionCursorTo(cursor, x, y);
|
||||
}
|
||||
return true;
|
||||
case selectSingleWord:
|
||||
|
@ -300,9 +301,9 @@ public final class FBView extends ZLTextView {
|
|||
return true;
|
||||
}
|
||||
|
||||
final ZLTextSelectionCursor cursor = getSelectionCursorInMovement();
|
||||
if (cursor != ZLTextSelectionCursor.None) {
|
||||
moveSelectionCursorTo(cursor, x, y, true);
|
||||
final SelectionCursor.Which cursor = getSelectionCursorInMovement();
|
||||
if (cursor != null) {
|
||||
moveSelectionCursorTo(cursor, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -334,8 +335,8 @@ public final class FBView extends ZLTextView {
|
|||
return true;
|
||||
}
|
||||
|
||||
final ZLTextSelectionCursor cursor = getSelectionCursorInMovement();
|
||||
if (cursor != ZLTextSelectionCursor.None) {
|
||||
final SelectionCursor.Which cursor = getSelectionCursorInMovement();
|
||||
if (cursor != null) {
|
||||
releaseSelectionCursor();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2015 FBReader.ORG Limited <contact@fbreader.org>
|
||||
*
|
||||
* 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.core.view;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import android.graphics.Rect;
|
||||
|
||||
public final class HorizontalConvexHull implements Hull {
|
||||
private final LinkedList<Rect> myRectangles = new LinkedList<Rect>();
|
||||
|
||||
public HorizontalConvexHull(Collection<Rect> rects) {
|
||||
for (Rect r : rects) {
|
||||
addRect(r);
|
||||
}
|
||||
normalize();
|
||||
}
|
||||
|
||||
private void addRect(Rect rectangle) {
|
||||
if (myRectangles.isEmpty()) {
|
||||
myRectangles.add(new Rect(rectangle));
|
||||
return;
|
||||
}
|
||||
final int top = rectangle.top;
|
||||
final int bottom = rectangle.bottom;
|
||||
for (ListIterator<Rect> iter = myRectangles.listIterator(); iter.hasNext(); ) {
|
||||
Rect r = iter.next();
|
||||
if (r.bottom <= top) {
|
||||
continue;
|
||||
}
|
||||
if (r.top >= bottom) {
|
||||
break;
|
||||
}
|
||||
if (r.top < top) {
|
||||
final Rect before = new Rect(r);
|
||||
before.bottom = top;
|
||||
r.top = top;
|
||||
iter.previous();
|
||||
iter.add(before);
|
||||
iter.next();
|
||||
}
|
||||
if (r.bottom > bottom) {
|
||||
final Rect after = new Rect(r);
|
||||
after.top = bottom;
|
||||
r.bottom = bottom;
|
||||
iter.add(after);
|
||||
}
|
||||
r.left = Math.min(r.left, rectangle.left);
|
||||
r.right = Math.max(r.right, rectangle.right);
|
||||
}
|
||||
|
||||
final Rect first = myRectangles.getFirst();
|
||||
if (top < first.top) {
|
||||
myRectangles.add(0, new Rect(rectangle.left, top, rectangle.right, Math.min(bottom, first.top)));
|
||||
}
|
||||
|
||||
final Rect last = myRectangles.getLast();
|
||||
if (bottom > last.bottom) {
|
||||
myRectangles.add(new Rect(rectangle.left, Math.max(top, last.bottom), rectangle.right, bottom));
|
||||
}
|
||||
}
|
||||
|
||||
private void normalize() {
|
||||
Rect previous = null;
|
||||
for (ListIterator<Rect> iter = myRectangles.listIterator(); iter.hasNext(); ) {
|
||||
final Rect current = iter.next();
|
||||
if (previous != null) {
|
||||
if ((previous.left == current.left) && (previous.right == current.right)) {
|
||||
previous.bottom = current.bottom;
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
if ((previous.bottom != current.top) &&
|
||||
(current.left <= previous.right) &&
|
||||
(previous.left <= current.right)) {
|
||||
iter.previous();
|
||||
iter.add(new Rect(
|
||||
Math.max(previous.left, current.left),
|
||||
previous.bottom,
|
||||
Math.min(previous.right, current.right),
|
||||
current.top
|
||||
));
|
||||
iter.next();
|
||||
}
|
||||
}
|
||||
previous = current;
|
||||
}
|
||||
}
|
||||
|
||||
public int distanceTo(int x, int y) {
|
||||
int distance = Integer.MAX_VALUE;
|
||||
for (Rect r : myRectangles) {
|
||||
final int xd = r.left > x ? r.left - x : (r.right < x ? x - r.right : 0);
|
||||
final int yd = r.top > y ? r.top - y : (r.bottom < y ? y - r.bottom : 0);
|
||||
distance = Math.min(distance, Math.max(xd, yd));
|
||||
if (distance == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
public boolean isBefore(int x, int y) {
|
||||
for (Rect r : myRectangles) {
|
||||
if (r.bottom < y || (r.top < y && r.right < x)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void draw(ZLPaintContext context, int mode) {
|
||||
if (mode == DrawMode.None) {
|
||||
return;
|
||||
}
|
||||
|
||||
final LinkedList<Rect> rectangles = new LinkedList<Rect>(myRectangles);
|
||||
while (!rectangles.isEmpty()) {
|
||||
final LinkedList<Rect> connected = new LinkedList<Rect>();
|
||||
Rect previous = null;
|
||||
for (final Iterator<Rect> iter = rectangles.iterator(); iter.hasNext(); ) {
|
||||
final Rect current = iter.next();
|
||||
if ((previous != null) &&
|
||||
((previous.left > current.right) || (current.left > previous.right))) {
|
||||
break;
|
||||
}
|
||||
iter.remove();
|
||||
connected.add(current);
|
||||
previous = current;
|
||||
}
|
||||
|
||||
final LinkedList<Integer> xList = new LinkedList<Integer>();
|
||||
final LinkedList<Integer> yList = new LinkedList<Integer>();
|
||||
int x = 0, xPrev = 0;
|
||||
|
||||
final ListIterator<Rect> iter = connected.listIterator();
|
||||
Rect r = iter.next();
|
||||
x = r.right + 2;
|
||||
xList.add(x); yList.add(r.top);
|
||||
while (iter.hasNext()) {
|
||||
xPrev = x;
|
||||
r = iter.next();
|
||||
x = r.right + 2;
|
||||
if (x != xPrev) {
|
||||
final int y = (x < xPrev) ? r.top + 2 : r.top;
|
||||
xList.add(xPrev); yList.add(y);
|
||||
xList.add(x); yList.add(y);
|
||||
}
|
||||
}
|
||||
xList.add(x); yList.add(r.bottom + 2);
|
||||
|
||||
r = iter.previous();
|
||||
x = r.left - 2;
|
||||
xList.add(x); yList.add(r.bottom + 2);
|
||||
while (iter.hasPrevious()) {
|
||||
xPrev = x;
|
||||
r = iter.previous();
|
||||
x = r.left - 2;
|
||||
if (x != xPrev) {
|
||||
final int y = (x > xPrev) ? r.bottom : r.bottom + 2;
|
||||
xList.add(xPrev); yList.add(y);
|
||||
xList.add(x); yList.add(y);
|
||||
}
|
||||
}
|
||||
xList.add(x); yList.add(r.top);
|
||||
|
||||
final int xs[] = new int[xList.size()];
|
||||
final int ys[] = new int[yList.size()];
|
||||
int count = 0;
|
||||
for (int xx : xList) {
|
||||
xs[count++] = xx;
|
||||
}
|
||||
count = 0;
|
||||
for (int yy : yList) {
|
||||
ys[count++] = yy;
|
||||
}
|
||||
|
||||
if ((mode & DrawMode.Fill) == DrawMode.Fill) {
|
||||
context.fillPolygon(xs, ys);
|
||||
}
|
||||
if ((mode & DrawMode.Outline) == DrawMode.Outline) {
|
||||
context.drawOutline(xs, ys);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
src/org/geometerplus/zlibrary/core/view/Hull.java
Normal file
32
src/org/geometerplus/zlibrary/core/view/Hull.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2015 FBReader.ORG Limited <contact@fbreader.org>
|
||||
*
|
||||
* 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.core.view;
|
||||
|
||||
public interface Hull {
|
||||
interface DrawMode {
|
||||
int None = 0;
|
||||
int Outline = 1;
|
||||
int Fill = 2;
|
||||
};
|
||||
|
||||
void draw(ZLPaintContext context, int mode);
|
||||
int distanceTo(int x, int y);
|
||||
boolean isBefore(int x, int y);
|
||||
}
|
|
@ -17,40 +17,27 @@
|
|||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.zlibrary.text.view;
|
||||
package org.geometerplus.zlibrary.core.view;
|
||||
|
||||
import org.geometerplus.zlibrary.core.library.ZLibrary;
|
||||
import org.geometerplus.zlibrary.core.util.ZLColor;
|
||||
|
||||
public enum ZLTextSelectionCursor {
|
||||
None,
|
||||
Left,
|
||||
Right;
|
||||
public abstract class SelectionCursor {
|
||||
public enum Which {
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
private static int ourHeight;
|
||||
private static int ourWidth;
|
||||
private static int ourAccent;
|
||||
|
||||
private static void init() {
|
||||
if (ourHeight == 0) {
|
||||
final int dpi = ZLibrary.Instance().getDisplayDPI();
|
||||
ourAccent = dpi / 12;
|
||||
ourWidth = dpi / 6;
|
||||
ourHeight = dpi / 4;
|
||||
public static void draw(ZLPaintContext context, Which which, int x, int y, ZLColor color) {
|
||||
context.setFillColor(color);
|
||||
final int dpi = ZLibrary.Instance().getDisplayDPI();
|
||||
final int unit = dpi / 120;
|
||||
final int xCenter = which == Which.Left ? x - unit - 1 : x + unit + 1;
|
||||
context.fillRectangle(xCenter - unit, y + dpi / 8, xCenter + unit, y - dpi / 8);
|
||||
if (which == Which.Left) {
|
||||
context.fillCircle(xCenter, y - dpi / 8, unit * 6);
|
||||
} else {
|
||||
context.fillCircle(xCenter, y + dpi / 8, unit * 6);
|
||||
}
|
||||
}
|
||||
|
||||
static int getHeight() {
|
||||
init();
|
||||
return ourHeight;
|
||||
}
|
||||
|
||||
static int getWidth() {
|
||||
init();
|
||||
return ourWidth;
|
||||
}
|
||||
|
||||
static int getAccent() {
|
||||
init();
|
||||
return ourAccent;
|
||||
}
|
||||
}
|
53
src/org/geometerplus/zlibrary/core/view/UnionHull.java
Normal file
53
src/org/geometerplus/zlibrary/core/view/UnionHull.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2015 FBReader.ORG Limited <contact@fbreader.org>
|
||||
*
|
||||
* 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.core.view;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class UnionHull implements Hull {
|
||||
private final List<Hull> myComponents;
|
||||
|
||||
public UnionHull(Hull ... components) {
|
||||
myComponents = new ArrayList<Hull>(Arrays.asList(components));
|
||||
}
|
||||
|
||||
public void draw(ZLPaintContext context, int mode) {
|
||||
for (Hull h : myComponents) {
|
||||
h.draw(context, mode);
|
||||
}
|
||||
}
|
||||
|
||||
public int distanceTo(int x, int y) {
|
||||
int dist = Integer.MAX_VALUE;
|
||||
for (Hull h : myComponents) {
|
||||
dist = Math.min(dist, h.distanceTo(x, y));
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
public boolean isBefore(int x, int y) {
|
||||
for (Hull h : myComponents) {
|
||||
if (h.isBefore(x, y)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
55
src/org/geometerplus/zlibrary/text/view/HullUtil.java
Normal file
55
src/org/geometerplus/zlibrary/text/view/HullUtil.java
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2015 FBReader.ORG Limited <contact@fbreader.org>
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import android.graphics.Rect;
|
||||
|
||||
import org.geometerplus.zlibrary.core.view.*;
|
||||
|
||||
abstract class HullUtil {
|
||||
static Hull hull(ZLTextElementArea[] areas) {
|
||||
return hull(Arrays.asList(areas));
|
||||
}
|
||||
|
||||
static Hull hull(List<ZLTextElementArea> areas) {
|
||||
final List<Rect> rectangles0 = new ArrayList<Rect>(areas.size());
|
||||
final List<Rect> rectangles1 = new ArrayList<Rect>(areas.size());
|
||||
for (ZLTextElementArea a : areas) {
|
||||
final Rect rect = new Rect(a.XStart, a.YStart, a.XEnd, a.YEnd);
|
||||
if (a.ColumnIndex == 0) {
|
||||
rectangles0.add(rect);
|
||||
} else {
|
||||
rectangles1.add(rect);
|
||||
}
|
||||
}
|
||||
if (rectangles0.isEmpty()) {
|
||||
return new HorizontalConvexHull(rectangles1);
|
||||
} else if (rectangles1.isEmpty()) {
|
||||
return new HorizontalConvexHull(rectangles0);
|
||||
} else {
|
||||
return new UnionHull(
|
||||
new HorizontalConvexHull(rectangles0),
|
||||
new HorizontalConvexHull(rectangles1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ public final class ZLTextElementArea extends ZLTextFixedPosition {
|
|||
public final int XEnd;
|
||||
public final int YStart;
|
||||
public final int YEnd;
|
||||
public final int ColumnIndex;
|
||||
|
||||
final int Length;
|
||||
final boolean AddHyphenationSign;
|
||||
|
@ -33,13 +34,14 @@ public final class ZLTextElementArea extends ZLTextFixedPosition {
|
|||
|
||||
private final boolean myIsLastInElement;
|
||||
|
||||
ZLTextElementArea(int paragraphIndex, int elementIndex, int charIndex, int length, boolean lastInElement, boolean addHyphenationSign, boolean changeStyle, ZLTextStyle style, ZLTextElement element, int xStart, int xEnd, int yStart, int yEnd) {
|
||||
ZLTextElementArea(int paragraphIndex, int elementIndex, int charIndex, int length, boolean lastInElement, boolean addHyphenationSign, boolean changeStyle, ZLTextStyle style, ZLTextElement element, int xStart, int xEnd, int yStart, int yEnd, int columnIndex) {
|
||||
super(paragraphIndex, elementIndex, charIndex);
|
||||
|
||||
XStart = xStart;
|
||||
XEnd = xEnd;
|
||||
YStart = yStart;
|
||||
YEnd = yEnd;
|
||||
ColumnIndex = columnIndex;
|
||||
|
||||
Length = length;
|
||||
myIsLastInElement = lastInElement;
|
||||
|
|
|
@ -38,9 +38,10 @@ final class ZLTextElementAreaVector {
|
|||
return myAreas.size();
|
||||
}
|
||||
|
||||
// TODO: remove this unsafe method
|
||||
public ZLTextElementArea get(int index) {
|
||||
return myAreas.get(index);
|
||||
public List<ZLTextElementArea> areas() {
|
||||
synchronized (myAreas) {
|
||||
return new ArrayList<ZLTextElementArea>(myAreas);
|
||||
}
|
||||
}
|
||||
|
||||
public ZLTextElementArea getFirstArea() {
|
||||
|
@ -168,6 +169,28 @@ final class ZLTextElementAreaVector {
|
|||
return bestRegion;
|
||||
}
|
||||
|
||||
static class RegionPair {
|
||||
ZLTextRegion Before;
|
||||
ZLTextRegion After;
|
||||
}
|
||||
|
||||
RegionPair findRegionsPair(int x, int y, int columnIndex, ZLTextRegion.Filter filter) {
|
||||
RegionPair pair = new RegionPair();
|
||||
synchronized (myElementRegions) {
|
||||
for (ZLTextRegion region : myElementRegions) {
|
||||
if (filter.accepts(region)) {
|
||||
if (region.isBefore(x, y, columnIndex)) {
|
||||
pair.Before = region;
|
||||
} else {
|
||||
pair.After = region;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pair;
|
||||
}
|
||||
|
||||
protected ZLTextRegion nextRegion(ZLTextRegion currentRegion, ZLTextView.Direction direction, ZLTextRegion.Filter filter) {
|
||||
synchronized (myElementRegions) {
|
||||
if (myElementRegions.isEmpty()) {
|
||||
|
|
|
@ -19,7 +19,10 @@
|
|||
|
||||
package org.geometerplus.zlibrary.text.view;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.geometerplus.zlibrary.core.util.ZLColor;
|
||||
import org.geometerplus.zlibrary.core.view.Hull;
|
||||
|
||||
public abstract class ZLTextHighlighting implements Comparable<ZLTextHighlighting> {
|
||||
public abstract boolean isEmpty();
|
||||
|
@ -31,6 +34,7 @@ public abstract class ZLTextHighlighting implements Comparable<ZLTextHighlightin
|
|||
|
||||
public abstract ZLColor getForegroundColor();
|
||||
public abstract ZLColor getBackgroundColor();
|
||||
public abstract ZLColor getOutlineColor();
|
||||
|
||||
boolean intersects(ZLTextPage page) {
|
||||
return
|
||||
|
@ -48,6 +52,24 @@ public abstract class ZLTextHighlighting implements Comparable<ZLTextHighlightin
|
|||
soul.compareTo(getEndPosition()) <= 0;
|
||||
}
|
||||
|
||||
final Hull hull(ZLTextPage page) {
|
||||
final ZLTextPosition startPosition = getStartPosition();
|
||||
final ZLTextPosition endPosition = getEndPosition();
|
||||
final List<ZLTextElementArea> areas = page.TextElementMap.areas();
|
||||
int startIndex = 0;
|
||||
int endIndex = 0;
|
||||
for (int i = 0; i < areas.size(); ++i) {
|
||||
final ZLTextElementArea a = areas.get(i);
|
||||
if (i == startIndex && startPosition.compareTo(a) > 0) {
|
||||
++startIndex;
|
||||
} else if (endPosition.compareTo(a) < 0) {
|
||||
break;
|
||||
}
|
||||
++endIndex;
|
||||
}
|
||||
return HullUtil.hull(areas.subList(startIndex, endIndex));
|
||||
}
|
||||
|
||||
public int compareTo(ZLTextHighlighting highlighting) {
|
||||
final int cmp = getStartPosition().compareTo(highlighting.getStartPosition());
|
||||
return cmp != 0 ? cmp : getEndPosition().compareTo(highlighting.getEndPosition());
|
||||
|
|
|
@ -1,205 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2015 FBReader.ORG Limited <contact@fbreader.org>
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.geometerplus.zlibrary.core.view.ZLPaintContext;
|
||||
|
||||
class ZLTextHorizontalConvexHull {
|
||||
private final LinkedList<Rectangle> myRectangles = new LinkedList<Rectangle>();
|
||||
|
||||
ZLTextHorizontalConvexHull(ZLTextElementArea[] textAreas) {
|
||||
for (ZLTextElementArea area : textAreas) {
|
||||
addArea(area);
|
||||
}
|
||||
normalize();
|
||||
}
|
||||
|
||||
private void addArea(ZLTextElementArea area) {
|
||||
if (myRectangles.isEmpty()) {
|
||||
myRectangles.add(new Rectangle(area.XStart, area.XEnd, area.YStart, area.YEnd));
|
||||
return;
|
||||
}
|
||||
final int top = area.YStart;
|
||||
final int bottom = area.YEnd;
|
||||
for (ListIterator<Rectangle> iter = myRectangles.listIterator(); iter.hasNext(); ) {
|
||||
Rectangle r = iter.next();
|
||||
if (r.Bottom <= top) {
|
||||
continue;
|
||||
}
|
||||
if (r.Top >= bottom) {
|
||||
break;
|
||||
}
|
||||
if (r.Top < top) {
|
||||
final Rectangle before = new Rectangle(r);
|
||||
before.Bottom = top;
|
||||
r.Top = top;
|
||||
iter.previous();
|
||||
iter.add(before);
|
||||
iter.next();
|
||||
}
|
||||
if (r.Bottom > bottom) {
|
||||
final Rectangle after = new Rectangle(r);
|
||||
after.Top = bottom;
|
||||
r.Bottom = bottom;
|
||||
iter.add(after);
|
||||
}
|
||||
r.Left = Math.min(r.Left, area.XStart);
|
||||
r.Right = Math.max(r.Right, area.XEnd);
|
||||
}
|
||||
|
||||
final Rectangle first = myRectangles.getFirst();
|
||||
if (top < first.Top) {
|
||||
myRectangles.add(0, new Rectangle(area.XStart, area.XEnd, top, Math.min(bottom, first.Top)));
|
||||
}
|
||||
|
||||
final Rectangle last = myRectangles.getLast();
|
||||
if (bottom > last.Bottom) {
|
||||
myRectangles.add(new Rectangle(area.XStart, area.XEnd, Math.max(top, last.Bottom), bottom));
|
||||
}
|
||||
}
|
||||
|
||||
private void normalize() {
|
||||
Rectangle previous = null;
|
||||
for (ListIterator<Rectangle> iter = myRectangles.listIterator(); iter.hasNext(); ) {
|
||||
final Rectangle current = iter.next();
|
||||
if (previous != null) {
|
||||
if ((previous.Left == current.Left) && (previous.Right == current.Right)) {
|
||||
previous.Bottom = current.Bottom;
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
if ((previous.Bottom != current.Top) &&
|
||||
(current.Left <= previous.Right) &&
|
||||
(previous.Left <= current.Right)) {
|
||||
iter.previous();
|
||||
iter.add(new Rectangle(
|
||||
Math.max(previous.Left, current.Left),
|
||||
Math.min(previous.Right, current.Right),
|
||||
previous.Bottom,
|
||||
current.Top
|
||||
));
|
||||
iter.next();
|
||||
}
|
||||
}
|
||||
previous = current;
|
||||
}
|
||||
}
|
||||
|
||||
int distanceTo(int x, int y) {
|
||||
int distance = Integer.MAX_VALUE;
|
||||
for (Rectangle r : myRectangles) {
|
||||
final int xd = (r.Left > x) ? r.Left - x : ((r.Right < x) ? x - r.Right : 0);
|
||||
final int yd = (r.Top > y) ? r.Top - y : ((r.Bottom < y) ? y - r.Bottom : 0);
|
||||
distance = Math.min(distance, Math.max(xd, yd));
|
||||
if (distance == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
void draw(ZLPaintContext context) {
|
||||
final LinkedList<Rectangle> rectangles = new LinkedList<Rectangle>(myRectangles);
|
||||
while (!rectangles.isEmpty()) {
|
||||
final LinkedList<Rectangle> connected = new LinkedList<Rectangle>();
|
||||
Rectangle previous = null;
|
||||
for (final Iterator<Rectangle> iter = rectangles.iterator(); iter.hasNext(); ) {
|
||||
final Rectangle current = iter.next();
|
||||
if ((previous != null) &&
|
||||
((previous.Left > current.Right) || (current.Left > previous.Right))) {
|
||||
break;
|
||||
}
|
||||
iter.remove();
|
||||
connected.add(current);
|
||||
previous = current;
|
||||
}
|
||||
|
||||
final LinkedList<Integer> xList = new LinkedList<Integer>();
|
||||
final LinkedList<Integer> yList = new LinkedList<Integer>();
|
||||
int x = 0, xPrev = 0;
|
||||
|
||||
final ListIterator<Rectangle> iter = connected.listIterator();
|
||||
Rectangle r = iter.next();
|
||||
x = r.Right + 2;
|
||||
xList.add(x); yList.add(r.Top);
|
||||
while (iter.hasNext()) {
|
||||
xPrev = x;
|
||||
r = iter.next();
|
||||
x = r.Right + 2;
|
||||
if (x != xPrev) {
|
||||
final int y = (x < xPrev) ? r.Top + 2 : r.Top;
|
||||
xList.add(xPrev); yList.add(y);
|
||||
xList.add(x); yList.add(y);
|
||||
}
|
||||
}
|
||||
xList.add(x); yList.add(r.Bottom + 2);
|
||||
|
||||
r = iter.previous();
|
||||
x = r.Left - 2;
|
||||
xList.add(x); yList.add(r.Bottom + 2);
|
||||
while (iter.hasPrevious()) {
|
||||
xPrev = x;
|
||||
r = iter.previous();
|
||||
x = r.Left - 2;
|
||||
if (x != xPrev) {
|
||||
final int y = (x > xPrev) ? r.Bottom : r.Bottom + 2;
|
||||
xList.add(xPrev); yList.add(y);
|
||||
xList.add(x); yList.add(y);
|
||||
}
|
||||
}
|
||||
xList.add(x); yList.add(r.Top);
|
||||
|
||||
final int xs[] = new int[xList.size()];
|
||||
final int ys[] = new int[yList.size()];
|
||||
int count = 0;
|
||||
for (int xx : xList) {
|
||||
xs[count++] = xx;
|
||||
}
|
||||
count = 0;
|
||||
for (int yy : yList) {
|
||||
ys[count++] = yy;
|
||||
}
|
||||
context.drawOutline(xs, ys);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Rectangle {
|
||||
int Left;
|
||||
int Right;
|
||||
int Top;
|
||||
int Bottom;
|
||||
|
||||
Rectangle(int left, int right, int top, int bottom) {
|
||||
Left = left;
|
||||
Right = right;
|
||||
Top = top;
|
||||
Bottom = bottom;
|
||||
}
|
||||
|
||||
Rectangle(Rectangle orig) {
|
||||
Left = orig.Left;
|
||||
Right = orig.Right;
|
||||
Top = orig.Top;
|
||||
Bottom = orig.Bottom;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,4 +35,9 @@ class ZLTextManualHighlighting extends ZLTextSimpleHighlighting {
|
|||
public ZLColor getForegroundColor() {
|
||||
return View.getHighlightingForegroundColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZLColor getOutlineColor() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.geometerplus.zlibrary.text.view;
|
|||
|
||||
import java.util.*;
|
||||
|
||||
import org.geometerplus.zlibrary.core.view.Hull;
|
||||
import org.geometerplus.zlibrary.core.view.ZLPaintContext;
|
||||
|
||||
public final class ZLTextRegion {
|
||||
|
@ -139,7 +140,8 @@ public final class ZLTextRegion {
|
|||
private ZLTextElementArea[] myAreas;
|
||||
private final int myFromIndex;
|
||||
private int myToIndex;
|
||||
private ZLTextHorizontalConvexHull myHull;
|
||||
private Hull myHull;
|
||||
private Hull myHull0; // convex hull for left page column
|
||||
|
||||
ZLTextRegion(Soul soul, List<ZLTextElementArea> list, int fromIndex) {
|
||||
mySoul = soul;
|
||||
|
@ -157,7 +159,7 @@ public final class ZLTextRegion {
|
|||
return mySoul;
|
||||
}
|
||||
|
||||
private ZLTextElementArea[] textAreas() {
|
||||
ZLTextElementArea[] textAreas() {
|
||||
if (myAreas == null || myAreas.length != myToIndex - myFromIndex) {
|
||||
synchronized (myAreaList) {
|
||||
myAreas = new ZLTextElementArea[myToIndex - myFromIndex];
|
||||
|
@ -168,12 +170,24 @@ public final class ZLTextRegion {
|
|||
}
|
||||
return myAreas;
|
||||
}
|
||||
private ZLTextHorizontalConvexHull convexHull() {
|
||||
Hull hull() {
|
||||
if (myHull == null) {
|
||||
myHull = new ZLTextHorizontalConvexHull(textAreas());
|
||||
myHull = HullUtil.hull(textAreas());
|
||||
}
|
||||
return myHull;
|
||||
}
|
||||
Hull hull0() {
|
||||
if (myHull0 == null) {
|
||||
final List<ZLTextElementArea> column0 = new ArrayList<ZLTextElementArea>();
|
||||
for (ZLTextElementArea a : textAreas()) {
|
||||
if (a.ColumnIndex == 0) {
|
||||
column0.add(a);
|
||||
}
|
||||
}
|
||||
myHull0 = HullUtil.hull(column0);
|
||||
}
|
||||
return myHull0;
|
||||
}
|
||||
|
||||
ZLTextElementArea getFirstArea() {
|
||||
return textAreas()[0];
|
||||
|
@ -208,12 +222,42 @@ public final class ZLTextRegion {
|
|||
return getLastArea().YEnd;
|
||||
}
|
||||
|
||||
void draw(ZLPaintContext context) {
|
||||
convexHull().draw(context);
|
||||
int distanceTo(int x, int y) {
|
||||
return hull().distanceTo(x, y);
|
||||
}
|
||||
|
||||
int distanceTo(int x, int y) {
|
||||
return convexHull().distanceTo(x, y);
|
||||
boolean isBefore(int x, int y, int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
default:
|
||||
case -1:
|
||||
return hull().isBefore(x, y);
|
||||
case 0:
|
||||
{
|
||||
int count0 = 0;
|
||||
int count1 = 0;
|
||||
for (ZLTextElementArea area : textAreas()) {
|
||||
if (area.ColumnIndex == 0) {
|
||||
++count0;
|
||||
} else {
|
||||
++count1;
|
||||
}
|
||||
}
|
||||
if (count0 == 0) {
|
||||
return false;
|
||||
} else if (count1 == 0) {
|
||||
return hull().isBefore(x, y);
|
||||
} else {
|
||||
return hull0().isBefore(x, y);
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
for (ZLTextElementArea area : textAreas()) {
|
||||
if (area.ColumnIndex == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return hull().isBefore(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isAtRightOf(ZLTextRegion other) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.geometerplus.zlibrary.text.view;
|
||||
|
||||
import org.geometerplus.zlibrary.core.util.ZLColor;
|
||||
import org.geometerplus.zlibrary.core.view.SelectionCursor;
|
||||
|
||||
class ZLTextSelection extends ZLTextHighlighting {
|
||||
static class Point {
|
||||
|
@ -37,7 +38,7 @@ class ZLTextSelection extends ZLTextHighlighting {
|
|||
private ZLTextRegion.Soul myLeftMostRegionSoul;
|
||||
private ZLTextRegion.Soul myRightMostRegionSoul;
|
||||
|
||||
private ZLTextSelectionCursor myCursorInMovement = ZLTextSelectionCursor.None;
|
||||
private SelectionCursor.Which myCursorInMovement = null;
|
||||
private final Point myCursorInMovementPoint = new Point(-1, -1);
|
||||
|
||||
private Scroller myScroller;
|
||||
|
@ -46,10 +47,6 @@ class ZLTextSelection extends ZLTextHighlighting {
|
|||
myView = view;
|
||||
}
|
||||
|
||||
ZLTextRegion.Soul getSoul() {
|
||||
return myLeftMostRegionSoul != null && myLeftMostRegionSoul.equals(myRightMostRegionSoul) ? myLeftMostRegionSoul : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return myLeftMostRegionSoul == null;
|
||||
|
@ -63,17 +60,17 @@ class ZLTextSelection extends ZLTextHighlighting {
|
|||
stop();
|
||||
myLeftMostRegionSoul = null;
|
||||
myRightMostRegionSoul = null;
|
||||
myCursorInMovement = ZLTextSelectionCursor.None;
|
||||
myCursorInMovement = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
void setCursorInMovement(ZLTextSelectionCursor cursor, int x, int y) {
|
||||
myCursorInMovement = cursor;
|
||||
void setCursorInMovement(SelectionCursor.Which which, int x, int y) {
|
||||
myCursorInMovement = which;
|
||||
myCursorInMovementPoint.X = x;
|
||||
myCursorInMovementPoint.Y = y;
|
||||
}
|
||||
|
||||
ZLTextSelectionCursor getCursorInMovement() {
|
||||
SelectionCursor.Which getCursorInMovement() {
|
||||
return myCursorInMovement;
|
||||
}
|
||||
|
||||
|
@ -96,7 +93,7 @@ class ZLTextSelection extends ZLTextHighlighting {
|
|||
}
|
||||
|
||||
void stop() {
|
||||
myCursorInMovement = ZLTextSelectionCursor.None;
|
||||
myCursorInMovement = null;
|
||||
if (myScroller != null) {
|
||||
myScroller.stop();
|
||||
myScroller = null;
|
||||
|
@ -120,7 +117,8 @@ class ZLTextSelection extends ZLTextHighlighting {
|
|||
myScroller = new Scroller(page, false, x, y);
|
||||
return;
|
||||
}
|
||||
} else if (lastArea != null && y + ZLTextSelectionCursor.getHeight() / 2 + ZLTextSelectionCursor.getAccent() / 2 > lastArea.YEnd) {
|
||||
//} else if (lastArea != null && y + ZLTextSelectionCursor.getHeight() / 2 + ZLTextSelectionCursor.getAccent() / 2 > lastArea.YEnd) {
|
||||
} else if (lastArea != null && y > lastArea.YEnd) {
|
||||
if (myScroller != null && !myScroller.scrollsForward()) {
|
||||
myScroller.stop();
|
||||
myScroller = null;
|
||||
|
@ -141,21 +139,40 @@ class ZLTextSelection extends ZLTextHighlighting {
|
|||
}
|
||||
|
||||
ZLTextRegion region = myView.findRegion(x, y, myView.maxSelectionDistance(), ZLTextRegion.AnyRegionFilter);
|
||||
if (region == null && myScroller != null) {
|
||||
region = myView.findRegion(x, y, ZLTextRegion.AnyRegionFilter);
|
||||
if (region == null) {
|
||||
final ZLTextElementAreaVector.RegionPair pair =
|
||||
myView.findRegionsPair(x, y, ZLTextRegion.AnyRegionFilter);
|
||||
if (pair.Before != null || pair.After != null) {
|
||||
final ZLTextRegion.Soul base =
|
||||
myCursorInMovement == SelectionCursor.Which.Right
|
||||
? myLeftMostRegionSoul : myRightMostRegionSoul;
|
||||
if (pair.Before != null) {
|
||||
if (base.compareTo(pair.Before.getSoul()) <= 0) {
|
||||
region = pair.Before;
|
||||
} else {
|
||||
region = pair.After;
|
||||
}
|
||||
} else {
|
||||
if (base.compareTo(pair.After.getSoul()) >= 0) {
|
||||
region = pair.After;
|
||||
} else {
|
||||
region = pair.Before;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (region == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ZLTextRegion.Soul soul = region.getSoul();
|
||||
if (myCursorInMovement == ZLTextSelectionCursor.Right) {
|
||||
if (myCursorInMovement == SelectionCursor.Which.Right) {
|
||||
if (myLeftMostRegionSoul.compareTo(soul) <= 0) {
|
||||
myRightMostRegionSoul = soul;
|
||||
} else {
|
||||
myRightMostRegionSoul = myLeftMostRegionSoul;
|
||||
myLeftMostRegionSoul = soul;
|
||||
myCursorInMovement = ZLTextSelectionCursor.Left;
|
||||
myCursorInMovement = SelectionCursor.Which.Left;
|
||||
}
|
||||
} else {
|
||||
if (myRightMostRegionSoul.compareTo(soul) >= 0) {
|
||||
|
@ -163,11 +180,11 @@ class ZLTextSelection extends ZLTextHighlighting {
|
|||
} else {
|
||||
myLeftMostRegionSoul = myRightMostRegionSoul;
|
||||
myRightMostRegionSoul = soul;
|
||||
myCursorInMovement = ZLTextSelectionCursor.Right;
|
||||
myCursorInMovement = SelectionCursor.Which.Right;
|
||||
}
|
||||
}
|
||||
|
||||
if (myCursorInMovement == ZLTextSelectionCursor.Right) {
|
||||
if (myCursorInMovement == SelectionCursor.Which.Right) {
|
||||
if (hasPartAfterPage(page)) {
|
||||
myView.turnPage(true, ZLTextView.ScrollingMode.SCROLL_LINES, 1);
|
||||
myView.Application.getViewWidget().reset();
|
||||
|
@ -276,6 +293,11 @@ class ZLTextSelection extends ZLTextHighlighting {
|
|||
return myView.getSelectionForegroundColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZLColor getOutlineColor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private class Scroller implements Runnable {
|
||||
private final ZLTextPage myPage;
|
||||
private final boolean myScrollForward;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.geometerplus.zlibrary.text.view;
|
||||
|
||||
import org.geometerplus.zlibrary.core.view.HorizontalConvexHull;
|
||||
|
||||
public abstract class ZLTextSimpleHighlighting extends ZLTextHighlighting {
|
||||
protected final ZLTextView View;
|
||||
private final ZLTextPosition myStartPosition;
|
||||
|
|
|
@ -21,13 +21,15 @@ package org.geometerplus.zlibrary.text.view;
|
|||
|
||||
import java.util.*;
|
||||
|
||||
import android.util.FloatMath;
|
||||
|
||||
import org.geometerplus.zlibrary.core.application.ZLApplication;
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
import org.geometerplus.zlibrary.core.image.ZLImageData;
|
||||
import org.geometerplus.zlibrary.core.library.ZLibrary;
|
||||
import org.geometerplus.zlibrary.core.util.RationalNumber;
|
||||
import org.geometerplus.zlibrary.core.util.ZLColor;
|
||||
import org.geometerplus.zlibrary.core.view.ZLPaintContext;
|
||||
import org.geometerplus.zlibrary.core.view.*;
|
||||
|
||||
import org.geometerplus.zlibrary.text.model.*;
|
||||
import org.geometerplus.zlibrary.text.hyphenation.*;
|
||||
|
@ -327,13 +329,9 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
}
|
||||
}
|
||||
|
||||
protected void moveSelectionCursorTo(ZLTextSelectionCursor cursor, int x, int y, boolean inMovement) {
|
||||
if (inMovement) {
|
||||
y -= ZLTextSelectionCursor.getHeight() / 2 + ZLTextSelectionCursor.getAccent() / 2;
|
||||
} else {
|
||||
y -= getTextStyleCollection().getBaseStyle().getFontSize() / 2;
|
||||
}
|
||||
mySelection.setCursorInMovement(cursor, x, y);
|
||||
protected void moveSelectionCursorTo(SelectionCursor.Which which, int x, int y) {
|
||||
y -= getTextStyleCollection().getBaseStyle().getFontSize() / 2;
|
||||
mySelection.setCursorInMovement(which, x, y);
|
||||
mySelection.expandTo(myCurrentPage, x, y);
|
||||
Application.getViewWidget().reset();
|
||||
Application.getViewWidget().repaint();
|
||||
|
@ -345,104 +343,68 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
Application.getViewWidget().repaint();
|
||||
}
|
||||
|
||||
protected ZLTextSelectionCursor getSelectionCursorInMovement() {
|
||||
protected SelectionCursor.Which getSelectionCursorInMovement() {
|
||||
return mySelection.getCursorInMovement();
|
||||
}
|
||||
|
||||
private ZLTextSelection.Point getSelectionCursorPoint(ZLTextPage page, ZLTextSelectionCursor cursor) {
|
||||
if (cursor == ZLTextSelectionCursor.None) {
|
||||
private ZLTextSelection.Point getSelectionCursorPoint(ZLTextPage page, SelectionCursor.Which which) {
|
||||
if (which == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (cursor == mySelection.getCursorInMovement()) {
|
||||
if (which == mySelection.getCursorInMovement()) {
|
||||
return mySelection.getCursorInMovementPoint();
|
||||
}
|
||||
|
||||
if (cursor == ZLTextSelectionCursor.Left) {
|
||||
if (which == SelectionCursor.Which.Left) {
|
||||
if (mySelection.hasPartBeforePage(page)) {
|
||||
return null;
|
||||
}
|
||||
final ZLTextElementArea selectionStartArea = mySelection.getStartArea(page);
|
||||
if (selectionStartArea != null) {
|
||||
return new ZLTextSelection.Point(selectionStartArea.XStart, selectionStartArea.YEnd);
|
||||
final ZLTextElementArea area = mySelection.getStartArea(page);
|
||||
if (area != null) {
|
||||
return new ZLTextSelection.Point(area.XStart, (area.YStart + area.YEnd) / 2);
|
||||
}
|
||||
} else {
|
||||
if (mySelection.hasPartAfterPage(page)) {
|
||||
return null;
|
||||
}
|
||||
final ZLTextElementArea selectionEndArea = mySelection.getEndArea(page);
|
||||
if (selectionEndArea != null) {
|
||||
return new ZLTextSelection.Point(selectionEndArea.XEnd, selectionEndArea.YEnd);
|
||||
final ZLTextElementArea area = mySelection.getEndArea(page);
|
||||
if (area != null) {
|
||||
return new ZLTextSelection.Point(area.XEnd, (area.YStart + area.YEnd) / 2);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private int distanceToCursor(int x, int y, ZLTextSelection.Point cursorPoint) {
|
||||
if (cursorPoint == null) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
final int dX, dY;
|
||||
|
||||
final int w = ZLTextSelectionCursor.getWidth() / 2;
|
||||
if (x < cursorPoint.X - w) {
|
||||
dX = cursorPoint.X - w - x;
|
||||
} else if (x > cursorPoint.X + w) {
|
||||
dX = x - cursorPoint.X - w;
|
||||
} else {
|
||||
dX = 0;
|
||||
}
|
||||
|
||||
final int h = ZLTextSelectionCursor.getHeight();
|
||||
if (y < cursorPoint.Y) {
|
||||
dY = cursorPoint.Y - y;
|
||||
} else if (y > cursorPoint.Y + h) {
|
||||
dY = y - cursorPoint.Y - h;
|
||||
} else {
|
||||
dY = 0;
|
||||
}
|
||||
|
||||
return Math.max(dX, dY);
|
||||
private float distanceToCursor(int x, int y, SelectionCursor.Which which) {
|
||||
final ZLTextSelection.Point point = getSelectionCursorPoint(myCurrentPage, which);
|
||||
return point != null ? FloatMath.hypot(x - point.X, y - point.Y) : Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
protected ZLTextSelectionCursor findSelectionCursor(int x, int y) {
|
||||
return findSelectionCursor(x, y, Integer.MAX_VALUE);
|
||||
protected SelectionCursor.Which findSelectionCursor(int x, int y) {
|
||||
return findSelectionCursor(x, y, Float.MAX_VALUE);
|
||||
}
|
||||
|
||||
protected ZLTextSelectionCursor findSelectionCursor(int x, int y, int maxDistance) {
|
||||
protected SelectionCursor.Which findSelectionCursor(int x, int y, float maxDistance) {
|
||||
if (mySelection.isEmpty()) {
|
||||
return ZLTextSelectionCursor.None;
|
||||
return null;
|
||||
}
|
||||
|
||||
final int leftDistance = distanceToCursor(
|
||||
x, y, getSelectionCursorPoint(myCurrentPage, ZLTextSelectionCursor.Left)
|
||||
);
|
||||
final int rightDistance = distanceToCursor(
|
||||
x, y, getSelectionCursorPoint(myCurrentPage, ZLTextSelectionCursor.Right)
|
||||
);
|
||||
final float leftDistance = distanceToCursor(x, y, SelectionCursor.Which.Left);
|
||||
final float rightDistance = distanceToCursor(x, y, SelectionCursor.Which.Right);
|
||||
|
||||
if (rightDistance < leftDistance) {
|
||||
return rightDistance <= maxDistance ? ZLTextSelectionCursor.Right : ZLTextSelectionCursor.None;
|
||||
return rightDistance <= maxDistance ? SelectionCursor.Which.Right : null;
|
||||
} else {
|
||||
return leftDistance <= maxDistance ? ZLTextSelectionCursor.Left : ZLTextSelectionCursor.None;
|
||||
return leftDistance <= maxDistance ? SelectionCursor.Which.Left : null;
|
||||
}
|
||||
}
|
||||
|
||||
private void drawSelectionCursor(ZLPaintContext context, ZLTextSelection.Point pt) {
|
||||
if (pt == null) {
|
||||
return;
|
||||
private void drawSelectionCursor(ZLPaintContext context, ZLTextPage page, SelectionCursor.Which which) {
|
||||
final ZLTextSelection.Point pt = getSelectionCursorPoint(page, which);
|
||||
if (pt != null) {
|
||||
SelectionCursor.draw(context, which, pt.X, pt.Y, getSelectionBackgroundColor());
|
||||
}
|
||||
|
||||
final int w = ZLTextSelectionCursor.getWidth() / 2;
|
||||
final int h = ZLTextSelectionCursor.getHeight();
|
||||
final int a = ZLTextSelectionCursor.getAccent();
|
||||
final int[] xs = { pt.X, pt.X + w, pt.X + w, pt.X - w, pt.X - w };
|
||||
final int[] ys = { pt.Y - a, pt.Y, pt.Y + h, pt.Y + h, pt.Y };
|
||||
context.setFillColor(context.getBackgroundColor(), 192);
|
||||
context.fillPolygon(xs, ys);
|
||||
context.setLineColor(getTextColor(ZLTextHyperlink.NO_LINK));
|
||||
context.drawPolygonalLine(xs, ys);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -501,34 +463,22 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
int x = getLeftMargin();
|
||||
int y = getTopMargin();
|
||||
int index = 0;
|
||||
int columnIndex = 0;
|
||||
ZLTextLineInfo previousInfo = null;
|
||||
for (ZLTextLineInfo info : lineInfos) {
|
||||
info.adjust(previousInfo);
|
||||
prepareTextLine(page, info, x, y);
|
||||
prepareTextLine(page, info, x, y, columnIndex);
|
||||
y += info.Height + info.Descent + info.VSpaceAfter;
|
||||
labels[++index] = page.TextElementMap.size();
|
||||
if (index == page.Column0Height) {
|
||||
y = getTopMargin();
|
||||
x += page.getTextWidth() + getSpaceBetweenColumns();
|
||||
columnIndex = 1;
|
||||
}
|
||||
previousInfo = info;
|
||||
}
|
||||
|
||||
final List<ZLTextHighlighting> hilites = findHilites(page);
|
||||
if (!hilites.isEmpty()) {
|
||||
x = getLeftMargin();
|
||||
y = getTopMargin();
|
||||
index = 0;
|
||||
for (ZLTextLineInfo info : lineInfos) {
|
||||
drawHighlightings(page, hilites, info, labels[index], labels[index + 1], x, y);
|
||||
y += info.Height + info.Descent + info.VSpaceAfter;
|
||||
++index;
|
||||
if (index == page.Column0Height) {
|
||||
y = getTopMargin();
|
||||
x += page.getTextWidth() + getSpaceBetweenColumns();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x = getLeftMargin();
|
||||
y = getTopMargin();
|
||||
|
@ -543,13 +493,34 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
}
|
||||
}
|
||||
|
||||
final ZLTextRegion outlinedElementRegion = getOutlinedRegion(page);
|
||||
if (outlinedElementRegion != null && myShowOutline) {
|
||||
outlinedElementRegion.draw(context);
|
||||
for (ZLTextHighlighting h : hilites) {
|
||||
int mode = Hull.DrawMode.None;
|
||||
|
||||
final ZLColor bgColor = h.getBackgroundColor();
|
||||
if (bgColor != null) {
|
||||
context.setFillColor(bgColor, 128);
|
||||
mode |= Hull.DrawMode.Fill;
|
||||
}
|
||||
|
||||
final ZLColor outlineColor = h.getOutlineColor();
|
||||
if (outlineColor != null) {
|
||||
context.setLineColor(outlineColor);
|
||||
mode |= Hull.DrawMode.Outline;
|
||||
}
|
||||
|
||||
if (mode != Hull.DrawMode.None) {
|
||||
h.hull(page).draw(getContext(), mode);
|
||||
}
|
||||
}
|
||||
|
||||
drawSelectionCursor(context, getSelectionCursorPoint(page, ZLTextSelectionCursor.Left));
|
||||
drawSelectionCursor(context, getSelectionCursorPoint(page, ZLTextSelectionCursor.Right));
|
||||
final ZLTextRegion outlinedElementRegion = getOutlinedRegion(page);
|
||||
if (outlinedElementRegion != null && myShowOutline) {
|
||||
context.setLineColor(getSelectionBackgroundColor());
|
||||
outlinedElementRegion.hull().draw(context, Hull.DrawMode.Outline);
|
||||
}
|
||||
|
||||
drawSelectionCursor(context, page, SelectionCursor.Which.Left);
|
||||
drawSelectionCursor(context, page, SelectionCursor.Which.Right);
|
||||
}
|
||||
|
||||
private ZLTextPage getPage(PageIndex pageIndex) {
|
||||
|
@ -847,45 +818,6 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
return hilites;
|
||||
}
|
||||
|
||||
private void drawHighlightings(ZLTextPage page, List<ZLTextHighlighting> hilites, ZLTextLineInfo info, int from, int to, int x, int y) {
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ZLTextElementArea fromArea = page.TextElementMap.get(from);
|
||||
final ZLTextElementArea toArea = page.TextElementMap.get(to - 1);
|
||||
for (ZLTextHighlighting h : hilites) {
|
||||
final ZLColor bgColor = h.getBackgroundColor();
|
||||
if (bgColor == null) {
|
||||
continue;
|
||||
}
|
||||
final ZLTextElementArea selectionStartArea = h.getStartArea(page);
|
||||
if (selectionStartArea == null || selectionStartArea.compareTo(toArea) > 0) {
|
||||
continue;
|
||||
}
|
||||
final ZLTextElementArea selectionEndArea = h.getEndArea(page);
|
||||
if (selectionEndArea == null || selectionEndArea.compareTo(fromArea) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int top = y + 1;
|
||||
int left, right, bottom = y + info.Height + info.Descent;
|
||||
if (selectionStartArea.compareTo(fromArea) < 0) {
|
||||
left = x;
|
||||
} else {
|
||||
left = selectionStartArea.XStart;
|
||||
}
|
||||
if (selectionEndArea.compareTo(toArea) > 0) {
|
||||
right = x + page.getTextWidth() - 1;
|
||||
bottom += info.VSpaceAfter;
|
||||
} else {
|
||||
right = selectionEndArea.XEnd;
|
||||
}
|
||||
getContext().setFillColor(bgColor);
|
||||
getContext().fillRectangle(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract ZLPaintContext.ColorAdjustingMode getAdjustingModeForImages();
|
||||
|
||||
private static final char[] SPACE = new char[] { ' ' };
|
||||
|
@ -895,9 +827,13 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
int index = from;
|
||||
final int endElementIndex = info.EndElementIndex;
|
||||
int charIndex = info.RealStartCharIndex;
|
||||
final List<ZLTextElementArea> pageAreas = page.TextElementMap.areas();
|
||||
if (to > pageAreas.size()) {
|
||||
return;
|
||||
}
|
||||
for (int wordIndex = info.RealStartElementIndex; wordIndex != endElementIndex && index < to; ++wordIndex, charIndex = 0) {
|
||||
final ZLTextElement element = paragraph.getElement(wordIndex);
|
||||
final ZLTextElementArea area = page.TextElementMap.get(index);
|
||||
final ZLTextElementArea area = pageAreas.get(index);
|
||||
if (element == area.Element) {
|
||||
++index;
|
||||
if (area.ChangeStyle) {
|
||||
|
@ -961,7 +897,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
}
|
||||
}
|
||||
if (index != to) {
|
||||
ZLTextElementArea area = page.TextElementMap.get(index++);
|
||||
ZLTextElementArea area = pageAreas.get(index++);
|
||||
if (area.ChangeStyle) {
|
||||
setTextStyle(area.Style);
|
||||
}
|
||||
|
@ -1306,7 +1242,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
return info;
|
||||
}
|
||||
|
||||
private void prepareTextLine(ZLTextPage page, ZLTextLineInfo info, int x, int y) {
|
||||
private void prepareTextLine(ZLTextPage page, ZLTextLineInfo info, int x, int y, int columnIndex) {
|
||||
y = Math.min(y + info.Height, getTopMargin() + page.getTextHeight() - 1);
|
||||
|
||||
final ZLPaintContext context = getContext();
|
||||
|
@ -1357,7 +1293,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
true, // is last in element
|
||||
false, // add hyphenation sign
|
||||
false, // changed style
|
||||
getTextStyle(), element, x, x + spaceLength, y, y
|
||||
getTextStyle(), element, x, x + spaceLength, y, y, columnIndex
|
||||
);
|
||||
} else {
|
||||
spaceElement = null;
|
||||
|
@ -1381,7 +1317,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
true, // is last in element
|
||||
false, // add hyphenation sign
|
||||
changeStyle, getTextStyle(), element,
|
||||
x, x + width - 1, y - height + 1, y + descent
|
||||
x, x + width - 1, y - height + 1, y + descent, columnIndex
|
||||
));
|
||||
changeStyle = false;
|
||||
wordOccurred = true;
|
||||
|
@ -1407,7 +1343,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
false, // is last in element
|
||||
addHyphenationSign,
|
||||
changeStyle, getTextStyle(), word,
|
||||
x, x + width - 1, y - height + 1, y + descent
|
||||
x, x + width - 1, y - height + 1, y + descent, columnIndex
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -1773,6 +1709,10 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
return myCurrentPage.TextElementMap.findRegion(x, y, maxDistance, filter);
|
||||
}
|
||||
|
||||
protected ZLTextElementAreaVector.RegionPair findRegionsPair(int x, int y, ZLTextRegion.Filter filter) {
|
||||
return myCurrentPage.TextElementMap.findRegionsPair(x, y, getColumnIndex(x), filter);
|
||||
}
|
||||
|
||||
protected boolean initSelection(int x, int y) {
|
||||
y -= getTextStyleCollection().getBaseStyle().getFontSize() / 2;
|
||||
if (!mySelection.start(x, y)) {
|
||||
|
@ -1790,8 +1730,8 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
}
|
||||
}
|
||||
|
||||
public ZLTextRegion.Soul getSelectionSoul() {
|
||||
return mySelection.getSoul();
|
||||
public ZLTextHighlighting getSelectionHighlighting() {
|
||||
return mySelection;
|
||||
}
|
||||
|
||||
public int getSelectionStartY() {
|
||||
|
|
|
@ -110,6 +110,13 @@ abstract class ZLTextViewBase extends ZLView {
|
|||
return getContextHeight() - getTopMargin() - getBottomMargin();
|
||||
}
|
||||
|
||||
protected int getColumnIndex(int x) {
|
||||
if (!twoColumnView()) {
|
||||
return -1;
|
||||
}
|
||||
return 2 * x <= getContextWidth() + getLeftMargin() - getRightMargin() ? 0 : 1;
|
||||
}
|
||||
|
||||
public int getTextColumnWidth() {
|
||||
return twoColumnView()
|
||||
? (getContextWidth() - getLeftMargin() - getSpaceBetweenColumns() - getRightMargin()) / 2
|
||||
|
|
|
@ -103,6 +103,10 @@ public final class ZLTextWord extends ZLTextElement {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getString();
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return new String(Data, Offset, Length);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue