From 53b6d627e7fe66ce47ee6ae01254abc070558e77 Mon Sep 17 00:00:00 2001
From: "Tadashi G. Takaoka" <takaoka@google.com>
Date: Thu, 30 Oct 2014 13:10:59 +0900
Subject: [PATCH] Refactor PointerTracker and MainKeyboardView

This CL reorganize the key press/release state visual drawing code.

Change-Id: I4aa10f57309ae2f81333a1e2bd863c23a7a41d82
---
 .../MainKeyboardAccessibilityDelegate.java    |  8 +-
 .../keyboard/MainKeyboardView.java            | 90 ++++++-----------
 .../inputmethod/keyboard/PointerTracker.java  | 98 +++++++++++--------
 .../keyboard/internal/DrawingProxy.java       | 33 ++++---
 .../keyboard/internal/TimerHandler.java       |  5 +-
 5 files changed, 112 insertions(+), 122 deletions(-)

diff --git a/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java b/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java
index 94a1ee6eba..e80982fc70 100644
--- a/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java
+++ b/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java
@@ -269,13 +269,9 @@ public final class MainKeyboardAccessibilityDelegate
                 eventTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0 /* metaState */);
         // Inject a fake down event to {@link PointerTracker} to handle a long press correctly.
         tracker.processMotionEvent(downEvent, mKeyDetector);
-        // The above fake down event triggers an unnecessary long press timer that should be
-        // canceled.
-        tracker.cancelLongPressTimer();
         downEvent.recycle();
-        // Invoke {@link MainKeyboardView#onLongPress(PointerTracker)} as if a long press timeout
-        // has passed.
-        mKeyboardView.onLongPress(tracker);
+        // Invoke {@link PointerTracker#onLongPressed()} as if a long press timeout has passed.
+        tracker.onLongPressed();
         // If {@link Key#hasNoPanelAutoMoreKeys()} is true (such as "0 +" key on the phone layout)
         // or a key invokes IME switcher dialog, we should just ignore the next
         // {@link #onRegisterHoverKey(Key,MotionEvent)}. It can be determined by whether
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 06b87bd9af..ad15fa2230 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -461,12 +461,17 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
         windowContentView.addView(mDrawingPreviewPlacerView);
     }
 
+    // Implements {@link DrawingProxy#onKeyPressed(Key,boolean)}.
     @Override
-    public void showKeyPreview(@Nonnull final Key key) {
-        // If the key is invalid or has no key preview, we must not show key preview.
-        if (key.noKeyPreview()) {
-            return;
+    public void onKeyPressed(@Nonnull final Key key, final boolean withPreview) {
+        key.onPressed();
+        invalidateKey(key);
+        if (withPreview && !key.noKeyPreview()) {
+            showKeyPreview(key);
         }
+    }
+
+    private void showKeyPreview(@Nonnull final Key key) {
         final Keyboard keyboard = getKeyboard();
         if (keyboard == null) {
             return;
@@ -483,15 +488,26 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
                 getWidth(), mOriginCoords, mDrawingPreviewPlacerView, isHardwareAccelerated());
     }
 
-    // Implements {@link DrawingProxy#dismissKeyPreviewWithoutDelay(Key)}.
-    @Override
-    public void dismissKeyPreviewWithoutDelay(@Nonnull final Key key) {
+    private void dismissKeyPreviewWithoutDelay(@Nonnull final Key key) {
         mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */);
         invalidateKey(key);
     }
 
+    // Implements {@link DrawingProxy#onKeyReleased(Key,boolean)}.
     @Override
-    public void dismissKeyPreview(@Nonnull final Key key) {
+    public void onKeyReleased(@Nonnull final Key key, final boolean withAnimation) {
+        key.onReleased();
+        invalidateKey(key);
+        if (!key.noKeyPreview()) {
+            if (withAnimation) {
+                dismissKeyPreview(key);
+            } else {
+                dismissKeyPreviewWithoutDelay(key);
+            }
+        }
+    }
+
+    private void dismissKeyPreview(@Nonnull final Key key) {
         if (isHardwareAccelerated()) {
             mKeyPreviewChoreographer.dismissKeyPreview(key, true /* withAnimation */);
             return;
@@ -574,7 +590,11 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
         mDrawingPreviewPlacerView.removeAllViews();
     }
 
-    private MoreKeysPanel onCreateMoreKeysPanel(final Key key, final Context context) {
+    // Implements {@link DrawingProxy@showMoreKeysKeyboard(Key,PointerTracker)}.
+    @Override
+    @Nullable
+    public MoreKeysPanel showMoreKeysKeyboard(@Nonnull final Key key,
+            @Nonnull final PointerTracker tracker) {
         final MoreKeySpec[] moreKeys = key.getMoreKeys();
         if (moreKeys == null) {
             return null;
@@ -590,7 +610,7 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
                     && !key.noKeyPreview() && moreKeys.length == 1
                     && mKeyPreviewDrawParams.getVisibleWidth() > 0;
             final MoreKeysKeyboard.Builder builder = new MoreKeysKeyboard.Builder(
-                    context, key, getKeyboard(), isSingleMoreKeyWithPreview,
+                    getContext(), key, getKeyboard(), isSingleMoreKeyWithPreview,
                     mKeyPreviewDrawParams.getVisibleWidth(),
                     mKeyPreviewDrawParams.getVisibleHeight(), newLabelPaint(key));
             moreKeysKeyboard = builder.build();
@@ -603,50 +623,6 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
                 (MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view);
         moreKeysKeyboardView.setKeyboard(moreKeysKeyboard);
         container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-        return moreKeysKeyboardView;
-    }
-
-    // Implements {@link DrawingProxy@onLongPress(PointerTracker)}.
-    /**
-     * Called when a key is long pressed.
-     * @param tracker the pointer tracker which pressed the parent key
-     */
-    @Override
-    public void onLongPress(@Nonnull final PointerTracker tracker) {
-        if (isShowingMoreKeysPanel()) {
-            return;
-        }
-        final Key key = tracker.getKey();
-        if (key == null) {
-            return;
-        }
-        final KeyboardActionListener listener = mKeyboardActionListener;
-        if (key.hasNoPanelAutoMoreKey()) {
-            final int moreKeyCode = key.getMoreKeys()[0].mCode;
-            tracker.onLongPressed();
-            listener.onPressKey(moreKeyCode, 0 /* repeatCount */, true /* isSinglePointer */);
-            listener.onCodeInput(moreKeyCode, Constants.NOT_A_COORDINATE,
-                    Constants.NOT_A_COORDINATE, false /* isKeyRepeat */);
-            listener.onReleaseKey(moreKeyCode, false /* withSliding */);
-            return;
-        }
-        final int code = key.getCode();
-        if (code == Constants.CODE_SPACE || code == Constants.CODE_LANGUAGE_SWITCH) {
-            // Long pressing the space key invokes IME switcher dialog.
-            if (listener.onCustomRequest(Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER)) {
-                tracker.onLongPressed();
-                listener.onReleaseKey(code, false /* withSliding */);
-                return;
-            }
-        }
-        openMoreKeysPanel(key, tracker);
-    }
-
-    private void openMoreKeysPanel(final Key key, final PointerTracker tracker) {
-        final MoreKeysPanel moreKeysPanel = onCreateMoreKeysPanel(key, getContext());
-        if (moreKeysPanel == null) {
-            return;
-        }
 
         final int[] lastCoords = CoordinateUtils.newInstance();
         tracker.getLastCoordinates(lastCoords);
@@ -664,10 +640,8 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
         // {@code mPreviewVisibleOffset} has been set appropriately in
         // {@link KeyboardView#showKeyPreview(PointerTracker)}.
         final int pointY = key.getY() + mKeyPreviewDrawParams.getVisibleOffset();
-        moreKeysPanel.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener);
-        tracker.onShowMoreKeysPanel(moreKeysPanel);
-        // TODO: Implement zoom in animation of more keys panel.
-        mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */);
+        moreKeysKeyboardView.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener);
+        return moreKeysKeyboardView;
     }
 
     public boolean isInDraggingFinger() {
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 7902ce852f..7b7dd7b72d 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -222,7 +222,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
         final int trackersSize = sTrackers.size();
         for (int i = 0; i < trackersSize; ++i) {
             final PointerTracker tracker = sTrackers.get(i);
-            tracker.setReleasedKeyGraphics(tracker.getKey());
+            tracker.setReleasedKeyGraphics(tracker.getKey(), true /* withAnimation */);
         }
     }
 
@@ -382,19 +382,18 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
         return mKeyDetector.detectHitKey(x, y);
     }
 
-    private void setReleasedKeyGraphics(@Nullable final Key key) {
+    private void setReleasedKeyGraphics(@Nullable final Key key, final boolean withAnimation) {
         if (key == null) {
             return;
         }
 
-        sDrawingProxy.dismissKeyPreview(key);
         // Even if the key is disabled, update the key release graphics just in case.
-        updateReleaseKeyGraphics(key);
+        sDrawingProxy.onKeyReleased(key, withAnimation);
 
         if (key.isShift()) {
             for (final Key shiftKey : mKeyboard.mShiftKeys) {
                 if (shiftKey != key) {
-                    updateReleaseKeyGraphics(shiftKey);
+                    sDrawingProxy.onKeyReleased(shiftKey, false /* withAnimation */);
                 }
             }
         }
@@ -403,11 +402,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
             final int altCode = key.getAltCode();
             final Key altKey = mKeyboard.getKey(altCode);
             if (altKey != null) {
-                updateReleaseKeyGraphics(altKey);
+                sDrawingProxy.onKeyReleased(altKey, false /* withAnimation */);
             }
             for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
                 if (k != key && k.getAltCode() == altCode) {
-                    updateReleaseKeyGraphics(k);
+                    sDrawingProxy.onKeyReleased(k, false /* withAnimation */);
                 }
             }
         }
@@ -418,7 +417,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
         return sTypingTimeRecorder.needsToSuppressKeyPreviewPopup(eventTime);
     }
 
-    private void setPressedKeyGraphics(final Key key, final long eventTime) {
+    private void setPressedKeyGraphics(@Nullable final Key key, final long eventTime) {
         if (key == null) {
             return;
         }
@@ -430,15 +429,13 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
             return;
         }
 
-        if (!key.noKeyPreview() && !sInGesture && !needsToSuppressKeyPreviewPopup(eventTime)) {
-            sDrawingProxy.showKeyPreview(key);
-        }
-        updatePressKeyGraphics(key);
+        final boolean noKeyPreview = sInGesture || needsToSuppressKeyPreviewPopup(eventTime);
+        sDrawingProxy.onKeyPressed(key, !noKeyPreview);
 
         if (key.isShift()) {
             for (final Key shiftKey : mKeyboard.mShiftKeys) {
                 if (shiftKey != key) {
-                    updatePressKeyGraphics(shiftKey);
+                    sDrawingProxy.onKeyPressed(shiftKey, false /* withPreview */);
                 }
             }
         }
@@ -447,26 +444,16 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
             final int altCode = key.getAltCode();
             final Key altKey = mKeyboard.getKey(altCode);
             if (altKey != null) {
-                updatePressKeyGraphics(altKey);
+                sDrawingProxy.onKeyPressed(altKey, false /* withPreview */);
             }
             for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
                 if (k != key && k.getAltCode() == altCode) {
-                    updatePressKeyGraphics(k);
+                    sDrawingProxy.onKeyPressed(k, false /* withPreview */);
                 }
             }
         }
     }
 
-    private static void updateReleaseKeyGraphics(final Key key) {
-        key.onReleased();
-        sDrawingProxy.invalidateKey(key);
-    }
-
-    private static void updatePressKeyGraphics(final Key key) {
-        key.onPressed();
-        sDrawingProxy.invalidateKey(key);
-    }
-
     public GestureStrokeDrawingPoints getGestureStrokeDrawingPoints() {
         return mGestureStrokeDrawingPoints;
     }
@@ -837,7 +824,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
     }
 
     private void processDraggingFingerOutFromOldKey(final Key oldKey) {
-        setReleasedKeyGraphics(oldKey);
+        setReleasedKeyGraphics(oldKey, true /* withAnimation */);
         callListenerOnRelease(oldKey, oldKey.getCode(), true /* withSliding */);
         startKeySelectionByDraggingFinger(oldKey);
         sTimerProxy.cancelKeyTimersOf(this);
@@ -880,12 +867,12 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
             }
             onUpEvent(x, y, eventTime);
             cancelTrackingForAction();
-            setReleasedKeyGraphics(oldKey);
+            setReleasedKeyGraphics(oldKey, true /* withAnimation */);
         } else {
             if (!mIsDetectingGesture) {
                 cancelTrackingForAction();
             }
-            setReleasedKeyGraphics(oldKey);
+            setReleasedKeyGraphics(oldKey, true /* withAnimation */);
         }
     }
 
@@ -913,7 +900,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
             onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, newKey);
             if (sInGesture) {
                 mCurrentKey = null;
-                setReleasedKeyGraphics(oldKey);
+                setReleasedKeyGraphics(oldKey, true /* withAnimation */);
                 return;
             }
         }
@@ -978,7 +965,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
         final int currentRepeatingKeyCode = mCurrentRepeatingKeyCode;
         mCurrentRepeatingKeyCode = Constants.NOT_A_CODE;
         // Release the last pressed key.
-        setReleasedKeyGraphics(currentKey);
+        setReleasedKeyGraphics(currentKey, true /* withAnimation */);
 
         if (isShowingMoreKeysPanel()) {
             if (!mIsTrackingForActionDisabled) {
@@ -1015,14 +1002,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
         }
     }
 
-    public void onShowMoreKeysPanel(final MoreKeysPanel panel) {
-        setReleasedKeyGraphics(mCurrentKey);
-        final int translatedX = panel.translateX(mLastX);
-        final int translatedY = panel.translateY(mLastY);
-        panel.onDownEvent(translatedX, translatedY, mPointerId, SystemClock.uptimeMillis());
-        mMoreKeysPanel = panel;
-    }
-
     @Override
     public void cancelTrackingForAction() {
         if (isShowingMoreKeysPanel()) {
@@ -1035,14 +1014,49 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
         return !mIsTrackingForActionDisabled;
     }
 
-    public void cancelLongPressTimer() {
+    public void onLongPressed() {
         sTimerProxy.cancelLongPressTimersOf(this);
+        if (isShowingMoreKeysPanel()) {
+            return;
+        }
+        final Key key = getKey();
+        if (key == null) {
+            return;
+        }
+        if (key.hasNoPanelAutoMoreKey()) {
+            cancelKeyTracking();
+            final int moreKeyCode = key.getMoreKeys()[0].mCode;
+            sListener.onPressKey(moreKeyCode, 0 /* repeatCont */, true /* isSinglePointer */);
+            sListener.onCodeInput(moreKeyCode, Constants.NOT_A_COORDINATE,
+                    Constants.NOT_A_COORDINATE, false /* isKeyRepeat */);
+            sListener.onReleaseKey(moreKeyCode, false /* withSliding */);
+            return;
+        }
+        final int code = key.getCode();
+        if (code == Constants.CODE_SPACE || code == Constants.CODE_LANGUAGE_SWITCH) {
+            // Long pressing the space key invokes IME switcher dialog.
+            if (sListener.onCustomRequest(Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER)) {
+                cancelKeyTracking();
+                sListener.onReleaseKey(code, false /* withSliding */);
+                return;
+            }
+        }
+
+        setReleasedKeyGraphics(key, false /* withAnimation */);
+        final MoreKeysPanel moreKeysPanel = sDrawingProxy.showMoreKeysKeyboard(key, this);
+        if (moreKeysPanel == null) {
+            return;
+        }
+        final int translatedX = moreKeysPanel.translateX(mLastX);
+        final int translatedY = moreKeysPanel.translateY(mLastY);
+        moreKeysPanel.onDownEvent(translatedX, translatedY, mPointerId, SystemClock.uptimeMillis());
+        mMoreKeysPanel = moreKeysPanel;
     }
 
-    public void onLongPressed() {
+    private void cancelKeyTracking() {
         resetKeySelectionByDraggingFinger();
         cancelTrackingForAction();
-        setReleasedKeyGraphics(mCurrentKey);
+        setReleasedKeyGraphics(mCurrentKey, true /* withAnimation */);
         sPointerTrackerQueue.remove(this);
     }
 
@@ -1059,7 +1073,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
 
     private void onCancelEventInternal() {
         sTimerProxy.cancelKeyTimersOf(this);
-        setReleasedKeyGraphics(mCurrentKey);
+        setReleasedKeyGraphics(mCurrentKey, true /* withAnimation */);
         resetKeySelectionByDraggingFinger();
         dismissMoreKeysPanel();
     }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java b/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java
index 7fc586a0f1..06bdfc41b9 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java
@@ -17,29 +17,36 @@
 package com.android.inputmethod.keyboard.internal;
 
 import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.MoreKeysPanel;
 import com.android.inputmethod.keyboard.PointerTracker;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 public interface DrawingProxy {
-    // TODO: Remove this method.
-    public void invalidateKey(@Nullable Key key);
-
-    // TODO: Rename this method to onKeyPressed.
-    public void showKeyPreview(@Nonnull Key key);
-
-    // TODO: Rename this method to onKeyReleased.
-    public void dismissKeyPreview(@Nonnull Key key);
+    /**
+     * Called when a key is being pressed.
+     * @param key the {@link Key} that is being pressed.
+     * @param withPreview true if key popup preview should be displayed.
+     */
+    public void onKeyPressed(@Nonnull Key key, boolean withPreview);
 
     /**
-     * Dismiss a key preview visual without delay.
-     * @param key the key whose preview visual should be dismissed.
+     * Called when a key is being released.
+     * @param key the {@link Key} that is being released.
+     * @param withAnimation when true, key popup preview should be dismissed with animation.
      */
-    public void dismissKeyPreviewWithoutDelay(@Nonnull Key key);
+    public void onKeyReleased(@Nonnull Key key, boolean withAnimation);
 
-    // TODO: Rename this method to onKeyLongPressed.
-    public void onLongPress(@Nonnull PointerTracker tracker);
+    /**
+     * Start showing more keys keyboard of a key that is being long pressed.
+     * @param key the {@link Key} that is being long pressed and showing more keys keyboard.
+     * @param tracker the {@link PointerTracker} that detects this long pressing.
+     * @return {@link MoreKeysPanel} that is being shown. null if there is no need to show more keys
+     *     keyboard.
+     */
+    @Nullable
+    public MoreKeysPanel showMoreKeysKeyboard(@Nonnull Key key, @Nonnull PointerTracker tracker);
 
     /**
      * Start a while-typing-animation.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
index 8068427bc4..91f3558eb5 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
@@ -66,7 +66,7 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<DrawingProxy>
         case MSG_LONGPRESS_SHIFT_KEY:
             cancelLongPressTimers();
             final PointerTracker tracker2 = (PointerTracker) msg.obj;
-            drawingProxy.onLongPress(tracker2);
+            tracker2.onLongPressed();
             break;
         case MSG_UPDATE_BATCH_INPUT:
             final PointerTracker tracker3 = (PointerTracker) msg.obj;
@@ -74,8 +74,7 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<DrawingProxy>
             startUpdateBatchInputTimer(tracker3);
             break;
         case MSG_DISMISS_KEY_PREVIEW:
-            final Key key = (Key) msg.obj;
-            drawingProxy.dismissKeyPreviewWithoutDelay(key);
+            drawingProxy.onKeyReleased((Key) msg.obj, false /* withAnimation */);
             break;
         case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT:
             drawingProxy.dismissGestureFloatingPreviewTextWithoutDelay();
-- 
GitLab