1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-04 18:29:23 +02:00

different options for 'dictionary' and 'translator'

This commit is contained in:
Nikolay Pultsin 2011-06-12 00:04:21 +01:00
parent 5df9f5fd9a
commit 48913e6404
23 changed files with 217 additions and 117 deletions

View file

@ -542,6 +542,7 @@
<node name="dictionary" value="Slovník">
<node name="summary" value="Nastavení slovníku"/>
<node name="dictionary" value="Slovník"/>
<node name="translator" value="Translator" toBeTranslated="true"/>
<node name="tappingAction" value="Dlouhé klepnutí">
<node name="doNothing" value="Dlouhé klepnutí nedělá nic"/>
<node name="selectSingleWord" value="Dlouhé klepnutí vybere slovo"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="Dictionary" toBeTranslated="true">
<node name="summary" value="Dictionary settings" 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="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>

View file

@ -542,6 +542,7 @@
<node name="dictionary" value="Dictionary">
<node name="summary" value="Dictionary settings"/>
<node name="dictionary" value="Dictionary"/>
<node name="translator" value="Translator"/>
<node name="tappingAction" value="Long tapping action">
<node name="doNothing" value="Long tapping does nothing"/>
<node name="selectSingleWord" value="Long tapping selects single word"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="Dictionnaire">
<node name="summary" value="Paramètres du dictionnaire"/>
<node name="dictionary" value="Dictionnaire"/>
<node name="translator" value="Translator" toBeTranslated="true"/>
<node name="tappingAction" value="Configuration de l'appui long">
<node name="doNothing" value="Un appui long ne fait rien"/>
<node name="selectSingleWord" value="Un appui long selectionne le mot"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="Dicionario">
<node name="summary" value="Preferencias do 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="doNothing" value="Pulsación longa non fai nada"/>
<node name="selectSingleWord" value="Pulsación longa selecciona a palabra"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="Szótár">
<node name="summary" value="Szótár beállításai"/>
<node name="dictionary" value="Szótár"/>
<node name="translator" value="Translator" toBeTranslated="true"/>
<node name="tappingAction" value="Hosszú érintés">
<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"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="Dictionary" toBeTranslated="true">
<node name="summary" value="Dictionary settings" 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="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="Woordenboek">
<node name="summary" value="Woordenboek instellingen"/>
<node name="dictionary" value="Woordenboek"/>
<node name="translator" value="Translator" toBeTranslated="true"/>
<node name="tappingAction" value="Long tapping action" toBeTranslated="true">
<node name="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="Словарь">
<node name="summary" value="Настройки словаря"/>
<node name="dictionary" value="Словарь"/>
<node name="translator" value="Переводчик"/>
<node name="tappingAction" value="Действие при долгом нажатии на экран">
<node name="doNothing" value="Ничего не делать"/>
<node name="selectSingleWord" value="Выделять одно слово"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="พจนานุกรม">
<node name="summary" value="การตั้งค่าพจนานุกรม"/>
<node name="dictionary" value="พจนานุกรม"/>
<node name="translator" value="Translator" toBeTranslated="true"/>
<node name="tappingAction" value="การทำงานเมื่อกดค้างที่หน้าจอ">
<node name="doNothing" value="ไม่มีอะไรเกิดขึ้น"/>
<node name="selectSingleWord" value="เลือกคำเมื่อกดค้างที่หน้าจอ"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="Dictionary" toBeTranslated="true">
<node name="summary" value="Dictionary settings" 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="doNothing" value="Long tapping does nothing" toBeTranslated="true"/>
<node name="selectSingleWord" value="Long tapping selects single word" toBeTranslated="true"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="Từ điển">
<node name="summary" value="Cài đặt 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="doNothing" value="Không làm gì khi nhấn giữ"/>
<node name="selectSingleWord" value="Chọn từ khi nhấn giữ"/>

View file

@ -528,6 +528,7 @@
<node name="dictionary" value="字典">
<node name="summary" value="字典设定"/>
<node name="dictionary" value="字典"/>
<node name="translator" value="Translator" toBeTranslated="true"/>
<node name="tappingAction" value="长拍触行为动作">
<node name="doNothing" value="长拍触不做任何动作"/>
<node name="selectSingleWord" value="长拍触选择词语"/>

View file

@ -547,6 +547,7 @@
<node name="dictionary" value="字典">
<node name="summary" value="字典設定"/>
<node name="dictionary" value="字典"/>
<node name="translator" value="Translator" toBeTranslated="true"/>
<node name="tappingAction" value="長按動作">
<node name="doNothing" value="長按不做任何動作"/>
<node name="selectSingleWord" value="長按選字"/>

View file

@ -165,6 +165,17 @@ public abstract class DictionaryUtil {
}
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 Intent intent = getDictionaryIntent(info, text);
try {
@ -190,17 +201,8 @@ public abstract class DictionaryUtil {
}
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(
activity, text.substring(start, end), true, region.getTop(), region.getBottom()
activity, word.toString(), true, region.getTop(), region.getBottom()
);
}

View file

@ -69,10 +69,10 @@ class SelectionPopup extends ButtonsPopupPanel {
final int diffTop = screenHeight - selectionEndY;
final int diffBottom = selectionStartY;
if (diffTop > diffBottom) {
verticalPosition = diffTop > myWindow.getHeight() + 10
verticalPosition = diffTop > myWindow.getHeight() + 20
? RelativeLayout.ALIGN_PARENT_BOTTOM : RelativeLayout.CENTER_VERTICAL;
} else {
verticalPosition = diffBottom > myWindow.getHeight() + 10
verticalPosition = diffBottom > myWindow.getHeight() + 20
? RelativeLayout.ALIGN_PARENT_TOP : RelativeLayout.CENTER_VERTICAL;
}

View file

@ -29,10 +29,13 @@ public class SelectionTranslateAction extends FBAndroidAction {
public void run() {
final FBView fbview = Reader.getTextView();
final int selectionStartY = fbview.getSelectionStartY(), selectionEndY = fbview.getSelectionEndY();
final String text = fbview.getSelectedText();
Reader.getTextView().clearSelection();
DictionaryUtil.openTextInDictionary(BaseActivity, text, false, selectionStartY, selectionEndY);
DictionaryUtil.openTextInDictionary(
BaseActivity,
fbview.getSelectedText(),
fbview.getCountOfSelectedWords() == 1,
fbview.getSelectionStartY(),
fbview.getSelectionEndY()
);
fbview.clearSelection();
}
}

View file

@ -601,17 +601,27 @@ public final class FBView extends ZLTextView {
@Override
protected void releaseSelectionCursor() {
super.releaseSelectionCursor();
myReader.doAction(ActionCode.SELECTION_SHOW_PANEL);
if (getCountOfSelectedWords() > 0) {
myReader.doAction(ActionCode.SELECTION_SHOW_PANEL);
}
}
public String getSelectedText() {
final TextBuilderTraverser traverser = new TextBuilderTraverser(this);
final TextBuildTraverser traverser = new TextBuildTraverser(this);
if (!isSelectionEmpty()) {
traverser.traverse(getSelectionStartPosition(), getSelectionEndPosition());
}
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;
@Override

View file

@ -21,10 +21,10 @@ package org.geometerplus.fbreader.fbreader;
import org.geometerplus.zlibrary.text.view.*;
class TextBuilderTraverser extends ZLTextTraverser {
class TextBuildTraverser extends ZLTextTraverser {
protected final StringBuilder myBuffer = new StringBuilder();
TextBuilderTraverser(ZLTextView view) {
TextBuildTraverser(ZLTextView view) {
super(view);
}

View file

@ -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;
}
}

View file

@ -29,9 +29,9 @@ final class ZLTextElementAreaVector {
private ZLTextRegion myCurrentElementRegion;
public void clear() {
myAreas.clear();
myElementRegions.clear();
myCurrentElementRegion = null;
myAreas.clear();
}
public boolean isEmpty() {
@ -95,9 +95,11 @@ final class ZLTextElementAreaVector {
if (soul == null) {
return null;
}
for (ZLTextRegion region : myElementRegions) {
if (soul.equals(region.getSoul())) {
return region;
synchronized (myElementRegions) {
for (ZLTextRegion region : myElementRegions) {
if (soul.equals(region.getSoul())) {
return region;
}
}
}
return null;
@ -106,12 +108,14 @@ final class ZLTextElementAreaVector {
ZLTextRegion findRegion(int x, int y, int maxDistance, ZLTextRegion.Filter filter) {
ZLTextRegion bestRegion = null;
int distance = maxDistance + 1;
for (ZLTextRegion region : myElementRegions) {
if (filter.accepts(region)) {
final int d = region.distanceTo(x, y);
if (d < distance) {
bestRegion = region;
distance = d;
synchronized (myElementRegions) {
for (ZLTextRegion region : myElementRegions) {
if (filter.accepts(region)) {
final int d = region.distanceTo(x, y);
if (d < distance) {
bestRegion = region;
distance = d;
}
}
}
}
@ -119,88 +123,90 @@ final class ZLTextElementAreaVector {
}
protected ZLTextRegion nextRegion(ZLTextRegion currentRegion, ZLTextView.Direction direction, ZLTextRegion.Filter filter) {
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;
synchronized (myElementRegions) {
if (myElementRegions.isEmpty()) {
return null;
}
case up:
ZLTextRegion firstCandidate = null;
for (; index >= 0; --index) {
final ZLTextRegion candidate = myElementRegions.get(index);
if (!filter.accepts(candidate)) {
continue;
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;
}
if (candidate.isExactlyOver(currentRegion)) {
return candidate;
break;
case leftToRight:
case down:
if (index == myElementRegions.size() - 1) {
return null;
} else {
++index;
}
if (firstCandidate == null && candidate.isOver(currentRegion)) {
firstCandidate = candidate;
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;
}
if (firstCandidate != null) {
return firstCandidate;
}
break;
case up:
ZLTextRegion firstCandidate = null;
for (; index >= 0; --index) {
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;
}

View file

@ -26,7 +26,7 @@ import org.geometerplus.zlibrary.core.view.ZLPaintContext;
class ZLTextHorizontalConvexHull {
private final LinkedList<Rectangle> myRectangles = new LinkedList<Rectangle>();
ZLTextHorizontalConvexHull(List<ZLTextElementArea> textAreas) {
ZLTextHorizontalConvexHull(ZLTextElementArea[] textAreas) {
for (ZLTextElementArea area : textAreas) {
addArea(area);
}

View file

@ -107,14 +107,16 @@ public final class ZLTextRegion {
};
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 int myToIndex;
private ZLTextHorizontalConvexHull myHull;
ZLTextRegion(Soul soul, List<ZLTextElementArea> list, int fromIndex) {
mySoul = soul;
myList = list;
myAreaList = list;
myFromIndex = fromIndex;
myToIndex = fromIndex + 1;
}
@ -128,8 +130,16 @@ public final class ZLTextRegion {
return mySoul;
}
private List<ZLTextElementArea> textAreas() {
return myList.subList(myFromIndex, myToIndex);
private ZLTextElementArea[] textAreas() {
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() {
if (myHull == null) {
@ -139,11 +149,12 @@ public final class ZLTextRegion {
}
ZLTextElementArea getFirstArea() {
return myList.get(myFromIndex);
return textAreas()[0];
}
ZLTextElementArea getLastArea() {
return myList.get(myToIndex - 1);
final ZLTextElementArea[] areas = textAreas();
return areas[areas.length - 1];
}
public int getTop() {
@ -189,8 +200,8 @@ public final class ZLTextRegion {
if (!isUnder(other)) {
return false;
}
final List<ZLTextElementArea> areas0 = textAreas();
final List<ZLTextElementArea> areas1 = other.textAreas();
final ZLTextElementArea[] areas0 = textAreas();
final ZLTextElementArea[] areas1 = other.textAreas();
for (ZLTextElementArea i : areas0) {
for (ZLTextElementArea j : areas1) {
if (i.XStart <= j.XEnd && j.XStart <= i.XEnd) {