[Libreoffice-commits] core.git: android/source

Ximeng Zu uznomis at yahoo.com
Mon Jul 31 21:16:37 UTC 2017


 android/source/src/java/org/libreoffice/InvalidationHandler.java           |   14 +
 android/source/src/java/org/libreoffice/LOKitShell.java                    |    1 
 android/source/src/java/org/libreoffice/LOKitThread.java                   |    2 
 android/source/src/java/org/libreoffice/LOKitTileProvider.java             |    6 
 android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java       |    9 
 android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java         |   10 
 android/source/src/java/org/libreoffice/canvas/CalcSelectionBox.java       |  111 ++++++++++
 android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java |   30 ++
 android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java       |  101 ++++++++-
 android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java       |   16 +
 android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java   |   51 ++++
 11 files changed, 337 insertions(+), 14 deletions(-)

New commits:
commit b9471511523d5c80b80a5e99d149af65e9915840
Author: Ximeng Zu <uznomis at yahoo.com>
Date:   Sun Jun 18 16:37:13 2017 -0500

    [Android Viewer] Add cell selection by row/column/all
    
    Added cell selection to Calc docs in Android Viewer with a
    similar behavior to LOOL wrt. row/column selection.
    The user can tap on any header to select whole row/column
    or select all by tapping the top left corner of the header.
    
    Change-Id: I34bdbb1aacc5fc0ed9175908936a8a5e6eec4ff4
    Reviewed-on: https://gerrit.libreoffice.org/39694
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/android/source/src/java/org/libreoffice/InvalidationHandler.java b/android/source/src/java/org/libreoffice/InvalidationHandler.java
index 5edc6c7dcb19..e5fdf05b120f 100644
--- a/android/source/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/source/src/java/org/libreoffice/InvalidationHandler.java
@@ -91,11 +91,22 @@ public class InvalidationHandler implements Document.MessageCallback {
                 Log.d(LOGTAG, "LOK_CALLBACK: Search not found.");
                 // this callback is never caught. Hope someone fix this.
                 break;
+            case Document.CALLBACK_CELL_CURSOR:
+                invalidateCellCursor(payload);
+                break;
             default:
                 Log.d(LOGTAG, "LOK_CALLBACK uncaught: " + messageID + " : " + payload);
         }
     }
 
+    private void invalidateCellCursor(String payload) {
+        RectF cellCursorRect = convertPayloadToRectangle(payload);
+
+        if (cellCursorRect != null) {
+            mDocumentOverlay.showCellSelection(cellCursorRect);
+        }
+    }
+
     /**
      * Handles the search result selection message, which is a JSONObject
      *
@@ -374,6 +385,9 @@ public class InvalidationHandler implements Document.MessageCallback {
             }
             changeStateTo(OverlayState.SELECTION);
             mDocumentOverlay.changeSelections(rectangles);
+            if (mContext.isSpreadsheet()) {
+                mDocumentOverlay.showHeaderSelection(rectangles.get(0));
+            }
         }
     }
 
diff --git a/android/source/src/java/org/libreoffice/LOKitShell.java b/android/source/src/java/org/libreoffice/LOKitShell.java
index 7b7525722250..c69e02669619 100644
--- a/android/source/src/java/org/libreoffice/LOKitShell.java
+++ b/android/source/src/java/org/libreoffice/LOKitShell.java
@@ -27,6 +27,7 @@ public class LOKitShell {
     private static final String LOGTAG = LOKitShell.class.getSimpleName();
 
     public static float getDpi(Context context) {
+        if (((LibreOfficeMainActivity)context).isSpreadsheet()) return 96f;
         DisplayMetrics metrics = context.getResources().getDisplayMetrics();
         return metrics.density * 160;
     }
diff --git a/android/source/src/java/org/libreoffice/LOKitThread.java b/android/source/src/java/org/libreoffice/LOKitThread.java
index 9ab54c20a1f8..50836ce5b65a 100644
--- a/android/source/src/java/org/libreoffice/LOKitThread.java
+++ b/android/source/src/java/org/libreoffice/LOKitThread.java
@@ -211,7 +211,7 @@ class LOKitThread extends Thread {
         LOKitShell.showProgressSpinner(mContext);
         mTileProvider.changePart(partIndex);
         mViewportMetrics = mLayerClient.getViewportMetrics();
-        mLayerClient.setViewportMetrics(mViewportMetrics.scaleTo(0.9f, new PointF()));
+        // mLayerClient.setViewportMetrics(mViewportMetrics.scaleTo(0.9f, new PointF()));
         refresh();
         LOKitShell.hideProgressSpinner(mContext);
     }
diff --git a/android/source/src/java/org/libreoffice/LOKitTileProvider.java b/android/source/src/java/org/libreoffice/LOKitTileProvider.java
index 3278265dfa3f..ba49cfaf26ee 100644
--- a/android/source/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/source/src/java/org/libreoffice/LOKitTileProvider.java
@@ -28,7 +28,6 @@ import java.nio.ByteBuffer;
  */
 class LOKitTileProvider implements TileProvider {
     private static final String LOGTAG = LOKitTileProvider.class.getSimpleName();
-    private static final float DPI_1X_ZOOM = 96f; // for use in Calc at fixed zoom 1x
     private static int TILE_SIZE = 256;
     private final float mTileWidth;
     private final float mTileHeight;
@@ -79,11 +78,10 @@ class LOKitTileProvider implements TileProvider {
         Log.i(LOGTAG, "====> mDocument = " + mDocument);
 
         if(isSpreadsheet()) {
-            mDPI = DPI_1X_ZOOM; // Calc has a fixed zoom at 1x
-        } else {
-            mDPI = LOKitShell.getDpi(mContext);
+            mContext.setIsSpreadsheet(true); // Calc is treated differently e.g. DPI = 96f
         }
 
+        mDPI = LOKitShell.getDpi(mContext);
         mTileWidth = pixelToTwip(TILE_SIZE, mDPI);
         mTileHeight = pixelToTwip(TILE_SIZE, mDPI);
 
diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 8354dca63aa3..b16812f0bc97 100755
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -93,6 +93,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
     private FontController mFontController;
     private SearchController mSearchController;
     private CalcHeadersController mCalcHeadersController;
+    private boolean mIsSpreadsheet;
 
     public GeckoLayerClient getLayerClient() {
         return mLayerClient;
@@ -703,6 +704,14 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
         });
     }
 
+    public void setIsSpreadsheet(boolean b) {
+        mIsSpreadsheet = b;
+    }
+
+    public boolean isSpreadsheet() {
+        return mIsSpreadsheet;
+    }
+
     private class DocumentPartClickListener implements android.widget.AdapterView.OnItemClickListener {
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
diff --git a/android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java b/android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java
index dc46f047c10c..c1f8e74e7ba2 100644
--- a/android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java
+++ b/android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java
@@ -13,9 +13,15 @@ public class CalcHeaderCell extends CommonCanvasElement {
     private RectF mBounds;
     private String mText;
 
-    public CalcHeaderCell(float left, float top, float width, float height, String text) {
+    public CalcHeaderCell(float left, float top, float width, float height, String text, boolean selected) {
         mBounds = new RectF(left, top, left + width, top + height);
-        mBgPaint.setStyle(Style.STROKE);
+        if (selected) {
+            // if the cell is selected, display filled
+            mBgPaint.setStyle(Style.FILL_AND_STROKE);
+        } else {
+            // if not, display only the frame
+            mBgPaint.setStyle(Style.STROKE);
+        }
         mBgPaint.setColor(Color.GRAY);
         mBgPaint.setAlpha(100);  // hard coded for now
         mTextPaint.setColor(Color.GRAY);
diff --git a/android/source/src/java/org/libreoffice/canvas/CalcSelectionBox.java b/android/source/src/java/org/libreoffice/canvas/CalcSelectionBox.java
new file mode 100644
index 000000000000..af31d708d44e
--- /dev/null
+++ b/android/source/src/java/org/libreoffice/canvas/CalcSelectionBox.java
@@ -0,0 +1,111 @@
+package org.libreoffice.canvas;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.RectF;
+
+import org.libreoffice.LOKitShell;
+import org.libreoffice.LibreOfficeMainActivity;
+import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
+
+/**
+ * CalcSelectionBox is the selection frame for the current highlighted area/cells
+ * in Calc.
+ */
+
+public class CalcSelectionBox extends CommonCanvasElement {
+    private static final long MINIMUM_HANDLE_UPDATE_TIME = 50 * 1000000;
+    private static final float CIRCLE_HANDLE_RADIUS = 8f;
+
+    public RectF mDocumentPosition;
+
+    private LibreOfficeMainActivity mContext;
+    private RectF mScreenPosition;
+    private long mLastTime = 0;
+    private Paint mPaint;
+    private Paint mCirclePaint;
+
+    public CalcSelectionBox(LibreOfficeMainActivity context) {
+        mContext = context;
+        mScreenPosition = new RectF();
+        mDocumentPosition = new RectF();
+        mPaint = new Paint();
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setColor(Color.BLACK);
+        mPaint.setStrokeWidth(2f);
+        mCirclePaint = new Paint();
+        mCirclePaint.setColor(Color.BLACK);
+        mCirclePaint.setStyle(Paint.Style.FILL);
+    }
+
+    /**
+     * Start of a touch and drag action on the box.
+     */
+    public void dragStart(PointF point) {}
+
+    /**
+     * End of a touch and drag action on the box.
+     */
+    public void dragEnd(PointF point) {}
+
+    /**
+     * Box has been dragged.
+     */
+    public void dragging(PointF point) {
+        long currentTime = System.nanoTime();
+        if (currentTime - mLastTime > MINIMUM_HANDLE_UPDATE_TIME) {
+            mLastTime = currentTime;
+            signalHandleMove(point.x, point.y);
+        }
+    }
+
+    /**
+     * Signal to move the handle to a new position to LO.
+     */
+    private void signalHandleMove(float newX, float newY) {
+        ImmutableViewportMetrics viewportMetrics = mContext.getLayerClient().getViewportMetrics();
+        float zoom = viewportMetrics.zoomFactor;
+        PointF origin = viewportMetrics.getOrigin();
+
+        PointF documentPoint = new PointF((newX+origin.x)/zoom , (newY+origin.y)/zoom);
+
+        if (documentPoint.x < mDocumentPosition.left || documentPoint.y < mDocumentPosition.top) {
+            LOKitShell.sendChangeHandlePositionEvent(SelectionHandle.HandleType.START, documentPoint);
+        } else if (documentPoint.x > mDocumentPosition.right || documentPoint.y > mDocumentPosition.bottom){
+            LOKitShell.sendChangeHandlePositionEvent(SelectionHandle.HandleType.END, documentPoint);
+        }
+    }
+
+    @Override
+    public boolean onHitTest(float x, float y) {
+        return mScreenPosition.contains(x, y);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        canvas.drawRect(mScreenPosition, mPaint);
+        canvas.drawCircle(mScreenPosition.left, mScreenPosition.top, CIRCLE_HANDLE_RADIUS, mCirclePaint);
+        canvas.drawCircle(mScreenPosition.right, mScreenPosition.bottom, CIRCLE_HANDLE_RADIUS, mCirclePaint);
+    }
+
+    public void reposition(RectF rect) {
+        mScreenPosition = rect;
+    }
+
+    @Override
+    public boolean contains(float x, float y) {
+        // test if in range of the box or the circular handles
+        boolean inRange =  new RectF(mScreenPosition.left - CIRCLE_HANDLE_RADIUS,
+                mScreenPosition.top - CIRCLE_HANDLE_RADIUS,
+                mScreenPosition.left + CIRCLE_HANDLE_RADIUS,
+                mScreenPosition.top + CIRCLE_HANDLE_RADIUS).contains(x, y)
+                || new RectF(mScreenPosition.right - CIRCLE_HANDLE_RADIUS,
+                mScreenPosition.bottom - CIRCLE_HANDLE_RADIUS,
+                mScreenPosition.right + CIRCLE_HANDLE_RADIUS,
+                mScreenPosition.bottom + CIRCLE_HANDLE_RADIUS).contains(x, y)
+                || onHitTest(x, y);
+        return inRange && isVisible();
+    }
+}
diff --git a/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java b/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java
index 80cb0e5791d8..ced93381f0ce 100644
--- a/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java
+++ b/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java
@@ -1,6 +1,8 @@
 package org.libreoffice.overlay;
 
+import android.graphics.RectF;
 import android.util.Log;
+import android.view.View;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -15,7 +17,6 @@ import java.util.ArrayList;
 
 public class CalcHeadersController {
     private static final String LOGTAG = CalcHeadersController.class.getSimpleName();
-    private static final float DPI_1X_ZOOM = 96f; // Calc uses a fixed zoom a 1x which is 96 dpi
 
     private final CalcHeadersView mCalcRowHeadersView;
     private final CalcHeadersView mCalcColumnHeadersView;
@@ -34,6 +35,12 @@ public class CalcHeadersController {
             mCalcColumnHeadersView.initialize(layerView, false);
         }
         LOKitShell.sendEvent(new LOEvent(LOEvent.UPDATE_CALC_HEADERS));
+        context.findViewById(R.id.calc_header_top_left).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SelectAll"));
+            }
+        });
     }
 
     public void setHeaders(String headers) {
@@ -64,12 +71,12 @@ public class CalcHeadersController {
             JSONArray rowResult = collectiveResult.getJSONArray("rows");
             for (int i = 0; i < rowResult.length(); i++) {
                 headerInfo.rowLabels.add(rowResult.getJSONObject(i).getString("text"));
-                headerInfo.rowDimens.add(twipToPixel(rowResult.getJSONObject(i).getLong("size"), DPI_1X_ZOOM));
+                headerInfo.rowDimens.add(twipToPixel(rowResult.getJSONObject(i).getLong("size"), LOKitShell.getDpi(mContext)));
             }
             JSONArray columnResult = collectiveResult.getJSONArray("columns");
             for (int i = 0; i < columnResult.length(); i++) {
                 headerInfo.columnLabels.add(columnResult.getJSONObject(i).getString("text"));
-                headerInfo.columnDimens.add(twipToPixel(columnResult.getJSONObject(i).getLong("size"), DPI_1X_ZOOM));
+                headerInfo.columnDimens.add(twipToPixel(columnResult.getJSONObject(i).getLong("size"), LOKitShell.getDpi(mContext)));
             }
             return headerInfo;
         } catch (JSONException e) {
@@ -82,12 +89,27 @@ public class CalcHeadersController {
         return input / 1440.0f * dpi;
     }
 
+    public void showHeaderSelection(RectF cellCursorRect) {
+        mCalcRowHeadersView.setHeaderSelection(cellCursorRect);
+        mCalcColumnHeadersView.setHeaderSelection(cellCursorRect);
+        showHeaders();
+    }
+
+    public void setPendingRowOrColumnSelectionToShowUp(boolean b) {
+        mCalcRowHeadersView.setPendingRowOrColumnSelectionToShowUp(b);
+        mCalcColumnHeadersView.setPendingRowOrColumnSelectionToShowUp(b);
+    }
+
+    public boolean pendingRowOrColumnSelectionToShowUp() {
+        return mCalcColumnHeadersView.pendingRowOrColumnSelectionToShowUp()
+                || mCalcRowHeadersView.pendingRowOrColumnSelectionToShowUp();
+    }
+
     private class HeaderInfo {
         ArrayList<String> rowLabels;
         ArrayList<Float> rowDimens;
         ArrayList<String> columnLabels;
         ArrayList<Float> columnDimens;
-
         private HeaderInfo() {
             rowLabels = new ArrayList<String>();
             rowDimens = new ArrayList<Float>();
diff --git a/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java b/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java
index d15941470bd7..7485b6c0cb6d 100644
--- a/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java
+++ b/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java
@@ -3,23 +3,33 @@ package org.libreoffice.overlay;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.PointF;
+import android.graphics.RectF;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
 
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.libreoffice.LOEvent;
+import org.libreoffice.LOKitShell;
 import org.libreoffice.canvas.CalcHeaderCell;
 import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
 import org.mozilla.gecko.gfx.LayerView;
 
 import java.util.ArrayList;
+import java.util.Collections;
 
 public class CalcHeadersView extends View implements View.OnTouchListener {
+    private static final String LOGTAG = CalcHeadersView.class.getSimpleName();
 
     private boolean mInitialized;
     private LayerView mLayerView;
     private boolean mIsRow; // true if this is for row headers, false for column
     private ArrayList<String> mLabels;
     private ArrayList<Float> mDimens;
+    private RectF mCellCursorRect;
+    private PointF pointOfTouch;
+    private boolean mPendingRowOrColumnSelectionToShowUp;
 
     public CalcHeadersView(Context context) {
         super(context);
@@ -55,6 +65,8 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
         ImmutableViewportMetrics metrics = mLayerView.getViewportMetrics();
         float zoom = metrics.getZoomFactor();
         PointF origin = metrics.getOrigin();
+
+        // Draw headers
         boolean inRangeOfVisibleHeaders = false; // a helper variable for skipping unnecessary onDraw()'s
         float top,bottom,left,right;
         for (int i = 1; i < mLabels.size(); i++) {
@@ -63,7 +75,12 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
                 bottom = -origin.y + zoom*mDimens.get(i);
                 if (top <= getHeight() && bottom >= 0) {
                     inRangeOfVisibleHeaders = true;
-                    new CalcHeaderCell(0f, top, getWidth(), bottom - top, mLabels.get(i)).onDraw(canvas);
+                    if (mCellCursorRect != null && bottom > mCellCursorRect.top - origin.y && top < mCellCursorRect.bottom - origin.y) {
+                        // if cell is within current selected portion
+                        new CalcHeaderCell(0f, top, getWidth(), bottom - top, mLabels.get(i), true).onDraw(canvas);
+                    } else {
+                        new CalcHeaderCell(0f, top, getWidth(), bottom - top, mLabels.get(i), false).onDraw(canvas);
+                    }
                 } else {
                     if (inRangeOfVisibleHeaders) {
                         break;
@@ -73,7 +90,12 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
                 left = -origin.x + zoom*mDimens.get(i-1);
                 right = -origin.x + zoom*mDimens.get(i);
                 if (left <= getWidth() && right >= 0) {
-                    new CalcHeaderCell(left, 0f, right - left, getHeight(), mLabels.get(i)).onDraw(canvas);
+                    if (mCellCursorRect != null && right > mCellCursorRect.left - origin.x && left < mCellCursorRect.right - origin.x) {
+                        // if cell is within current selected portion
+                        new CalcHeaderCell(left, 0f, right - left, getHeight(), mLabels.get(i), true).onDraw(canvas);
+                    } else {
+                        new CalcHeaderCell(left, 0f, right - left, getHeight(), mLabels.get(i), false).onDraw(canvas);
+                    }
                 } else {
                     if (inRangeOfVisibleHeaders) {
                         break;
@@ -83,13 +105,86 @@ public class CalcHeadersView extends View implements View.OnTouchListener {
         }
     }
 
+    /**
+     * Handle the triggered touch event.
+     */
     @Override
-    public boolean onTouch(View v, MotionEvent event) {
+    public boolean onTouch(View view, MotionEvent event) {
+        PointF point = new PointF(event.getX(), event.getY());
+        switch (event.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                pointOfTouch = point;
+                return true;
+            case MotionEvent.ACTION_UP:
+                if (pointOfTouch != null) {
+                    highlightRowOrColumn();
+                }
+        }
         return false;
     }
 
+    /**
+     * Handle a single tap event on a header cell.
+     * Selects whole row/column.
+     */
+    private void highlightRowOrColumn() {
+        int searchedIndex, index;
+        ImmutableViewportMetrics metrics = mLayerView.getViewportMetrics();
+        float zoom = metrics.getZoomFactor();
+        PointF origin = metrics.getOrigin();
+        if (mIsRow) {
+            searchedIndex = Collections.binarySearch(mDimens, (pointOfTouch.y+origin.y)/zoom);
+        } else {
+            searchedIndex = Collections.binarySearch(mDimens, (pointOfTouch.x+origin.x)/zoom);
+        }
+        // converting searched index to real index on headers
+        if (searchedIndex < 0) {
+            index = - searchedIndex - 2;
+        } else {
+            index = searchedIndex;
+        }
+        try {
+            JSONObject rootJson = new JSONObject();
+            addProperty(rootJson, "Modifier", "unsigned short", "0");
+            if (mIsRow) {
+                addProperty(rootJson, "Row", "unsigned short", String.valueOf(index));
+                LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SelectRow", rootJson.toString()));
+            } else {
+                addProperty(rootJson, "Col", "unsigned short", String.valueOf(index));
+                LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SelectColumn", rootJson.toString()));
+            }
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        // At this point, InvalidationHandler.java will have received two callbacks.
+        // One is for text selection (first) and the other for cell selection (second).
+        // The second will override the first on headers which is not wanted.
+        // setPendingRowOrColumnSelectionToShowUp(true) will skip the second call.
+        setPendingRowOrColumnSelectionToShowUp(true);
+        pointOfTouch = null;
+    }
+
+    public void setPendingRowOrColumnSelectionToShowUp(boolean b) {
+        mPendingRowOrColumnSelectionToShowUp = b;
+    }
+
+    public boolean pendingRowOrColumnSelectionToShowUp() {
+        return mPendingRowOrColumnSelectionToShowUp;
+    }
+
+    private void addProperty(JSONObject json, String parentValue, String type, String value) throws JSONException {
+        JSONObject child = new JSONObject();
+        child.put("type", type);
+        child.put("value", value);
+        json.put(parentValue, child);
+    }
+
     public void setHeaders(ArrayList<String> labels, ArrayList<Float> dimens) {
         mLabels = labels;
         mDimens = dimens;
     }
+
+    public void setHeaderSelection(RectF cellCursorRect) {
+        mCellCursorRect = cellCursorRect;
+    }
 }
diff --git a/android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java b/android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java
index 4809921012bc..47669797fb1c 100644
--- a/android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java
+++ b/android/source/src/java/org/libreoffice/overlay/DocumentOverlay.java
@@ -242,6 +242,22 @@ public class DocumentOverlay {
         mDocumentOverlayView.setCalcHeadersController(calcHeadersController);
     }
 
+    public void showCellSelection(final RectF cellCursorRect) {
+        LOKitShell.getMainHandler().post(new Runnable() {
+            public void run() {
+                mDocumentOverlayView.showCellSelection(cellCursorRect);
+            }
+        });
+    }
+
+    public void showHeaderSelection(final RectF cellCursorRect) {
+        LOKitShell.getMainHandler().post(new Runnable() {
+            public void run() {
+                mDocumentOverlayView.showHeaderSelection(cellCursorRect);
+            }
+        });
+    }
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java b/android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java
index 7d5ab1972d39..d5cfcaa3edc3 100644
--- a/android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java
+++ b/android/source/src/java/org/libreoffice/overlay/DocumentOverlayView.java
@@ -19,6 +19,7 @@ import android.view.MotionEvent;
 import android.view.View;
 
 import org.libreoffice.LibreOfficeMainActivity;
+import org.libreoffice.canvas.CalcSelectionBox;
 import org.libreoffice.canvas.Cursor;
 import org.libreoffice.canvas.GraphicSelection;
 import org.libreoffice.canvas.PageNumberRect;
@@ -69,6 +70,9 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
     private int previousIndex = 0; // previous page number, used to compare with the current
     private CalcHeadersController mCalcHeadersController;
 
+    private CalcSelectionBox mCalcSelectionBox;
+    private boolean mCalcSelectionBoxDragging;
+
     public DocumentOverlayView(Context context) {
         super(context);
     }
@@ -168,6 +172,11 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
             mScaledSelections.add(scaledSelection);
         }
 
+        if (mCalcSelectionBox != null) {
+            rect = convertToScreen(mCalcSelectionBox.mDocumentPosition, x, y, zoom);
+            mCalcSelectionBox.reposition(rect);
+        }
+
         RectF scaledGraphicSelection = convertToScreen(mGraphicSelection.mRectangle, x, y, zoom);
         mGraphicSelection.reposition(scaledGraphicSelection);
         invalidate();
@@ -216,6 +225,10 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
             }
         }
 
+        if (mCalcSelectionBox != null) {
+            mCalcSelectionBox.draw(canvas);
+        }
+
         mGraphicSelection.draw(canvas);
 
         if (mCalcHeadersController != null) {
@@ -368,6 +381,12 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
                         mHandleMiddle.dragStart(point);
                         mDragHandle = mHandleMiddle;
                         return true;
+                    } else if (mCalcSelectionBox != null &&
+                            mCalcSelectionBox.contains(point.x, point.y) &&
+                            !mHandleStart.isVisible()) {
+                        mCalcSelectionBox.dragStart(point);
+                        mCalcSelectionBoxDragging = true;
+                        return true;
                     }
                 }
             }
@@ -380,6 +399,9 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
                 } else if (mDragHandle != null) {
                     mDragHandle.dragEnd(point);
                     mDragHandle = null;
+                } else if (mCalcSelectionBoxDragging) {
+                    mCalcSelectionBox.dragEnd(point);
+                    mCalcSelectionBoxDragging = false;
                 }
             }
             case MotionEvent.ACTION_MOVE: {
@@ -389,6 +411,8 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
                     return true;
                 } else if (mDragHandle != null) {
                     mDragHandle.dragging(point);
+                } else if (mCalcSelectionBoxDragging) {
+                    mCalcSelectionBox.dragging(point);
                 }
             }
         }
@@ -457,6 +481,33 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
 
     public void setCalcHeadersController(CalcHeadersController calcHeadersController) {
         mCalcHeadersController = calcHeadersController;
+        mCalcSelectionBox = new CalcSelectionBox((LibreOfficeMainActivity) getContext());
+    }
+
+    public void showCellSelection(RectF cellCursorRect) {
+        if (mCalcHeadersController == null || mCalcSelectionBox == null) return;
+        if (RectUtils.fuzzyEquals(mCalcSelectionBox.mDocumentPosition, cellCursorRect)) {
+            return;
+        }
+
+        // show selection on main GL view (i.e. in the document)
+        RectUtils.assign(mCalcSelectionBox.mDocumentPosition, cellCursorRect);
+        mCalcSelectionBox.setVisible(true);
+
+        ImmutableViewportMetrics metrics = mLayerView.getViewportMetrics();
+        repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
+
+        // show selection on headers
+        if (!mCalcHeadersController.pendingRowOrColumnSelectionToShowUp()) {
+            showHeaderSelection(cellCursorRect);
+        } else {
+            mCalcHeadersController.setPendingRowOrColumnSelectionToShowUp(false);
+        }
+    }
+
+    public void showHeaderSelection(RectF rect) {
+        if (mCalcHeadersController == null) return;
+        mCalcHeadersController.showHeaderSelection(rect);
     }
 }
 


More information about the Libreoffice-commits mailing list