diff options
author | Ximeng Zu <uznomis@yahoo.com> | 2017-06-18 16:37:13 -0500 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2017-07-31 23:15:48 +0200 |
commit | b9471511523d5c80b80a5e99d149af65e9915840 (patch) | |
tree | 4c8fb05425bd6dba1b278e04e10efd5c91db3e76 /android/source | |
parent | 90ac4671c13ed4f548bb4188355b02217b9e24ba (diff) |
[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@libreoffice.org>
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'android/source')
11 files changed, 337 insertions, 14 deletions
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); } } |