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.text.InputType;
     22 import android.text.TextUtils;
     23 import android.view.inputmethod.EditorInfo;
     24 import android.view.inputmethod.InputMethodSubtype;
     25 
     26 import com.android.inputmethod.compat.EditorInfoCompatUtils;
     27 import com.android.inputmethod.latin.utils.InputTypeUtils;
     28 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
     29 
     30 import java.util.Arrays;
     31 import java.util.Locale;
     32 
     33 /**
     34  * Unique identifier for each keyboard type.
     35  */
     36 public final class KeyboardId {
     37     public static final int MODE_TEXT = 0;
     38     public static final int MODE_URL = 1;
     39     public static final int MODE_EMAIL = 2;
     40     public static final int MODE_IM = 3;
     41     public static final int MODE_PHONE = 4;
     42     public static final int MODE_NUMBER = 5;
     43     public static final int MODE_DATE = 6;
     44     public static final int MODE_TIME = 7;
     45     public static final int MODE_DATETIME = 8;
     46 
     47     public static final int ELEMENT_ALPHABET = 0;
     48     public static final int ELEMENT_ALPHABET_MANUAL_SHIFTED = 1;
     49     public static final int ELEMENT_ALPHABET_AUTOMATIC_SHIFTED = 2;
     50     public static final int ELEMENT_ALPHABET_SHIFT_LOCKED = 3;
     51     public static final int ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED = 4;
     52     public static final int ELEMENT_SYMBOLS = 5;
     53     public static final int ELEMENT_SYMBOLS_SHIFTED = 6;
     54     public static final int ELEMENT_PHONE = 7;
     55     public static final int ELEMENT_PHONE_SYMBOLS = 8;
     56     public static final int ELEMENT_NUMBER = 9;
     57     public static final int ELEMENT_EMOJI_RECENTS = 10;
     58     public static final int ELEMENT_EMOJI_CATEGORY1 = 11;
     59     public static final int ELEMENT_EMOJI_CATEGORY2 = 12;
     60     public static final int ELEMENT_EMOJI_CATEGORY3 = 13;
     61     public static final int ELEMENT_EMOJI_CATEGORY4 = 14;
     62     public static final int ELEMENT_EMOJI_CATEGORY5 = 15;
     63     public static final int ELEMENT_EMOJI_CATEGORY6 = 16;
     64 
     65     public final InputMethodSubtype mSubtype;
     66     public final Locale mLocale;
     67     public final int mWidth;
     68     public final int mHeight;
     69     public final int mMode;
     70     public final int mElementId;
     71     private final EditorInfo mEditorInfo;
     72     public final boolean mClobberSettingsKey;
     73     public final boolean mShortcutKeyEnabled;
     74     public final boolean mShortcutKeyOnSymbols;
     75     public final boolean mLanguageSwitchKeyEnabled;
     76     public final String mCustomActionLabel;
     77     public final boolean mHasShortcutKey;
     78 
     79     private final int mHashCode;
     80 
     81     public KeyboardId(final int elementId, final KeyboardLayoutSet.Params params) {
     82         mSubtype = params.mSubtype;
     83         mLocale = SubtypeLocaleUtils.getSubtypeLocale(mSubtype);
     84         mWidth = params.mKeyboardWidth;
     85         mHeight = params.mKeyboardHeight;
     86         mMode = params.mMode;
     87         mElementId = elementId;
     88         mEditorInfo = params.mEditorInfo;
     89         mClobberSettingsKey = params.mNoSettingsKey;
     90         mShortcutKeyEnabled = params.mVoiceKeyEnabled;
     91         mShortcutKeyOnSymbols = mShortcutKeyEnabled && !params.mVoiceKeyOnMain;
     92         mLanguageSwitchKeyEnabled = params.mLanguageSwitchKeyEnabled;
     93         mCustomActionLabel = (mEditorInfo.actionLabel != null)
     94                 ? mEditorInfo.actionLabel.toString() : null;
     95         final boolean alphabetMayHaveShortcutKey = isAlphabetKeyboard(elementId)
     96                 && !mShortcutKeyOnSymbols;
     97         final boolean symbolsMayHaveShortcutKey = (elementId == KeyboardId.ELEMENT_SYMBOLS)
     98                 && mShortcutKeyOnSymbols;
     99         mHasShortcutKey = mShortcutKeyEnabled
    100                 && (alphabetMayHaveShortcutKey || symbolsMayHaveShortcutKey);
    101 
    102         mHashCode = computeHashCode(this);
    103     }
    104 
    105     private static int computeHashCode(final KeyboardId id) {
    106         return Arrays.hashCode(new Object[] {
    107                 id.mElementId,
    108                 id.mMode,
    109                 id.mWidth,
    110                 id.mHeight,
    111                 id.passwordInput(),
    112                 id.mClobberSettingsKey,
    113                 id.mShortcutKeyEnabled,
    114                 id.mShortcutKeyOnSymbols,
    115                 id.mLanguageSwitchKeyEnabled,
    116                 id.isMultiLine(),
    117                 id.imeAction(),
    118                 id.mCustomActionLabel,
    119                 id.navigateNext(),
    120                 id.navigatePrevious(),
    121                 id.mSubtype
    122         });
    123     }
    124 
    125     private boolean equals(final KeyboardId other) {
    126         if (other == this)
    127             return true;
    128         return other.mElementId == mElementId
    129                 && other.mMode == mMode
    130                 && other.mWidth == mWidth
    131                 && other.mHeight == mHeight
    132                 && other.passwordInput() == passwordInput()
    133                 && other.mClobberSettingsKey == mClobberSettingsKey
    134                 && other.mShortcutKeyEnabled == mShortcutKeyEnabled
    135                 && other.mShortcutKeyOnSymbols == mShortcutKeyOnSymbols
    136                 && other.mLanguageSwitchKeyEnabled == mLanguageSwitchKeyEnabled
    137                 && other.isMultiLine() == isMultiLine()
    138                 && other.imeAction() == imeAction()
    139                 && TextUtils.equals(other.mCustomActionLabel, mCustomActionLabel)
    140                 && other.navigateNext() == navigateNext()
    141                 && other.navigatePrevious() == navigatePrevious()
    142                 && other.mSubtype.equals(mSubtype);
    143     }
    144 
    145     private static boolean isAlphabetKeyboard(final int elementId) {
    146         return elementId < ELEMENT_SYMBOLS;
    147     }
    148 
    149     public boolean isAlphabetKeyboard() {
    150         return isAlphabetKeyboard(mElementId);
    151     }
    152 
    153     public boolean navigateNext() {
    154         return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0
    155                 || imeAction() == EditorInfo.IME_ACTION_NEXT;
    156     }
    157 
    158     public boolean navigatePrevious() {
    159         return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0
    160                 || imeAction() == EditorInfo.IME_ACTION_PREVIOUS;
    161     }
    162 
    163     public boolean passwordInput() {
    164         final int inputType = mEditorInfo.inputType;
    165         return InputTypeUtils.isPasswordInputType(inputType)
    166                 || InputTypeUtils.isVisiblePasswordInputType(inputType);
    167     }
    168 
    169     public boolean isMultiLine() {
    170         return (mEditorInfo.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0;
    171     }
    172 
    173     public int imeAction() {
    174         return InputTypeUtils.getImeOptionsActionIdFromEditorInfo(mEditorInfo);
    175     }
    176 
    177     @Override
    178     public boolean equals(final Object other) {
    179         return other instanceof KeyboardId && equals((KeyboardId) other);
    180     }
    181 
    182     @Override
    183     public int hashCode() {
    184         return mHashCode;
    185     }
    186 
    187     @Override
    188     public String toString() {
    189         return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s %s%s%s%s%s%s%s%s%s]",
    190                 elementIdToName(mElementId),
    191                 mLocale, mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
    192                 mWidth, mHeight,
    193                 modeName(mMode),
    194                 imeAction(),
    195                 (navigateNext() ? "navigateNext" : ""),
    196                 (navigatePrevious() ? "navigatePrevious" : ""),
    197                 (mClobberSettingsKey ? " clobberSettingsKey" : ""),
    198                 (passwordInput() ? " passwordInput" : ""),
    199                 (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""),
    200                 (mShortcutKeyOnSymbols ? " shortcutKeyOnSymbols" : ""),
    201                 (mHasShortcutKey ? " hasShortcutKey" : ""),
    202                 (mLanguageSwitchKeyEnabled ? " languageSwitchKeyEnabled" : ""),
    203                 (isMultiLine() ? "isMultiLine" : "")
    204         );
    205     }
    206 
    207     public static boolean equivalentEditorInfoForKeyboard(final EditorInfo a, final EditorInfo b) {
    208         if (a == null && b == null) return true;
    209         if (a == null || b == null) return false;
    210         return a.inputType == b.inputType
    211                 && a.imeOptions == b.imeOptions
    212                 && TextUtils.equals(a.privateImeOptions, b.privateImeOptions);
    213     }
    214 
    215     public static String elementIdToName(final int elementId) {
    216         switch (elementId) {
    217         case ELEMENT_ALPHABET: return "alphabet";
    218         case ELEMENT_ALPHABET_MANUAL_SHIFTED: return "alphabetManualShifted";
    219         case ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: return "alphabetAutomaticShifted";
    220         case ELEMENT_ALPHABET_SHIFT_LOCKED: return "alphabetShiftLocked";
    221         case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: return "alphabetShiftLockShifted";
    222         case ELEMENT_SYMBOLS: return "symbols";
    223         case ELEMENT_SYMBOLS_SHIFTED: return "symbolsShifted";
    224         case ELEMENT_PHONE: return "phone";
    225         case ELEMENT_PHONE_SYMBOLS: return "phoneSymbols";
    226         case ELEMENT_NUMBER: return "number";
    227         case ELEMENT_EMOJI_RECENTS: return "emojiRecents";
    228         case ELEMENT_EMOJI_CATEGORY1: return "emojiCategory1";
    229         case ELEMENT_EMOJI_CATEGORY2: return "emojiCategory2";
    230         case ELEMENT_EMOJI_CATEGORY3: return "emojiCategory3";
    231         case ELEMENT_EMOJI_CATEGORY4: return "emojiCategory4";
    232         case ELEMENT_EMOJI_CATEGORY5: return "emojiCategory5";
    233         case ELEMENT_EMOJI_CATEGORY6: return "emojiCategory6";
    234         default: return null;
    235         }
    236     }
    237 
    238     public static String modeName(final int mode) {
    239         switch (mode) {
    240         case MODE_TEXT: return "text";
    241         case MODE_URL: return "url";
    242         case MODE_EMAIL: return "email";
    243         case MODE_IM: return "im";
    244         case MODE_PHONE: return "phone";
    245         case MODE_NUMBER: return "number";
    246         case MODE_DATE: return "date";
    247         case MODE_TIME: return "time";
    248         case MODE_DATETIME: return "datetime";
    249         default: return null;
    250         }
    251     }
    252 
    253     public static String actionName(final int actionId) {
    254         return (actionId == InputTypeUtils.IME_ACTION_CUSTOM_LABEL) ? "actionCustomLabel"
    255                 : EditorInfoCompatUtils.imeActionName(actionId);
    256     }
    257 }
    258