From ffbe3db71ea0f96b408e22418547a8ff898f380e Mon Sep 17 00:00:00 2001 From: fred ross-perry Date: Fri, 26 Aug 2016 09:50:48 -0700 Subject: 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. --- .../com/artifex/mupdf/android/ColorDialog.java | 204 +++++++++++ .../com/artifex/mupdf/android/DocActivityView.java | 126 ++++++- .../com/artifex/mupdf/android/DocPageView.java | 371 ++++++++++++++++++++- .../java/com/artifex/mupdf/android/DocView.java | 227 ++++++++++++- .../com/artifex/mupdf/android/LineWidthDialog.java | 128 +++++++ .../com/artifex/mupdf/android/ToolbarButton.java | 31 ++ .../example/mupdf/src/main/res/drawable/colors.xml | 13 + .../mupdf/src/main/res/drawable/icon_delete.xml | 20 ++ .../mupdf/src/main/res/drawable/icon_draw.xml | 26 ++ .../mupdf/src/main/res/drawable/icon_highlight.xml | 21 ++ .../src/main/res/drawable/icon_line_color.xml | 14 + .../src/main/res/drawable/icon_line_thickness.xml | 14 + .../mupdf/src/main/res/drawable/icon_note.xml | 30 ++ .../src/main/res/drawable/number_format_popup.xml | 13 + .../src/main/res/drawable/toolbar_button2.xml | 17 + .../main/res/drawable/transparent_color_swatch.xml | 22 ++ .../mupdf/src/main/res/drawable/wheel_bg.xml | 29 ++ .../mupdf/src/main/res/drawable/wheel_val.xml | 27 ++ .../mupdf/src/main/res/layout/annotate_toolbar.xml | 223 ++++++++++++- .../example/mupdf/src/main/res/layout/colors.xml | 95 ++++++ .../mupdf/src/main/res/layout/file_toolbar.xml | 10 +- .../src/main/res/layout/line_width_dialog.xml | 15 + .../mupdf/src/main/res/layout/line_width_item.xml | 25 ++ .../mupdf/src/main/res/layout/pages_toolbar.xml | 6 +- .../mupdf/src/main/res/layout/search_toolbar.xml | 4 +- .../example/mupdf/src/main/res/values/strings.xml | 3 + .../example/mupdf/src/main/res/values/styles.xml | 11 + 27 files changed, 1690 insertions(+), 35 deletions(-) create mode 100644 platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/ColorDialog.java create mode 100644 platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/LineWidthDialog.java create mode 100644 platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/ToolbarButton.java create mode 100644 platform/android/example/mupdf/src/main/res/drawable/colors.xml create mode 100755 platform/android/example/mupdf/src/main/res/drawable/icon_delete.xml create mode 100644 platform/android/example/mupdf/src/main/res/drawable/icon_draw.xml create mode 100755 platform/android/example/mupdf/src/main/res/drawable/icon_highlight.xml create mode 100755 platform/android/example/mupdf/src/main/res/drawable/icon_line_color.xml create mode 100755 platform/android/example/mupdf/src/main/res/drawable/icon_line_thickness.xml create mode 100755 platform/android/example/mupdf/src/main/res/drawable/icon_note.xml create mode 100644 platform/android/example/mupdf/src/main/res/drawable/number_format_popup.xml create mode 100644 platform/android/example/mupdf/src/main/res/drawable/toolbar_button2.xml create mode 100644 platform/android/example/mupdf/src/main/res/drawable/transparent_color_swatch.xml create mode 100644 platform/android/example/mupdf/src/main/res/drawable/wheel_bg.xml create mode 100644 platform/android/example/mupdf/src/main/res/drawable/wheel_val.xml create mode 100644 platform/android/example/mupdf/src/main/res/layout/colors.xml create mode 100644 platform/android/example/mupdf/src/main/res/layout/line_width_dialog.xml create mode 100644 platform/android/example/mupdf/src/main/res/layout/line_width_item.xml create mode 100644 platform/android/example/mupdf/src/main/res/values/styles.xml (limited to 'platform/android/example') 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 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 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 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 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 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 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 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 + + + + + + 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 @@ + + + + + + + \ 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 @@ + + + + + + + + \ 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 @@ + + + + + + + + \ 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 @@ + + + + + \ 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 @@ + + + + + \ 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 @@ + + + + + + + + \ 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 @@ + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + \ 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 @@ + + + + + + + + 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"> - + android:id="@+id/highlight_button" + android:src="@drawable/icon_highlight" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:text="NOTE"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + +