[Libreoffice-commits] core.git: Branch 'feature/tiled-editing' - 6 commits - android/experimental

Tomaž Vajngerl tomaz.vajngerl at collabora.co.uk
Wed Feb 25 23:40:40 PST 2015


 android/experimental/LOAndroid3/res/drawable/text_cursor.xml                      |    6 
 android/experimental/LOAndroid3/res/layout/text_selection_handles.xml             |    5 
 android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java |  155 ++++++----
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java         |    7 
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java   |    5 
 android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorLayer.java     |   12 
 android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java      |  109 ++++---
 android/experimental/LOAndroid3/src/java/org/libreoffice/TileProviderFactory.java |    5 
 8 files changed, 204 insertions(+), 100 deletions(-)

New commits:
commit bd5e7776f12fd144c26b6f10659f732c880d2bf1
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Feb 26 16:29:43 2015 +0900

    android: add OverlayState to track the state of overlay
    
    Overlay can either be in state NONE - no overlay elements should
    be shown (this is the deocument reader state), CURSOR - cursor
    and the cursor handle are shown, SELECTION - selection and
    selection handles are shown. The states can change either by
    an invalidation or touch input.
    
    Change-Id: Ia15eb58193675b3799c0014a91f4429a729e30d4

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
index 8933c88..fb46c77 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
@@ -18,10 +18,12 @@ public class InvalidationHandler {
 
     private TextCursorLayer mTextCursorLayer;
     private TextSelection mTextSelection;
+    private OverlayState mState;
 
     public InvalidationHandler(LibreOfficeMainActivity mainActivity) {
         mTextCursorLayer = mainActivity.getTextCursorLayer();
         mTextSelection = mainActivity.getTextSelection();
+        mState = OverlayState.NONE;
     }
 
     /**
@@ -54,6 +56,10 @@ public class InvalidationHandler {
         }
     }
 
+    public void setOverlayState(OverlayState state) {
+        this.mState = state;
+    }
+
     /**
      * Parses the payload text with rectangle coordinates and converts to rectangle in pixel coordinates
      *
@@ -133,18 +139,19 @@ public class InvalidationHandler {
      * @param payload
      */
     private void invalidateCursor(String payload) {
-        RectF cursorRectangle = convertPayloadToRectangle(payload);
-        if (cursorRectangle != null) {
-            TextSelection textSelection = LibreOfficeMainActivity.mAppContext.getTextSelection();
-            textSelection.positionHandle(TextSelectionHandle.HandleType.MIDDLE, createRectangleUnderSelection(cursorRectangle));
-            textSelection.showHandle(TextSelectionHandle.HandleType.MIDDLE);
-
-            textSelection.hideHandle(TextSelectionHandle.HandleType.START);
-            textSelection.hideHandle(TextSelectionHandle.HandleType.END);
-
-            TextCursorLayer textCursorLayer = LibreOfficeMainActivity.mAppContext.getTextCursorLayer();
-            textCursorLayer.positionCursor(cursorRectangle);
-            textCursorLayer.showCursor();
+        if (mState == OverlayState.CURSOR) {
+            RectF cursorRectangle = convertPayloadToRectangle(payload);
+            if (cursorRectangle != null) {
+                TextSelection textSelection = LibreOfficeMainActivity.mAppContext.getTextSelection();
+                textSelection.positionHandle(TextSelectionHandle.HandleType.MIDDLE, createRectangleUnderSelection(cursorRectangle));
+                textSelection.showHandle(TextSelectionHandle.HandleType.MIDDLE);
+                textSelection.hideHandle(TextSelectionHandle.HandleType.START);
+                textSelection.hideHandle(TextSelectionHandle.HandleType.END);
+
+                TextCursorLayer textCursorLayer = LibreOfficeMainActivity.mAppContext.getTextCursorLayer();
+                textCursorLayer.positionCursor(cursorRectangle);
+                textCursorLayer.showCursor();
+            }
         }
     }
 
@@ -154,12 +161,15 @@ public class InvalidationHandler {
      * @param payload
      */
     private void invalidateSelectionStart(String payload) {
+        if (mState == OverlayState.NONE) {
+            return;
+        }
         RectF selectionRectangle = convertPayloadToRectangle(payload);
         if (selectionRectangle != null) {
             mTextSelection.positionHandle(TextSelectionHandle.HandleType.START, createRectangleUnderSelection(selectionRectangle));
             mTextSelection.showHandle(TextSelectionHandle.HandleType.START);
             mTextSelection.hideHandle(TextSelectionHandle.HandleType.MIDDLE);
-            mTextCursorLayer.hideCursor();
+            mState = OverlayState.SELECTION;
         }
     }
 
@@ -169,12 +179,15 @@ public class InvalidationHandler {
      * @param payload
      */
     private void invalidateSelectionEnd(String payload) {
+        if (mState == OverlayState.NONE) {
+            return;
+        }
         RectF selectionRect = convertPayloadToRectangle(payload);
         if (selectionRect != null) {
             mTextSelection.positionHandle(TextSelectionHandle.HandleType.END, createRectangleUnderSelection(selectionRect));
             mTextSelection.showHandle(TextSelectionHandle.HandleType.END);
             mTextSelection.hideHandle(TextSelectionHandle.HandleType.MIDDLE);
-            mTextCursorLayer.hideCursor();
+            mState = OverlayState.SELECTION;
         }
     }
 
@@ -184,12 +197,23 @@ public class InvalidationHandler {
      * @param payload
      */
     private void invalidateSelection(String payload) {
+        if (mState == OverlayState.NONE) {
+            return;
+        }
         if (payload.isEmpty()) {
+            mState = OverlayState.CURSOR;
             mTextSelection.hideHandle(TextSelectionHandle.HandleType.START);
             mTextSelection.hideHandle(TextSelectionHandle.HandleType.END);
         } else {
+            mState = OverlayState.SELECTION;
             List<RectF> rects = convertPayloadToRectangles(payload);
             mTextCursorLayer.changeSelections(rects);
         }
     }
+
+    public enum OverlayState {
+        NONE,
+        CURSOR,
+        SELECTION
+    }
 }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index fa7fb59..c2dbb23 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -233,10 +233,12 @@ public class LOKitThread extends Thread {
         if (touchType.equals("LongPress")) {
             LibreOfficeMainActivity.mAppContext.hideSoftKeyboard();
             mTileProvider.mouseButtonDown(mDocumentTouchCoordinate, 2);
+            mInvalidationHandler.setOverlayState(InvalidationHandler.OverlayState.SELECTION);
         } else { // "SingleTap"
             LibreOfficeMainActivity.mAppContext.showSoftKeyboard();
             mTileProvider.mouseButtonDown(mDocumentTouchCoordinate, 1);
             mTileProvider.mouseButtonUp(mDocumentTouchCoordinate, 1);
+            mInvalidationHandler.setOverlayState(InvalidationHandler.OverlayState.CURSOR);
         }
     }
 
commit 268fee35fe6aff55bb891652c817137a589bce8f
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Feb 26 16:24:42 2015 +0900

    android: swap position of invalidateCursor and invalidateTiles
    
    Change-Id: Iebc21915b92c82b0def3f4f61fb2128c2942d122

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
index cfef907..8933c88 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
@@ -116,6 +116,18 @@ public class InvalidationHandler {
     }
 
     /**
+     * Handles the tile invalidation message
+     *
+     * @param payload
+     */
+    private void invalidateTiles(String payload) {
+        RectF rectangle = convertPayloadToRectangle(payload);
+        if (rectangle != null) {
+            LOKitShell.sendTileInvalidationRequest(rectangle);
+        }
+    }
+
+    /**
      * Handles the cursor invalidation message
      *
      * @param payload
@@ -137,18 +149,6 @@ public class InvalidationHandler {
     }
 
     /**
-     * Handles the tile invalidation message
-     *
-     * @param payload
-     */
-    private void invalidateTiles(String payload) {
-        RectF rectangle = convertPayloadToRectangle(payload);
-        if (rectangle != null) {
-            LOKitShell.sendTileInvalidationRequest(rectangle);
-        }
-    }
-
-    /**
      * Handles the selection start invalidation message
      *
      * @param payload
commit 2dd45e008002c945829763543e3980671d75f8ab
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Feb 26 16:18:08 2015 +0900

    android: support parsing selection rectangles, rectructure code
    
    Add support to parse selection rectangles (series of rectangles
    separated by ";"). Additionally restructure and clean up the code
    in InvalidationHandler to be better readable - better comments,
    better variable and method names.
    
    Change-Id: I64d1dc4a806831bd47ca9f14478bec8192035461

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
index a43127b..cfef907 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
@@ -7,6 +7,9 @@ import org.libreoffice.kit.Document;
 import org.mozilla.gecko.TextSelection;
 import org.mozilla.gecko.TextSelectionHandle;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Parses (interprets) and handles invalidation messages from LibreOffice.
  */
@@ -52,17 +55,17 @@ public class InvalidationHandler {
     }
 
     /**
-     * Parses the invalidation message text and converts to rectangle in pixel coordinates
+     * Parses the payload text with rectangle coordinates and converts to rectangle in pixel coordinates
      *
-     * @param messageText - invalidation message text
+     * @param payload - invalidation message payload text
      * @return rectangle in pixel coordinates
      */
-    private RectF convertCallbackMessageStringToRectF(String messageText) {
-        if (messageText.equals("EMPTY")) {
+    private RectF convertPayloadToRectangle(String payload) {
+        if (payload.equals("EMPTY")) {
             return null;
         }
 
-        String[] coordinates = messageText.split(",");
+        String[] coordinates = payload.split(",");
 
         if (coordinates.length != 4) {
             return null;
@@ -85,18 +88,51 @@ public class InvalidationHandler {
     }
 
     /**
+     * Parses the payload text with more rectangles (separated by ';') and converts to a list of rectangles.
+     *
+     * @param payload - invalidation message payload text
+     * @return list of rectangles
+     */
+    private List<RectF> convertPayloadToRectangles(String payload) {
+        List<RectF> rectangles = new ArrayList<RectF>();
+        String[] rectangleArray = payload.split(";");
+
+        for (String coordinates : rectangleArray) {
+            RectF rectangle = convertPayloadToRectangle(payload);
+            rectangles.add(rectangle);
+        }
+
+        return rectangles;
+    }
+
+    /**
+     * From input rectangle, create a new rectangle which positions under the input rectangle.
+     *
+     * @param rectangle - input rectangle
+     * @return new rectangle positioned under the input rectangle
+     */
+    private RectF createRectangleUnderSelection(RectF rectangle) {
+        return new RectF(rectangle.centerX(), rectangle.bottom, rectangle.centerX(), rectangle.bottom);
+    }
+
+    /**
      * Handles the cursor invalidation message
      *
      * @param payload
      */
     private void invalidateCursor(String payload) {
-        RectF rect = convertCallbackMessageStringToRectF(payload);
-        if (rect != null) {
-            RectF underSelection = new RectF(rect.centerX(), rect.bottom, rect.centerX(), rect.bottom);
-            mTextSelection.positionHandle(TextSelectionHandle.HandleType.MIDDLE, underSelection);
-            mTextSelection.showHandle(TextSelectionHandle.HandleType.MIDDLE);
-            mTextCursorLayer.positionCursor(rect);
-            mTextCursorLayer.showCursor();
+        RectF cursorRectangle = convertPayloadToRectangle(payload);
+        if (cursorRectangle != null) {
+            TextSelection textSelection = LibreOfficeMainActivity.mAppContext.getTextSelection();
+            textSelection.positionHandle(TextSelectionHandle.HandleType.MIDDLE, createRectangleUnderSelection(cursorRectangle));
+            textSelection.showHandle(TextSelectionHandle.HandleType.MIDDLE);
+
+            textSelection.hideHandle(TextSelectionHandle.HandleType.START);
+            textSelection.hideHandle(TextSelectionHandle.HandleType.END);
+
+            TextCursorLayer textCursorLayer = LibreOfficeMainActivity.mAppContext.getTextCursorLayer();
+            textCursorLayer.positionCursor(cursorRectangle);
+            textCursorLayer.showCursor();
         }
     }
 
@@ -106,9 +142,9 @@ public class InvalidationHandler {
      * @param payload
      */
     private void invalidateTiles(String payload) {
-        RectF rect = convertCallbackMessageStringToRectF(payload);
-        if (rect != null) {
-            LOKitShell.sendTileInvalidationRequest(rect);
+        RectF rectangle = convertPayloadToRectangle(payload);
+        if (rectangle != null) {
+            LOKitShell.sendTileInvalidationRequest(rectangle);
         }
     }
 
@@ -118,10 +154,9 @@ public class InvalidationHandler {
      * @param payload
      */
     private void invalidateSelectionStart(String payload) {
-        RectF rect = convertCallbackMessageStringToRectF(payload);
-        if (rect != null) {
-            RectF underSelection = new RectF(rect.centerX(), rect.bottom, rect.centerX(), rect.bottom);
-            mTextSelection.positionHandle(TextSelectionHandle.HandleType.START, underSelection);
+        RectF selectionRectangle = convertPayloadToRectangle(payload);
+        if (selectionRectangle != null) {
+            mTextSelection.positionHandle(TextSelectionHandle.HandleType.START, createRectangleUnderSelection(selectionRectangle));
             mTextSelection.showHandle(TextSelectionHandle.HandleType.START);
             mTextSelection.hideHandle(TextSelectionHandle.HandleType.MIDDLE);
             mTextCursorLayer.hideCursor();
@@ -134,10 +169,9 @@ public class InvalidationHandler {
      * @param payload
      */
     private void invalidateSelectionEnd(String payload) {
-        RectF rect = convertCallbackMessageStringToRectF(payload);
-        if (rect != null) {
-            RectF underSelection = new RectF(rect.centerX(), rect.bottom, rect.centerX(), rect.bottom);
-            mTextSelection.positionHandle(TextSelectionHandle.HandleType.END, underSelection);
+        RectF selectionRect = convertPayloadToRectangle(payload);
+        if (selectionRect != null) {
+            mTextSelection.positionHandle(TextSelectionHandle.HandleType.END, createRectangleUnderSelection(selectionRect));
             mTextSelection.showHandle(TextSelectionHandle.HandleType.END);
             mTextSelection.hideHandle(TextSelectionHandle.HandleType.MIDDLE);
             mTextCursorLayer.hideCursor();
@@ -153,7 +187,9 @@ public class InvalidationHandler {
         if (payload.isEmpty()) {
             mTextSelection.hideHandle(TextSelectionHandle.HandleType.START);
             mTextSelection.hideHandle(TextSelectionHandle.HandleType.END);
+        } else {
+            List<RectF> rects = convertPayloadToRectangles(payload);
+            mTextCursorLayer.changeSelections(rects);
         }
     }
-
 }
commit 9929f81d8bc4643538d52b8b8492bb245c541b56
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Feb 26 15:53:49 2015 +0900

    android: create InvalidationHandler outside of LOKitTileProvider
    
    Change-Id: I79bb20ca5a16a2ebdc6ed3f1c97a483173b0762b

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
index ae18647b..a43127b 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
@@ -13,14 +13,19 @@ import org.mozilla.gecko.TextSelectionHandle;
 public class InvalidationHandler {
     private static String LOGTAG = InvalidationHandler.class.getSimpleName();
 
-    public InvalidationHandler() {
+    private TextCursorLayer mTextCursorLayer;
+    private TextSelection mTextSelection;
+
+    public InvalidationHandler(LibreOfficeMainActivity mainActivity) {
+        mTextCursorLayer = mainActivity.getTextCursorLayer();
+        mTextSelection = mainActivity.getTextSelection();
     }
 
     /**
      * Processes invalidation message
      *
      * @param messageID - ID of the message
-     * @param payload - additional invalidation message payload
+     * @param payload   - additional invalidation message payload
      */
     public void processMessage(int messageID, String payload) {
         switch (messageID) {
@@ -28,6 +33,7 @@ public class InvalidationHandler {
                 invalidateTiles(payload);
                 break;
             case Document.CALLBACK_INVALIDATE_VISIBLE_CURSOR:
+                Log.i(LOGTAG, "Cursor: " + payload);
                 invalidateCursor(payload);
                 break;
             case Document.CALLBACK_INVALIDATE_TEXT_SELECTION:
@@ -80,24 +86,23 @@ public class InvalidationHandler {
 
     /**
      * Handles the cursor invalidation message
+     *
      * @param payload
      */
     private void invalidateCursor(String payload) {
         RectF rect = convertCallbackMessageStringToRectF(payload);
         if (rect != null) {
             RectF underSelection = new RectF(rect.centerX(), rect.bottom, rect.centerX(), rect.bottom);
-            TextSelection textSelection = LibreOfficeMainActivity.mAppContext.getTextSelection();
-            textSelection.positionHandle(TextSelectionHandle.HandleType.MIDDLE, underSelection);
-            textSelection.showHandle(TextSelectionHandle.HandleType.MIDDLE);
-
-            TextCursorLayer textCursorLayer = LibreOfficeMainActivity.mAppContext.getTextCursorLayer();
-            textCursorLayer.positionCursor(rect);
-            textCursorLayer.showCursor();
+            mTextSelection.positionHandle(TextSelectionHandle.HandleType.MIDDLE, underSelection);
+            mTextSelection.showHandle(TextSelectionHandle.HandleType.MIDDLE);
+            mTextCursorLayer.positionCursor(rect);
+            mTextCursorLayer.showCursor();
         }
     }
 
     /**
      * Handles the tile invalidation message
+     *
      * @param payload
      */
     private void invalidateTiles(String payload) {
@@ -109,51 +114,45 @@ public class InvalidationHandler {
 
     /**
      * Handles the selection start invalidation message
+     *
      * @param payload
      */
     private void invalidateSelectionStart(String payload) {
         RectF rect = convertCallbackMessageStringToRectF(payload);
         if (rect != null) {
             RectF underSelection = new RectF(rect.centerX(), rect.bottom, rect.centerX(), rect.bottom);
-            TextSelection textSelection = LibreOfficeMainActivity.mAppContext.getTextSelection();
-            textSelection.positionHandle(TextSelectionHandle.HandleType.START, underSelection);
-            textSelection.showHandle(TextSelectionHandle.HandleType.START);
-
-            textSelection.hideHandle(TextSelectionHandle.HandleType.MIDDLE);
-
-            TextCursorLayer textCursorLayer = LibreOfficeMainActivity.mAppContext.getTextCursorLayer();
-            textCursorLayer.hideCursor();
+            mTextSelection.positionHandle(TextSelectionHandle.HandleType.START, underSelection);
+            mTextSelection.showHandle(TextSelectionHandle.HandleType.START);
+            mTextSelection.hideHandle(TextSelectionHandle.HandleType.MIDDLE);
+            mTextCursorLayer.hideCursor();
         }
     }
 
     /**
      * Handles the selection end invalidation message
+     *
      * @param payload
      */
     private void invalidateSelectionEnd(String payload) {
         RectF rect = convertCallbackMessageStringToRectF(payload);
         if (rect != null) {
             RectF underSelection = new RectF(rect.centerX(), rect.bottom, rect.centerX(), rect.bottom);
-            TextSelection textSelection = LibreOfficeMainActivity.mAppContext.getTextSelection();
-            textSelection.positionHandle(TextSelectionHandle.HandleType.END, underSelection);
-            textSelection.showHandle(TextSelectionHandle.HandleType.END);
-
-            textSelection.hideHandle(TextSelectionHandle.HandleType.MIDDLE);
-
-            TextCursorLayer textCursorLayer = LibreOfficeMainActivity.mAppContext.getTextCursorLayer();
-            textCursorLayer.hideCursor();
+            mTextSelection.positionHandle(TextSelectionHandle.HandleType.END, underSelection);
+            mTextSelection.showHandle(TextSelectionHandle.HandleType.END);
+            mTextSelection.hideHandle(TextSelectionHandle.HandleType.MIDDLE);
+            mTextCursorLayer.hideCursor();
         }
     }
 
     /**
      * Handles the selection invalidation message
+     *
      * @param payload
      */
     private void invalidateSelection(String payload) {
         if (payload.isEmpty()) {
-            TextSelection textSelection = LibreOfficeMainActivity.mAppContext.getTextSelection();
-            textSelection.hideHandle(TextSelectionHandle.HandleType.START);
-            textSelection.hideHandle(TextSelectionHandle.HandleType.END);
+            mTextSelection.hideHandle(TextSelectionHandle.HandleType.START);
+            mTextSelection.hideHandle(TextSelectionHandle.HandleType.END);
         }
     }
 
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index 0507efc..fa7fb59 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -24,10 +24,12 @@ public class LOKitThread extends Thread {
 
     private LibreOfficeMainActivity mApplication;
     private TileProvider mTileProvider;
+    private InvalidationHandler mInvalidationHandler;
     private ImmutableViewportMetrics mViewportMetrics;
     private GeckoLayerClient mLayerClient;
 
     public LOKitThread() {
+        mInvalidationHandler = null;
         TileProviderFactory.initialize();
     }
 
@@ -154,7 +156,8 @@ public class LOKitThread extends Thread {
 
         mLayerClient = mApplication.getLayerClient();
 
-        mTileProvider = TileProviderFactory.create(mLayerClient, filename);
+        mInvalidationHandler = new InvalidationHandler(LibreOfficeMainActivity.mAppContext);
+        mTileProvider = TileProviderFactory.create(mLayerClient, mInvalidationHandler, filename);
 
         if (mTileProvider.isReady()) {
             LOKitShell.showProgressSpinner();
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
index f99cda0..f1faf71 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
@@ -37,12 +37,13 @@ public class LOKitTileProvider implements TileProvider, Document.MessageCallback
     private float mWidthTwip;
     private float mHeightTwip;
 
-    private InvalidationHandler mInvalidationHandler = new InvalidationHandler();
+    private InvalidationHandler mInvalidationHandler;
 
     private long objectCreationTime = System.currentTimeMillis();
 
-    public LOKitTileProvider(GeckoLayerClient layerClient, String input) {
+    public LOKitTileProvider(GeckoLayerClient layerClient, InvalidationHandler invalidationHandler, String input) {
         mLayerClient = layerClient;
+        mInvalidationHandler = invalidationHandler;
         mDPI = (float) LOKitShell.getDpi();
         mTileWidth = pixelToTwip(TILE_SIZE, mDPI);
         mTileHeight = pixelToTwip(TILE_SIZE, mDPI);
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProviderFactory.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProviderFactory.java
index b79e56e..60982f6 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProviderFactory.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProviderFactory.java
@@ -8,7 +8,6 @@ public class TileProviderFactory {
     private static TileProviderID currentTileProvider = TileProviderID.LOKIT;
 
     private TileProviderFactory() {
-
     }
 
     public static void initialize() {
@@ -17,9 +16,9 @@ public class TileProviderFactory {
         }
     }
 
-    public static TileProvider create(GeckoLayerClient layerClient, String filename) {
+    public static TileProvider create(GeckoLayerClient layerClient, InvalidationHandler invalidationHandler, String filename) {
         if (currentTileProvider == TileProviderID.LOKIT) {
-            return new LOKitTileProvider(layerClient, filename);
+            return new LOKitTileProvider(layerClient, invalidationHandler, filename);
         } else {
             return new MockTileProvider(layerClient, filename);
         }
commit f47c44fb778ff6b00b8814d3c9a4f6c67b08c820
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Feb 26 15:43:42 2015 +0900

    android: add selection support to TextCursorView{Layer}
    
    TextCursorView is a overlay view on top of document view which
    is used to draw the cursor (and blink it too). This also adds
    selection rectangles drawing to the same view so both can be drawn
    at the same time.
    
    Change-Id: I3ce034d90597bac4569f04ac903a5443c28cb38e

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorLayer.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorLayer.java
index 1e6f167..92080e9 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorLayer.java
@@ -9,6 +9,8 @@ import org.mozilla.gecko.gfx.Layer;
 import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.util.FloatUtils;
 
+import java.util.List;
+
 /**
  * The TextCursorLayer is a layer which is responsible for showing the cursor and
  * controls its position, height and visibility.
@@ -74,7 +76,15 @@ public class TextCursorLayer extends Layer {
     public void positionCursor(final RectF position) {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.changePosition(position);
+                mCursorView.changeCursorPosition(position);
+            }
+        });
+    }
+
+    public void changeSelections(final List<RectF> selections) {
+        LOKitShell.getMainHandler().post(new Runnable() {
+            public void run() {
+                mCursorView.changeSelections(selections);
             }
         });
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java
index 93600c6..1aa24ce 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java
@@ -15,47 +15,58 @@ import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
 import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.gfx.RectUtils;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Text cursor view responsible to show the cursor drawable on the screen.
  */
 public class TextCursorView extends View {
     private static final String LOGTAG = TextCursorView.class.getSimpleName();
+    private static final float CURSOR_WIDTH = 2f;
 
-    private boolean mCursorAnimationEnabled = false;
+    private boolean mInitialized = false;
     private RectF mCursorPosition = new RectF();
-    private PointF mCursorScaledPosition = new PointF();
-
-    private float mCursorHeight = 0f;
-    private float mCursorWidth = 2f;
-
+    private RectF mCursorScaledPosition = new RectF();
     private int mCursorAlpha = 0;
 
+    private List<RectF> mSelections = new ArrayList<RectF>();
+    private List<RectF> mScaledSelections = new ArrayList<RectF>();
+    private Paint mCursorPaint = new Paint();
+    private Paint mSelectionPaint = new Paint();
+
     public TextCursorView(Context context) {
         super(context);
-        startCursorAnimation();
+        initialize();
     }
 
     public TextCursorView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        startCursorAnimation();
+        initialize();
     }
 
     public TextCursorView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        startCursorAnimation();
+        initialize();
     }
 
-    private void startCursorAnimation() {
-        if (!mCursorAnimationEnabled) {
-            mCursorAnimationEnabled = true;
+    private void initialize() {
+        if (!mInitialized) {
             postDelayed(cursorAnimation, 500);
+
+            mCursorPaint.setColor(Color.BLACK);
+            mCursorPaint.setAlpha(0);
+            mSelectionPaint.setColor(Color.BLUE);
+            mSelectionPaint.setAlpha(50);
+
+            mInitialized = true;
         }
     }
 
-    public void changePosition(RectF position) {
+    public void changeCursorPosition(RectF position) {
         LayerView layerView = LOKitShell.getLayerView();
         if (layerView == null) {
-            Log.e(LOGTAG, "Can't position handle because layerView is null");
+            Log.e(LOGTAG, "Can't position cursor because layerView is null");
             return;
         }
 
@@ -64,32 +75,46 @@ public class TextCursorView extends View {
         repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
     }
 
-    public void repositionWithViewport(float x, float y, float zoom) {
-        RectF scaledRectangle = RectUtils.scale(mCursorPosition, zoom);
+    public void changeSelections(List<RectF> selectionRects) {
+        LayerView layerView = LOKitShell.getLayerView();
+        if (layerView == null) {
+            Log.e(LOGTAG, "Can't position selections because layerView is null");
+            return;
+        }
+
+        mSelections = selectionRects;
 
-        mCursorScaledPosition = new PointF(scaledRectangle.left - x, scaledRectangle.top - y);
-        mCursorHeight = scaledRectangle.height();
+        ImmutableViewportMetrics metrics = layerView.getViewportMetrics();
+        repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
+    }
 
+    public void repositionWithViewport(float x, float y, float zoom) {
+        mCursorScaledPosition = RectUtils.scale(mCursorPosition, zoom);
+        mCursorScaledPosition.offset(-x, -y);
+        mCursorScaledPosition.right = mCursorScaledPosition.left + CURSOR_WIDTH;
+
+        mScaledSelections.clear();
+        for (RectF selection : mSelections) {
+            RectF scaledSelection = RectUtils.scale(selection, zoom);
+            scaledSelection.offset(-x, -y);
+            mScaledSelections.add(scaledSelection);
+        }
         invalidate();
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
-        Paint paint = new Paint();
-        paint.setColor(Color.BLACK);
-        paint.setAlpha(mCursorAlpha);
-        RectF cursorRect = new RectF(
-                mCursorScaledPosition.x,
-                mCursorScaledPosition.y,
-                mCursorScaledPosition.x + mCursorWidth,
-                mCursorScaledPosition.y + mCursorHeight);
-        canvas.drawRect(cursorRect, paint);
+        canvas.drawRect(mCursorScaledPosition, mCursorPaint);
+
+        for (RectF selection : mScaledSelections) {
+            canvas.drawRect(selection, mSelectionPaint);
+        }
     }
 
     private Runnable cursorAnimation = new Runnable() {
         public void run() {
-            mCursorAlpha = mCursorAlpha == 0 ? 0xFF : 0;
+            mCursorPaint.setAlpha(mCursorPaint.getAlpha() == 0 ? 0xFF : 0);
             invalidate();
             postDelayed(cursorAnimation, 500);
         }
commit 021adaf2ba16a0f5eec44a20fa2478a469f1281b
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Feb 26 13:25:58 2015 +0900

    android: change TextCursorView parent to View and draw with canvas
    
    Previously TextCursorView was subclassing ImageView and a drawable
    to draw the cursor by scaling the drawable, which is not an ideal
    solution. This is now changed so that the TextCursorView is a
    proper subclass of View and draws the cursor using canvas.
    
    Change-Id: I27b1ea73911afbfe9eee6bf382db5368ae449308

diff --git a/android/experimental/LOAndroid3/res/drawable/text_cursor.xml b/android/experimental/LOAndroid3/res/drawable/text_cursor.xml
deleted file mode 100644
index f39e6e8..0000000
--- a/android/experimental/LOAndroid3/res/drawable/text_cursor.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
-    <size android:width="2px" />
-    <size android:height="1px" />
-    <solid android:color="#000000"/>
-</shape>
\ No newline at end of file
diff --git a/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml b/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml
index 8d8d014..3de21f6 100644
--- a/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml
+++ b/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml
@@ -28,9 +28,8 @@
                                            gecko:handleType="end"/>
 
     <org.libreoffice.TextCursorView android:id="@+id/text_cursor_view"
-                                    android:layout_width="wrap_content"
-                                    android:layout_height="wrap_content"
-                                    android:src="@drawable/text_cursor"
+                                    android:layout_width="fill_parent"
+                                    android:layout_height="fill_parent"
                                     android:visibility="gone"/>
 
 </merge>
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java
index b2508b6..93600c6 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java
@@ -1,10 +1,14 @@
 package org.libreoffice;
 
 import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
 import android.graphics.RectF;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.widget.ImageView;
+import android.view.View;
 import android.widget.RelativeLayout;
 
 import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
@@ -14,22 +18,38 @@ import org.mozilla.gecko.gfx.RectUtils;
 /**
  * Text cursor view responsible to show the cursor drawable on the screen.
  */
-public class TextCursorView extends ImageView {
+public class TextCursorView extends View {
     private static final String LOGTAG = TextCursorView.class.getSimpleName();
 
-    private RectF mPosition;
-    private RelativeLayout.LayoutParams mLayoutParams;
+    private boolean mCursorAnimationEnabled = false;
+    private RectF mCursorPosition = new RectF();
+    private PointF mCursorScaledPosition = new PointF();
 
-    private int mLeft;
-    private int mTop;
+    private float mCursorHeight = 0f;
+    private float mCursorWidth = 2f;
 
-    private int mWidth;
-    private int mHeight;
-    private int mAlpha = 0;
+    private int mCursorAlpha = 0;
+
+    public TextCursorView(Context context) {
+        super(context);
+        startCursorAnimation();
+    }
 
     public TextCursorView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        postDelayed(cursorAnimation, 500);
+        startCursorAnimation();
+    }
+
+    public TextCursorView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        startCursorAnimation();
+    }
+
+    private void startCursorAnimation() {
+        if (!mCursorAnimationEnabled) {
+            mCursorAnimationEnabled = true;
+            postDelayed(cursorAnimation, 500);
+        }
     }
 
     public void changePosition(RectF position) {
@@ -39,45 +59,37 @@ public class TextCursorView extends ImageView {
             return;
         }
 
-        mPosition = position;
-
-        mWidth = Math.round(position.width());
-        mHeight = Math.round(position.height());
-
+        mCursorPosition = position;
         ImmutableViewportMetrics metrics = layerView.getViewportMetrics();
         repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
     }
 
     public void repositionWithViewport(float x, float y, float zoom) {
-        RectF scaled = RectUtils.scale(mPosition, zoom);
+        RectF scaledRectangle = RectUtils.scale(mCursorPosition, zoom);
 
-        mLeft = Math.round(scaled.centerX() - x);
-        mTop = Math.round(scaled.centerY() - y);
+        mCursorScaledPosition = new PointF(scaledRectangle.left - x, scaledRectangle.top - y);
+        mCursorHeight = scaledRectangle.height();
 
-        setScaleY(scaled.height());
-        setLayoutPosition();
+        invalidate();
     }
 
-    private void setLayoutPosition() {
-        if (mLayoutParams == null) {
-            mLayoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
-            // Set negative right/bottom margins so that the handles can be dragged outside of
-            // the content area (if they are dragged to the left/top, the dyanmic margins set
-            // below will take care of that).
-            mLayoutParams.rightMargin = 0 - mWidth;
-            mLayoutParams.bottomMargin = 0 - mHeight;
-        }
-
-        mLayoutParams.leftMargin = mLeft;
-        mLayoutParams.topMargin = mTop;
-
-        setLayoutParams(mLayoutParams);
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        Paint paint = new Paint();
+        paint.setColor(Color.BLACK);
+        paint.setAlpha(mCursorAlpha);
+        RectF cursorRect = new RectF(
+                mCursorScaledPosition.x,
+                mCursorScaledPosition.y,
+                mCursorScaledPosition.x + mCursorWidth,
+                mCursorScaledPosition.y + mCursorHeight);
+        canvas.drawRect(cursorRect, paint);
     }
 
     private Runnable cursorAnimation = new Runnable() {
         public void run() {
-            mAlpha = mAlpha == 0 ? 0xFF : 0;
-            getDrawable().setAlpha(mAlpha);
+            mCursorAlpha = mCursorAlpha == 0 ? 0xFF : 0;
             invalidate();
             postDelayed(cursorAnimation, 500);
         }


More information about the Libreoffice-commits mailing list