summaryrefslogtreecommitdiff
path: root/platform/android
diff options
context:
space:
mode:
authorfred ross-perry <fredross-perry@Fred-Ross-Perrys-Computer.local>2016-08-26 09:50:48 -0700
committerfred ross-perry <fredross-perry@Fred-Ross-Perrys-Computer.local>2016-09-14 08:53:32 -0700
commitffbe3db71ea0f96b408e22418547a8ff898f380e (patch)
tree2f34407ef3c229a949b0a2b514e307297437a169 /platform/android
parente18d11b63af0ca8a302f23b32ffc24578c830989 (diff)
downloadmupdf-ffbe3db71ea0f96b408e22418547a8ff898f380e.tar.xz
Android example - drawing ink annotations
This commit puts in the UI for drawing with color and line thickness. But it does not yet save this to the document.
Diffstat (limited to 'platform/android')
-rw-r--r--platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/ColorDialog.java204
-rw-r--r--platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocActivityView.java126
-rwxr-xr-xplatform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocPageView.java371
-rw-r--r--platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocView.java227
-rw-r--r--platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/LineWidthDialog.java128
-rw-r--r--platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/ToolbarButton.java31
-rw-r--r--platform/android/example/mupdf/src/main/res/drawable/colors.xml13
-rwxr-xr-xplatform/android/example/mupdf/src/main/res/drawable/icon_delete.xml20
-rw-r--r--platform/android/example/mupdf/src/main/res/drawable/icon_draw.xml26
-rwxr-xr-xplatform/android/example/mupdf/src/main/res/drawable/icon_highlight.xml21
-rwxr-xr-xplatform/android/example/mupdf/src/main/res/drawable/icon_line_color.xml14
-rwxr-xr-xplatform/android/example/mupdf/src/main/res/drawable/icon_line_thickness.xml14
-rwxr-xr-xplatform/android/example/mupdf/src/main/res/drawable/icon_note.xml30
-rw-r--r--platform/android/example/mupdf/src/main/res/drawable/number_format_popup.xml13
-rw-r--r--platform/android/example/mupdf/src/main/res/drawable/toolbar_button2.xml17
-rw-r--r--platform/android/example/mupdf/src/main/res/drawable/transparent_color_swatch.xml22
-rw-r--r--platform/android/example/mupdf/src/main/res/drawable/wheel_bg.xml29
-rw-r--r--platform/android/example/mupdf/src/main/res/drawable/wheel_val.xml27
-rw-r--r--platform/android/example/mupdf/src/main/res/layout/annotate_toolbar.xml223
-rw-r--r--platform/android/example/mupdf/src/main/res/layout/colors.xml95
-rw-r--r--platform/android/example/mupdf/src/main/res/layout/file_toolbar.xml10
-rw-r--r--platform/android/example/mupdf/src/main/res/layout/line_width_dialog.xml15
-rw-r--r--platform/android/example/mupdf/src/main/res/layout/line_width_item.xml25
-rw-r--r--platform/android/example/mupdf/src/main/res/layout/pages_toolbar.xml6
-rw-r--r--platform/android/example/mupdf/src/main/res/layout/search_toolbar.xml4
-rw-r--r--platform/android/example/mupdf/src/main/res/values/strings.xml3
-rw-r--r--platform/android/example/mupdf/src/main/res/values/styles.xml11
27 files changed, 1690 insertions, 35 deletions
diff --git a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/ColorDialog.java b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/ColorDialog.java
new file mode 100644
index 00000000..5da38c2e
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/ColorDialog.java
@@ -0,0 +1,204 @@
+package com.artifex.mupdf.android;
+
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
+import android.widget.TextView;
+
+import com.artifex.mupdf.fitz.R;
+
+public class ColorDialog implements View.OnTouchListener, PopupWindow.OnDismissListener {
+
+ // these are set in the constructor.
+ private final Context mContext;
+ private final View mAnchor;
+ private final ColorChangedListener mListener;
+ private final int mDialogType;
+ private boolean mAutoDismiss = false;
+
+ // only one ColorDialog at a time please.
+ private static ColorDialog singleton = null;
+
+ // a popup window for us.
+ private PopupWindow popupWindow;
+
+ // two different variants of this dilog
+ public static final int FG_COLORS = 1;
+ public static final int BG_COLORS = 2;
+
+ // allowable foreground colors. These come from UE2FileViewerApp
+ private final String mFgColors[] = {"#000000", "#FFFFFF", "#D8D8D8", "#808080", "#EEECE1", "#1F497D",
+ "#0070C0", "#C0504D", "#9BBB59", "#8064A2", "#4BACC6", "#F79646", "#FF0000",
+ "#FFFF00", "#DBE5F1", "#F2DCDB", "#EBF1DD", "#00B050"};
+
+ // constructor
+ public ColorDialog(int dialogType, Context context, View anchor, ColorChangedListener listener, boolean autoDismiss)
+ {
+ mContext = context;
+ mAnchor = anchor;
+ mListener = listener;
+ mDialogType = dialogType;
+ mAutoDismiss = autoDismiss;
+ }
+
+ // whether or not to show the title
+ private boolean mShowTitle = true;
+ public void setShowTitle(boolean val) {mShowTitle = val;}
+
+ // time to show the dialog
+ public void show()
+ {
+ // remember us
+ singleton = this;
+
+ // get the layout
+ View popupView = LayoutInflater.from(mContext).inflate(R.layout.colors, null);
+
+ // set the title
+ TextView tv = (TextView)popupView.findViewById(R.id.color_dialog_title);
+ if (mShowTitle) {
+ if (mDialogType == BG_COLORS)
+ tv.setText(mContext.getString(R.string.background));
+ else
+ tv.setText(mContext.getString(R.string.color));
+ }
+ else {
+ tv.setVisibility(View.GONE);
+ }
+
+ // choose the list of colors to use
+ String colors[] = mFgColors;
+
+ // get the three rows of buttons from the layout
+ LinearLayout rows[] = new LinearLayout[3];
+ rows[0] = (LinearLayout)popupView.findViewById(R.id.fontcolors_row1);
+ rows[1] = (LinearLayout)popupView.findViewById(R.id.fontcolors_row2);
+ rows[2] = (LinearLayout)popupView.findViewById(R.id.fontcolors_row3);
+
+ // Set up a button for each color.
+ // Hide buttons for which there are no colors.
+ int icolor = 0;
+ int irow;
+ for (irow=0; irow<rows.length; irow++) {
+ LinearLayout row = rows[irow];
+ int count = row.getChildCount();
+ for (int i=0; i<count; i++) {
+ Button button = (Button)row.getChildAt(i);
+ if (icolor+1 <= colors.length) {
+ button.setVisibility(View.VISIBLE);
+ button.setBackgroundColor(Color.parseColor(colors[icolor]));
+ button.setTag(colors[icolor]);
+ button.setOnClickListener(new Button.OnClickListener() {
+ @Override
+ public void onClick(View v)
+ {
+ mListener.onColorChanged((String)v.getTag());
+ if (mAutoDismiss)
+ dismiss();
+ }
+ });
+ }
+ else {
+ button.setVisibility(View.GONE);
+ }
+ icolor++;
+ }
+ }
+
+ // Set up the transaparent button if we're doing background colors.
+ Button tpb = (Button) popupView.findViewById(R.id.transparent_color_button);
+ if (mDialogType==ColorDialog.BG_COLORS) {
+ tpb.setVisibility(View.VISIBLE);
+ tpb.setOnClickListener(new Button.OnClickListener() {
+ @Override
+ public void onClick(View v)
+ {
+ mListener.onColorChanged((String)v.getTag());
+ }
+ });
+ }
+ else
+ tpb.setVisibility(View.GONE);
+
+ // get screen width
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ DisplayMetrics metrics = new DisplayMetrics();
+ wm.getDefaultDisplay().getMetrics(metrics);
+ int screenWidth = metrics.widthPixels;
+
+ // put everything in a popup window and show it.
+ // by default that's the upper right corner, but the dialog is draggable.
+ popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ popupWindow.setFocusable(true);
+ popupView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ popupWindow.showAtLocation(mAnchor, Gravity.TOP|Gravity.LEFT, screenWidth-popupView.getMeasuredWidth()-15, 100);
+ popupWindow.setClippingEnabled(false);
+ // this enables dragging
+ popupView.setOnTouchListener(this);
+ // this allows us to know when the popup is being dismissed
+ popupWindow.setOnDismissListener(this);
+ }
+
+ // internal function to dismiss the popup.
+ public void dismiss()
+ {
+ popupWindow.dismiss();
+ singleton = null;
+ }
+
+ // static function to dismiss the popup.
+ static public void finish()
+ {
+ if (singleton!=null)
+ singleton.dismiss();
+ }
+
+ // this function is called when the user taps outside the popup.
+ // we make sure to dismiss it properly.
+ @Override
+ public void onDismiss() {
+ dismiss();
+ }
+
+ // we're an onTouch listener for the popup window.
+ // we use that to allow for dragging the popup around.
+
+ private int start[];
+ private final Point down = new Point();
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+
+ start = new int[2];
+ popupWindow.getContentView().getLocationOnScreen(start);
+ down.set((int) event.getRawX(), (int) event.getRawY());
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+
+ int dx = down.x - (int)event.getRawX();
+ int dy = down.y - (int)event.getRawY();
+ popupWindow.update(start[0]-dx, start[1]-dy,-1, -1, true);
+ break;
+ }
+ return true;
+ }
+
+ public interface ColorChangedListener {
+ void onColorChanged(String color);
+ }
+
+}
diff --git a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocActivityView.java b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocActivityView.java
index e56ed43d..26624ab5 100644
--- a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocActivityView.java
+++ b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocActivityView.java
@@ -2,6 +2,7 @@ package com.artifex.mupdf.android;
import android.app.Activity;
import android.content.Context;
+import android.graphics.Color;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.util.Log;
@@ -26,7 +27,7 @@ import com.artifex.mupdf.fitz.Link;
import com.artifex.mupdf.fitz.Outline;
import com.artifex.mupdf.fitz.R;
-public class DocActivityView extends FrameLayout implements TabHost.OnTabChangeListener, View.OnClickListener
+public class DocActivityView extends FrameLayout implements TabHost.OnTabChangeListener, View.OnClickListener, DocView.SelectionChangeListener
{
private DocView mDocView;
private DocReflowView mDocReflowView;
@@ -55,7 +56,15 @@ public class DocActivityView extends FrameLayout implements TabHost.OnTabChangeL
private ImageButton mPrintButton;
private ImageButton mShareButton;
private ImageButton mOpenInButton;
+
private ImageButton mToggleAnnotButton;
+ private ImageButton mHighlightButton;
+ private ImageButton mDeleteButton;
+
+ private ImageButton mNoteButton;
+ private ImageButton mDrawButton;
+ private ImageButton mLineColorButton;
+ private ImageButton mLineThicknessButton;
public DocActivityView(Context context)
{
@@ -356,6 +365,23 @@ public class DocActivityView extends FrameLayout implements TabHost.OnTabChangeL
mToggleAnnotButton = (ImageButton)findViewById(R.id.show_annot_button);
mToggleAnnotButton.setOnClickListener(this);
+ mHighlightButton = (ImageButton)findViewById(R.id.highlight_button);
+ mHighlightButton.setOnClickListener(this);
+
+ mNoteButton = (ImageButton)findViewById(R.id.note_button);
+ mNoteButton.setOnClickListener(this);
+
+ mDrawButton = (ImageButton)findViewById(R.id.draw_button);
+ mDrawButton.setOnClickListener(this);
+
+ mLineColorButton = (ImageButton)findViewById(R.id.line_color_button);
+ mLineColorButton.setOnClickListener(this);
+
+ mLineThicknessButton = (ImageButton)findViewById(R.id.line_thickness_button);
+ mLineThicknessButton.setOnClickListener(this);
+
+ mDeleteButton = (ImageButton)findViewById(R.id.delete_button);
+ mDeleteButton.setOnClickListener(this);
mDoc = new Document(path);
@@ -409,6 +435,10 @@ public class DocActivityView extends FrameLayout implements TabHost.OnTabChangeL
{
mDocPagesView.clone(mDocView);
}
+
+ mHighlightButton.setEnabled(false);
+ mDocView.setSelectionChangeListener(this);
+ onSelectionChanged();
}
public void showUI(boolean show)
@@ -481,10 +511,12 @@ public class DocActivityView extends FrameLayout implements TabHost.OnTabChangeL
{
if (v == mReflowButton)
onReflowButton();
+
if (v == mFirstPageButton)
onFirstPageButton();
if (v == mLastPageButton)
onLastPageButton();
+
if (v == mSearchButton)
onShowSearch();
if (v == mSearchText)
@@ -493,6 +525,7 @@ public class DocActivityView extends FrameLayout implements TabHost.OnTabChangeL
onSearchNextButton();
if (v == mSearchPreviousButton)
onSearchPreviousButton();
+
if (v == mBackButton)
onBackButton();
@@ -506,8 +539,22 @@ public class DocActivityView extends FrameLayout implements TabHost.OnTabChangeL
onShareButton();
if (v == mOpenInButton)
onOpenInButton();
+
if (v == mToggleAnnotButton)
onToggleAnnotButton();
+ if (v == mHighlightButton)
+ onHighlightButton();
+ if (v == mDeleteButton)
+ onDeleteButton();
+
+ if (v == mNoteButton)
+ onNoteButton();
+ if (v == mDrawButton)
+ onDrawButton();
+ if (v == mLineColorButton)
+ onLineColorButton();
+ if (v == mLineThicknessButton)
+ onLineThicknessButton();
}
public void onSearchNextButton()
@@ -647,6 +694,83 @@ public class DocActivityView extends FrameLayout implements TabHost.OnTabChangeL
mDocView.toggleAnnotations();
}
+ private void onHighlightButton()
+ {
+ mDocView.onHighlight();
+ }
+
+ private void onNoteButton()
+ {
+ mDocView.onNoteMode();
+ }
+
+ private void onDrawButton()
+ {
+ mDocView.onDrawMode();
+ }
+
+ private void onLineColorButton()
+ {
+ if (mDocView.getDrawMode() || mDocView.hasInkAnnotationSelected())
+ {
+ ColorDialog dlg = new ColorDialog(ColorDialog.BG_COLORS,
+ getContext(), mLineColorButton, new ColorDialog.ColorChangedListener()
+ {
+ @Override
+ public void onColorChanged(String color)
+ {
+ int icolor = Color.parseColor(color);
+ mDocView.setInkLineColor(icolor);
+ mLineColorButton.setColorFilter(icolor, PorterDuff.Mode.SRC_IN);
+ }
+ }, true);
+ dlg.setShowTitle(false);
+ dlg.show();
+ }
+ }
+
+ private void onLineThicknessButton()
+ {
+ if (mDocView.getDrawMode() || mDocView.hasInkAnnotationSelected())
+ {
+ float val = mDocView.getInkLineThickness();
+ LineWidthDialog.show(getContext(), mLineThicknessButton, val,
+ new LineWidthDialog.WidthChangedListener()
+ {
+ @Override
+ public void onWidthChanged(float value)
+ {
+ mDocView.setInkLineThickness(value);
+ }
+ });
+ }
+ }
+
+ private void onDeleteButton()
+ {
+ mDocView.onDelete();
+ }
+
+ public void onSelectionChanged()
+ {
+ boolean hasSel = mDocView.hasSelection();
+ boolean hasInkAnnotSel = mDocView.hasInkAnnotationSelected();
+
+ mHighlightButton.setEnabled(hasSel);
+
+ boolean noteMode = mDocView.getNoteMode();
+ mNoteButton.setSelected(noteMode);
+ findViewById(R.id.note_holder).setSelected(noteMode);
+
+ boolean drawMode = mDocView.getDrawMode();
+ mDrawButton.setSelected(drawMode);
+ mLineColorButton.setEnabled(drawMode || hasInkAnnotSel);
+ mLineThicknessButton.setEnabled(drawMode || hasInkAnnotSel);
+ mDeleteButton.setEnabled(!drawMode && hasInkAnnotSel);
+
+ findViewById(R.id.draw_tools_holder).setSelected(drawMode);
+ }
+
private OnDoneListener mDoneListener = null;
public void setOnDoneListener(OnDoneListener l) {mDoneListener = l;}
public interface OnDoneListener
diff --git a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocPageView.java b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocPageView.java
index 50f526f6..0bde1f03 100755
--- a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocPageView.java
+++ b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocPageView.java
@@ -7,10 +7,13 @@ import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
+import android.graphics.PointF;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.AsyncTask;
import android.support.v4.content.ContextCompat;
import android.util.Log;
+import android.util.TypedValue;
import android.view.KeyEvent.Callback;
import android.view.View;
import android.view.ViewGroup;
@@ -27,6 +30,8 @@ import com.artifex.mupdf.fitz.StructuredText;
import com.artifex.mupdf.fitz.android.AndroidDrawDevice;
import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.ListIterator;
public class DocPageView extends View implements Callback
{
@@ -550,6 +555,17 @@ public class DocPageView extends View implements Callback
canvas.drawRect(mHighlightingRect, mSearchHighlightPainter);
}
+ // draw ink annotations
+ if (mInkAnnots != null)
+ {
+ Iterator<InkAnnotation> it = mInkAnnots.iterator();
+ while (it.hasNext())
+ {
+ InkAnnotation annot = it.next();
+ annot.draw(canvas);
+ }
+ }
+
// draw blue dot
if (isMostVisible)
{
@@ -668,11 +684,24 @@ public class DocPageView extends View implements Callback
return screenToPage(p.x, p.y);
}
+ public PointF screenToPage(PointF p)
+ {
+ Point pp = screenToPage(new Point((int)p.x, (int)p.y));
+ return new PointF(pp.x, pp.y);
+ }
+
private double getFactor()
{
return mZoom * mScale * mResolution / 72f;
}
+ private double pageToScreen(double val)
+ {
+ double factor = getFactor();
+
+ return factor * val;
+ }
+
private Point screenToPage(int screenX, int screenY)
{
// convert to view-relative
@@ -702,6 +731,36 @@ public class DocPageView extends View implements Callback
return new Point(viewX, viewY);
}
+ public void pageToView(Point pageP, Point viewP)
+ {
+ double factor = getFactor();
+
+ int x = (int) (((double) pageP.x) * factor);
+ int y = (int) (((double) pageP.y) * factor);
+
+ viewP.set(x, y);
+ }
+
+ public void pageToView(PointF pageP, PointF viewP)
+ {
+ double factor = getFactor();
+
+ float x = (pageP.x * (float)factor);
+ float y = (pageP.y * (float)factor);
+
+ viewP.set(x, y);
+ }
+
+ private PointF pageToView(PointF pageP)
+ {
+ double factor = getFactor();
+
+ float x = (pageP.x * (float)factor);
+ float y = (pageP.y * (float)factor);
+
+ return new PointF(x, y);
+ }
+
public void pageToView(Rect pageR, Rect viewR)
{
double factor = getFactor();
@@ -751,6 +810,35 @@ public class DocPageView extends View implements Callback
public boolean onSingleTap(int x, int y)
{
+ // see if an ink annotation has been tapped on
+ if (mInkAnnots != null)
+ {
+ boolean hit = false;
+
+ // switch to page coordinates
+ Point pt = screenToPage(x, y);
+
+ // iterate in reverse order
+ ListIterator<InkAnnotation> li = mInkAnnots.listIterator(mInkAnnots.size());
+ while (li.hasPrevious())
+ {
+ InkAnnotation annot = li.previous();
+ annot.setSelected(false);
+ if(annot.hitTest(pt))
+ {
+ if (!hit)
+ annot.setSelected(true);
+ hit = true;
+ }
+ }
+
+ if (hit)
+ {
+ invalidate();
+ return true;
+ }
+ }
+
// NOTE: when double-tapping, a single-tap will also happen first.
// so that must be safe to do.
@@ -765,17 +853,53 @@ public class DocPageView extends View implements Callback
// during layout, a DocView-relative rect is calculated and stashed here.
private final Rect mChildRect = new Rect();
-
public void setChildRect(Rect r)
{
mChildRect.set(r);
}
-
public Rect getChildRect()
{
return mChildRect;
}
+ private ArrayList<InkAnnotation> mInkAnnots;
+
+ public void startDraw(float x, float y, int color, float thickness)
+ {
+ // create annotation list
+ if (mInkAnnots == null)
+ mInkAnnots = new ArrayList<>();
+
+ // add a new annotation to the list
+ // convert thickness from pt to pixels
+ float px = thickness * (float)getFactor();
+ InkAnnotation annot = new InkAnnotation(color, px);
+ mInkAnnots.add(annot);
+
+ // add first point to the new annot, in page coords
+ PointF pScreen = new PointF(x, y);
+ PointF pPage = screenToPage(pScreen);
+ annot.add(pPage);
+
+ invalidate();
+ }
+
+ public void continueDraw(float x, float y)
+ {
+ if (mInkAnnots!=null && mInkAnnots.size()>0)
+ {
+ // get the most recent annotation
+ InkAnnotation annot = mInkAnnots.get(mInkAnnots.size()-1);
+
+ // add the point, in page coords
+ PointF pScreen = new PointF(x, y);
+ PointF pPage = screenToPage(pScreen);
+ annot.add(pPage);
+
+ invalidate();
+ }
+ }
+
private class RenderTaskParams
{
RenderTaskParams(RenderListener listener, Matrix ctm, Bitmap bitmap,
@@ -865,4 +989,247 @@ public class DocPageView extends View implements Callback
}
}
+ private InkAnnotation getSelectedInkAnnotation()
+ {
+ if (mInkAnnots != null)
+ {
+ // iterate in reverse order
+ ListIterator<InkAnnotation> li = mInkAnnots.listIterator(mInkAnnots.size());
+ while (li.hasPrevious())
+ {
+ InkAnnotation annot = li.previous();
+ if (annot.isSelected())
+ return annot;
+ }
+ }
+
+ return null;
+ }
+
+ public boolean hasInkAnnotationSelected()
+ {
+ return (getSelectedInkAnnotation() != null);
+ }
+
+ public void setSelectedInkLineColor(int val)
+ {
+ InkAnnotation annot = getSelectedInkAnnotation();
+ if (annot != null)
+ {
+ annot.setLineColor(val);
+ invalidate();
+ }
+ }
+
+ public void setSelectedInkLineThickness(float val)
+ {
+ InkAnnotation annot = getSelectedInkAnnotation();
+ if (annot != null)
+ {
+ float px = val * (float)getFactor();
+ annot.setLineThickness(px);
+ invalidate();
+ }
+ }
+
+ public void deleteSelectedInkAnnotation()
+ {
+ InkAnnotation annot = getSelectedInkAnnotation();
+ if (annot != null)
+ {
+ mInkAnnots.remove(annot);
+ invalidate();
+ }
+ }
+
+//-----------------------------------------------------
+
+ public class InkAnnotation
+ {
+ private float mLineThickness;
+ public void setLineThickness(float lineThickness) {mLineThickness = lineThickness;}
+
+ private int mLineColor;
+ public void setLineColor(int lineColor) {mLineColor = lineColor;}
+
+ private boolean mSelected = false;
+ public void setSelected(boolean sel) {mSelected = sel;}
+ public boolean isSelected() {return mSelected;}
+
+ private ArrayList<PointF> mArc;
+
+ // touch margin is 2mm either side of the arc
+ private final float HIT_MARGIN = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 2,
+ getResources().getDisplayMetrics());
+
+ public InkAnnotation(int lineColor, float lineThickness)
+ {
+ mLineColor = lineColor;
+ mLineThickness = lineThickness;
+ mArc = new ArrayList<>();
+ }
+
+ public void add(PointF p)
+ {
+ mArc.add(p);
+ }
+
+ public boolean hitTest(Point pt)
+ {
+ PointF p1, p2;
+ PointF ptf = new PointF(pt);
+
+ if (mArc.size() >= 2)
+ {
+ Iterator<PointF> iit = mArc.iterator();
+ p1 = iit.next();
+ while (iit.hasNext())
+ {
+ p2 = iit.next();
+
+ // test
+ double d = LineToPointDistance2D(p1, p2, ptf);
+ d = pageToScreen(d);
+
+ if (d <= HIT_MARGIN)
+ {
+ return true;
+ }
+
+ p1 = p2;
+ }
+ }
+ else
+ {
+ p1 = mArc.get(0);
+
+ // test
+ double d = Distance(p1, ptf);
+ d = pageToScreen(d);
+
+ if (d <= HIT_MARGIN)
+ {
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
+ public void draw(Canvas canvas)
+ {
+ Path path = new Path();
+ PointF pPage;
+ PointF pView = new PointF();
+
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setDither(true);
+ paint.setStrokeJoin(Paint.Join.ROUND);
+ paint.setStrokeCap(Paint.Cap.ROUND);
+ paint.setStyle(Paint.Style.FILL);
+ paint.setStrokeWidth(mLineThickness * mScale);
+ paint.setColor(mLineColor);
+
+ RectF bounds = new RectF();
+
+ if (mArc.size() >= 2)
+ {
+ Iterator<PointF> iit = mArc.iterator();
+ pPage = iit.next();
+ pageToView(pPage, pView);
+ float mX = pView.x;
+ float mY = pView.y;
+ path.moveTo(mX, mY);
+ while (iit.hasNext())
+ {
+ pPage = iit.next();
+ pageToView(pPage, pView);
+ float x = pView.x;
+ float y = pView.y;
+ path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
+ mX = x;
+ mY = y;
+ }
+ path.lineTo(mX, mY);
+ paint.setStyle(Paint.Style.STROKE);
+ canvas.drawPath(path, paint);
+
+ path.computeBounds(bounds, true);
+ }
+ else
+ {
+ pPage = mArc.get(0);
+ pageToView(pPage, pView);
+ float r = mLineThickness * mScale / 2;
+ bounds.set(pView.x-r, pView.y-r, pView.x+r, pView.y+r);
+ canvas.drawCircle(pView.x, pView.y, r, paint);
+ }
+
+ if (isSelected())
+ {
+ // expand the bounds to account for ine thickness
+ float px = mLineThickness * mScale / 2;
+ bounds.inset(-px, -px);
+
+ mHighlightingRect.set((int)bounds.left, (int)bounds.top, (int)bounds.right, (int)bounds.bottom);
+ canvas.drawRect(mHighlightingRect, mSelectionHighlightPainter);
+ }
+ }
+
+ private double DotProduct(PointF pointA, PointF pointB, PointF pointC)
+ {
+ double[] AB = new double[2];
+ double[] BC = new double[2];
+ AB[0] = pointB.x - pointA.x;
+ AB[1] = pointB.y - pointA.y;
+ BC[0] = pointC.x - pointB.x;
+ BC[1] = pointC.y - pointB.y;
+ double dot = AB[0] * BC[0] + AB[1] * BC[1];
+
+ return dot;
+ }
+
+ //Compute the cross product AB x AC
+ private double CrossProduct(PointF pointA, PointF pointB, PointF pointC)
+ {
+ double[] AB = new double[2];
+ double[] AC = new double[2];
+ AB[0] = pointB.x - pointA.x;
+ AB[1] = pointB.y - pointA.y;
+ AC[0] = pointC.x - pointA.x;
+ AC[1] = pointC.y - pointA.y;
+ double cross = AB[0] * AC[1] - AB[1] * AC[0];
+
+ return cross;
+ }
+
+ //Compute the distance from A to B
+ double Distance(PointF pointA, PointF pointB)
+ {
+ double d1 = pointA.x - pointB.x;
+ double d2 = pointA.y - pointB.y;
+
+ return Math.sqrt(d1 * d1 + d2 * d2);
+ }
+
+ //Compute the distance from AB to C
+ double LineToPointDistance2D(PointF pointA, PointF pointB, PointF pointC)
+ {
+ double dist = CrossProduct(pointA, pointB, pointC) / Distance(pointA, pointB);
+ if (true)
+ {
+ double dot1 = DotProduct(pointA, pointB, pointC);
+ if (dot1 > 0)
+ return Distance(pointB, pointC);
+
+ double dot2 = DotProduct(pointB, pointA, pointC);
+ if (dot2 > 0)
+ return Distance(pointA, pointC);
+ }
+ return Math.abs(dist);
+ }
+ }
+
}
diff --git a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocView.java b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocView.java
index 346b887b..11ad2601 100644
--- a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocView.java
+++ b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocView.java
@@ -7,8 +7,9 @@ import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
-import android.view.View;
+import android.view.MotionEvent;
import android.widget.RelativeLayout;
+import android.widget.Toast;
import com.artifex.mupdf.fitz.Page;
import com.artifex.mupdf.fitz.R;
@@ -109,11 +110,6 @@ public class DocView extends DocViewBase implements DragHandleListener
mSelectionHandleBottomRight.show(show);
}
- private boolean getSelectionHandlesVisible()
- {
- return (mSelectionHandleTopLeft.getVisibility() == View.VISIBLE);
- }
-
@Override
protected void doSingleTap(float fx, float fy)
{
@@ -123,18 +119,20 @@ public class DocView extends DocViewBase implements DragHandleListener
if (dpv == null)
return;
- if (getSelectionHandlesVisible())
+ if (!getDrawMode())
{
- // hide handles and remove selection from pages
- showSelectionHandles(false);
- int numPages = getPageCount();
- for (int i = 0; i < numPages; i++)
+ if (dpv.onSingleTap(p.x, p.y))
{
- DocPageView cv = (DocPageView) getOrCreateChild(i);
- cv.removeSelection();
- if (cv.isReallyVisible())
- cv.invalidate();
+ onChangeSelection();
+ return;
}
+ onChangeSelection();
+ }
+
+ if (hasSelection())
+ {
+ clearSelection();
+ onChangeSelection();
}
else
{
@@ -142,20 +140,88 @@ public class DocView extends DocViewBase implements DragHandleListener
Rect r = dpv.selectWord(p);
if (r != null)
{
- // show handles
showSelectionHandles(true);
- // set highlight boundaries
selectionStartPage = dpv;
selectionStartLoc.set(r.left, r.top);
selectionEndPage = dpv;
selectionEndLoc.set(r.right, r.bottom);
moveHandlesToCorners();
+
+ onChangeSelection();
}
}
}
+ private void clearSelection()
+ {
+ selectionStartPage = null;
+ selectionEndPage = null;
+ showSelectionHandles(false);
+ int numPages = getPageCount();
+ for (int i = 0; i < numPages; i++)
+ {
+ DocPageView cv = (DocPageView) getOrCreateChild(i);
+ cv.removeSelection();
+ if (cv.isReallyVisible())
+ cv.invalidate();
+ }
+ }
+
+ public boolean hasSelection()
+ {
+ return (selectionStartPage != null && selectionEndPage != null);
+ }
+
+ public boolean hasInkAnnotationSelected()
+ {
+ int numPages = getPageCount();
+ for (int i = 0; i < numPages; i++)
+ {
+ DocPageView cv = (DocPageView) getOrCreateChild(i);
+ if (cv.hasInkAnnotationSelected())
+ return true;
+ }
+
+ return false;
+ }
+
+ public void setSelectedInkLineColor(int val)
+ {
+ int numPages = getPageCount();
+ for (int i = 0; i < numPages; i++)
+ {
+ DocPageView cv = (DocPageView) getOrCreateChild(i);
+ if (cv.hasInkAnnotationSelected())
+ cv.setSelectedInkLineColor(val);
+ }
+ }
+
+ public void setSelectedInkLineThickness(float val)
+ {
+ int numPages = getPageCount();
+ for (int i = 0; i < numPages; i++)
+ {
+ DocPageView cv = (DocPageView) getOrCreateChild(i);
+ if (cv.hasInkAnnotationSelected())
+ cv.setSelectedInkLineThickness(val);
+ }
+ }
+
+ private void onChangeSelection()
+ {
+ if (mSelectionChangeListener != null)
+ mSelectionChangeListener.onSelectionChanged();
+ }
+
+ private SelectionChangeListener mSelectionChangeListener = null;
+ public void setSelectionChangeListener (SelectionChangeListener l) {mSelectionChangeListener = l;}
+ public interface SelectionChangeListener
+ {
+ public void onSelectionChanged();
+ }
+
@Override
protected void doDoubleTap(float fx, float fy)
{
@@ -214,6 +280,7 @@ public class DocView extends DocViewBase implements DragHandleListener
selectionStartPage = pageView1;
p1 = pageView1.screenToPage(p1);
selectionStartLoc.set(p1.x, p1.y);
+ onChangeSelection();
}
}
@@ -228,6 +295,7 @@ public class DocView extends DocViewBase implements DragHandleListener
selectionEndPage = pageView2;
p2 = pageView2.screenToPage(p2);
selectionEndLoc.set(p2.x, p2.y);
+ onChangeSelection();
}
}
@@ -417,4 +485,129 @@ public class DocView extends DocViewBase implements DragHandleListener
}
}
+ public void onHighlight()
+ {
+ if (hasSelection())
+ {
+ Toast.makeText(getContext(),"onHighlight", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ private boolean mNoteMode = false;
+ public boolean getNoteMode() {return mNoteMode;}
+ public void onNoteMode()
+ {
+ mNoteMode = !mNoteMode;
+ mDrawMode = false;
+ clearSelection();
+ onChangeSelection();
+ }
+
+ private boolean mDrawMode = false;
+ public boolean getDrawMode() {return mDrawMode;}
+ public void onDrawMode()
+ {
+ mDrawMode = !mDrawMode;
+ mNoteMode = false;
+ clearSelection();
+ onChangeSelection();
+ }
+
+ public void onDelete()
+ {
+ int numPages = getPageCount();
+ for (int i = 0; i < numPages; i++)
+ {
+ DocPageView cv = (DocPageView) getOrCreateChild(i);
+ if (cv.hasInkAnnotationSelected())
+ cv.deleteSelectedInkAnnotation();
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event)
+ {
+ if (mDrawMode)
+ {
+ float x = event.getX();
+ float y = event.getY();
+ switch (event.getAction())
+ {
+ case MotionEvent.ACTION_DOWN:
+ touch_start(x, y);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ touch_move(x, y);
+ break;
+ case MotionEvent.ACTION_UP:
+ touch_up();
+ break;
+ }
+
+ return true;
+ }
+
+ return super.onTouchEvent(event);
+ }
+
+ private float mX, mY;
+ private static final float TOUCH_TOLERANCE = 2;
+
+ private int mCurrentInkLineColor = 0xFFFF0000;
+ public void setInkLineColor(int val)
+ {
+ mCurrentInkLineColor=val;
+
+ // also change any selected annotation
+ if (hasInkAnnotationSelected())
+ setSelectedInkLineColor(val);
+ }
+ public int getInkLineColor() {return mCurrentInkLineColor;}
+
+ private float mCurrentInkLineThickness = 4.5f;
+ public float getInkLineThickness() {return mCurrentInkLineThickness;}
+ public void setInkLineThickness(float val)
+ {
+ mCurrentInkLineThickness=val;
+
+ // also change any selected annotation
+ if (hasInkAnnotationSelected())
+ setSelectedInkLineThickness(val);
+ }
+
+ private void touch_start(float x, float y)
+ {
+ Point p = eventToScreen(x, y);
+ final DocPageView dpv = findPageViewContainingPoint(p.x, p.y, false);
+ if (dpv != null)
+ {
+ dpv.startDraw(p.x, p.y, mCurrentInkLineColor, mCurrentInkLineThickness);
+ }
+
+ mX = x;
+ mY = y;
+ }
+
+ private void touch_move(float x, float y) {
+
+ float dx = Math.abs(x - mX);
+ float dy = Math.abs(y - mY);
+ if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
+ {
+ Point p = eventToScreen(x, y);
+ final DocPageView dpv = findPageViewContainingPoint(p.x, p.y, false);
+ if (dpv != null)
+ {
+ dpv.continueDraw(p.x, p.y);
+ }
+ mX = x;
+ mY = y;
+ }
+ }
+
+ private void touch_up()
+ {
+ // NOOP
+ }
+
}
diff --git a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/LineWidthDialog.java b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/LineWidthDialog.java
new file mode 100644
index 00000000..beea9d98
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/LineWidthDialog.java
@@ -0,0 +1,128 @@
+package com.artifex.mupdf.android;
+
+import android.content.Context;
+import android.database.DataSetObserver;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.PopupWindow;
+import android.widget.TextView;
+
+import com.artifex.mupdf.fitz.R;
+
+import kankan.wheel.widget.OnWheelScrollListener;
+import kankan.wheel.widget.WheelView;
+import kankan.wheel.widget.adapters.WheelViewAdapter;
+
+public class LineWidthDialog
+{
+ private static final int POPUP_OFFSET = 30;
+
+ private static final float values[] = new float[] {0.25f, 0.5f, 1, 1.5f, 3, 4.5f, 6, 8, 12, 18, 24};
+
+ public static void show(Context context, View anchor, float val, final WidthChangedListener listener)
+ {
+ float currentValue = val;
+
+ View layout = View.inflate(context, R.layout.line_width_dialog, null);
+
+ View wv = layout.findViewById(R.id.wheel);
+ WheelView wheel = (WheelView)wv;
+
+ final LineWidthAdapter adapter = new LineWidthAdapter(context, values);
+
+ wheel.setViewAdapter(adapter);
+ wheel.setVisibleItems(5);
+
+ wheel.setCurrentItem(0);
+ for (int i=0;i<values.length;i++)
+ {
+ if (values[i] == currentValue)
+ wheel.setCurrentItem(i);
+ }
+
+ wheel.addScrollingListener(new OnWheelScrollListener() {
+ @Override
+ public void onScrollingStarted(WheelView wheel) {}
+
+ @Override
+ public void onScrollingFinished(WheelView wheel) {
+ listener.onWidthChanged(values[wheel.getCurrentItem()]);
+ }
+ });
+
+ // make a popup window
+ final PopupWindow popup = new PopupWindow(layout,
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ popup.setFocusable(true);
+
+ // now show the popup
+ popup.showAsDropDown(anchor,POPUP_OFFSET,POPUP_OFFSET);
+ }
+
+ public static class LineWidthAdapter implements WheelViewAdapter
+ {
+ public LineWidthAdapter(Context context, float values[]) {
+ super();
+ mValues = values;
+ mContext = context;
+ }
+
+ private Context mContext;
+ private float mValues[];
+
+ @Override
+ public View getItem(int position, View convertView, ViewGroup parent)
+ {
+ // make a View if needed.
+ if (convertView == null)
+ {
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ convertView = inflater.inflate(R.layout.line_width_item, parent, false);
+ }
+
+ // get the value
+ float value = values[position];
+
+ // set the text string
+ TextView tv = ((TextView)convertView.findViewById(R.id.value));
+ if(value == (int) value)
+ tv.setText(String.format("%d pt",(int)value));
+ else
+ tv.setText(String.format("%s pt",value));
+
+ // adjust the height of the line
+ int h = (int)(value*3f/2f);
+ if (h<1)
+ h = 1;
+ View bar = ((View)convertView.findViewById(R.id.bar));
+ bar.getLayoutParams().height = h;
+ bar.setLayoutParams(bar.getLayoutParams());
+
+ return convertView;
+ }
+
+ @Override
+ public int getItemsCount() {
+ return mValues.length;
+ }
+
+ @Override
+ public View getEmptyItem(View convertView, ViewGroup parent) {
+ return null;
+ }
+
+ @Override
+ public void registerDataSetObserver(DataSetObserver observer) {
+ }
+
+ @Override
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ }
+ }
+
+ public interface WidthChangedListener {
+ void onWidthChanged(float value);
+ }
+
+}
diff --git a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/ToolbarButton.java b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/ToolbarButton.java
new file mode 100644
index 00000000..5760df48
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/ToolbarButton.java
@@ -0,0 +1,31 @@
+package com.artifex.mupdf.android;
+
+import android.content.Context;
+import android.graphics.PorterDuff;
+import android.support.annotation.ColorInt;
+import android.util.AttributeSet;
+import android.widget.ImageButton;
+
+public class ToolbarButton extends ImageButton
+{
+ // Color.GRAY (0xFF888888) is too dark. Use something lighter.
+ @ColorInt
+ private static final int MYGRAY = 0xFFAAAAAA;
+
+ public ToolbarButton(Context context) {
+ super(context);
+ }
+
+ public ToolbarButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override public void setEnabled(boolean enabled)
+ {
+ super.setEnabled(enabled);
+ if (enabled)
+ setColorFilter(null);
+ else
+ setColorFilter(MYGRAY, PorterDuff.Mode.SRC_IN);
+ }
+}
diff --git a/platform/android/example/mupdf/src/main/res/drawable/colors.xml b/platform/android/example/mupdf/src/main/res/drawable/colors.xml
new file mode 100644
index 00000000..eff1250e
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/colors.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <stroke android:width="1dp" android:color="#797979" />
+ <solid android:color="@color/bluish_grey" />
+ <corners
+ android:radius="7dp" />
+ <padding
+ android:top="10dp"
+ android:left="10dp"
+ android:right="10dp"
+ android:bottom="10dp"
+ />
+</shape>
diff --git a/platform/android/example/mupdf/src/main/res/drawable/icon_delete.xml b/platform/android/example/mupdf/src/main/res/drawable/icon_delete.xml
new file mode 100755
index 00000000..d027b030
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/icon_delete.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="50dp"
+ android:height="50dp"
+ android:viewportWidth="50"
+ android:viewportHeight="50">
+
+ <path
+ android:strokeColor="#333333"
+ android:strokeWidth="1.331"
+ android:pathData="M 25 9.92 C 33.3284540274 9.92 40.08 16.6715459726 40.08 25 C 40.08 33.3284540274 33.3284540274 40.08 25 40.08 C 16.6715459726 40.08 9.92 33.3284540274 9.92 25 C 9.92 16.6715459726 16.6715459726 9.92 25 9.92 Z" />
+ <path
+ android:strokeColor="#333333"
+ android:strokeWidth="1.774"
+ android:pathData="M 17.622 32.934 L 32.257 18.299" />
+ <path
+ android:strokeColor="#333333"
+ android:strokeWidth="1.774"
+ android:pathData="M 32.257 32.934 L 17.622 18.297" />
+</vector> \ No newline at end of file
diff --git a/platform/android/example/mupdf/src/main/res/drawable/icon_draw.xml b/platform/android/example/mupdf/src/main/res/drawable/icon_draw.xml
new file mode 100644
index 00000000..808efdaa
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/icon_draw.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="50dp"
+ android:height="50dp"
+ android:viewportWidth="50"
+ android:viewportHeight="50">
+
+ <path
+ android:fillColor="#333333"
+ android:pathData="M33.1075,16.6386 L38.7232,19.2633 L31.7612,34.159 L26.1455,31.5343
+L33.1075,16.6386 Z" />
+ <path
+ android:fillColor="#333333"
+ android:pathData="M25.735,32.435 L31.334,35.052 L25.884,39.634 Z" />
+ <path
+ android:fillColor="#333333"
+ android:pathData="M39.29,18.067 L41.299,13.773 C41.358,13.646,41.302,13.495,41.176,13.435
+L36.02,11.025 C35.893,10.965,35.741,11.021,35.682,11.148 L33.675,15.442
+L39.29,18.067 Z" />
+ <path
+ android:strokeColor="#333333"
+ android:strokeWidth="1.04"
+ android:strokeLineCap="round"
+ android:pathData="M8.738,10.366 C8.738,10.366,26.245,13.833,24.685,17.3
+C23.125,20.765,9.953,21.286,8.738,25.793 C7.525,30.3,24.859,39.313,24.859,39.313" />
+</vector> \ No newline at end of file
diff --git a/platform/android/example/mupdf/src/main/res/drawable/icon_highlight.xml b/platform/android/example/mupdf/src/main/res/drawable/icon_highlight.xml
new file mode 100755
index 00000000..f42b88d9
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/icon_highlight.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="50dp"
+ android:height="50dp"
+ android:viewportWidth="50"
+ android:viewportHeight="50">
+
+ <path
+ android:fillColor="#333333"
+ android:pathData="M 20.629 22.61 L 27.374 29.355 L 22.483 30.848 L 19.701 28.068 Z" />
+ <path
+ android:fillColor="#333333"
+ android:pathData="M27.909,28.668l12.17-12.032c0.153-0.154,0.153-0.404,0.001-0.557l-6.199-6.251
+c-0.154-0.154-0.404-0.155-0.559-0.001L21.154,21.861L27.909,28.668z" />
+ <path
+ android:fillColor="#333333"
+ android:pathData="M 18.992 28.629 L 14.841 32.359 L 20.726 32.404 L 21.803 31.594 Z" />
+ <path
+ android:fillColor="#333333"
+ android:pathData="M 9.76 34.59 H 40.24 V 40.287 H 9.76 V 34.59 Z" />
+</vector> \ No newline at end of file
diff --git a/platform/android/example/mupdf/src/main/res/drawable/icon_line_color.xml b/platform/android/example/mupdf/src/main/res/drawable/icon_line_color.xml
new file mode 100755
index 00000000..1c79066a
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/icon_line_color.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="50dp"
+ android:height="50dp"
+ android:viewportWidth="50"
+ android:viewportHeight="50">
+
+ <path
+ android:strokeColor="#81DBE7"
+ android:strokeWidth="1.56"
+ android:pathData="M40.797,35.303
+c0,1.518-1.229,2.747-2.747,2.747h-26.1c-1.516,0-2.747-1.229-2.747-2.747V14.698c0-1.518,1.231-2.748,2.747-2.748h26.1
+c1.519,0,2.747,1.23,2.747,2.748V35.303z" />
+</vector> \ No newline at end of file
diff --git a/platform/android/example/mupdf/src/main/res/drawable/icon_line_thickness.xml b/platform/android/example/mupdf/src/main/res/drawable/icon_line_thickness.xml
new file mode 100755
index 00000000..1e48a6c9
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/icon_line_thickness.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="50dp"
+ android:height="50dp"
+ android:viewportWidth="50"
+ android:viewportHeight="50">
+
+ <path
+ android:strokeColor="#333333"
+ android:strokeWidth="2.6"
+ android:pathData="M40.797,35.303
+c0,1.518-1.229,2.747-2.747,2.747h-26.1c-1.517,0-2.747-1.229-2.747-2.747V14.698c0-1.518,1.23-2.748,2.747-2.748h26.1
+c1.519,0,2.747,1.23,2.747,2.748V35.303z" />
+</vector> \ No newline at end of file
diff --git a/platform/android/example/mupdf/src/main/res/drawable/icon_note.xml b/platform/android/example/mupdf/src/main/res/drawable/icon_note.xml
new file mode 100755
index 00000000..1f5732e3
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/icon_note.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="50dp"
+ android:height="50dp"
+ android:viewportWidth="50"
+ android:viewportHeight="50">
+
+ <path
+ android:strokeColor="#333333"
+ android:strokeWidth="1.372"
+ android:strokeMiterLimit="10"
+ android:pathData="M12.204,32.945
+H10.09c-0.632,0-1.145-0.516-1.145-1.145V11.896c0-0.63,0.513-1.143,1.145-1.143h29.821c0.632,0,1.144,0.513,1.144,1.143v19.904
+c0,0.629-0.512,1.145-1.144,1.145H18.507l-6.303,6.301V32.945z" />
+ <path
+ android:strokeColor="#333333"
+ android:strokeWidth="1.769"
+ android:strokeMiterLimit="10"
+ android:pathData="M 16.993 17.862 L 30.559 17.862" />
+ <path
+ android:strokeColor="#333333"
+ android:strokeWidth="1.769"
+ android:strokeMiterLimit="10"
+ android:pathData="M 16.993 26.564 L 28.381 26.564" />
+ <path
+ android:strokeColor="#333333"
+ android:strokeWidth="1.769"
+ android:strokeMiterLimit="10"
+ android:pathData="M 16.993 22.213 L 31.885 22.213" />
+</vector> \ No newline at end of file
diff --git a/platform/android/example/mupdf/src/main/res/drawable/number_format_popup.xml b/platform/android/example/mupdf/src/main/res/drawable/number_format_popup.xml
new file mode 100644
index 00000000..5154168b
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/number_format_popup.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <stroke android:width="1dp" android:color="@color/formula_popup_background" />
+ <solid android:color="@color/number_format_popup_background" />
+ <corners
+ android:radius="7dp" />
+ <padding
+ android:top="5dp"
+ android:left="5dp"
+ android:right="5dp"
+ android:bottom="5dp"
+ />
+</shape>
diff --git a/platform/android/example/mupdf/src/main/res/drawable/toolbar_button2.xml b/platform/android/example/mupdf/src/main/res/drawable/toolbar_button2.xml
new file mode 100644
index 00000000..d624e85f
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/toolbar_button2.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true">
+ <shape>
+ <solid android:color="@color/white" />
+ <corners android:radius="12dp"/>
+ <!--<padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" />-->
+ </shape>
+ </item>
+ <item>
+ <shape>
+ <solid android:color="@color/button_normal" />
+ <!--<padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" />-->
+ </shape>
+ </item>
+</selector>
diff --git a/platform/android/example/mupdf/src/main/res/drawable/transparent_color_swatch.xml b/platform/android/example/mupdf/src/main/res/drawable/transparent_color_swatch.xml
new file mode 100644
index 00000000..fdf3d369
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/transparent_color_swatch.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item>
+ <shape>
+ <stroke android:color="@color/black" android:width="1dp" />
+ <solid android:color="@color/white" />
+ </shape>
+ </item>
+
+ <item>
+ <rotate
+ android:fromDegrees="45">
+ <shape
+ android:shape="line" >
+ <stroke android:color="@color/red" android:width="4dp" />
+ </shape>
+ </rotate>
+ </item>
+
+</layer-list>
diff --git a/platform/android/example/mupdf/src/main/res/drawable/wheel_bg.xml b/platform/android/example/mupdf/src/main/res/drawable/wheel_bg.xml
new file mode 100644
index 00000000..f9fdd27a
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/wheel_bg.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Android Wheel Control.
+ http://android-devblog.blogspot.com/2010/05/wheel-ui-contol.html
+
+ Copyright 2010 Yuri Kanivets
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="#ffffff" />
+ <stroke android:width="1dp" android:color="#ffffff" />
+ </shape>
+ </item>
+
+</layer-list> \ No newline at end of file
diff --git a/platform/android/example/mupdf/src/main/res/drawable/wheel_val.xml b/platform/android/example/mupdf/src/main/res/drawable/wheel_val.xml
new file mode 100644
index 00000000..45f7f5c9
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/drawable/wheel_val.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Android Wheel Control.
+ http://android-devblog.blogspot.com/2010/05/wheel-ui-contol.html
+
+ Copyright 2010 Yuri Kanivets
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#00ffffff"/>
+ <stroke android:width="1dp"
+ android:dashWidth="3px"
+ android:dashGap="3px"
+ android:color="#ff000000" />
+</shape>
diff --git a/platform/android/example/mupdf/src/main/res/layout/annotate_toolbar.xml b/platform/android/example/mupdf/src/main/res/layout/annotate_toolbar.xml
index 767a27b0..50814a44 100644
--- a/platform/android/example/mupdf/src/main/res/layout/annotate_toolbar.xml
+++ b/platform/android/example/mupdf/src/main/res/layout/annotate_toolbar.xml
@@ -19,27 +19,168 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
+ android:gravity="center_horizontal"
android:paddingLeft="10dp"
android:paddingRight="10dp">
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:layout_centerVertical="true"
android:background="@drawable/toolbar_button"
- android:id="@+id/show_annot_button"
- android:src="@drawable/icon_toggle_annotations" />
+ android:id="@+id/highlight_button"
+ android:src="@drawable/icon_highlight" />
<TextView
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="@color/black"
+ android:textSize="11sp"
+ android:text="HIGHLIGHT"/>
+ </LinearLayout>
+
+ <!--a divider-->
+ <View
+ android:layout_width="1dp"
+ android:paddingRight="3dp" android:paddingLeft="3dp"
+ android:layout_height="match_parent"
+ android:background="#FF8E8F90" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:id="@+id/draw_tools_holder"
+ android:background="@drawable/toolbar_button2"
+ >
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp">
+
+ <com.artifex.mupdf.android.ToolbarButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:layout_centerVertical="true"
+ android:background="@drawable/toolbar_button2"
+ android:id="@+id/draw_button"
+ android:src="@drawable/icon_draw" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="@color/black"
+ android:textSize="11sp"
+ android:text="DRAW"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp">
+
+ <com.artifex.mupdf.android.ToolbarButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:layout_centerVertical="true"
+ android:background="@drawable/toolbar_button2"
+ android:id="@+id/line_color_button"
+ android:src="@drawable/icon_line_color" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="@color/black"
+ android:textSize="11sp"
+ android:text=""/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp">
+
+ <com.artifex.mupdf.android.ToolbarButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:layout_centerVertical="true"
+ android:background="@drawable/toolbar_button2"
+ android:id="@+id/line_thickness_button"
+ android:src="@drawable/icon_line_thickness" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="@color/black"
+ android:textSize="11sp"
+ android:text=""/>
+ </LinearLayout>
+
+
+ </LinearLayout>
+
+ <!--a divider-->
+ <View
+ android:layout_width="1dp"
+ android:paddingRight="3dp" android:paddingLeft="3dp"
+ android:layout_height="match_parent"
+ android:background="#FF8E8F90" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:id="@+id/note_holder"
+ android:background="@drawable/toolbar_button2"
+ >
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp">
+
+ <com.artifex.mupdf.android.ToolbarButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:layout_centerVertical="true"
+ android:background="@drawable/toolbar_button2"
+ android:id="@+id/note_button"
+ android:src="@drawable/icon_note" />
+
+ <TextView
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/black"
android:textSize="11sp"
- android:text="TOGGLE"/>
+ android:text="NOTE"/>
</LinearLayout>
+
+ </LinearLayout>
+
+
<!--a divider-->
<View
android:layout_width="1dp"
@@ -47,6 +188,78 @@
android:layout_height="match_parent"
android:background="#FF8E8F90" />
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp">
+
+ <com.artifex.mupdf.android.ToolbarButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:layout_centerVertical="true"
+ android:background="@drawable/toolbar_button"
+ android:id="@+id/delete_button"
+ android:src="@drawable/icon_delete" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="@color/black"
+ android:textSize="11sp"
+ android:text="DELETE"/>
+ </LinearLayout>
+
+
+ <!--
+ this layout holds some buttons for testing
+ normally it's not shown.
+ -->
+
+ <LinearLayout
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <!--a divider-->
+ <View
+ android:layout_width="1dp"
+ android:paddingRight="3dp" android:paddingLeft="3dp"
+ android:layout_height="match_parent"
+ android:background="#FF8E8F90" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp">
+
+ <com.artifex.mupdf.android.ToolbarButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:layout_centerVertical="true"
+ android:background="@drawable/toolbar_button"
+ android:id="@+id/show_annot_button"
+ android:src="@drawable/icon_toggle_annotations" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="@color/black"
+ android:textSize="11sp"
+ android:text="TOGGLE"/>
+ </LinearLayout>
+
+ </LinearLayout>
+
</LinearLayout>
</HorizontalScrollView>
diff --git a/platform/android/example/mupdf/src/main/res/layout/colors.xml b/platform/android/example/mupdf/src/main/res/layout/colors.xml
new file mode 100644
index 00000000..d7d7aa91
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/layout/colors.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/colors"
+ android:orientation="vertical"
+ >
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="false"
+ android:layout_alignParentTop="true"
+ android:id="@+id/font_panel">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/bluish_grey"
+ android:textColor="#FFFFFFFF"
+ android:textSize="12pt"
+ android:id="@+id/color_dialog_title" />
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:id="@+id/fontcolors_row1" >
+
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+
+ </LinearLayout>
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:id="@+id/fontcolors_row2">
+
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+
+ </LinearLayout>
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:id="@+id/fontcolors_row3">
+
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+ <Button style="@style/font_color_button" android:background="#000000" android:tag="#000000"/>
+
+ <Button style="@style/font_color_button"
+ android:id="@+id/transparent_color_button"
+ android:background="@drawable/transparent_color_swatch"
+ android:tag="transparent"/>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </RelativeLayout>
+
+ <!--<Button-->
+ <!--android:layout_width="wrap_content"-->
+ <!--android:layout_height="wrap_content"-->
+ <!--android:text="@string/done"-->
+ <!--android:id="@+id/done_button"-->
+ <!--android:background="@drawable/button"-->
+ <!--android:textColor="#FFFFFFFF"-->
+ <!--android:layout_gravity="right"/>-->
+
+</LinearLayout>
diff --git a/platform/android/example/mupdf/src/main/res/layout/file_toolbar.xml b/platform/android/example/mupdf/src/main/res/layout/file_toolbar.xml
index 6468c9d0..a35d2ed9 100644
--- a/platform/android/example/mupdf/src/main/res/layout/file_toolbar.xml
+++ b/platform/android/example/mupdf/src/main/res/layout/file_toolbar.xml
@@ -22,7 +22,7 @@
android:paddingLeft="10dp"
android:paddingRight="10dp">
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
@@ -47,7 +47,7 @@
android:paddingLeft="10dp"
android:paddingRight="10dp">
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
@@ -79,7 +79,7 @@
android:paddingLeft="10dp"
android:paddingRight="10dp">
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
@@ -104,7 +104,7 @@
android:paddingLeft="10dp"
android:paddingRight="10dp">
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
@@ -129,7 +129,7 @@
android:paddingLeft="10dp"
android:paddingRight="10dp">
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
diff --git a/platform/android/example/mupdf/src/main/res/layout/line_width_dialog.xml b/platform/android/example/mupdf/src/main/res/layout/line_width_dialog.xml
new file mode 100644
index 00000000..5c47ab1d
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/layout/line_width_dialog.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/number_format_popup">
+
+ <kankan.wheel.widget.WheelView
+ android:layout_width="300dp"
+ android:layout_height="wrap_content"
+ android:id="@+id/wheel">
+
+ </kankan.wheel.widget.WheelView>
+
+</LinearLayout>
diff --git a/platform/android/example/mupdf/src/main/res/layout/line_width_item.xml b/platform/android/example/mupdf/src/main/res/layout/line_width_item.xml
new file mode 100644
index 00000000..0d960c7e
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/layout/line_width_item.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <View
+ android:id="@+id/bar"
+ android:layout_gravity="center_vertical"
+ android:layout_width="200dp"
+ android:layout_marginLeft="5dp"
+ android:layout_marginRight="5dp"
+ android:layout_height="1dp"
+ android:background="@color/black" />
+
+ <TextView
+ android:id="@+id/value"
+ android:layout_gravity="center_vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:textColor="@color/black"
+ android:textSize="20sp"/>
+
+</LinearLayout>
diff --git a/platform/android/example/mupdf/src/main/res/layout/pages_toolbar.xml b/platform/android/example/mupdf/src/main/res/layout/pages_toolbar.xml
index 06ffa233..22e01a20 100644
--- a/platform/android/example/mupdf/src/main/res/layout/pages_toolbar.xml
+++ b/platform/android/example/mupdf/src/main/res/layout/pages_toolbar.xml
@@ -23,7 +23,7 @@
android:paddingLeft="10dp"
android:paddingRight="10dp">
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
@@ -50,7 +50,7 @@
android:paddingRight="10dp"
>
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
@@ -85,7 +85,7 @@
android:paddingRight="10dp"
>
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
diff --git a/platform/android/example/mupdf/src/main/res/layout/search_toolbar.xml b/platform/android/example/mupdf/src/main/res/layout/search_toolbar.xml
index 973639bc..2b67e67d 100644
--- a/platform/android/example/mupdf/src/main/res/layout/search_toolbar.xml
+++ b/platform/android/example/mupdf/src/main/res/layout/search_toolbar.xml
@@ -63,7 +63,7 @@
android:gravity="center"
>
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
@@ -88,7 +88,7 @@
android:gravity="center"
>
- <ImageButton
+ <com.artifex.mupdf.android.ToolbarButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
diff --git a/platform/android/example/mupdf/src/main/res/values/strings.xml b/platform/android/example/mupdf/src/main/res/values/strings.xml
index 3709da70..cc919a69 100644
--- a/platform/android/example/mupdf/src/main/res/values/strings.xml
+++ b/platform/android/example/mupdf/src/main/res/values/strings.xml
@@ -13,4 +13,7 @@
<string name="ok">OK</string>
<string name="cancel">Cancel</string>
+ <string name="background">Background</string>
+ <string name="color">Color</string>
+
</resources>
diff --git a/platform/android/example/mupdf/src/main/res/values/styles.xml b/platform/android/example/mupdf/src/main/res/values/styles.xml
new file mode 100644
index 00000000..d767ff7f
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <!-- font color selection button. -->
+ <style name="font_color_button" parent="@android:style/Widget.Button">
+ <item name="android:layout_height">20pt</item>
+ <item name="android:layout_width">20pt</item>
+ <item name="android:layout_margin">12dp</item>
+ </style>
+
+</resources>