mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-03 17:59:33 +02:00
footnotes toasts (in progress)
This commit is contained in:
parent
b9422621fd
commit
a0fc30a1b4
14 changed files with 312 additions and 130 deletions
|
@ -1,7 +1,6 @@
|
||||||
===== 2.4 (Apr ??, 2015) =====
|
===== 2.4 (Apr ??, 2015) =====
|
||||||
* (planned) Tablet-oriented preferences dialog
|
* (planned) Tablet-oriented preferences dialog
|
||||||
* (planned) Sync: single book upload
|
* (planned) Sync: single book upload
|
||||||
* (planned) Editable notes (by Tamotsu Takahashi)
|
|
||||||
* (planned) Fixed authors list/tags list editing
|
* (planned) Fixed authors list/tags list editing
|
||||||
* (planned) CSS selectors priority
|
* (planned) CSS selectors priority
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,12 @@ package org.geometerplus.android.fbreader;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.github.johnpersano.supertoasts.SuperActivityToast;
|
||||||
|
import com.github.johnpersano.supertoasts.SuperToast;
|
||||||
|
import com.github.johnpersano.supertoasts.util.OnClickWrapper;
|
||||||
|
|
||||||
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
|
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
|
||||||
import org.geometerplus.zlibrary.text.view.*;
|
import org.geometerplus.zlibrary.text.view.*;
|
||||||
|
@ -63,7 +69,27 @@ class ProcessHyperlinkAction extends FBAndroidAction {
|
||||||
break;
|
break;
|
||||||
case FBHyperlinkType.INTERNAL:
|
case FBHyperlinkType.INTERNAL:
|
||||||
Reader.Collection.markHyperlinkAsVisited(Reader.getCurrentBook(), hyperlink.Id);
|
Reader.Collection.markHyperlinkAsVisited(Reader.getCurrentBook(), hyperlink.Id);
|
||||||
Reader.tryOpenFootnote(hyperlink.Id);
|
{
|
||||||
|
final FBReaderApp.FootnoteData data = Reader.getFootnoteData(hyperlink.Id);
|
||||||
|
if (data != null) {
|
||||||
|
final SuperActivityToast toast =
|
||||||
|
new SuperActivityToast(BaseActivity, SuperToast.Type.BUTTON);
|
||||||
|
toast.setText(data.Text);
|
||||||
|
toast.setDuration(SuperToast.Duration.LONG);
|
||||||
|
toast.setButtonIcon(
|
||||||
|
android.R.drawable.ic_menu_more,
|
||||||
|
"More"
|
||||||
|
//ZLResource.resource("dialog").getResource("button").getResource("edit").getValue()
|
||||||
|
);
|
||||||
|
toast.setOnClickWrapper(new OnClickWrapper("ftnt", new SuperToast.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view, Parcelable token) {
|
||||||
|
Reader.tryOpenFootnote(hyperlink.Id);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
toast.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (soul instanceof ZLTextImageRegionSoul) {
|
} else if (soul instanceof ZLTextImageRegionSoul) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class SelectionCopyAction extends FBAndroidAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run(Object ... params) {
|
protected void run(Object ... params) {
|
||||||
final String text = Reader.getTextView().getSelectedText();
|
final String text = Reader.getTextView().getSelectedSnippet().getText();
|
||||||
Reader.getTextView().clearSelection();
|
Reader.getTextView().clearSelection();
|
||||||
|
|
||||||
final ClipboardManager clipboard =
|
final ClipboardManager clipboard =
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class SelectionShareAction extends FBAndroidAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run(Object ... params) {
|
protected void run(Object ... params) {
|
||||||
final String text = Reader.getTextView().getSelectedText();
|
final String text = Reader.getTextView().getSelectedSnippet().getText();
|
||||||
final String title = Reader.getCurrentBook().getTitle();
|
final String title = Reader.getCurrentBook().getTitle();
|
||||||
Reader.getTextView().clearSelection();
|
Reader.getTextView().clearSelection();
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class SelectionTranslateAction extends FBAndroidAction {
|
||||||
final FBView fbview = Reader.getTextView();
|
final FBView fbview = Reader.getTextView();
|
||||||
DictionaryUtil.openTextInDictionary(
|
DictionaryUtil.openTextInDictionary(
|
||||||
BaseActivity,
|
BaseActivity,
|
||||||
fbview.getSelectedText(),
|
fbview.getSelectedSnippet().getText(),
|
||||||
fbview.getCountOfSelectedWords() == 1,
|
fbview.getCountOfSelectedWords() == 1,
|
||||||
fbview.getSelectionStartY(),
|
fbview.getSelectionStartY(),
|
||||||
fbview.getSelectionEndY()
|
fbview.getSelectionEndY()
|
||||||
|
|
|
@ -23,6 +23,8 @@ import java.util.*;
|
||||||
|
|
||||||
import org.geometerplus.zlibrary.core.util.MiscUtil;
|
import org.geometerplus.zlibrary.core.util.MiscUtil;
|
||||||
import org.geometerplus.zlibrary.text.view.*;
|
import org.geometerplus.zlibrary.text.view.*;
|
||||||
|
import org.geometerplus.zlibrary.text.util.TextSnippet;
|
||||||
|
import org.geometerplus.zlibrary.text.util.TextSnippetImpl;
|
||||||
|
|
||||||
public final class Bookmark extends ZLTextFixedPosition {
|
public final class Bookmark extends ZLTextFixedPosition {
|
||||||
public enum DateType {
|
public enum DateType {
|
||||||
|
@ -33,86 +35,7 @@ public final class Bookmark extends ZLTextFixedPosition {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Bookmark createBookmark(Book book, String modelId, ZLTextWordCursor startCursor, int maxWords, boolean isVisible) {
|
public static Bookmark createBookmark(Book book, String modelId, ZLTextWordCursor startCursor, int maxWords, boolean isVisible) {
|
||||||
final ZLTextWordCursor cursor = new ZLTextWordCursor(startCursor);
|
return new Bookmark(book, modelId, new TextSnippetImpl(startCursor, maxWords), isVisible);
|
||||||
|
|
||||||
final Buffer buffer = new Buffer(cursor);
|
|
||||||
final Buffer sentenceBuffer = new Buffer(cursor);
|
|
||||||
final Buffer phraseBuffer = new Buffer(cursor);
|
|
||||||
|
|
||||||
int wordCounter = 0;
|
|
||||||
int sentenceCounter = 0;
|
|
||||||
int storedWordCounter = 0;
|
|
||||||
boolean lineIsNonEmpty = false;
|
|
||||||
boolean appendLineBreak = false;
|
|
||||||
mainLoop:
|
|
||||||
while (wordCounter < maxWords && sentenceCounter < 3) {
|
|
||||||
while (cursor.isEndOfParagraph()) {
|
|
||||||
if (!cursor.nextParagraph()) {
|
|
||||||
break mainLoop;
|
|
||||||
}
|
|
||||||
if (!buffer.isEmpty() && cursor.getParagraphCursor().isEndOfSection()) {
|
|
||||||
break mainLoop;
|
|
||||||
}
|
|
||||||
if (!phraseBuffer.isEmpty()) {
|
|
||||||
sentenceBuffer.append(phraseBuffer);
|
|
||||||
}
|
|
||||||
if (!sentenceBuffer.isEmpty()) {
|
|
||||||
if (appendLineBreak) {
|
|
||||||
buffer.append("\n");
|
|
||||||
}
|
|
||||||
buffer.append(sentenceBuffer);
|
|
||||||
++sentenceCounter;
|
|
||||||
storedWordCounter = wordCounter;
|
|
||||||
}
|
|
||||||
lineIsNonEmpty = false;
|
|
||||||
if (!buffer.isEmpty()) {
|
|
||||||
appendLineBreak = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final ZLTextElement element = cursor.getElement();
|
|
||||||
if (element instanceof ZLTextWord) {
|
|
||||||
final ZLTextWord word = (ZLTextWord)element;
|
|
||||||
if (lineIsNonEmpty) {
|
|
||||||
phraseBuffer.append(" ");
|
|
||||||
}
|
|
||||||
phraseBuffer.Builder.append(word.Data, word.Offset, word.Length);
|
|
||||||
phraseBuffer.Cursor.setCursor(cursor);
|
|
||||||
phraseBuffer.Cursor.setCharIndex(word.Length);
|
|
||||||
++wordCounter;
|
|
||||||
lineIsNonEmpty = true;
|
|
||||||
switch (word.Data[word.Offset + word.Length - 1]) {
|
|
||||||
case ',':
|
|
||||||
case ':':
|
|
||||||
case ';':
|
|
||||||
case ')':
|
|
||||||
sentenceBuffer.append(phraseBuffer);
|
|
||||||
break;
|
|
||||||
case '.':
|
|
||||||
case '!':
|
|
||||||
case '?':
|
|
||||||
++sentenceCounter;
|
|
||||||
if (appendLineBreak) {
|
|
||||||
buffer.append("\n");
|
|
||||||
appendLineBreak = false;
|
|
||||||
}
|
|
||||||
sentenceBuffer.append(phraseBuffer);
|
|
||||||
buffer.append(sentenceBuffer);
|
|
||||||
storedWordCounter = wordCounter;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cursor.nextWord();
|
|
||||||
}
|
|
||||||
if (storedWordCounter < 4) {
|
|
||||||
if (sentenceBuffer.isEmpty()) {
|
|
||||||
sentenceBuffer.append(phraseBuffer);
|
|
||||||
}
|
|
||||||
if (appendLineBreak) {
|
|
||||||
buffer.append("\n");
|
|
||||||
}
|
|
||||||
buffer.append(sentenceBuffer);
|
|
||||||
}
|
|
||||||
return new Bookmark(book, modelId, startCursor, buffer.Cursor, buffer.Builder.toString(), isVisible);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private long myId;
|
private long myId;
|
||||||
|
@ -187,18 +110,18 @@ mainLoop:
|
||||||
}
|
}
|
||||||
|
|
||||||
// creates new bookmark
|
// creates new bookmark
|
||||||
public Bookmark(Book book, String modelId, ZLTextPosition start, ZLTextPosition end, String text, boolean isVisible) {
|
public Bookmark(Book book, String modelId, TextSnippet snippet, boolean isVisible) {
|
||||||
super(start);
|
super(snippet.getStart());
|
||||||
|
|
||||||
myId = -1;
|
myId = -1;
|
||||||
Uid = newUUID();
|
Uid = newUUID();
|
||||||
BookId = book.getId();
|
BookId = book.getId();
|
||||||
BookTitle = book.getTitle();
|
BookTitle = book.getTitle();
|
||||||
myText = text;
|
myText = snippet.getText();
|
||||||
CreationDate = new Date();
|
CreationDate = new Date();
|
||||||
ModelId = modelId;
|
ModelId = modelId;
|
||||||
IsVisible = isVisible;
|
IsVisible = isVisible;
|
||||||
myEnd = new ZLTextFixedPosition(end);
|
myEnd = new ZLTextFixedPosition(snippet.getEnd());
|
||||||
myStyleId = 1;
|
myStyleId = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,29 +270,6 @@ mainLoop:
|
||||||
MiscUtil.equals(myText, other.myText);
|
MiscUtil.equals(myText, other.myText);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Buffer {
|
|
||||||
final StringBuilder Builder = new StringBuilder();
|
|
||||||
final ZLTextWordCursor Cursor;
|
|
||||||
|
|
||||||
Buffer(ZLTextWordCursor cursor) {
|
|
||||||
Cursor = new ZLTextWordCursor(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isEmpty() {
|
|
||||||
return Builder.length() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(Buffer buffer) {
|
|
||||||
Builder.append(buffer.Builder);
|
|
||||||
Cursor.setCursor(buffer.Cursor);
|
|
||||||
buffer.Builder.delete(0, buffer.Builder.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(CharSequence data) {
|
|
||||||
Builder.append(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String newUUID() {
|
private static String newUUID() {
|
||||||
return UUID.randomUUID().toString();
|
return UUID.randomUUID().toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.geometerplus.zlibrary.core.util.*;
|
||||||
|
|
||||||
import org.geometerplus.zlibrary.text.hyphenation.ZLTextHyphenator;
|
import org.geometerplus.zlibrary.text.hyphenation.ZLTextHyphenator;
|
||||||
import org.geometerplus.zlibrary.text.model.ZLTextModel;
|
import org.geometerplus.zlibrary.text.model.ZLTextModel;
|
||||||
|
import org.geometerplus.zlibrary.text.util.EmptyTextSnippet;
|
||||||
import org.geometerplus.zlibrary.text.view.*;
|
import org.geometerplus.zlibrary.text.view.*;
|
||||||
|
|
||||||
import org.geometerplus.fbreader.book.*;
|
import org.geometerplus.fbreader.book.*;
|
||||||
|
@ -210,11 +211,32 @@ public final class FBReaderApp extends ZLApplication {
|
||||||
return (FBView)getCurrentView();
|
return (FBView)getCurrentView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class FootnoteData {
|
||||||
|
public final String Text;
|
||||||
|
public final boolean IsFull;
|
||||||
|
|
||||||
|
private FootnoteData(String text, boolean isFull) {
|
||||||
|
Text = text;
|
||||||
|
IsFull = isFull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FootnoteData getFootnoteData(String id) {
|
||||||
|
if (Model == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final BookModel.Label label = Model.getLabel(id);
|
||||||
|
if (label == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new FootnoteData("Here will be the footnote text", false);
|
||||||
|
}
|
||||||
|
|
||||||
public void tryOpenFootnote(String id) {
|
public void tryOpenFootnote(String id) {
|
||||||
if (Model != null) {
|
if (Model != null) {
|
||||||
myJumpEndPosition = null;
|
myJumpEndPosition = null;
|
||||||
myJumpTimeStamp = null;
|
myJumpTimeStamp = null;
|
||||||
BookModel.Label label = Model.getLabel(id);
|
final BookModel.Label label = Model.getLabel(id);
|
||||||
if (label != null) {
|
if (label != null) {
|
||||||
if (label.ModelId == null) {
|
if (label.ModelId == null) {
|
||||||
if (getTextView() == BookTextView) {
|
if (getTextView() == BookTextView) {
|
||||||
|
@ -242,14 +264,11 @@ public final class FBReaderApp extends ZLApplication {
|
||||||
|
|
||||||
public Bookmark addSelectionBookmark() {
|
public Bookmark addSelectionBookmark() {
|
||||||
final FBView fbView = getTextView();
|
final FBView fbView = getTextView();
|
||||||
final String text = fbView.getSelectedText();
|
|
||||||
|
|
||||||
final Bookmark bookmark = new Bookmark(
|
final Bookmark bookmark = new Bookmark(
|
||||||
Model.Book,
|
Model.Book,
|
||||||
fbView.getModel().getId(),
|
fbView.getModel().getId(),
|
||||||
fbView.getSelectionStartPosition(),
|
fbView.getSelectedSnippet(),
|
||||||
fbView.getSelectionEndPosition(),
|
|
||||||
text,
|
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
Collection.saveBookmark(bookmark);
|
Collection.saveBookmark(bookmark);
|
||||||
|
@ -320,7 +339,7 @@ public final class FBReaderApp extends ZLApplication {
|
||||||
if (pos == null) {
|
if (pos == null) {
|
||||||
pos = new ZLTextFixedPosition(0, 0, 0);
|
pos = new ZLTextFixedPosition(0, 0, 0);
|
||||||
}
|
}
|
||||||
bm = new Bookmark(book, "", pos, pos, "", false);
|
bm = new Bookmark(book, "", new EmptyTextSnippet(pos), false);
|
||||||
}
|
}
|
||||||
myExternalFileOpener.openFile((ExternalFormatPlugin)plugin, book, bm);
|
myExternalFileOpener.openFile((ExternalFormatPlugin)plugin, book, bm);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -29,6 +29,8 @@ import org.geometerplus.zlibrary.core.util.ZLColor;
|
||||||
import org.geometerplus.zlibrary.core.view.ZLPaintContext;
|
import org.geometerplus.zlibrary.core.view.ZLPaintContext;
|
||||||
|
|
||||||
import org.geometerplus.zlibrary.text.model.ZLTextModel;
|
import org.geometerplus.zlibrary.text.model.ZLTextModel;
|
||||||
|
import org.geometerplus.zlibrary.text.util.TextSnippet;
|
||||||
|
import org.geometerplus.zlibrary.text.util.TextSnippetImpl;
|
||||||
import org.geometerplus.zlibrary.text.view.*;
|
import org.geometerplus.zlibrary.text.view.*;
|
||||||
import org.geometerplus.zlibrary.text.view.style.ZLTextStyleCollection;
|
import org.geometerplus.zlibrary.text.view.style.ZLTextStyleCollection;
|
||||||
|
|
||||||
|
@ -79,7 +81,7 @@ public final class FBView extends ZLTextView {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ZLTextRegion hyperlinkRegion = findRegion(x, y, MAX_SELECTION_DISTANCE, ZLTextRegion.HyperlinkFilter);
|
final ZLTextRegion hyperlinkRegion = findRegion(x, y, maxSelectionDistance(), ZLTextRegion.HyperlinkFilter);
|
||||||
if (hyperlinkRegion != null) {
|
if (hyperlinkRegion != null) {
|
||||||
selectRegion(hyperlinkRegion);
|
selectRegion(hyperlinkRegion);
|
||||||
myReader.getViewWidget().reset();
|
myReader.getViewWidget().reset();
|
||||||
|
@ -103,7 +105,7 @@ public final class FBView extends ZLTextView {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ZLTextHighlighting highlighting = findHighlighting(x, y, MAX_SELECTION_DISTANCE);
|
final ZLTextHighlighting highlighting = findHighlighting(x, y, maxSelectionDistance());
|
||||||
if (highlighting instanceof BookmarkHighlighting) {
|
if (highlighting instanceof BookmarkHighlighting) {
|
||||||
myReader.runAction(
|
myReader.runAction(
|
||||||
ActionCode.SELECTION_BOOKMARK,
|
ActionCode.SELECTION_BOOKMARK,
|
||||||
|
@ -141,7 +143,7 @@ public final class FBView extends ZLTextView {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ZLTextSelectionCursor cursor = findSelectionCursor(x, y, MAX_SELECTION_DISTANCE);
|
final ZLTextSelectionCursor cursor = findSelectionCursor(x, y, maxSelectionDistance());
|
||||||
if (cursor != ZLTextSelectionCursor.None) {
|
if (cursor != ZLTextSelectionCursor.None) {
|
||||||
myReader.runAction(ActionCode.SELECTION_HIDE_PANEL);
|
myReader.runAction(ActionCode.SELECTION_HIDE_PANEL);
|
||||||
moveSelectionCursorTo(cursor, x, y);
|
moveSelectionCursorTo(cursor, x, y);
|
||||||
|
@ -238,7 +240,7 @@ public final class FBView extends ZLTextView {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ZLTextRegion region = findRegion(x, y, MAX_SELECTION_DISTANCE, ZLTextRegion.AnyRegionFilter);
|
final ZLTextRegion region = findRegion(x, y, maxSelectionDistance(), ZLTextRegion.AnyRegionFilter);
|
||||||
if (region != null) {
|
if (region != null) {
|
||||||
final ZLTextRegion.Soul soul = region.getSoul();
|
final ZLTextRegion.Soul soul = region.getSoul();
|
||||||
boolean doSelectRegion = false;
|
boolean doSelectRegion = false;
|
||||||
|
@ -294,7 +296,7 @@ public final class FBView extends ZLTextView {
|
||||||
soul instanceof ZLTextWordRegionSoul) {
|
soul instanceof ZLTextWordRegionSoul) {
|
||||||
if (myReader.MiscOptions.WordTappingAction.getValue() !=
|
if (myReader.MiscOptions.WordTappingAction.getValue() !=
|
||||||
MiscOptions.WordTappingActionEnum.doNothing) {
|
MiscOptions.WordTappingActionEnum.doNothing) {
|
||||||
region = findRegion(x, y, MAX_SELECTION_DISTANCE, ZLTextRegion.AnyRegionFilter);
|
region = findRegion(x, y, maxSelectionDistance(), ZLTextRegion.AnyRegionFilter);
|
||||||
if (region != null) {
|
if (region != null) {
|
||||||
soul = region.getSoul();
|
soul = region.getSoul();
|
||||||
if (soul instanceof ZLTextHyperlinkRegionSoul
|
if (soul instanceof ZLTextHyperlinkRegionSoul
|
||||||
|
@ -738,12 +740,14 @@ public final class FBView extends ZLTextView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSelectedText() {
|
public TextSnippet getSelectedSnippet() {
|
||||||
|
final ZLTextPosition start = getSelectionStartPosition();
|
||||||
|
final ZLTextPosition end = getSelectionEndPosition();
|
||||||
final TextBuildTraverser traverser = new TextBuildTraverser(this);
|
final TextBuildTraverser traverser = new TextBuildTraverser(this);
|
||||||
if (!isSelectionEmpty()) {
|
if (!isSelectionEmpty()) {
|
||||||
traverser.traverse(getSelectionStartPosition(), getSelectionEndPosition());
|
traverser.traverse(start, end);
|
||||||
}
|
}
|
||||||
return traverser.getText();
|
return new TextSnippetImpl(start, end, traverser.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCountOfSelectedWords() {
|
public int getCountOfSelectedWords() {
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
import org.geometerplus.zlibrary.text.view.ZLTextFixedPosition;
|
||||||
|
import org.geometerplus.zlibrary.text.view.ZLTextPosition;
|
||||||
|
|
||||||
|
public class EmptyTextSnippet implements TextSnippet {
|
||||||
|
private final ZLTextPosition myPosition;
|
||||||
|
|
||||||
|
public EmptyTextSnippet(ZLTextPosition position) {
|
||||||
|
myPosition = new ZLTextFixedPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZLTextPosition getStart() {
|
||||||
|
return myPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZLTextPosition getEnd() {
|
||||||
|
return myPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
28
src/org/geometerplus/zlibrary/text/util/TextSnippet.java
Normal file
28
src/org/geometerplus/zlibrary/text/util/TextSnippet.java
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
import org.geometerplus.zlibrary.text.view.ZLTextPosition;
|
||||||
|
|
||||||
|
public interface TextSnippet {
|
||||||
|
ZLTextPosition getStart();
|
||||||
|
ZLTextPosition getEnd();
|
||||||
|
String getText();
|
||||||
|
}
|
157
src/org/geometerplus/zlibrary/text/util/TextSnippetImpl.java
Normal file
157
src/org/geometerplus/zlibrary/text/util/TextSnippetImpl.java
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.geometerplus.zlibrary.text.view.*;
|
||||||
|
|
||||||
|
public class TextSnippetImpl implements TextSnippet {
|
||||||
|
private final ZLTextPosition myStart;
|
||||||
|
private final ZLTextPosition myEnd;
|
||||||
|
private final String myText;
|
||||||
|
|
||||||
|
public TextSnippetImpl(ZLTextPosition start, ZLTextPosition end, String text) {
|
||||||
|
myStart = start;
|
||||||
|
myEnd = end;
|
||||||
|
myText = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextSnippetImpl(ZLTextWordCursor start, int maxWords) {
|
||||||
|
final ZLTextWordCursor cursor = new ZLTextWordCursor(start);
|
||||||
|
|
||||||
|
final Buffer buffer = new Buffer(cursor);
|
||||||
|
final Buffer sentenceBuffer = new Buffer(cursor);
|
||||||
|
final Buffer phraseBuffer = new Buffer(cursor);
|
||||||
|
|
||||||
|
int wordCounter = 0;
|
||||||
|
int sentenceCounter = 0;
|
||||||
|
int storedWordCounter = 0;
|
||||||
|
boolean lineIsNonEmpty = false;
|
||||||
|
boolean appendLineBreak = false;
|
||||||
|
mainLoop:
|
||||||
|
while (wordCounter < maxWords && sentenceCounter < 3) {
|
||||||
|
while (cursor.isEndOfParagraph()) {
|
||||||
|
if (!cursor.nextParagraph()) {
|
||||||
|
break mainLoop;
|
||||||
|
}
|
||||||
|
if (!buffer.isEmpty() && cursor.getParagraphCursor().isEndOfSection()) {
|
||||||
|
break mainLoop;
|
||||||
|
}
|
||||||
|
if (!phraseBuffer.isEmpty()) {
|
||||||
|
sentenceBuffer.append(phraseBuffer);
|
||||||
|
}
|
||||||
|
if (!sentenceBuffer.isEmpty()) {
|
||||||
|
if (appendLineBreak) {
|
||||||
|
buffer.append("\n");
|
||||||
|
}
|
||||||
|
buffer.append(sentenceBuffer);
|
||||||
|
++sentenceCounter;
|
||||||
|
storedWordCounter = wordCounter;
|
||||||
|
}
|
||||||
|
lineIsNonEmpty = false;
|
||||||
|
if (!buffer.isEmpty()) {
|
||||||
|
appendLineBreak = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final ZLTextElement element = cursor.getElement();
|
||||||
|
if (element instanceof ZLTextWord) {
|
||||||
|
final ZLTextWord word = (ZLTextWord)element;
|
||||||
|
if (lineIsNonEmpty) {
|
||||||
|
phraseBuffer.append(" ");
|
||||||
|
}
|
||||||
|
phraseBuffer.Builder.append(word.Data, word.Offset, word.Length);
|
||||||
|
phraseBuffer.Cursor.setCursor(cursor);
|
||||||
|
phraseBuffer.Cursor.setCharIndex(word.Length);
|
||||||
|
++wordCounter;
|
||||||
|
lineIsNonEmpty = true;
|
||||||
|
switch (word.Data[word.Offset + word.Length - 1]) {
|
||||||
|
case ',':
|
||||||
|
case ':':
|
||||||
|
case ';':
|
||||||
|
case ')':
|
||||||
|
sentenceBuffer.append(phraseBuffer);
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
case '!':
|
||||||
|
case '?':
|
||||||
|
++sentenceCounter;
|
||||||
|
if (appendLineBreak) {
|
||||||
|
buffer.append("\n");
|
||||||
|
appendLineBreak = false;
|
||||||
|
}
|
||||||
|
sentenceBuffer.append(phraseBuffer);
|
||||||
|
buffer.append(sentenceBuffer);
|
||||||
|
storedWordCounter = wordCounter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor.nextWord();
|
||||||
|
}
|
||||||
|
if (storedWordCounter < 4) {
|
||||||
|
if (sentenceBuffer.isEmpty()) {
|
||||||
|
sentenceBuffer.append(phraseBuffer);
|
||||||
|
}
|
||||||
|
if (appendLineBreak) {
|
||||||
|
buffer.append("\n");
|
||||||
|
}
|
||||||
|
buffer.append(sentenceBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
myStart = new ZLTextFixedPosition(start);
|
||||||
|
myEnd = buffer.Cursor;
|
||||||
|
myText = buffer.Builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Buffer {
|
||||||
|
final StringBuilder Builder = new StringBuilder();
|
||||||
|
final ZLTextWordCursor Cursor;
|
||||||
|
|
||||||
|
Buffer(ZLTextWordCursor cursor) {
|
||||||
|
Cursor = new ZLTextWordCursor(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isEmpty() {
|
||||||
|
return Builder.length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(Buffer buffer) {
|
||||||
|
Builder.append(buffer.Builder);
|
||||||
|
Cursor.setCursor(buffer.Cursor);
|
||||||
|
buffer.Builder.delete(0, buffer.Builder.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(CharSequence data) {
|
||||||
|
Builder.append(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZLTextPosition getStart() {
|
||||||
|
return myStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZLTextPosition getEnd() {
|
||||||
|
return myEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return myText;
|
||||||
|
}
|
||||||
|
}
|
|
@ -82,7 +82,7 @@ class ZLTextSelection extends ZLTextHighlighting {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
final ZLTextRegion region = myView.findRegion(
|
final ZLTextRegion region = myView.findRegion(
|
||||||
x, y, ZLTextView.MAX_SELECTION_DISTANCE, ZLTextRegion.AnyRegionFilter
|
x, y, myView.maxSelectionDistance(), ZLTextRegion.AnyRegionFilter
|
||||||
);
|
);
|
||||||
if (region == null) {
|
if (region == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -137,7 +137,7 @@ class ZLTextSelection extends ZLTextHighlighting {
|
||||||
myScroller.setXY(x, y);
|
myScroller.setXY(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZLTextRegion region = myView.findRegion(x, y, ZLTextView.MAX_SELECTION_DISTANCE, ZLTextRegion.AnyRegionFilter);
|
ZLTextRegion region = myView.findRegion(x, y, myView.maxSelectionDistance(), ZLTextRegion.AnyRegionFilter);
|
||||||
if (region == null && myScroller != null) {
|
if (region == null && myScroller != null) {
|
||||||
region = myView.findRegion(x, y, ZLTextRegion.AnyRegionFilter);
|
region = myView.findRegion(x, y, ZLTextRegion.AnyRegionFilter);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,6 @@ import org.geometerplus.zlibrary.text.hyphenation.*;
|
||||||
import org.geometerplus.zlibrary.text.view.style.ZLTextStyleCollection;
|
import org.geometerplus.zlibrary.text.view.style.ZLTextStyleCollection;
|
||||||
|
|
||||||
public abstract class ZLTextView extends ZLTextViewBase {
|
public abstract class ZLTextView extends ZLTextViewBase {
|
||||||
public static final int MAX_SELECTION_DISTANCE = 10;
|
|
||||||
|
|
||||||
public interface ScrollingMode {
|
public interface ScrollingMode {
|
||||||
int NO_OVERLAPPING = 0;
|
int NO_OVERLAPPING = 0;
|
||||||
int KEEP_LINES = 1;
|
int KEEP_LINES = 1;
|
||||||
|
|
|
@ -43,6 +43,14 @@ abstract class ZLTextViewBase extends ZLView {
|
||||||
super(application);
|
super(application);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int myMaxSelectionDistance = 0;
|
||||||
|
protected final int maxSelectionDistance() {
|
||||||
|
if (myMaxSelectionDistance == 0) {
|
||||||
|
myMaxSelectionDistance = ZLibrary.Instance().getDisplayDPI() / 20;
|
||||||
|
}
|
||||||
|
return myMaxSelectionDistance;
|
||||||
|
}
|
||||||
|
|
||||||
protected void resetMetrics() {
|
protected void resetMetrics() {
|
||||||
myMetrics = null;
|
myMetrics = null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue