summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
Diffstat (limited to 'android')
-rw-r--r--android/ReadMe.txt17
-rw-r--r--android/jni/mupdf.c92
-rw-r--r--android/res/layout/textentry.xml8
-rw-r--r--android/src/com/artifex/mupdf/MuPDFCore.java33
-rw-r--r--android/src/com/artifex/mupdf/MuPDFPageView.java72
-rw-r--r--android/src/com/artifex/mupdf/WidgetType.java8
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
+}