summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorPaul Gardiner <paulg.artifex@glidos.net>2013-01-10 14:41:17 +0000
committerPaul Gardiner <paulg.artifex@glidos.net>2013-01-10 14:41:17 +0000
commita9df730e0c215f8ff213814686a8df0767cece31 (patch)
tree68d2724ad27e00f2b9535abd7daff6e4dd8502a6 /android
parent5ffe63ad521dc71b33d9c280ad108ca495a450d1 (diff)
downloadmupdf-a9df730e0c215f8ff213814686a8df0767cece31.tar.xz
Android: add text selection
although not actually do anything with the selection yet
Diffstat (limited to 'android')
-rw-r--r--android/res/drawable-ldpi/ic_select.pngbin0 -> 247 bytes
-rw-r--r--android/res/drawable-mdpi/ic_select.pngbin0 -> 280 bytes
-rw-r--r--android/res/layout/buttons.xml12
-rw-r--r--android/res/values/strings.xml1
-rw-r--r--android/src/com/artifex/mupdf/MuPDFActivity.java36
-rw-r--r--android/src/com/artifex/mupdf/MuPDFPageView.java5
-rw-r--r--android/src/com/artifex/mupdf/PageView.java118
7 files changed, 141 insertions, 31 deletions
diff --git a/android/res/drawable-ldpi/ic_select.png b/android/res/drawable-ldpi/ic_select.png
new file mode 100644
index 00000000..81af6738
--- /dev/null
+++ b/android/res/drawable-ldpi/ic_select.png
Binary files differ
diff --git a/android/res/drawable-mdpi/ic_select.png b/android/res/drawable-mdpi/ic_select.png
new file mode 100644
index 00000000..9eaf6924
--- /dev/null
+++ b/android/res/drawable-mdpi/ic_select.png
Binary files differ
diff --git a/android/res/layout/buttons.xml b/android/res/layout/buttons.xml
index 642e6e6a..c8c95153 100644
--- a/android/res/layout/buttons.xml
+++ b/android/res/layout/buttons.xml
@@ -35,12 +35,22 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
- android:layout_toLeftOf="@+id/outlineButton"
+ android:layout_toLeftOf="@+id/selectButton"
android:contentDescription="@string/link_control"
android:background="@drawable/button"
android:src="@drawable/ic_link" />
<ImageButton
+ android:id="@+id/selectButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_toLeftOf="@+id/outlineButton"
+ android:contentDescription="@string/select"
+ android:background="@drawable/button"
+ android:src="@drawable/ic_select" />
+
+ <ImageButton
android:id="@+id/outlineButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml
index 729b5445..2022e3eb 100644
--- a/android/res/values/strings.xml
+++ b/android/res/values/strings.xml
@@ -16,4 +16,5 @@
<string name="searching_">Searching...</string>
<string name="link_control">Link highlighting and enabling</string>
<string name="no_further_occurences_found">No further occurences found</string>
+ <string name="select">Select</string>
</resources>
diff --git a/android/src/com/artifex/mupdf/MuPDFActivity.java b/android/src/com/artifex/mupdf/MuPDFActivity.java
index 0c35cadf..d083fc60 100644
--- a/android/src/com/artifex/mupdf/MuPDFActivity.java
+++ b/android/src/com/artifex/mupdf/MuPDFActivity.java
@@ -11,6 +11,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Color;
+import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Bundle;
@@ -95,6 +96,7 @@ public class MuPDFActivity extends Activity
private int mPageSliderRes;
private TextView mPageNumberView;
private ImageButton mSearchButton;
+ private ImageButton mSelectButton;
private ImageButton mCancelButton;
private ImageButton mOutlineButton;
private ViewSwitcher mTopBarSwitcher;
@@ -107,6 +109,7 @@ public class MuPDFActivity extends Activity
//private SearchTaskResult mSearchTaskResult;
private AlertDialog.Builder mAlertBuilder;
private boolean mLinkHighlight = false;
+ private boolean mSelecting = false;
private final Handler mHandler = new Handler();
private boolean mAlertsActive= false;
private AsyncTask<Void,Void,MuPDFAlert> mAlertTask;
@@ -343,7 +346,7 @@ public class MuPDFActivity extends Activity
private boolean showButtonsDisabled;
public boolean onSingleTapUp(MotionEvent e) {
- if (!showButtonsDisabled) {
+ if (!mSelecting && !showButtonsDisabled) {
MuPDFPageView pageView = (MuPDFPageView) mDocView.getDisplayedView();
if (MuPDFCore.javascriptSupported() && pageView.passClickEvent(e.getX(), e.getY())) {
// If the page consumes the event do nothing else
@@ -385,10 +388,26 @@ public class MuPDFActivity extends Activity
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- if (!showButtonsDisabled)
- hideButtons();
+ if (!mSelecting) {
+ if (!showButtonsDisabled)
+ hideButtons();
- return super.onScroll(e1, e2, distanceX, distanceY);
+ return super.onScroll(e1, e2, distanceX, distanceY);
+ } else {
+ MuPDFPageView pageView = (MuPDFPageView) mDocView.getDisplayedView();
+ if (pageView != null)
+ pageView.selectText(e1.getX(), e1.getY(), e2.getX(), e2.getY());
+ return true;
+ }
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2,
+ float velocityX, float velocityY) {
+ if (!mSelecting)
+ return super.onFling(e1, e2, velocityX, velocityY);
+ else
+ return true;
}
public boolean onScaleBegin(ScaleGestureDetector d) {
@@ -489,6 +508,14 @@ public class MuPDFActivity extends Activity
}
});
+ // Activate the select button
+ mSelectButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ mSelecting = !mSelecting;
+ mSelectButton.setColorFilter(Color.WHITE, mSelecting?PorterDuff.Mode.XOR: PorterDuff.Mode.DST);
+ }
+ });
+
mCancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
searchModeOff();
@@ -776,6 +803,7 @@ public class MuPDFActivity extends Activity
mPageSlider = (SeekBar)mButtonsView.findViewById(R.id.pageSlider);
mPageNumberView = (TextView)mButtonsView.findViewById(R.id.pageNumber);
mSearchButton = (ImageButton)mButtonsView.findViewById(R.id.searchButton);
+ mSelectButton = (ImageButton)mButtonsView.findViewById(R.id.selectButton);
mCancelButton = (ImageButton)mButtonsView.findViewById(R.id.cancel);
mOutlineButton = (ImageButton)mButtonsView.findViewById(R.id.outlineButton);
mTopBarSwitcher = (ViewSwitcher)mButtonsView.findViewById(R.id.switcher);
diff --git a/android/src/com/artifex/mupdf/MuPDFPageView.java b/android/src/com/artifex/mupdf/MuPDFPageView.java
index 68031837..8360ba09 100644
--- a/android/src/com/artifex/mupdf/MuPDFPageView.java
+++ b/android/src/com/artifex/mupdf/MuPDFPageView.java
@@ -217,6 +217,11 @@ public class MuPDFPageView extends PageView {
}
@Override
+ protected TextWord[][] getText() {
+ return mCore.textLines(mPageNumber);
+ }
+
+ @Override
public void setPage(final int page, PointF size) {
mLoadWidgetAreas = new AsyncTask<Void,Void,RectF[]> () {
@Override
diff --git a/android/src/com/artifex/mupdf/PageView.java b/android/src/com/artifex/mupdf/PageView.java
index bdbed438..e45aff83 100644
--- a/android/src/com/artifex/mupdf/PageView.java
+++ b/android/src/com/artifex/mupdf/PageView.java
@@ -1,5 +1,8 @@
package com.artifex.mupdf;
+import java.util.ArrayList;
+import java.util.Iterator;
+
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
@@ -53,6 +56,7 @@ public abstract class PageView extends ViewGroup {
private ImageView mEntire; // Image rendered at minimum zoom
private BitmapHolder mEntireBm;
+ private AsyncTask<Void,Void,TextWord[][]> mGetText;
private AsyncTask<Void,Void,LinkInfo[]> mGetLinkInfo;
private AsyncTask<Void,Void,Void> mDrawEntire;
@@ -63,6 +67,8 @@ public abstract class PageView extends ViewGroup {
private AsyncTask<PatchInfo,Void,PatchInfo> mDrawPatch;
private RectF mSearchBoxes[];
protected LinkInfo mLinks[];
+ private RectF mSelectBox;
+ private TextWord mText[][];
private View mSearchView;
private boolean mIsBlank;
private boolean mHighlightLinks;
@@ -82,8 +88,9 @@ public abstract class PageView extends ViewGroup {
protected abstract void drawPage(BitmapHolder h, int sizeX, int sizeY, int patchX, int patchY, int patchWidth, int patchHeight);
protected abstract void updatePage(BitmapHolder h, int sizeX, int sizeY, int patchX, int patchY, int patchWidth, int patchHeight);
protected abstract LinkInfo[] getLinkInfo();
+ protected abstract TextWord[][] getText();
- public void releaseResources() {
+ private void reinit() {
// Cancel pending render task
if (mDrawEntire != null) {
mDrawEntire.cancel(true);
@@ -95,6 +102,16 @@ public abstract class PageView extends ViewGroup {
mDrawPatch = null;
}
+ if (mGetLinkInfo != null) {
+ mGetLinkInfo.cancel(true);
+ mGetLinkInfo = null;
+ }
+
+ if (mGetText != null) {
+ mGetText.cancel(true);
+ mGetText = null;
+ }
+
mIsBlank = true;
mPageNumber = 0;
@@ -111,6 +128,15 @@ public abstract class PageView extends ViewGroup {
mPatch.setImageBitmap(null);
}
+ mSearchBoxes = null;
+ mLinks = null;
+ mSelectBox = null;
+ mText = null;
+ }
+
+ public void releaseResources() {
+ reinit();
+
if (mBusyIndicator != null) {
removeView(mBusyIndicator);
mBusyIndicator = null;
@@ -118,33 +144,9 @@ public abstract class PageView extends ViewGroup {
}
public void blank(int page) {
- // Cancel pending render task
- if (mDrawEntire != null) {
- mDrawEntire.cancel(true);
- mDrawEntire = null;
- }
-
- if (mDrawPatch != null) {
- mDrawPatch.cancel(true);
- mDrawPatch = null;
- }
-
- mIsBlank = true;
+ reinit();
mPageNumber = page;
- if (mSize == null)
- mSize = mParentSize;
-
- if (mEntire != null) {
- mEntireBm.setBm(null);
- mEntire.setImageBitmap(null);
- }
-
- if (mPatch != null) {
- mPatchBm.setBm(null);
- mPatch.setImageBitmap(null);
- }
-
if (mBusyIndicator == null) {
mBusyIndicator = new ProgressBar(mContext);
mBusyIndicator.setIndeterminate(true);
@@ -255,6 +257,41 @@ public abstract class PageView extends ViewGroup {
link.rect.right*scale, link.rect.bottom*scale,
paint);
}
+
+ if (mSelectBox != null && mText != null) {
+ paint.setColor(HIGHLIGHT_COLOR);
+
+ ArrayList<TextWord[]> lines = new ArrayList<TextWord[]>();
+ for (TextWord[] line : mText)
+ if (line[0].bottom > mSelectBox.top && line[0].top < mSelectBox.bottom)
+ lines.add(line);
+
+ Iterator<TextWord[]> it = lines.iterator();
+ while (it.hasNext()) {
+ TextWord[] line = it.next();
+ boolean startLine = line[0].top < mSelectBox.top;
+ boolean endLine = line[0].bottom > mSelectBox.bottom;
+ float start = Float.NEGATIVE_INFINITY;
+ float end = Float.POSITIVE_INFINITY;
+
+ if (startLine && endLine) {
+ start = Math.min(mSelectBox.left, mSelectBox.right);
+ end = Math.max(mSelectBox.left, mSelectBox.right);
+ } else if (startLine) {
+ start = mSelectBox.left;
+ } else if (endLine) {
+ end = mSelectBox.right;
+ }
+
+ RectF rect = new RectF();
+ for (TextWord word : line)
+ if (word.right > start && word.left < end)
+ rect.union(word);
+
+ if (!rect.isEmpty())
+ canvas.drawRect(rect.left*scale, rect.top*scale, rect.right*scale, rect.bottom*scale, paint);
+ }
+ }
}
};
@@ -275,6 +312,35 @@ public abstract class PageView extends ViewGroup {
mSearchView.invalidate();
}
+ public void selectText(float x0, float y0, float x1, float y1) {
+ float scale = mSourceScale*(float)getWidth()/(float)mSize.x;
+ float docRelX0 = (x0 - getLeft())/scale;
+ float docRelY0 = (y0 - getTop())/scale;
+ float docRelX1 = (x1 - getLeft())/scale;
+ float docRelY1 = (y1 - getTop())/scale;
+ // Order on Y but maintain the point grouping
+ if (docRelY0 <= docRelY1)
+ mSelectBox = new RectF(docRelX0, docRelY0, docRelX1, docRelY1);
+ else
+ mSelectBox = new RectF(docRelX1, docRelY1, docRelX0, docRelY0);
+
+ if (mText == null) {
+ mGetText = new AsyncTask<Void,Void,TextWord[][]>() {
+ @Override
+ protected TextWord[][] doInBackground(Void... params) {
+ return getText();
+ }
+ @Override
+ protected void onPostExecute(TextWord[][] result) {
+ mText = result;
+ mSearchView.invalidate();
+ }
+ };
+
+ mGetText.execute();
+ }
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int x, y;