From ff961ddf8c58df569c97684bfd83a01b2a9470aa Mon Sep 17 00:00:00 2001
From: "Tadashi G. Takaoka" <takaoka@google.com>
Date: Thu, 24 Jan 2013 16:08:33 +0900
Subject: [PATCH] Add preliminary graphics of sliding key input preview

Bug: 7548583
Change-Id: Idde6a62f9e64458055c99c893b71c02d1adc7b04
---
 java/res/values/attrs.xml                     |  2 ++
 java/res/values/colors.xml                    |  3 ++
 java/res/values/config.xml                    | 16 ++++-----
 java/res/values/strings.xml                   |  3 ++
 java/res/values/styles.xml                    |  3 ++
 java/res/xml/prefs.xml                        |  5 +++
 .../keyboard/MainKeyboardView.java            |  4 +++
 .../inputmethod/keyboard/PointerTracker.java  | 12 +++----
 .../internal/SlidingKeyInputPreview.java      | 33 +++++++++++++++----
 .../android/inputmethod/latin/LatinIME.java   | 23 ++++++-------
 .../android/inputmethod/latin/Settings.java   |  1 +
 .../inputmethod/latin/SettingsValues.java     |  3 ++
 12 files changed, 76 insertions(+), 32 deletions(-)

diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 850b1b8dc..51a0758e6 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -83,6 +83,8 @@
         <attr name="touchNoiseThresholdDistance" format="dimension" />
         <!-- Sliding key input enable -->
         <attr name="slidingKeyInputEnable" format="boolean" />
+        <attr name="slidingKeyInputPreviewColor" format="color" />
+        <attr name="slidingKeyInputPreviewWidth" format="dimension" />
         <!-- Key repeat start timeout -->
         <attr name="keyRepeatStartTimeout" format="integer" />
         <!-- Key repeat interval in millisecond. -->
diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml
index da4d87cca..c0ea321ce 100644
--- a/java/res/values/colors.xml
+++ b/java/res/values/colors.xml
@@ -17,6 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <!-- Color resources for default, and Gingerbread theme. -->
     <color name="highlight_color_default">#FFFCAE00</color>
+    <color name="highlight_translucent_color_default">#99FCAE00</color>
     <color name="key_text_color_default">@android:color/white</color>
     <color name="key_text_shadow_color_default">#BB000000</color>
     <color name="key_text_inactivated_color_default">@android:color/white</color>
@@ -39,7 +40,9 @@
     <color name="spacebar_text_color_stone">@android:color/black</color>
     <color name="spacebar_text_shadow_color_stone">#D0FFFFFF</color>
     <!-- Color resources for IceCreamSandwich theme. -->
+    <!-- android:color/holo_blue_light value is #FF33B5E5 -->
     <color name="highlight_color_ics">@android:color/holo_blue_light</color>
+    <color name="highlight_translucent_color_ics">#9933B5E5</color>
     <color name="key_text_color_ics">@android:color/white</color>
     <color name="key_text_shadow_color_ics">@android:color/transparent</color>
     <color name="key_text_inactivated_color_ics">#66E0E4E5</color>
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 6b3c891c7..82166df92 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -46,14 +46,7 @@
     <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
     <string name="config_default_keyboard_theme_index" translatable="false">5</string>
     <integer name="config_max_more_keys_column">5</integer>
-    <!--
-         Configuration for KeyboardView
-    -->
-    <integer name="config_key_preview_linger_timeout">70</integer>
-    <integer name="config_gesture_floating_preview_text_linger_timeout">200</integer>
-    <integer name="config_gesture_preview_trail_fadeout_start_delay">100</integer>
-    <integer name="config_gesture_preview_trail_fadeout_duration">800</integer>
-    <integer name="config_gesture_preview_trail_update_interval">20</integer>
+
     <!--
          Configuration for MainKeyboardView
     -->
@@ -61,7 +54,10 @@
     <dimen name="config_key_hysteresis_distance_for_sliding_modifier">8.0dp</dimen>
     <integer name="config_touch_noise_threshold_time">40</integer>
     <dimen name="config_touch_noise_threshold_distance">12.6dp</dimen>
+    <integer name="config_key_preview_linger_timeout">70</integer>
     <bool name="config_sliding_key_input_enabled">true</bool>
+    <!-- Sliding key input preview parameters -->
+    <dimen name="config_sliding_key_input_preview_width">8.0dp</dimen>
     <integer name="config_key_repeat_start_timeout">400</integer>
     <integer name="config_key_repeat_interval">50</integer>
     <integer name="config_default_longpress_key_timeout">300</integer>  <!-- milliseconds -->
@@ -74,6 +70,10 @@
     <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if
          false -->
     <bool name="config_show_more_keys_keyboard_at_touched_point">false</bool>
+    <integer name="config_gesture_floating_preview_text_linger_timeout">200</integer>
+    <integer name="config_gesture_preview_trail_fadeout_start_delay">100</integer>
+    <integer name="config_gesture_preview_trail_fadeout_duration">800</integer>
+    <integer name="config_gesture_preview_trail_update_interval">20</integer>
     <!-- Static threshold for gesture after fast typing (msec) -->
     <integer name="config_gesture_static_time_threshold_after_fast_typing">500</integer>
     <!-- Static threshold for starting gesture detection (keyWidth%/sec) -->
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index e39cafc7f..d8c2e84f5 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -69,6 +69,9 @@
     <!-- Option summary for showing language switch key [CHAR LIMIT=65] -->
     <string name="show_language_switch_key_summary">Show when multiple input languages are enabled</string>
 
+    <!-- Option to enable sliding key input preview. The user can see a rubber band during sliding key input. [CHAR LIMIT=30]-->
+    <string name="sliding_key_input_preview">Sliding key input preview</string>
+
     <!-- Option for the dismiss delay of the key popup [CHAR LIMIT=25] -->
     <string name="key_preview_popup_dismiss_delay">Key popup dismiss delay</string>
     <!-- Description for delay for dismissing a popup on keypress: no delay [CHAR LIMIT=15] -->
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index f71963ad1..f07f2d352 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -78,6 +78,8 @@
         <item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item>
         <item name="touchNoiseThresholdDistance">@dimen/config_touch_noise_threshold_distance</item>
         <item name="slidingKeyInputEnable">@bool/config_sliding_key_input_enabled</item>
+        <item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_default</item>
+        <item name="slidingKeyInputPreviewWidth">@dimen/config_sliding_key_input_preview_width</item>
         <item name="keyRepeatStartTimeout">@integer/config_key_repeat_start_timeout</item>
         <item name="keyRepeatInterval">@integer/config_key_repeat_interval</item>
         <item name="longPressShiftLockTimeout">@integer/config_longpress_shift_lock_timeout</item>
@@ -336,6 +338,7 @@
         <item name="keyPreviewOffset">@dimen/key_preview_offset_ics</item>
         <item name="keyTextShadowColor">@color/key_text_shadow_color_ics</item>
         <item name="keyTextShadowRadius">0.0</item>
+        <item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_ics</item>
         <item name="gestureFloatingPreviewTextColor">@color/highlight_color_ics</item>
         <item name="gesturePreviewTrailColor">@color/highlight_color_ics</item>
     </style>
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index 84e7f54ab..cff7505f4 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -142,6 +142,11 @@
                 android:key="custom_input_styles"
                 android:title="@string/custom_input_styles_title" />
             <!-- Values for popup dismiss delay are added programatically -->
+            <CheckBoxPreference
+                android:key="pref_sliding_key_input_preview"
+                android:title="@string/sliding_key_input_preview"
+                android:persistent="true"
+                android:defaultValue="true" />
             <ListPreference
                 android:key="pref_key_preview_popup_dismiss_delay"
                 android:title="@string/key_preview_popup_dismiss_delay" />
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index cf89ef210..1dd7b06dd 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -879,6 +879,10 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
         mDrawingHandler.dismissKeyPreview(mKeyPreviewLingerTimeout, tracker);
     }
 
+    public void setSlidingKeyInputPreviewEnabled(final boolean enabled) {
+        mSlidingKeyInputPreview.setPreviewEnabled(enabled);
+    }
+
     @Override
     public void showSlidingKeyInputPreview(final PointerTracker tracker) {
         locatePreviewPlacerView();
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 1988bb855..d54b98ccc 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -951,12 +951,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
             return;
         }
 
-        if (isShowingMoreKeysPanel()) {
-            final int translatedX = mMoreKeysPanel.translateX(x);
-            final int translatedY = mMoreKeysPanel.translateY(y);
-            mMoreKeysPanel.onMoveEvent(translatedX, translatedY, mPointerId, eventTime);
-        }
-
         if (sShouldHandleGesture && me != null) {
             // Add historical points to gesture path.
             final int pointerIndex = me.findPointerIndex(mPointerId);
@@ -971,7 +965,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
         }
 
         if (isShowingMoreKeysPanel()) {
-            // Do not handle sliding keys (or show key pop-ups) when the MoreKeysPanel is visible.
+            final int translatedX = mMoreKeysPanel.translateX(x);
+            final int translatedY = mMoreKeysPanel.translateY(y);
+            mMoreKeysPanel.onMoveEvent(translatedX, translatedY, mPointerId, eventTime);
+            onMoveKey(x, y);
+            mDrawingProxy.showSlidingKeyInputPreview(this);
             return;
         }
         onMoveEventInternal(x, y, eventTime);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputPreview.java b/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputPreview.java
index 322f981c4..37f4e3582 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputPreview.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputPreview.java
@@ -18,25 +18,40 @@ package com.android.inputmethod.keyboard.internal;
 
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
 import android.view.View;
 
 import com.android.inputmethod.keyboard.PointerTracker;
 import com.android.inputmethod.latin.CoordinateUtils;
+import com.android.inputmethod.latin.R;
 
 /**
  * Draw rubber band preview graphics during sliding key input.
  */
 public final class SlidingKeyInputPreview extends AbstractDrawingPreview {
+    private final int mPreviewWidth;
+
     private boolean mShowSlidingKeyInputPreview;
-    private final int[] mRubberBandFrom = CoordinateUtils.newInstance();
-    private final int[] mRubberBandTo = CoordinateUtils.newInstance();
+    private final int[] mPreviewFrom = CoordinateUtils.newInstance();
+    private final int[] mPreviewTo = CoordinateUtils.newInstance();
+
+    // TODO: Finalize the rubber band preview implementation.
+    private final RoundedLine mRoundedLine = new RoundedLine();
+    private final Paint mPaint = new Paint();
 
     public SlidingKeyInputPreview(final View drawingView, final TypedArray mainKeyboardViewAttr) {
         super(drawingView);
+        final int previewColor = mainKeyboardViewAttr.getColor(
+                R.styleable.MainKeyboardView_slidingKeyInputPreviewColor, 0);
+        mPreviewWidth = mainKeyboardViewAttr.getDimensionPixelSize(
+                R.styleable.MainKeyboardView_slidingKeyInputPreviewWidth, 0);
+        mPaint.setColor(previewColor);
     }
 
     public void dismissSlidingKeyInputPreview() {
         mShowSlidingKeyInputPreview = false;
+        getDrawingView().invalidate();
     }
 
     /**
@@ -45,10 +60,16 @@ public final class SlidingKeyInputPreview extends AbstractDrawingPreview {
      */
     @Override
     public void drawPreview(final Canvas canvas) {
-        if (!isPreviewEnabled() || mShowSlidingKeyInputPreview == false) {
+        if (!isPreviewEnabled() || !mShowSlidingKeyInputPreview) {
             return;
         }
-        // TODO: Implement rubber band preview
+
+        // TODO: Finalize the rubber band preview implementation.
+        final int radius = mPreviewWidth / 2;
+        final Path path = mRoundedLine.makePath(
+                CoordinateUtils.x(mPreviewFrom), CoordinateUtils.y(mPreviewFrom), radius,
+                CoordinateUtils.x(mPreviewTo), CoordinateUtils.y(mPreviewTo), radius);
+        canvas.drawPath(path, mPaint);
     }
 
     /**
@@ -61,8 +82,8 @@ public final class SlidingKeyInputPreview extends AbstractDrawingPreview {
             mShowSlidingKeyInputPreview = false;
             return;
         }
-        tracker.getDownCoordinates(mRubberBandFrom);
-        tracker.getLastCoordinates(mRubberBandTo);
+        tracker.getDownCoordinates(mPreviewFrom);
+        tracker.getLastCoordinates(mPreviewTo);
         mShowSlidingKeyInputPreview = true;
         getDrawingView().invalidate();
     }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 70eb6e657..6f11acf1a 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -71,7 +71,6 @@ import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardActionListener;
 import com.android.inputmethod.keyboard.KeyboardId;
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.KeyboardView;
 import com.android.inputmethod.keyboard.MainKeyboardView;
 import com.android.inputmethod.latin.Utils.Stats;
 import com.android.inputmethod.latin.define.ProductionFlag;
@@ -653,6 +652,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
         super.onStartInputView(editorInfo, restarting);
         final KeyboardSwitcher switcher = mKeyboardSwitcher;
         final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();
+        final SettingsValues currentSettings = mSettings.getCurrent();
 
         if (editorInfo == null) {
             Log.e(TAG, "Null EditorInfo in onStartInputView()");
@@ -706,7 +706,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
             accessUtils.onStartInputViewInternal(mainKeyboardView, editorInfo, restarting);
         }
 
-        final boolean inputTypeChanged = !mSettings.getCurrent().isSameInputType(editorInfo);
+        final boolean inputTypeChanged = !currentSettings.isSameInputType(editorInfo);
         final boolean isDifferentTextField = !restarting || inputTypeChanged;
         if (isDifferentTextField) {
             mSubtypeSwitcher.updateParametersOnStartInputView();
@@ -737,12 +737,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
             mainKeyboardView.closing();
             loadSettings();
 
-            if (mSuggest != null && mSettings.getCurrent().mCorrectionEnabled) {
-                mSuggest.setAutoCorrectionThreshold(
-                        mSettings.getCurrent().mAutoCorrectionThreshold);
+            if (mSuggest != null && currentSettings.mCorrectionEnabled) {
+                mSuggest.setAutoCorrectionThreshold(currentSettings.mAutoCorrectionThreshold);
             }
 
-            switcher.loadKeyboard(editorInfo, mSettings.getCurrent());
+            switcher.loadKeyboard(editorInfo, currentSettings);
         } else if (restarting) {
             // TODO: Come up with a more comprehensive way to reset the keyboard layout when
             // a keyboard layout set doesn't get reloaded in this method.
@@ -764,12 +763,14 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
         mHandler.cancelDoubleSpacePeriodTimer();
 
         mainKeyboardView.setMainDictionaryAvailability(mIsMainDictionaryAvailable);
-        mainKeyboardView.setKeyPreviewPopupEnabled(mSettings.getCurrent().mKeyPreviewPopupOn,
-                mSettings.getCurrent().mKeyPreviewPopupDismissDelay);
+        mainKeyboardView.setKeyPreviewPopupEnabled(currentSettings.mKeyPreviewPopupOn,
+                currentSettings.mKeyPreviewPopupDismissDelay);
+        mainKeyboardView.setSlidingKeyInputPreviewEnabled(
+                currentSettings.mSlidingKeyInputPreviewEnabled);
         mainKeyboardView.setGestureHandlingEnabledByUser(
-                mSettings.getCurrent().mGestureInputEnabled);
-        mainKeyboardView.setGesturePreviewMode(mSettings.getCurrent().mGesturePreviewTrailEnabled,
-                mSettings.getCurrent().mGestureFloatingPreviewTextEnabled);
+                currentSettings.mGestureInputEnabled);
+        mainKeyboardView.setGesturePreviewMode(currentSettings.mGesturePreviewTrailEnabled,
+                currentSettings.mGestureFloatingPreviewTextEnabled);
 
         // If we have a user dictionary addition in progress, we should check now if we should
         // replace the previously committed string with the word that has actually been added
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 408ea4a49..49e19c272 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -55,6 +55,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
     public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction";
     public static final String PREF_GESTURE_SETTINGS = "gesture_typing_settings";
     public static final String PREF_GESTURE_INPUT = "gesture_input";
+    public static final String PREF_SLIDING_KEY_INPUT_PREVIEW = "pref_sliding_key_input_preview";
     public static final String PREF_KEY_LONGPRESS_TIMEOUT = "pref_key_longpress_timeout";
     public static final String PREF_VIBRATION_DURATION_SETTINGS =
             "pref_vibration_duration_settings";
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 29e79e4cc..f43382cb5 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -59,6 +59,7 @@ public final class SettingsValues {
     public final boolean mGestureInputEnabled;
     public final boolean mGesturePreviewTrailEnabled;
     public final boolean mGestureFloatingPreviewTextEnabled;
+    public final boolean mSlidingKeyInputPreviewEnabled;
     public final int mKeyLongpressTimeout;
 
     // From the input box
@@ -107,6 +108,8 @@ public final class SettingsValues {
         mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON,
                 res.getBoolean(R.bool.config_default_sound_enabled));
         mKeyPreviewPopupOn = Settings.readKeyPreviewPopupEnabled(prefs, res);
+        mSlidingKeyInputPreviewEnabled = prefs.getBoolean(
+                Settings.PREF_SLIDING_KEY_INPUT_PREVIEW, true);
         final String voiceModeMain = res.getString(R.string.voice_mode_main);
         final String voiceModeOff = res.getString(R.string.voice_mode_off);
         mVoiceMode = prefs.getString(Settings.PREF_VOICE_MODE, voiceModeMain);