Home | History | Annotate | Download | only in keyboard
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.inputmethod.keyboard;
     18 
     19 import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
     20 
     21 import android.content.res.Configuration;
     22 import android.text.InputType;
     23 import android.text.TextUtils;
     24 import android.view.inputmethod.EditorInfo;
     25 import android.view.inputmethod.InputMethodSubtype;
     26 
     27 import com.android.inputmethod.compat.EditorInfoCompatUtils;
     28 import com.android.inputmethod.latin.InputTypeUtils;
     29 import com.android.inputmethod.latin.SubtypeLocale;
     30 
     31 import java.util.Arrays;
     32 import java.util.Locale;
     33 
     34 /**
     35  * Unique identifier for each keyboard type.
     36  */
     37 public final class KeyboardId {
     38     public static final int MODE_TEXT = 0;
     39     public static final int MODE_URL = 1;
     40     public static final int MODE_EMAIL = 2;
     41     public static final int MODE_IM = 3;
     42     public static final int MODE_PHONE = 4;
     43     public static final int MODE_NUMBER = 5;
     44     public static final int MODE_DATE = 6;
     45     public static final int MODE_TIME = 7;
     46     public static final int MODE_DATETIME = 8;
     47 
     48     public static final int ELEMENT_ALPHABET = 0;
     49     public static final int ELEMENT_ALPHABET_MANUAL_SHIFTED = 1;
     50     public static final int ELEMENT_ALPHABET_AUTOMATIC_SHIFTED = 2;
     51     public static final int ELEMENT_ALPHABET_SHIFT_LOCKED = 3;
     52     public static final int ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED = 4;
     53     public static final int ELEMENT_SYMBOLS = 5;
     54     public static final int ELEMENT_SYMBOLS_SHIFTED = 6;
     55     public static final int ELEMENT_PHONE = 7;
     56     public static final int ELEMENT_PHONE_SYMBOLS = 8;
     57     public static final int ELEMENT_NUMBER = 9;
     58 
     59     public final InputMethodSubtype mSubtype;
     60     public final Locale mLocale;
     61     // TODO: Remove this member. It is used only for logging purpose.
     62     public final int mOrientation;
     63     public final int mWidth;
     64     public final int mHeight;
     65     public final int mMode;
     66     public final int mElementId;
     67     private final EditorInfo mEditorInfo;
     68     public final boolean mClobberSettingsKey;
     69     public final boolean mShortcutKeyEnabled;
     70     public final boolean mShortcutKeyOnSymbols;
     71     public final boolean mLanguageSwitchKeyEnabled;
     72     public final String mCustomActionLabel;
     73     public final boolean mHasShortcutKey;
     74 
     75     private final int mHashCode;
     76 
     77     public KeyboardId(final int elementId, final KeyboardLayoutSet.Params params) {
     78         mSubtype = params.mSubtype;
     79         mLocale = SubtypeLocale.getSubtypeLocale(mSubtype);
     80         mOrientation = params.mOrientation;
     81         mWidth = params.mKeyboardWidth;
     82         mHeight = params.mKeyboardHeight;
     83         mMode = params.mMode;
     84         mElementId = elementId;
     85         mEditorInfo = params.mEditorInfo;
     86         mClobberSettingsKey = params.mNoSettingsKey;
     87         mShortcutKeyEnabled = params.mVoiceKeyEnabled;
     88         mShortcutKeyOnSymbols = mShortcutKeyEnabled && !params.mVoiceKeyOnMain;
     89         mLanguageSwitchKeyEnabled = params.mLanguageSwitchKeyEnabled;
     90         mCustomActionLabel = (mEditorInfo.actionLabel != null)
     91                 ? mEditorInfo.actionLabel.toString() : null;
     92         final boolean alphabetMayHaveShortcutKey = isAlphabetKeyboard(elementId)
     93                 && !mShortcutKeyOnSymbols;
     94         final boolean symbolsMayHaveShortcutKey = (elementId == KeyboardId.ELEMENT_SYMBOLS)
     95                 && mShortcutKeyOnSymbols;
     96         mHasShortcutKey = mShortcutKeyEnabled
     97                 && (alphabetMayHaveShortcutKey || symbolsMayHaveShortcutKey);
     98 
     99         mHashCode = computeHashCode(this);
    100     }
    101 
    102     private static int computeHashCode(final KeyboardId id) {
    103         return Arrays.hashCode(new Object[] {
    104                 id.mOrientation,
    105                 id.mElementId,
    106                 id.mMode,
    107                 id.mWidth,
    108                 id.mHeight,
    109                 id.passwordInput(),
    110                 id.mClobberSettingsKey,
    111                 id.mShortcutKeyEnabled,
    112                 id.mShortcutKeyOnSymbols,
    113                 id.mLanguageSwitchKeyEnabled,
    114                 id.isMultiLine(),
    115                 id.imeAction(),
    116                 id.mCustomActionLabel,
    117                 id.navigateNext(),
    118                 id.navigatePrevious(),
    119                 id.mSubtype
    120         });
    121     }
    122 
    123     private boolean equals(final KeyboardId other) {
    124         if (other == this)
    125             return true;
    126         return other.mOrientation == mOrientation
    127                 && other.mElementId == mElementId
    128                 && other.mMode == mMode
    129                 && other.mWidth == mWidth
    130                 && other.mHeight == mHeight
    131                 && other.passwordInput() == passwordInput()
    132                 && other.mClobberSettingsKey == mClobberSettingsKey
    133                 && other.mShortcutKeyEnabled == mShortcutKeyEnabled
    134                 && other.mShortcutKeyOnSymbols == mShortcutKeyOnSymbols
    135                 && other.mLanguageSwitchKeyEnabled == mLanguageSwitchKeyEnabled
    136                 && other.isMultiLine() == isMultiLine()
    137                 && other.imeAction() == imeAction()
    138                 && TextUtils.equals(other.mCustomActionLabel, mCustomActionLabel)
    139                 && other.navigateNext() == navigateNext()
    140                 && other.navigatePrevious() == navigatePrevious()
    141                 && other.mSubtype.equals(mSubtype);
    142     }
    143 
    144     private static boolean isAlphabetKeyboard(final int elementId) {
    145         return elementId < ELEMENT_SYMBOLS;
    146     }
    147 
    148     public boolean isAlphabetKeyboard() {
    149         return isAlphabetKeyboard(mElementId);
    150     }
    151 
    152     public boolean navigateNext() {
    153         return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0
    154                 || imeAction() == EditorInfo.IME_ACTION_NEXT;
    155     }
    156 
    157     public boolean navigatePrevious() {
    158         return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0
    159                 || imeAction() == EditorInfo.IME_ACTION_PREVIOUS;
    160     }
    161 
    162     public boolean passwordInput() {
    163         final int inputType = mEditorInfo.inputType;
    164         return InputTypeUtils.isPasswordInputType(inputType)
    165                 || InputTypeUtils.isVisiblePasswordInputType(inputType);
    166     }
    167 
    168     public boolean isMultiLine() {
    169         return (mEditorInfo.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0;
    170     }
    171 
    172     public int imeAction() {
    173         return InputTypeUtils.getImeOptionsActionIdFromEditorInfo(mEditorInfo);
    174     }
    175 
    176     @Override
    177     public boolean equals(final Object other) {
    178         return other instanceof KeyboardId && equals((KeyboardId) other);
    179     }
    180 
    181     @Override
    182     public int hashCode() {
    183         return mHashCode;
    184     }
    185 
    186     @Override
    187     public String toString() {
    188         final String orientation = (mOrientation == Configuration.ORIENTATION_PORTRAIT)
    189                 ? "port" : "land";
    190         return String.format("[%s %s:%s %s:%dx%d %s %s %s%s%s%s%s%s%s%s%s]",
    191                 elementIdToName(mElementId),
    192                 mLocale,
    193                 mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
    194                 orientation, mWidth, mHeight,
    195                 modeName(mMode),
    196                 imeAction(),
    197                 (navigateNext() ? "navigateNext" : ""),
    198                 (navigatePrevious() ? "navigatePrevious" : ""),
    199                 (mClobberSettingsKey ? " clobberSettingsKey" : ""),
    200                 (passwordInput() ? " passwordInput" : ""),
    201                 (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""),
    202                 (mShortcutKeyOnSymbols ? " shortcutKeyOnSymbols" : ""),
    203                 (mHasShortcutKey ? " hasShortcutKey" : ""),
    204                 (mLanguageSwitchKeyEnabled ? " languageSwitchKeyEnabled" : ""),
    205                 (isMultiLine() ? "isMultiLine" : "")
    206         );
    207     }
    208 
    209     public static boolean equivalentEditorInfoForKeyboard(final EditorInfo a, final EditorInfo b) {
    210         if (a == null && b == null) return true;
    211         if (a == null || b == null) return false;
    212         return a.inputType == b.inputType
    213                 && a.imeOptions == b.imeOptions
    214                 && TextUtils.equals(a.privateImeOptions, b.privateImeOptions);
    215     }
    216 
    217     public static String elementIdToName(final int elementId) {
    218         switch (elementId) {
    219         case ELEMENT_ALPHABET: return "alphabet";
    220         case ELEMENT_ALPHABET_MANUAL_SHIFTED: return "alphabetManualShifted";
    221         case ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: return "alphabetAutomaticShifted";
    222         case ELEMENT_ALPHABET_SHIFT_LOCKED: return "alphabetShiftLocked";
    223         case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: return "alphabetShiftLockShifted";
    224         case ELEMENT_SYMBOLS: return "symbols";
    225         case ELEMENT_SYMBOLS_SHIFTED: return "symbolsShifted";
    226         case ELEMENT_PHONE: return "phone";
    227         case ELEMENT_PHONE_SYMBOLS: return "phoneSymbols";
    228         case ELEMENT_NUMBER: return "number";
    229         default: return null;
    230         }
    231     }
    232 
    233     public static String modeName(final int mode) {
    234         switch (mode) {
    235         case MODE_TEXT: return "text";
    236         case MODE_URL: return "url";
    237         case MODE_EMAIL: return "email";
    238         case MODE_IM: return "im";
    239         case MODE_PHONE: return "phone";
    240         case MODE_NUMBER: return "number";
    241         case MODE_DATE: return "date";
    242         case MODE_TIME: return "time";
    243         case MODE_DATETIME: return "datetime";
    244         default: return null;
    245         }
    246     }
    247 
    248     public static String actionName(final int actionId) {
    249         return (actionId == InputTypeUtils.IME_ACTION_CUSTOM_LABEL) ? "actionCustomLabel"
    250                 : EditorInfoCompatUtils.imeActionName(actionId);
    251     }
    252 }
    253