diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2013-06-19 15:29:44 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2013-06-20 16:45:35 +0200 |
commit | 0a927854a10e1e6b9770a81e2e1d9f3093631757 (patch) | |
tree | 3d65d820d9fdba2d0d394d99c36290c851b78ca0 /platform/android/src/com/artifex/mupdfdemo/MuPDFPageView.java | |
parent | 1ae8f19179c5f0f8c6352b3c7855465325d5449a (diff) | |
download | mupdf-0a927854a10e1e6b9770a81e2e1d9f3093631757.tar.xz |
Rearrange source files.
Diffstat (limited to 'platform/android/src/com/artifex/mupdfdemo/MuPDFPageView.java')
-rw-r--r-- | platform/android/src/com/artifex/mupdfdemo/MuPDFPageView.java | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/platform/android/src/com/artifex/mupdfdemo/MuPDFPageView.java b/platform/android/src/com/artifex/mupdfdemo/MuPDFPageView.java new file mode 100644 index 00000000..043b90ab --- /dev/null +++ b/platform/android/src/com/artifex/mupdfdemo/MuPDFPageView.java @@ -0,0 +1,502 @@ +package com.artifex.mupdfdemo; + +import java.util.ArrayList; + +import android.app.AlertDialog; +import android.content.ClipData; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Bitmap; +import android.graphics.Point; +import android.graphics.PointF; +import android.graphics.RectF; +import android.view.LayoutInflater; +import android.view.WindowManager; +import android.widget.EditText; + +abstract class PassClickResultVisitor { + public abstract void visitText(PassClickResultText result); + public abstract void visitChoice(PassClickResultChoice result); +} + +class PassClickResult { + public final boolean changed; + + public PassClickResult(boolean _changed) { + changed = _changed; + } + + public void acceptVisitor(PassClickResultVisitor visitor) { + } +} + +class PassClickResultText extends PassClickResult { + public final String text; + + public PassClickResultText(boolean _changed, String _text) { + super(_changed); + text = _text; + } + + public void acceptVisitor(PassClickResultVisitor visitor) { + visitor.visitText(this); + } +} + +class PassClickResultChoice extends PassClickResult { + public final String [] options; + public final String [] selected; + + public PassClickResultChoice(boolean _changed, String [] _options, String [] _selected) { + super(_changed); + options = _options; + selected = _selected; + } + + public void acceptVisitor(PassClickResultVisitor visitor) { + visitor.visitChoice(this); + } +} + +public class MuPDFPageView extends PageView implements MuPDFView { + private final MuPDFCore mCore; + private AsyncTask<Void,Void,PassClickResult> mPassClick; + private RectF mWidgetAreas[]; + private Annotation mAnnotations[]; + private int mSelectedAnnotationIndex = -1; + private AsyncTask<Void,Void,RectF[]> mLoadWidgetAreas; + private AsyncTask<Void,Void,Annotation[]> mLoadAnnotations; + private AlertDialog.Builder mTextEntryBuilder; + private AlertDialog.Builder mChoiceEntryBuilder; + private AlertDialog mTextEntry; + private EditText mEditText; + private AsyncTask<String,Void,Boolean> mSetWidgetText; + private AsyncTask<String,Void,Void> mSetWidgetChoice; + private AsyncTask<PointF[],Void,Void> mAddStrikeOut; + private AsyncTask<PointF[][],Void,Void> mAddInk; + private AsyncTask<Integer,Void,Void> mDeleteAnnotation; + private Runnable changeReporter; + + public MuPDFPageView(Context c, MuPDFCore core, Point parentSize) { + super(c, parentSize); + mCore = core; + mTextEntryBuilder = new AlertDialog.Builder(c); + mTextEntryBuilder.setTitle(getContext().getString(R.string.fill_out_text_field)); + LayoutInflater inflater = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mEditText = (EditText)inflater.inflate(R.layout.textentry, null); + mTextEntryBuilder.setView(mEditText); + mTextEntryBuilder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + mTextEntryBuilder.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + mSetWidgetText = new AsyncTask<String,Void,Boolean> () { + @Override + protected Boolean doInBackground(String... arg0) { + return mCore.setFocusedWidgetText(mPageNumber, arg0[0]); + } + @Override + protected void onPostExecute(Boolean result) { + changeReporter.run(); + if (!result) + invokeTextDialog(mEditText.getText().toString()); + } + }; + + mSetWidgetText.execute(mEditText.getText().toString()); + } + }); + mTextEntry = mTextEntryBuilder.create(); + + mChoiceEntryBuilder = new AlertDialog.Builder(c); + mChoiceEntryBuilder.setTitle(getContext().getString(R.string.choose_value)); + } + + public LinkInfo hitLink(float x, float y) { + // Since link highlighting was implemented, the super class + // PageView has had sufficient information to be able to + // perform this method directly. Making that change would + // make MuPDFCore.hitLinkPage superfluous. + float scale = mSourceScale*(float)getWidth()/(float)mSize.x; + float docRelX = (x - getLeft())/scale; + float docRelY = (y - getTop())/scale; + + for (LinkInfo l: mLinks) + if (l.rect.contains(docRelX, docRelY)) + return l; + + return null; + } + + private void invokeTextDialog(String text) { + mEditText.setText(text); + mTextEntry.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + mTextEntry.show(); + } + + private void invokeChoiceDialog(final String [] options) { + mChoiceEntryBuilder.setItems(options, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + mSetWidgetChoice = new AsyncTask<String,Void,Void>() { + @Override + protected Void doInBackground(String... params) { + String [] sel = {params[0]}; + mCore.setFocusedWidgetChoiceSelected(sel); + return null; + } + + @Override + protected void onPostExecute(Void result) { + changeReporter.run(); + } + }; + + mSetWidgetChoice.execute(options[which]); + } + }); + AlertDialog dialog = mChoiceEntryBuilder.create(); + dialog.show(); + } + + public void setChangeReporter(Runnable reporter) { + changeReporter = reporter; + } + + public Hit passClickEvent(float x, float y) { + float scale = mSourceScale*(float)getWidth()/(float)mSize.x; + final float docRelX = (x - getLeft())/scale; + final float docRelY = (y - getTop())/scale; + boolean hit = false; + int i; + + if (mAnnotations != null) { + for (i = 0; i < mAnnotations.length; i++) + if (mAnnotations[i].contains(docRelX, docRelY)) { + hit = true; + break; + } + + if (hit) { + switch (mAnnotations[i].type) { + case HIGHLIGHT: + case UNDERLINE: + case SQUIGGLY: + case STRIKEOUT: + case INK: + mSelectedAnnotationIndex = i; + setItemSelectBox(mAnnotations[i]); + return Hit.Annotation; + } + } + } + + mSelectedAnnotationIndex = -1; + setItemSelectBox(null); + + if (!MuPDFCore.javascriptSupported()) + return Hit.Nothing; + + if (mWidgetAreas != null) { + for (i = 0; i < mWidgetAreas.length && !hit; i++) + if (mWidgetAreas[i].contains(docRelX, docRelY)) + hit = true; + } + + if (hit) { + mPassClick = new AsyncTask<Void,Void,PassClickResult>() { + @Override + protected PassClickResult doInBackground(Void... arg0) { + return mCore.passClickEvent(mPageNumber, docRelX, docRelY); + } + + @Override + protected void onPostExecute(PassClickResult result) { + if (result.changed) { + changeReporter.run(); + } + + result.acceptVisitor(new PassClickResultVisitor() { + @Override + public void visitText(PassClickResultText result) { + invokeTextDialog(result.text); + } + + @Override + public void visitChoice(PassClickResultChoice result) { + invokeChoiceDialog(result.options); + } + }); + } + }; + + mPassClick.execute(); + return Hit.Widget; + } + + return Hit.Nothing; + } + + public boolean copySelection() { + final StringBuilder text = new StringBuilder(); + + processSelectedText(new TextProcessor() { + StringBuilder line; + + public void onStartLine() { + line = new StringBuilder(); + } + + public void onWord(TextWord word) { + if (line.length() > 0) + line.append(' '); + line.append(word.w); + } + + public void onEndLine() { + if (text.length() > 0) + text.append('\n'); + text.append(line); + } + }); + + if (text.length() == 0) + return false; + + int currentApiVersion = android.os.Build.VERSION.SDK_INT; + if (currentApiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) { + android.content.ClipboardManager cm = (android.content.ClipboardManager)mContext.getSystemService(Context.CLIPBOARD_SERVICE); + + cm.setPrimaryClip(ClipData.newPlainText("MuPDF", text)); + } else { + android.text.ClipboardManager cm = (android.text.ClipboardManager)mContext.getSystemService(Context.CLIPBOARD_SERVICE); + cm.setText(text); + } + + deselectText(); + + return true; + } + + public boolean markupSelection(final Annotation.Type type) { + final ArrayList<PointF> quadPoints = new ArrayList<PointF>(); + processSelectedText(new TextProcessor() { + RectF rect; + + public void onStartLine() { + rect = new RectF(); + } + + public void onWord(TextWord word) { + rect.union(word); + } + + public void onEndLine() { + if (!rect.isEmpty()) { + quadPoints.add(new PointF(rect.left, rect.bottom)); + quadPoints.add(new PointF(rect.right, rect.bottom)); + quadPoints.add(new PointF(rect.right, rect.top)); + quadPoints.add(new PointF(rect.left, rect.top)); + } + } + }); + + if (quadPoints.size() == 0) + return false; + + mAddStrikeOut = new AsyncTask<PointF[],Void,Void>() { + @Override + protected Void doInBackground(PointF[]... params) { + addMarkup(params[0], type); + return null; + } + + @Override + protected void onPostExecute(Void result) { + loadAnnotations(); + update(); + } + }; + + mAddStrikeOut.execute(quadPoints.toArray(new PointF[quadPoints.size()])); + + deselectText(); + + return true; + } + + public void deleteSelectedAnnotation() { + if (mSelectedAnnotationIndex != -1) { + if (mDeleteAnnotation != null) + mDeleteAnnotation.cancel(true); + + mDeleteAnnotation = new AsyncTask<Integer,Void,Void>() { + @Override + protected Void doInBackground(Integer... params) { + mCore.deleteAnnotation(mPageNumber, params[0]); + return null; + } + + @Override + protected void onPostExecute(Void result) { + loadAnnotations(); + update(); + } + }; + + mDeleteAnnotation.execute(mSelectedAnnotationIndex); + + mSelectedAnnotationIndex = -1; + setItemSelectBox(null); + } + } + + public void deselectAnnotation() { + mSelectedAnnotationIndex = -1; + setItemSelectBox(null); + } + + public boolean saveDraw() { + PointF[][] path = getDraw(); + + if (path == null) + return false; + + if (mAddInk != null) { + mAddInk.cancel(true); + mAddInk = null; + } + mAddInk = new AsyncTask<PointF[][],Void,Void>() { + @Override + protected Void doInBackground(PointF[][]... params) { + mCore.addInkAnnotation(mPageNumber, params[0]); + return null; + } + + @Override + protected void onPostExecute(Void result) { + loadAnnotations(); + update(); + } + + }; + + mAddInk.execute(getDraw()); + cancelDraw(); + + return true; + } + + @Override + protected Bitmap drawPage(int sizeX, int sizeY, + int patchX, int patchY, int patchWidth, int patchHeight) { + return mCore.drawPage(mPageNumber, sizeX, sizeY, patchX, patchY, patchWidth, patchHeight); + } + + @Override + protected Bitmap updatePage(BitmapHolder h, int sizeX, int sizeY, + int patchX, int patchY, int patchWidth, int patchHeight) { + return mCore.updatePage(h, mPageNumber, sizeX, sizeY, patchX, patchY, patchWidth, patchHeight); + } + + @Override + protected LinkInfo[] getLinkInfo() { + return mCore.getPageLinks(mPageNumber); + } + + @Override + protected TextWord[][] getText() { + return mCore.textLines(mPageNumber); + } + + @Override + protected void addMarkup(PointF[] quadPoints, Annotation.Type type) { + mCore.addMarkupAnnotation(mPageNumber, quadPoints, type); + } + + private void loadAnnotations() { + mAnnotations = null; + if (mLoadAnnotations != null) + mLoadAnnotations.cancel(true); + mLoadAnnotations = new AsyncTask<Void,Void,Annotation[]> () { + @Override + protected Annotation[] doInBackground(Void... params) { + return mCore.getAnnoations(mPageNumber); + } + + @Override + protected void onPostExecute(Annotation[] result) { + mAnnotations = result; + } + }; + + mLoadAnnotations.execute(); + } + + @Override + public void setPage(final int page, PointF size) { + loadAnnotations(); + + mLoadWidgetAreas = new AsyncTask<Void,Void,RectF[]> () { + @Override + protected RectF[] doInBackground(Void... arg0) { + return mCore.getWidgetAreas(page); + } + + @Override + protected void onPostExecute(RectF[] result) { + mWidgetAreas = result; + } + }; + + mLoadWidgetAreas.execute(); + + super.setPage(page, size); + } + + public void setScale(float scale) { + // This type of view scales automatically to fit the size + // determined by the parent view groups during layout + } + + @Override + public void releaseResources() { + if (mPassClick != null) { + mPassClick.cancel(true); + mPassClick = null; + } + + if (mLoadWidgetAreas != null) { + mLoadWidgetAreas.cancel(true); + mLoadWidgetAreas = null; + } + + if (mLoadAnnotations != null) { + mLoadAnnotations.cancel(true); + mLoadAnnotations = null; + } + + if (mSetWidgetText != null) { + mSetWidgetText.cancel(true); + mSetWidgetText = null; + } + + if (mSetWidgetChoice != null) { + mSetWidgetChoice.cancel(true); + mSetWidgetChoice = null; + } + + if (mAddStrikeOut != null) { + mAddStrikeOut.cancel(true); + mAddStrikeOut = null; + } + + if (mDeleteAnnotation != null) { + mDeleteAnnotation.cancel(true); + mDeleteAnnotation = null; + } + + super.releaseResources(); + } +} |