/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 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.LayerView; import static org.libreoffice.canvas.GraphicSelectionHandle.HandlePosition; /** * This class is responsible to draw and reposition the selection * rectangle. */ public class GraphicSelection extends CommonCanvasElement { private final Paint mPaintStroke; private final Paint mPaintFill; public RectF mRectangle = new RectF(); public RectF mScaledRectangle = new RectF(); private RectF mDrawRectangle = new RectF(); private DragType mType = DragType.NONE; private PointF mStartDragPosition; private GraphicSelectionHandle mHandles[] = new GraphicSelectionHandle[8]; private GraphicSelectionHandle mDragHandle = null; private boolean mTriggerSinglePress = false; private LibreOfficeMainActivity mContext; /** * Construct the graphic selection. */ public GraphicSelection(LibreOfficeMainActivity context) { mContext = context; // Create the paint, which is needed at drawing mPaintStroke = new Paint(); mPaintStroke.setStyle(Paint.Style.STROKE); mPaintStroke.setColor(Color.GRAY); mPaintStroke.setStrokeWidth(2); mPaintStroke.setAntiAlias(true); mPaintFill = new Paint(); mPaintFill.setStyle(Paint.Style.FILL); mPaintFill.setColor(Color.WHITE); mPaintFill.setAlpha(200); mPaintFill.setAntiAlias(true); // Create the handles of the selection mHandles[0] = new GraphicSelectionHandle(HandlePosition.TOP_LEFT); mHandles[1] = new GraphicSelectionHandle(HandlePosition.TOP); mHandles[2] = new GraphicSelectionHandle(HandlePosition.TOP_RIGHT); mHandles[3] = new GraphicSelectionHandle(HandlePosition.LEFT); mHandles[4] = new GraphicSelectionHandle(HandlePosition.RIGHT); mHandles[5] = new GraphicSelectionHandle(HandlePosition.BOTTOM_LEFT); mHandles[6] = new GraphicSelectionHandle(HandlePosition.BOTTOM); mHandles[7] = new GraphicSelectionHandle(HandlePosition.BOTTOM_RIGHT); } /** * Viewport has changed, reposition the selection to the new rectangle. * @param scaledRectangle - rectangle of selection position on the document */ public void reposition(RectF scaledRectangle) { mScaledRectangle = scaledRectangle; mDrawRectangle = scaledRectangle; // rectangle that will be draw // reposition the handles too mHandles[0].reposition(scaledRectangle.left, scaledRectangle.top); mHandles[1].reposition(scaledRectangle.centerX(), scaledRectangle.top); mHandles[2].reposition(scaledRectangle.right, scaledRectangle.top); mHandles[3].reposition(scaledRectangle.left, scaledRectangle.centerY()); mHandles[4].reposition(scaledRectangle.right, scaledRectangle.centerY()); mHandles[5].reposition(scaledRectangle.left, scaledRectangle.bottom); mHandles[6].reposition(scaledRectangle.centerX(), scaledRectangle.bottom); mHandles[7].reposition(scaledRectangle.right, scaledRectangle.bottom); } /** * Hit test for the selection. * @see org.libreoffice.canvas.CanvasElement#draw(android.graphics.Canvas) */ @Override public boolean onHitTest(float x, float y) { // Check if handle was hit for (GraphicSelectionHandle handle : mHandles) { if (handle.contains(x, y)) { return true; } } return mScaledRectangle.contains(x, y); } /** * Draw the selection on the canvas. * @see org.libreoffice.canvas.CanvasElement#draw(android.graphics.Canvas) */ @Override public void onDraw(Canvas canvas) { canvas.drawRect(mDrawRectangle, mPaintStroke); if (mType != DragType.NONE) { canvas.drawRect(mDrawRectangle, mPaintFill); } for (GraphicSelectionHandle handle : mHandles) { handle.draw(canvas); } } /** * Dragging on the screen has started. * @param position - position where the dragging started */ public void dragStart(PointF position) { mDragHandle = null; mType = DragType.NONE; for (GraphicSelectionHandle handle : mHandles) { if (handle.contains(position.x, position.y)) { mDragHandle = handle; mDragHandle.select(); mType = DragType.EXTEND; sendGraphicSelectionStart(handle.mPosition); } } if (mDragHandle == null) { mType = DragType.MOVE; sendGraphicSelectionStart(position); } mStartDragPosition = position; mTriggerSinglePress = true; } /** * Dragging is in process. * @param position - position of the drag */ public void dragging(PointF position) { if (mType == DragType.MOVE) { float deltaX = position.x - mStartDragPosition.x; float deltaY = position.y - mStartDragPosition.y; mDrawRectangle = new RectF(mScaledRectangle); mDrawRectangle.offset(deltaX, deltaY); } else if (mType == DragType.EXTEND) { adaptDrawRectangle(position.x, position.y); } mTriggerSinglePress = false; } /** * Dragging has ended. * @param position - last position of the drag */ public void dragEnd(PointF position) { PointF point = new PointF(); if (mDragHandle != null) { point.x = mDragHandle.mPosition.x; point.y = mDragHandle.mPosition.y; mDragHandle.reset(); mDragHandle = null; } else { point.x = mStartDragPosition.x; point.y = mStartDragPosition.y; } float deltaX = position.x - mStartDragPosition.x; float deltaY = position.y - mStartDragPosition.y; point.offset(deltaX, deltaY); sendGraphicSelectionEnd(point); if (mTriggerSinglePress && mDragHandle == null) { onSinglePress(point); mTriggerSinglePress = false; } mDrawRectangle = mScaledRectangle; mType = DragType.NONE; } /** * Adapt the selection depending on which handle was dragged. */ private void adaptDrawRectangle(float x, float y) { mDrawRectangle = new RectF(mScaledRectangle); switch(mDragHandle.getHandlePosition()) { case TOP_LEFT: mDrawRectangle.left = x; mDrawRectangle.top = y; break; case TOP: mDrawRectangle.top = y; break; case TOP_RIGHT: mDrawRectangle.right = x; mDrawRectangle.top = y; break; case LEFT: mDrawRectangle.left = x; break; case RIGHT: mDrawRectangle.right = x; break; case BOTTOM_LEFT: mDrawRectangle.left = x; mDrawRectangle.bottom = y; break; case BOTTOM: mDrawRectangle.bottom = y; break; case BOTTOM_RIGHT: mDrawRectangle.right = x; mDrawRectangle.bottom = y; break; } } /** * Send graphic selection start event to LOKitTread. * @param screenPosition - screen position of the selection */ private void sendGraphicSelectionStart(PointF screenPosition) { sendGraphicSelection("GraphicSelectionStart", screenPosition); } /** * Send graphic selection end event to LOKitTread. * @param screenPosition - screen position of the selection */ private void sendGraphicSelectionEnd(PointF screenPosition) { sendGraphicSelection("GraphicSelectionEnd", screenPosition); } /** * Send graphic selection event to LOKitTread. * @param type - type of the graphic selection * @param screenPosition - screen position of the selection */ private void sendGraphicSelection(String type, PointF screenPosition) { LayerView layerView = mContext.getLayerClient().getView(); if (layerView != null) { // Position is in screen coordinates. We need to convert them to // document coordinates. PointF documentPoint = layerView.getLayerClient().convertViewPointToLayerPoint(screenPosition); LOKitShell.sendTouchEvent(type, documentPoint); } } /** * When a single press (no dragging happened) was performed. */ private void onSinglePress(PointF screenPosition) { sendGraphicSelection("LongPress", screenPosition); } /** * Set the visibility of the graphic selection. */ @Override public void setVisible(boolean visible) { super.setVisible(visible); for (GraphicSelectionHandle handle: mHandles) { handle.setVisible(visible); } } /** * Reset the selection. */ public void reset() { mDragHandle = null; for (GraphicSelectionHandle handle : mHandles) { handle.reset(); } } /** * Type of the selection dragging. */ public enum DragType { NONE, MOVE, EXTEND } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */