diff options
Diffstat (limited to 'android')
-rw-r--r-- | android/ReadMe.txt | 17 | ||||
-rw-r--r-- | android/jni/mupdf.c | 92 | ||||
-rw-r--r-- | android/res/layout/textentry.xml | 8 | ||||
-rw-r--r-- | android/src/com/artifex/mupdf/MuPDFCore.java | 33 | ||||
-rw-r--r-- | android/src/com/artifex/mupdf/MuPDFPageView.java | 72 | ||||
-rw-r--r-- | android/src/com/artifex/mupdf/WidgetType.java | 8 |
6 files changed, 223 insertions, 7 deletions
diff --git a/android/ReadMe.txt b/android/ReadMe.txt index c3f33dea..dfe620e1 100644 --- a/android/ReadMe.txt +++ b/android/ReadMe.txt @@ -168,3 +168,20 @@ our app), execute: adb logcat Good luck! + +Forms support +~~~~~~~~~~~~~ + +To build with PDF forms support, the only change is to the ndk-build stage. +Run: + + V8_BUILD=yes ndk-build + +The build will need v8 headers and libraries to be present in the thirdparty +directory. The files assumed are: + + thirdparty/v8-3.9/android/libv8_base.a + thirdparty/v8-3.9/android/libv8_snapshot.a + thirdparty/v8-3.9/include/v8.h + thirdparty/v8-3.9/include/v8stdint.h + diff --git a/android/jni/mupdf.c b/android/jni/mupdf.c index d4105115..2ec02bf8 100644 --- a/android/jni/mupdf.c +++ b/android/jni/mupdf.c @@ -22,6 +22,14 @@ #define MAX_SEARCH_HITS (500) +enum +{ + NONE, + TEXT, + LISTBOX, + COMBOBOX +}; + /* Globals */ fz_colorspace *colorspace; fz_document *doc; @@ -769,3 +777,87 @@ Java_com_artifex_mupdf_MuPDFCore_passClickEventInternal(JNIEnv * env, jobject th return changed; } + +JNIEXPORT jstring JNICALL +Java_com_artifex_mupdf_MuPDFCore_getFocusedWidgetTextInternal(JNIEnv * env, jobject thiz) +{ + char *text = ""; + + fz_try(ctx) + { + fz_interactive *idoc = fz_interact(doc); + + if (idoc) + { + fz_widget *focus = fz_focused_widget(idoc); + + if (focus) + text = fz_text_widget_text(idoc, focus); + } + } + fz_catch(ctx) + { + LOGE("getFocusedWidgetText failed: %s", ctx->error->message); + } + + return (*env)->NewStringUTF(env, text); +} + +JNIEXPORT int JNICALL +Java_com_artifex_mupdf_MuPDFCore_setFocusedWidgetTextInternal(JNIEnv * env, jobject thiz, jstring jtext) +{ + const char *text; + int result = 0; + + text = (*env)->GetStringUTFChars(env, jtext, NULL); + if (text == NULL) + { + LOGE("Failed to get text"); + return 0; + } + + fz_try(ctx) + { + fz_interactive *idoc = fz_interact(doc); + + if (idoc) + { + fz_widget *focus = fz_focused_widget(idoc); + + if (focus) + result = fz_text_widget_set_text(idoc, focus, text); + } + } + fz_catch(ctx) + { + LOGE("setFocusedWidgetText failed: %s", ctx->error->message); + } + + (*env)->ReleaseStringUTFChars(env, jtext, text); + + return result; +} + +JNIEXPORT int JNICALL +Java_com_artifex_mupdf_MuPDFCore_getFocusedWidgetTypeInternal(JNIEnv * env, jobject thiz) +{ + fz_interactive *idoc = fz_interact(doc); + fz_widget *focus; + + if (idoc == NULL) + return NONE; + + focus = fz_focused_widget(idoc); + + if (focus == NULL) + return NONE; + + switch (fz_widget_get_type(focus)) + { + case FZ_WIDGET_TYPE_TEXT: return TEXT; + case FZ_WIDGET_TYPE_LISTBOX: return LISTBOX; + case FZ_WIDGET_TYPE_COMBOBOX: return COMBOBOX; + } + + return NONE; +} diff --git a/android/res/layout/textentry.xml b/android/res/layout/textentry.xml new file mode 100644 index 00000000..0ac4b44d --- /dev/null +++ b/android/res/layout/textentry.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<EditText xmlns:android="http://schemas.android.com/apk/res/android" + android:singleLine="false" + android:minLines="3" + android:inputType="textMultiLine" + android:layout_width="match_parent" + android:layout_height="wrap_content" > +</EditText>
\ No newline at end of file diff --git a/android/src/com/artifex/mupdf/MuPDFCore.java b/android/src/com/artifex/mupdf/MuPDFCore.java index e7653f9e..f2017f77 100644 --- a/android/src/com/artifex/mupdf/MuPDFCore.java +++ b/android/src/com/artifex/mupdf/MuPDFCore.java @@ -31,6 +31,9 @@ public class MuPDFCore private static native RectF[] searchPage(String text); private static native int getPageLink(int page, float x, float y); private static native int passClickEventInternal(int page, float x, float y); + private static native int setFocusedWidgetTextInternal(String text); + private static native String getFocusedWidgetTextInternal(); + private static native int getFocusedWidgetTypeInternal(); private static native LinkInfo [] getPageLinksInternal(int page); private static native RectF[] getWidgetAreasInternal(int page); private static native OutlineItem [] getOutlineInternal(); @@ -95,8 +98,21 @@ public class MuPDFCore return bm; } - public synchronized boolean passClickEvent(int page, float x, float y) { + public synchronized PassClickResult passClickEvent(int page, float x, float y) { boolean changed = passClickEventInternal(page, x, y) != 0; + int type = getFocusedWidgetTypeInternal(); + WidgetType wtype = WidgetType.values()[type]; + String text; + + switch (wtype) + { + case TEXT: + text = getFocusedWidgetTextInternal(); + break; + default: + text = ""; + break; + } if (changed) { if (page == pageNum) @@ -105,7 +121,20 @@ public class MuPDFCore markDirtyInternal(page); } - return changed; + return new PassClickResult(changed, wtype, text); + } + + public synchronized boolean setFocusedWidgetText(int page, String text) { + boolean success; + gotoPage(page); + success = setFocusedWidgetTextInternal(text) != 0 ? true : false; + + if (success) { + pageNum = -1; + markDirtyInternal(page); + } + + return success; } public synchronized int hitLinkPage(int page, float x, float y) { diff --git a/android/src/com/artifex/mupdf/MuPDFPageView.java b/android/src/com/artifex/mupdf/MuPDFPageView.java index 9cb430ef..a2063f59 100644 --- a/android/src/com/artifex/mupdf/MuPDFPageView.java +++ b/android/src/com/artifex/mupdf/MuPDFPageView.java @@ -1,20 +1,70 @@ package com.artifex.mupdf; +import android.app.AlertDialog; 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; + +class PassClickResult { + public final boolean changed; + public final WidgetType type; + public final String text; + + public PassClickResult(boolean _changed, WidgetType _type, String _text) { + changed = _changed; + type = _type; + text = _text; + } +} public class MuPDFPageView extends PageView { private final MuPDFCore mCore; - private SafeAsyncTask<Void,Void,Boolean> mPassClick; + private SafeAsyncTask<Void,Void,PassClickResult> mPassClick; private RectF mWidgetAreas[]; private SafeAsyncTask<Void,Void,RectF[]> mLoadWidgetAreas; + private AlertDialog.Builder mTextEntryBuilder; + private AlertDialog mTextEntry; + private EditText mEditText; + private SafeAsyncTask<String,Void,Boolean> mSetWidgetText; public MuPDFPageView(Context c, MuPDFCore core, Point parentSize) { super(c, parentSize); mCore = core; + mTextEntryBuilder = new AlertDialog.Builder(c); + mTextEntryBuilder.setTitle("MuPDF: 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("Cancel", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + mTextEntryBuilder.setPositiveButton("Okay", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + mSetWidgetText = new SafeAsyncTask<String,Void,Boolean> () { + @Override + protected Boolean doInBackground(String... arg0) { + return mCore.setFocusedWidgetText(mPageNumber, arg0[0]); + } + @Override + protected void onPostExecute(Boolean result) { + update(); + if (!result) + invokeTextDialog(mEditText.getText().toString()); + } + }; + + mSetWidgetText.execute(mEditText.getText().toString()); + } + }); + mTextEntry = mTextEntryBuilder.create(); } public int hitLinkPage(float x, float y) { @@ -29,6 +79,12 @@ public class MuPDFPageView extends PageView { return mCore.hitLinkPage(mPageNumber, docRelX, docRelY); } + private void invokeTextDialog(String text) { + mEditText.setText(text); + mTextEntry.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + mTextEntry.show(); + } + public boolean passClickEvent(float x, float y) { float scale = mSourceScale*(float)getWidth()/(float)mSize.x; final float docRelX = (x - getLeft())/scale; @@ -42,17 +98,23 @@ public class MuPDFPageView extends PageView { } if (hitWidget) { - mPassClick = new SafeAsyncTask<Void,Void,Boolean>() { + mPassClick = new SafeAsyncTask<Void,Void,PassClickResult>() { @Override - protected Boolean doInBackground(Void... arg0) { + protected PassClickResult doInBackground(Void... arg0) { return mCore.passClickEvent(mPageNumber, docRelX, docRelY); } @Override - protected void onPostExecute(Boolean result) { - if (result) { + protected void onPostExecute(PassClickResult result) { + if (result.changed) { update(); } + + switch(result.type) { + case TEXT: + invokeTextDialog(result.text); + break; + } } }; diff --git a/android/src/com/artifex/mupdf/WidgetType.java b/android/src/com/artifex/mupdf/WidgetType.java new file mode 100644 index 00000000..170232f4 --- /dev/null +++ b/android/src/com/artifex/mupdf/WidgetType.java @@ -0,0 +1,8 @@ +package com.artifex.mupdf; + +public enum WidgetType { + NONE, + TEXT, + LISTBOX, + COMBOBOX +} |