From c42f285b35b24af792b71259445eb7e975a50a29 Mon Sep 17 00:00:00 2001
From: "Tadashi G. Takaoka" <takaoka@google.com>
Date: Mon, 12 Dec 2011 16:11:37 +0900
Subject: [PATCH] Introduce KeyboardSet to hold related KeyboardIds

This change moves
  * KeyboardSwitcher.getKeyboardId to KeyboardSet.<init> and
    KeyboardSet.getKeyboardId.
  * KeyboardSwitcher.getF2KeyMode to KeyboardSet.
This is the first step to get rid of shift state from Keyboard.

Bug: 5002108
Bug: 5679585
Change-Id: I2a5a97e5e89277bc606916d45c1afbc8d105d773
---
 .../inputmethod/keyboard/KeyboardSet.java     | 134 ++++++++++++++++++
 .../keyboard/KeyboardSwitcher.java            |  90 ++----------
 2 files changed, 144 insertions(+), 80 deletions(-)
 create mode 100644 java/src/com/android/inputmethod/keyboard/KeyboardSet.java

diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
new file mode 100644
index 000000000..a803188da
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.inputmethod.latin.LatinIME;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.SettingsValues;
+import com.android.inputmethod.latin.SubtypeSwitcher;
+import com.android.inputmethod.latin.Utils;
+
+import java.util.Locale;
+
+/**
+ * This class has a set of {@link KeyboardId}s. Each of them represents a different keyboard
+ * specific to a keyboard state, such as alphabet, symbols, and so on.  Layouts in the same
+ * {@link KeyboardSet} are related to each other.
+ * A {@link KeyboardSet} needs to be created for each {@link android.view.inputmethod.EditorInfo}.
+ */
+public class KeyboardSet {
+    // TODO: Make these KeyboardId private.
+    public final KeyboardId mAlphabetId;
+    public final KeyboardId mSymbolsId;
+    public final KeyboardId mSymbolsShiftedId;
+
+    KeyboardSet(Builder builder) {
+        mAlphabetId = builder.getKeyboardId(false, false);
+        mSymbolsId = builder.getKeyboardId(true, false);
+        mSymbolsShiftedId = builder.getKeyboardId(true, true);
+    }
+
+    public static class Builder {
+        private final Resources mResources;
+        private final EditorInfo mEditorInfo;
+
+        private final int mMode;
+        private final boolean mVoiceKeyEnabled;
+        private final boolean mNoSettingsKey;
+        private final boolean mHasSettingsKey;
+        private final int mF2KeyMode;
+        private final boolean mVoiceKeyOnMain;
+        private final Locale mLocale;
+        private final Configuration mConf;
+        private final DisplayMetrics mMetrics;
+
+        public Builder(Context context, EditorInfo editorInfo, SettingsValues settingsValues) {
+            mResources = context.getResources();
+            mEditorInfo = editorInfo;
+            final SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
+            final String packageName = context.getPackageName();
+
+            mMode = Utils.getKeyboardMode(mEditorInfo);
+            final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
+            @SuppressWarnings("deprecation")
+            final boolean noMicrophone = Utils.inPrivateImeOptions(
+                    packageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
+                    || Utils.inPrivateImeOptions(
+                            null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo);
+            mVoiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo) && !noMicrophone;
+            mVoiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
+            mNoSettingsKey = Utils.inPrivateImeOptions(
+                    packageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
+            mHasSettingsKey = settingsKeyEnabled && !mNoSettingsKey;
+            mF2KeyMode = getF2KeyMode(settingsKeyEnabled, mNoSettingsKey);
+            final boolean forceAscii = Utils.inPrivateImeOptions(
+                    packageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
+            final boolean asciiCapable = subtypeSwitcher.currentSubtypeContainsExtraValueKey(
+                    LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
+            mLocale = (forceAscii && !asciiCapable) ? Locale.US : subtypeSwitcher.getInputLocale();
+            mConf = mResources.getConfiguration();
+            mMetrics = mResources.getDisplayMetrics();
+        }
+
+        public KeyboardSet build() {
+            return new KeyboardSet(this);
+        }
+
+        KeyboardId getKeyboardId(boolean isSymbols, boolean isShift) {
+            final int xmlId = getXmlId(mMode, isSymbols, isShift);
+            final boolean hasShortCutKey = mVoiceKeyEnabled && (isSymbols != mVoiceKeyOnMain);
+            return new KeyboardId(mResources.getResourceEntryName(xmlId), xmlId, mLocale,
+                    mConf.orientation, mMetrics.widthPixels, mMode, mEditorInfo, mHasSettingsKey,
+                    mF2KeyMode, mNoSettingsKey, mVoiceKeyEnabled, hasShortCutKey);
+        }
+
+        private static int getXmlId(int mode, boolean isSymbols, boolean isShift) {
+            switch (mode) {
+            case KeyboardId.MODE_PHONE:
+                return (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
+            case KeyboardId.MODE_NUMBER:
+                return R.xml.kbd_number;
+            default:
+                if (isSymbols) {
+                    return isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
+                }
+                return R.xml.kbd_qwerty;
+            }
+        }
+
+        private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) {
+            if (noSettingsKey) {
+                // Never shows the Settings key
+                return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
+            }
+
+            if (settingsKeyEnabled) {
+                return KeyboardId.F2KEY_MODE_SETTINGS;
+            } else {
+                // It should be alright to fall back to the Settings key on 7-inch layouts
+                // even when the Settings key is not explicitly enabled.
+                return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
+            }
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 5c2779213..165e9aec7 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -18,9 +18,7 @@ package com.android.inputmethod.keyboard;
 
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.InflateException;
@@ -65,14 +63,11 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
     private InputView mCurrentInputView;
     private LatinKeyboardView mKeyboardView;
     private LatinIME mInputMethodService;
-    private String mPackageName;
     private Resources mResources;
 
     private KeyboardState mState;
 
-    private KeyboardId mMainKeyboardId;
-    private KeyboardId mSymbolsKeyboardId;
-    private KeyboardId mSymbolsShiftedKeyboardId;
+    private KeyboardSet mKeyboardSet;
 
     private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
             new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
@@ -100,7 +95,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
 
     private void initInternal(LatinIME ims, SharedPreferences prefs) {
         mInputMethodService = ims;
-        mPackageName = ims.getPackageName();
         mResources = ims.getResources();
         mPrefs = prefs;
         mSubtypeSwitcher = SubtypeSwitcher.getInstance();
@@ -133,20 +127,19 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
 
     public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) {
         try {
-            mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues);
-            mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues);
-            mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues);
+            mKeyboardSet = new KeyboardSet.Builder(mInputMethodService, editorInfo, settingsValues)
+                    .build();
             mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols),
                     hasDistinctMultitouch());
             // TODO: Should get rid of this special case handling for Phone Number layouts once we
             // have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted
             // respectively.
-            if (mMainKeyboardId.isPhoneKeyboard()) {
+            if (mKeyboardSet.mAlphabetId.isPhoneKeyboard()) {
                 mState.onToggleAlphabetAndSymbols();
             }
         } catch (RuntimeException e) {
-            Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e);
-            LatinImeLogger.logOnException(mMainKeyboardId.toString(), e);
+            Log.w(TAG, "loading keyboard failed: " + mKeyboardSet.mAlphabetId, e);
+            LatinImeLogger.logOnException(mKeyboardSet.mAlphabetId.toString(), e);
         }
     }
 
@@ -177,6 +170,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
         updateShiftState();
     }
 
+    // TODO: Move this method to KeyboardSet.
     private LatinKeyboard getKeyboard(KeyboardId id) {
         final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id);
         LatinKeyboard keyboard = (ref == null) ? null : ref.get();
@@ -215,55 +209,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
         return keyboard;
     }
 
-    private KeyboardId getKeyboardId(EditorInfo editorInfo, final boolean isSymbols,
-            final boolean isShift, SettingsValues settingsValues) {
-        final int mode = Utils.getKeyboardMode(editorInfo);
-        final int xmlId;
-        switch (mode) {
-        case KeyboardId.MODE_PHONE:
-            xmlId = (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
-            break;
-        case KeyboardId.MODE_NUMBER:
-            xmlId = R.xml.kbd_number;
-            break;
-        default:
-            if (isSymbols) {
-                xmlId = isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
-            } else {
-                xmlId = R.xml.kbd_qwerty;
-            }
-            break;
-        }
-
-        final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
-        @SuppressWarnings("deprecation")
-        final boolean noMicrophone = Utils.inPrivateImeOptions(
-                mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
-                || Utils.inPrivateImeOptions(
-                        null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo);
-        final boolean voiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo)
-                && !noMicrophone;
-        final boolean voiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
-        final boolean noSettingsKey = Utils.inPrivateImeOptions(
-                mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
-        final boolean hasSettingsKey = settingsKeyEnabled && !noSettingsKey;
-        final int f2KeyMode = getF2KeyMode(settingsKeyEnabled, noSettingsKey);
-        final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain);
-        final boolean forceAscii = Utils.inPrivateImeOptions(
-                mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
-        final boolean asciiCapable = mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
-                LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
-        final Locale locale = (forceAscii && !asciiCapable)
-                ? Locale.US : mSubtypeSwitcher.getInputLocale();
-        final Configuration conf = mResources.getConfiguration();
-        final DisplayMetrics dm = mResources.getDisplayMetrics();
-
-        return new KeyboardId(
-                mResources.getResourceEntryName(xmlId), xmlId, locale, conf.orientation,
-                dm.widthPixels, mode, editorInfo, hasSettingsKey, f2KeyMode, noSettingsKey,
-                voiceKeyEnabled, hasShortcutKey);
-    }
-
     public boolean isAlphabetMode() {
         final Keyboard keyboard = getLatinKeyboard();
         return keyboard != null && keyboard.mId.isAlphabetKeyboard();
@@ -393,19 +338,19 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setSymbolsKeyboard() {
-        setKeyboard(getKeyboard(mSymbolsKeyboardId));
+        setKeyboard(getKeyboard(mKeyboardSet.mSymbolsId));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetKeyboard() {
-        setKeyboard(getKeyboard(mMainKeyboardId));
+        setKeyboard(getKeyboard(mKeyboardSet.mAlphabetId));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setSymbolsShiftedKeyboard() {
-        final Keyboard keyboard = getKeyboard(mSymbolsShiftedKeyboardId);
+        final Keyboard keyboard = getKeyboard(mKeyboardSet.mSymbolsShiftedId);
         setKeyboard(keyboard);
         // TODO: Remove this logic once we introduce initial keyboard shift state attribute.
         // Symbol shift keyboard may have a shift key that has a caps lock style indicator (a.k.a.
@@ -518,19 +463,4 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
             }
         }
     }
-
-    private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) {
-        if (noSettingsKey) {
-            // Never shows the Settings key
-            return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
-        }
-
-        if (settingsKeyEnabled) {
-            return KeyboardId.F2KEY_MODE_SETTINGS;
-        } else {
-            // It should be alright to fall back to the Settings key on 7-inch layouts
-            // even when the Settings key is not explicitly enabled.
-            return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
-        }
-    }
 }