mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-05 02:39:23 +02:00
different options for 'dictionary' and 'translator'
This commit is contained in:
parent
5df9f5fd9a
commit
48913e6404
23 changed files with 217 additions and 117 deletions
|
@ -542,6 +542,7 @@
|
||||||
<node name="dictionary" value="Slovník">
|
<node name="dictionary" value="Slovník">
|
||||||
<node name="summary" value="Nastavení slovníku"/>
|
<node name="summary" value="Nastavení slovníku"/>
|
||||||
<node name="dictionary" value="Slovník"/>
|
<node name="dictionary" value="Slovník"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="Dlouhé klepnutí">
|
<node name="tappingAction" value="Dlouhé klepnutí">
|
||||||
<node name="doNothing" value="Dlouhé klepnutí nedělá nic"/>
|
<node name="doNothing" value="Dlouhé klepnutí nedělá nic"/>
|
||||||
<node name="selectSingleWord" value="Dlouhé klepnutí vybere slovo"/>
|
<node name="selectSingleWord" value="Dlouhé klepnutí vybere slovo"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="Dictionary" toBeTranslated="true">
|
<node name="dictionary" value="Dictionary" toBeTranslated="true">
|
||||||
<node name="summary" value="Dictionary settings" toBeTranslated="true"/>
|
<node name="summary" value="Dictionary settings" toBeTranslated="true"/>
|
||||||
<node name="dictionary" value="Dictionary" toBeTranslated="true"/>
|
<node name="dictionary" value="Dictionary" toBeTranslated="true"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="Long tapping action" toBeTranslated="true">
|
<node name="tappingAction" value="Long tapping action" toBeTranslated="true">
|
||||||
<node name="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
|
<node name="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
|
||||||
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>
|
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>
|
||||||
|
|
|
@ -542,6 +542,7 @@
|
||||||
<node name="dictionary" value="Dictionary">
|
<node name="dictionary" value="Dictionary">
|
||||||
<node name="summary" value="Dictionary settings"/>
|
<node name="summary" value="Dictionary settings"/>
|
||||||
<node name="dictionary" value="Dictionary"/>
|
<node name="dictionary" value="Dictionary"/>
|
||||||
|
<node name="translator" value="Translator"/>
|
||||||
<node name="tappingAction" value="Long tapping action">
|
<node name="tappingAction" value="Long tapping action">
|
||||||
<node name="doNothing" value="Long tapping does nothing"/>
|
<node name="doNothing" value="Long tapping does nothing"/>
|
||||||
<node name="selectSingleWord" value="Long tapping selects single word"/>
|
<node name="selectSingleWord" value="Long tapping selects single word"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="Dictionnaire">
|
<node name="dictionary" value="Dictionnaire">
|
||||||
<node name="summary" value="Paramètres du dictionnaire"/>
|
<node name="summary" value="Paramètres du dictionnaire"/>
|
||||||
<node name="dictionary" value="Dictionnaire"/>
|
<node name="dictionary" value="Dictionnaire"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="Configuration de l'appui long">
|
<node name="tappingAction" value="Configuration de l'appui long">
|
||||||
<node name="doNothing" value="Un appui long ne fait rien"/>
|
<node name="doNothing" value="Un appui long ne fait rien"/>
|
||||||
<node name="selectSingleWord" value="Un appui long selectionne le mot"/>
|
<node name="selectSingleWord" value="Un appui long selectionne le mot"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="Dicionario">
|
<node name="dictionary" value="Dicionario">
|
||||||
<node name="summary" value="Preferencias do dicionario"/>
|
<node name="summary" value="Preferencias do dicionario"/>
|
||||||
<node name="dictionary" value="Dicionario"/>
|
<node name="dictionary" value="Dicionario"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="Acción de pulsación longa">
|
<node name="tappingAction" value="Acción de pulsación longa">
|
||||||
<node name="doNothing" value="Pulsación longa non fai nada"/>
|
<node name="doNothing" value="Pulsación longa non fai nada"/>
|
||||||
<node name="selectSingleWord" value="Pulsación longa selecciona a palabra"/>
|
<node name="selectSingleWord" value="Pulsación longa selecciona a palabra"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="Szótár">
|
<node name="dictionary" value="Szótár">
|
||||||
<node name="summary" value="Szótár beállításai"/>
|
<node name="summary" value="Szótár beállításai"/>
|
||||||
<node name="dictionary" value="Szótár"/>
|
<node name="dictionary" value="Szótár"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="Hosszú érintés">
|
<node name="tappingAction" value="Hosszú érintés">
|
||||||
<node name="doNothing" value="Nem történik semmi hosszú érintésre"/>
|
<node name="doNothing" value="Nem történik semmi hosszú érintésre"/>
|
||||||
<node name="selectSingleWord" value="A hosszú érintés kijelöli a szót"/>
|
<node name="selectSingleWord" value="A hosszú érintés kijelöli a szót"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="Dictionary" toBeTranslated="true">
|
<node name="dictionary" value="Dictionary" toBeTranslated="true">
|
||||||
<node name="summary" value="Dictionary settings" toBeTranslated="true"/>
|
<node name="summary" value="Dictionary settings" toBeTranslated="true"/>
|
||||||
<node name="dictionary" value="Dictionary" toBeTranslated="true"/>
|
<node name="dictionary" value="Dictionary" toBeTranslated="true"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="Long tapping action" toBeTranslated="true">
|
<node name="tappingAction" value="Long tapping action" toBeTranslated="true">
|
||||||
<node name="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
|
<node name="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
|
||||||
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>
|
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="Woordenboek">
|
<node name="dictionary" value="Woordenboek">
|
||||||
<node name="summary" value="Woordenboek instellingen"/>
|
<node name="summary" value="Woordenboek instellingen"/>
|
||||||
<node name="dictionary" value="Woordenboek"/>
|
<node name="dictionary" value="Woordenboek"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="Long tapping action" toBeTranslated="true">
|
<node name="tappingAction" value="Long tapping action" toBeTranslated="true">
|
||||||
<node name="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
|
<node name="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
|
||||||
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>
|
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="Словарь">
|
<node name="dictionary" value="Словарь">
|
||||||
<node name="summary" value="Настройки словаря"/>
|
<node name="summary" value="Настройки словаря"/>
|
||||||
<node name="dictionary" value="Словарь"/>
|
<node name="dictionary" value="Словарь"/>
|
||||||
|
<node name="translator" value="Переводчик"/>
|
||||||
<node name="tappingAction" value="Действие при долгом нажатии на экран">
|
<node name="tappingAction" value="Действие при долгом нажатии на экран">
|
||||||
<node name="doNothing" value="Ничего не делать"/>
|
<node name="doNothing" value="Ничего не делать"/>
|
||||||
<node name="selectSingleWord" value="Выделять одно слово"/>
|
<node name="selectSingleWord" value="Выделять одно слово"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="พจนานุกรม">
|
<node name="dictionary" value="พจนานุกรม">
|
||||||
<node name="summary" value="การตั้งค่าพจนานุกรม"/>
|
<node name="summary" value="การตั้งค่าพจนานุกรม"/>
|
||||||
<node name="dictionary" value="พจนานุกรม"/>
|
<node name="dictionary" value="พจนานุกรม"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="การทำงานเมื่อกดค้างที่หน้าจอ">
|
<node name="tappingAction" value="การทำงานเมื่อกดค้างที่หน้าจอ">
|
||||||
<node name="doNothing" value="ไม่มีอะไรเกิดขึ้น"/>
|
<node name="doNothing" value="ไม่มีอะไรเกิดขึ้น"/>
|
||||||
<node name="selectSingleWord" value="เลือกคำเมื่อกดค้างที่หน้าจอ"/>
|
<node name="selectSingleWord" value="เลือกคำเมื่อกดค้างที่หน้าจอ"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="Dictionary" toBeTranslated="true">
|
<node name="dictionary" value="Dictionary" toBeTranslated="true">
|
||||||
<node name="summary" value="Dictionary settings" toBeTranslated="true"/>
|
<node name="summary" value="Dictionary settings" toBeTranslated="true"/>
|
||||||
<node name="dictionary" value="Dictionary" toBeTranslated="true"/>
|
<node name="dictionary" value="Dictionary" toBeTranslated="true"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="Long tapping action" toBeTranslated="true">
|
<node name="tappingAction" value="Long tapping action" toBeTranslated="true">
|
||||||
<node name="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
|
<node name="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
|
||||||
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>
|
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="Từ điển">
|
<node name="dictionary" value="Từ điển">
|
||||||
<node name="summary" value="Cài đặt từ điển"/>
|
<node name="summary" value="Cài đặt từ điển"/>
|
||||||
<node name="dictionary" value="Từ điển"/>
|
<node name="dictionary" value="Từ điển"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="Nhấn giữ">
|
<node name="tappingAction" value="Nhấn giữ">
|
||||||
<node name="doNothing" value="Không làm gì khi nhấn giữ"/>
|
<node name="doNothing" value="Không làm gì khi nhấn giữ"/>
|
||||||
<node name="selectSingleWord" value="Chọn từ khi nhấn giữ"/>
|
<node name="selectSingleWord" value="Chọn từ khi nhấn giữ"/>
|
||||||
|
|
|
@ -528,6 +528,7 @@
|
||||||
<node name="dictionary" value="字典">
|
<node name="dictionary" value="字典">
|
||||||
<node name="summary" value="字典设定"/>
|
<node name="summary" value="字典设定"/>
|
||||||
<node name="dictionary" value="字典"/>
|
<node name="dictionary" value="字典"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="长拍触行为动作">
|
<node name="tappingAction" value="长拍触行为动作">
|
||||||
<node name="doNothing" value="长拍触不做任何动作"/>
|
<node name="doNothing" value="长拍触不做任何动作"/>
|
||||||
<node name="selectSingleWord" value="长拍触选择词语"/>
|
<node name="selectSingleWord" value="长拍触选择词语"/>
|
||||||
|
|
|
@ -547,6 +547,7 @@
|
||||||
<node name="dictionary" value="字典">
|
<node name="dictionary" value="字典">
|
||||||
<node name="summary" value="字典設定"/>
|
<node name="summary" value="字典設定"/>
|
||||||
<node name="dictionary" value="字典"/>
|
<node name="dictionary" value="字典"/>
|
||||||
|
<node name="translator" value="Translator" toBeTranslated="true"/>
|
||||||
<node name="tappingAction" value="長按動作">
|
<node name="tappingAction" value="長按動作">
|
||||||
<node name="doNothing" value="長按不做任何動作"/>
|
<node name="doNothing" value="長按不做任何動作"/>
|
||||||
<node name="selectSingleWord" value="長按選字"/>
|
<node name="selectSingleWord" value="長按選字"/>
|
||||||
|
|
|
@ -165,6 +165,17 @@ public abstract class DictionaryUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void openTextInDictionary(Activity activity, String text, boolean singleWord, int selectionTop, int selectionBottom) {
|
public static void openTextInDictionary(Activity activity, String text, boolean singleWord, int selectionTop, int selectionBottom) {
|
||||||
|
if (singleWord) {
|
||||||
|
int start = 0;
|
||||||
|
int end = text.length();
|
||||||
|
for (; start < end && !Character.isLetterOrDigit(text.charAt(start)); ++start);
|
||||||
|
for (; start < end && !Character.isLetterOrDigit(text.charAt(end - 1)); --end);
|
||||||
|
if (start == end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
text = text.substring(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
final PackageInfo info = getCurrentDictionaryInfo(singleWord);
|
final PackageInfo info = getCurrentDictionaryInfo(singleWord);
|
||||||
final Intent intent = getDictionaryIntent(info, text);
|
final Intent intent = getDictionaryIntent(info, text);
|
||||||
try {
|
try {
|
||||||
|
@ -190,17 +201,8 @@ public abstract class DictionaryUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void openWordInDictionary(Activity activity, ZLTextWord word, ZLTextRegion region) {
|
public static void openWordInDictionary(Activity activity, ZLTextWord word, ZLTextRegion region) {
|
||||||
final String text = word.toString();
|
|
||||||
int start = 0;
|
|
||||||
int end = text.length();
|
|
||||||
for (; start < end && !Character.isLetterOrDigit(text.charAt(start)); ++start);
|
|
||||||
for (; start < end && !Character.isLetterOrDigit(text.charAt(end - 1)); --end);
|
|
||||||
if (start == end) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
openTextInDictionary(
|
openTextInDictionary(
|
||||||
activity, text.substring(start, end), true, region.getTop(), region.getBottom()
|
activity, word.toString(), true, region.getTop(), region.getBottom()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,10 +69,10 @@ class SelectionPopup extends ButtonsPopupPanel {
|
||||||
final int diffTop = screenHeight - selectionEndY;
|
final int diffTop = screenHeight - selectionEndY;
|
||||||
final int diffBottom = selectionStartY;
|
final int diffBottom = selectionStartY;
|
||||||
if (diffTop > diffBottom) {
|
if (diffTop > diffBottom) {
|
||||||
verticalPosition = diffTop > myWindow.getHeight() + 10
|
verticalPosition = diffTop > myWindow.getHeight() + 20
|
||||||
? RelativeLayout.ALIGN_PARENT_BOTTOM : RelativeLayout.CENTER_VERTICAL;
|
? RelativeLayout.ALIGN_PARENT_BOTTOM : RelativeLayout.CENTER_VERTICAL;
|
||||||
} else {
|
} else {
|
||||||
verticalPosition = diffBottom > myWindow.getHeight() + 10
|
verticalPosition = diffBottom > myWindow.getHeight() + 20
|
||||||
? RelativeLayout.ALIGN_PARENT_TOP : RelativeLayout.CENTER_VERTICAL;
|
? RelativeLayout.ALIGN_PARENT_TOP : RelativeLayout.CENTER_VERTICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,13 @@ public class SelectionTranslateAction extends FBAndroidAction {
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
final FBView fbview = Reader.getTextView();
|
final FBView fbview = Reader.getTextView();
|
||||||
final int selectionStartY = fbview.getSelectionStartY(), selectionEndY = fbview.getSelectionEndY();
|
DictionaryUtil.openTextInDictionary(
|
||||||
final String text = fbview.getSelectedText();
|
BaseActivity,
|
||||||
Reader.getTextView().clearSelection();
|
fbview.getSelectedText(),
|
||||||
DictionaryUtil.openTextInDictionary(BaseActivity, text, false, selectionStartY, selectionEndY);
|
fbview.getCountOfSelectedWords() == 1,
|
||||||
|
fbview.getSelectionStartY(),
|
||||||
|
fbview.getSelectionEndY()
|
||||||
|
);
|
||||||
|
fbview.clearSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -601,17 +601,27 @@ public final class FBView extends ZLTextView {
|
||||||
@Override
|
@Override
|
||||||
protected void releaseSelectionCursor() {
|
protected void releaseSelectionCursor() {
|
||||||
super.releaseSelectionCursor();
|
super.releaseSelectionCursor();
|
||||||
myReader.doAction(ActionCode.SELECTION_SHOW_PANEL);
|
if (getCountOfSelectedWords() > 0) {
|
||||||
|
myReader.doAction(ActionCode.SELECTION_SHOW_PANEL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSelectedText() {
|
public String getSelectedText() {
|
||||||
final TextBuilderTraverser traverser = new TextBuilderTraverser(this);
|
final TextBuildTraverser traverser = new TextBuildTraverser(this);
|
||||||
if (!isSelectionEmpty()) {
|
if (!isSelectionEmpty()) {
|
||||||
traverser.traverse(getSelectionStartPosition(), getSelectionEndPosition());
|
traverser.traverse(getSelectionStartPosition(), getSelectionEndPosition());
|
||||||
}
|
}
|
||||||
return traverser.getText();
|
return traverser.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCountOfSelectedWords() {
|
||||||
|
final WordCountTraverser traverser = new WordCountTraverser(this);
|
||||||
|
if (!isSelectionEmpty()) {
|
||||||
|
traverser.traverse(getSelectionStartPosition(), getSelectionEndPosition());
|
||||||
|
}
|
||||||
|
return traverser.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
public static final int SCROLLBAR_SHOW_AS_FOOTER = 3;
|
public static final int SCROLLBAR_SHOW_AS_FOOTER = 3;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,10 +21,10 @@ package org.geometerplus.fbreader.fbreader;
|
||||||
|
|
||||||
import org.geometerplus.zlibrary.text.view.*;
|
import org.geometerplus.zlibrary.text.view.*;
|
||||||
|
|
||||||
class TextBuilderTraverser extends ZLTextTraverser {
|
class TextBuildTraverser extends ZLTextTraverser {
|
||||||
protected final StringBuilder myBuffer = new StringBuilder();
|
protected final StringBuilder myBuffer = new StringBuilder();
|
||||||
|
|
||||||
TextBuilderTraverser(ZLTextView view) {
|
TextBuildTraverser(ZLTextView view) {
|
||||||
super(view);
|
super(view);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007-2011 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.fbreader.fbreader;
|
||||||
|
|
||||||
|
import org.geometerplus.zlibrary.text.view.*;
|
||||||
|
|
||||||
|
class WordCountTraverser extends ZLTextTraverser {
|
||||||
|
protected int myCount;
|
||||||
|
|
||||||
|
WordCountTraverser(ZLTextView view) {
|
||||||
|
super(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processWord(ZLTextWord word) {
|
||||||
|
++myCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processControlElement(ZLTextControlElement control) {
|
||||||
|
// does nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processSpace() {
|
||||||
|
// does nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processEndOfParagraph() {
|
||||||
|
// does nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return myCount;
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,9 +29,9 @@ final class ZLTextElementAreaVector {
|
||||||
private ZLTextRegion myCurrentElementRegion;
|
private ZLTextRegion myCurrentElementRegion;
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
myAreas.clear();
|
|
||||||
myElementRegions.clear();
|
myElementRegions.clear();
|
||||||
myCurrentElementRegion = null;
|
myCurrentElementRegion = null;
|
||||||
|
myAreas.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
|
@ -95,9 +95,11 @@ final class ZLTextElementAreaVector {
|
||||||
if (soul == null) {
|
if (soul == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (ZLTextRegion region : myElementRegions) {
|
synchronized (myElementRegions) {
|
||||||
if (soul.equals(region.getSoul())) {
|
for (ZLTextRegion region : myElementRegions) {
|
||||||
return region;
|
if (soul.equals(region.getSoul())) {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -106,12 +108,14 @@ final class ZLTextElementAreaVector {
|
||||||
ZLTextRegion findRegion(int x, int y, int maxDistance, ZLTextRegion.Filter filter) {
|
ZLTextRegion findRegion(int x, int y, int maxDistance, ZLTextRegion.Filter filter) {
|
||||||
ZLTextRegion bestRegion = null;
|
ZLTextRegion bestRegion = null;
|
||||||
int distance = maxDistance + 1;
|
int distance = maxDistance + 1;
|
||||||
for (ZLTextRegion region : myElementRegions) {
|
synchronized (myElementRegions) {
|
||||||
if (filter.accepts(region)) {
|
for (ZLTextRegion region : myElementRegions) {
|
||||||
final int d = region.distanceTo(x, y);
|
if (filter.accepts(region)) {
|
||||||
if (d < distance) {
|
final int d = region.distanceTo(x, y);
|
||||||
bestRegion = region;
|
if (d < distance) {
|
||||||
distance = d;
|
bestRegion = region;
|
||||||
|
distance = d;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,88 +123,90 @@ final class ZLTextElementAreaVector {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ZLTextRegion nextRegion(ZLTextRegion currentRegion, ZLTextView.Direction direction, ZLTextRegion.Filter filter) {
|
protected ZLTextRegion nextRegion(ZLTextRegion currentRegion, ZLTextView.Direction direction, ZLTextRegion.Filter filter) {
|
||||||
if (myElementRegions.isEmpty()) {
|
synchronized (myElementRegions) {
|
||||||
return null;
|
if (myElementRegions.isEmpty()) {
|
||||||
}
|
return null;
|
||||||
|
|
||||||
int index = currentRegion != null ? myElementRegions.indexOf(currentRegion) : -1;
|
|
||||||
|
|
||||||
switch (direction) {
|
|
||||||
case rightToLeft:
|
|
||||||
case up:
|
|
||||||
if (index == -1) {
|
|
||||||
index = myElementRegions.size() - 1;
|
|
||||||
} else if (index == 0) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
--index;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case leftToRight:
|
|
||||||
case down:
|
|
||||||
if (index == myElementRegions.size() - 1) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (direction) {
|
|
||||||
case rightToLeft:
|
|
||||||
for (; index >= 0; --index) {
|
|
||||||
final ZLTextRegion candidate = myElementRegions.get(index);
|
|
||||||
if (filter.accepts(candidate) && candidate.isAtLeftOf(currentRegion)) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case leftToRight:
|
|
||||||
for (; index < myElementRegions.size(); ++index) {
|
|
||||||
final ZLTextRegion candidate = myElementRegions.get(index);
|
|
||||||
if (filter.accepts(candidate) && candidate.isAtRightOf(currentRegion)) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case down:
|
|
||||||
{
|
|
||||||
ZLTextRegion firstCandidate = null;
|
|
||||||
for (; index < myElementRegions.size(); ++index) {
|
|
||||||
final ZLTextRegion candidate = myElementRegions.get(index);
|
|
||||||
if (!filter.accepts(candidate)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (candidate.isExactlyUnder(currentRegion)) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
if (firstCandidate == null && candidate.isUnder(currentRegion)) {
|
|
||||||
firstCandidate = candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (firstCandidate != null) {
|
|
||||||
return firstCandidate;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case up:
|
|
||||||
ZLTextRegion firstCandidate = null;
|
int index = currentRegion != null ? myElementRegions.indexOf(currentRegion) : -1;
|
||||||
for (; index >= 0; --index) {
|
|
||||||
final ZLTextRegion candidate = myElementRegions.get(index);
|
switch (direction) {
|
||||||
if (!filter.accepts(candidate)) {
|
case rightToLeft:
|
||||||
continue;
|
case up:
|
||||||
|
if (index == -1) {
|
||||||
|
index = myElementRegions.size() - 1;
|
||||||
|
} else if (index == 0) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
--index;
|
||||||
}
|
}
|
||||||
if (candidate.isExactlyOver(currentRegion)) {
|
break;
|
||||||
return candidate;
|
case leftToRight:
|
||||||
|
case down:
|
||||||
|
if (index == myElementRegions.size() - 1) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
++index;
|
||||||
}
|
}
|
||||||
if (firstCandidate == null && candidate.isOver(currentRegion)) {
|
break;
|
||||||
firstCandidate = candidate;
|
}
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case rightToLeft:
|
||||||
|
for (; index >= 0; --index) {
|
||||||
|
final ZLTextRegion candidate = myElementRegions.get(index);
|
||||||
|
if (filter.accepts(candidate) && candidate.isAtLeftOf(currentRegion)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case leftToRight:
|
||||||
|
for (; index < myElementRegions.size(); ++index) {
|
||||||
|
final ZLTextRegion candidate = myElementRegions.get(index);
|
||||||
|
if (filter.accepts(candidate) && candidate.isAtRightOf(currentRegion)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case down:
|
||||||
|
{
|
||||||
|
ZLTextRegion firstCandidate = null;
|
||||||
|
for (; index < myElementRegions.size(); ++index) {
|
||||||
|
final ZLTextRegion candidate = myElementRegions.get(index);
|
||||||
|
if (!filter.accepts(candidate)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (candidate.isExactlyUnder(currentRegion)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
if (firstCandidate == null && candidate.isUnder(currentRegion)) {
|
||||||
|
firstCandidate = candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (firstCandidate != null) {
|
||||||
|
return firstCandidate;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (firstCandidate != null) {
|
case up:
|
||||||
return firstCandidate;
|
ZLTextRegion firstCandidate = null;
|
||||||
}
|
for (; index >= 0; --index) {
|
||||||
break;
|
final ZLTextRegion candidate = myElementRegions.get(index);
|
||||||
|
if (!filter.accepts(candidate)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (candidate.isExactlyOver(currentRegion)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
if (firstCandidate == null && candidate.isOver(currentRegion)) {
|
||||||
|
firstCandidate = candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (firstCandidate != null) {
|
||||||
|
return firstCandidate;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import org.geometerplus.zlibrary.core.view.ZLPaintContext;
|
||||||
class ZLTextHorizontalConvexHull {
|
class ZLTextHorizontalConvexHull {
|
||||||
private final LinkedList<Rectangle> myRectangles = new LinkedList<Rectangle>();
|
private final LinkedList<Rectangle> myRectangles = new LinkedList<Rectangle>();
|
||||||
|
|
||||||
ZLTextHorizontalConvexHull(List<ZLTextElementArea> textAreas) {
|
ZLTextHorizontalConvexHull(ZLTextElementArea[] textAreas) {
|
||||||
for (ZLTextElementArea area : textAreas) {
|
for (ZLTextElementArea area : textAreas) {
|
||||||
addArea(area);
|
addArea(area);
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,14 +107,16 @@ public final class ZLTextRegion {
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Soul mySoul;
|
private final Soul mySoul;
|
||||||
private final List<ZLTextElementArea> myList;
|
// this field must be accessed in synchronized context only
|
||||||
|
private final List<ZLTextElementArea> myAreaList;
|
||||||
|
private ZLTextElementArea[] myAreas;
|
||||||
private final int myFromIndex;
|
private final int myFromIndex;
|
||||||
private int myToIndex;
|
private int myToIndex;
|
||||||
private ZLTextHorizontalConvexHull myHull;
|
private ZLTextHorizontalConvexHull myHull;
|
||||||
|
|
||||||
ZLTextRegion(Soul soul, List<ZLTextElementArea> list, int fromIndex) {
|
ZLTextRegion(Soul soul, List<ZLTextElementArea> list, int fromIndex) {
|
||||||
mySoul = soul;
|
mySoul = soul;
|
||||||
myList = list;
|
myAreaList = list;
|
||||||
myFromIndex = fromIndex;
|
myFromIndex = fromIndex;
|
||||||
myToIndex = fromIndex + 1;
|
myToIndex = fromIndex + 1;
|
||||||
}
|
}
|
||||||
|
@ -128,8 +130,16 @@ public final class ZLTextRegion {
|
||||||
return mySoul;
|
return mySoul;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ZLTextElementArea> textAreas() {
|
private ZLTextElementArea[] textAreas() {
|
||||||
return myList.subList(myFromIndex, myToIndex);
|
if (myAreas == null || myAreas.length != myToIndex - myFromIndex) {
|
||||||
|
synchronized (myAreaList) {
|
||||||
|
myAreas = new ZLTextElementArea[myToIndex - myFromIndex];
|
||||||
|
for (int i = 0; i < myAreas.length; ++i) {
|
||||||
|
myAreas[i] = myAreaList.get(i + myFromIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return myAreas;
|
||||||
}
|
}
|
||||||
private ZLTextHorizontalConvexHull convexHull() {
|
private ZLTextHorizontalConvexHull convexHull() {
|
||||||
if (myHull == null) {
|
if (myHull == null) {
|
||||||
|
@ -139,11 +149,12 @@ public final class ZLTextRegion {
|
||||||
}
|
}
|
||||||
|
|
||||||
ZLTextElementArea getFirstArea() {
|
ZLTextElementArea getFirstArea() {
|
||||||
return myList.get(myFromIndex);
|
return textAreas()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
ZLTextElementArea getLastArea() {
|
ZLTextElementArea getLastArea() {
|
||||||
return myList.get(myToIndex - 1);
|
final ZLTextElementArea[] areas = textAreas();
|
||||||
|
return areas[areas.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTop() {
|
public int getTop() {
|
||||||
|
@ -189,8 +200,8 @@ public final class ZLTextRegion {
|
||||||
if (!isUnder(other)) {
|
if (!isUnder(other)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final List<ZLTextElementArea> areas0 = textAreas();
|
final ZLTextElementArea[] areas0 = textAreas();
|
||||||
final List<ZLTextElementArea> areas1 = other.textAreas();
|
final ZLTextElementArea[] areas1 = other.textAreas();
|
||||||
for (ZLTextElementArea i : areas0) {
|
for (ZLTextElementArea i : areas0) {
|
||||||
for (ZLTextElementArea j : areas1) {
|
for (ZLTextElementArea j : areas1) {
|
||||||
if (i.XStart <= j.XEnd && j.XStart <= i.XEnd) {
|
if (i.XStart <= j.XEnd && j.XStart <= i.XEnd) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue