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"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * 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.InputTypeUtils;
     28 import com.android.inputmethod.latin.SubtypeLocale;
     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 
     58     public static final int FORM_FACTOR_PHONE = 0;
     59     public static final int FORM_FACTOR_TABLET7 = 1;
     60     public static final int FORM_FACTOR_TABLET10 = 2;
     61 
     62     private static final int IME_ACTION_CUSTOM_LABEL = EditorInfo.IME_MASK_ACTION + 1;
     63 
     64     public final InputMethodSubtype mSubtype;
     65     public final Locale mLocale;
     66     public final int mDeviceFormFactor;
     67     public final int mOrientation;
     68     public final int mWidth;
     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 mHasShortcutKey;
     75     public final boolean mLanguageSwitchKeyEnabled;
     76     public final String mCustomActionLabel;
     77 
     78     private final int mHashCode;
     79 
     80     public KeyboardId(int elementId, InputMethodSubtype subtype, int deviceFormFactor,
     81             int orientation, int width, int mode, EditorInfo editorInfo, boolean clobberSettingsKey,
     82             boolean shortcutKeyEnabled, boolean hasShortcutKey, boolean languageSwitchKeyEnabled) {
     83         mSubtype = subtype;
     84         mLocale = SubtypeLocale.getSubtypeLocale(subtype);
     85         mDeviceFormFactor = deviceFormFactor;
     86         mOrientation = orientation;
     87         mWidth = width;
     88         mMode = mode;
     89         mElementId = elementId;
     90         mEditorInfo = editorInfo;
     91         mClobberSettingsKey = clobberSettingsKey;
     92         mShortcutKeyEnabled = shortcutKeyEnabled;
     93         mHasShortcutKey = hasShortcutKey;
     94         mLanguageSwitchKeyEnabled = languageSwitchKeyEnabled;
     95         mCustomActionLabel = (editorInfo.actionLabel != null)
     96                 ? editorInfo.actionLabel.toString() : null;
     97 
     98         mHashCode = computeHashCode(this);
     99     }
    100 
    101     private static int computeHashCode(KeyboardId id) {
    102         return Arrays.hashCode(new Object[] {
    103                 id.mDeviceFormFactor,
    104                 id.mOrientation,
    105                 id.mElementId,
    106                 id.mMode,
    107                 id.mWidth,
    108                 id.passwordInput(),
    109                 id.mClobberSettingsKey,
    110                 id.mShortcutKeyEnabled,
    111                 id.mHasShortcutKey,
    112                 id.mLanguageSwitchKeyEnabled,
    113                 id.isMultiLine(),
    114                 id.imeAction(),
    115                 id.mCustomActionLabel,
    116                 id.navigateNext(),
    117                 id.navigatePrevious(),
    118                 id.mSubtype
    119         });
    120     }
    121 
    122     private boolean equals(KeyboardId other) {
    123         if (other == this)
    124             return true;
    125         return other.mDeviceFormFactor == mDeviceFormFactor
    126                 && other.mOrientation == mOrientation
    127                 && other.mElementId == mElementId
    128                 && other.mMode == mMode
    129                 && other.mWidth == mWidth
    130                 && other.passwordInput() == passwordInput()
    131                 && other.mClobberSettingsKey == mClobberSettingsKey
    132                 && other.mShortcutKeyEnabled == mShortcutKeyEnabled
    133                 && other.mHasShortcutKey == mHasShortcutKey
    134                 && other.mLanguageSwitchKeyEnabled == mLanguageSwitchKeyEnabled
    135                 && other.isMultiLine() == isMultiLine()
    136                 && other.imeAction() == imeAction()
    137                 && TextUtils.equals(other.mCustomActionLabel, mCustomActionLabel)
    138                 && other.navigateNext() == navigateNext()
    139                 && other.navigatePrevious() == navigatePrevious()
    140                 && other.mSubtype.equals(mSubtype);
    141     }
    142 
    143     public boolean isAlphabetKeyboard() {
    144         return mElementId < ELEMENT_SYMBOLS;
    145     }
    146 
    147     public boolean navigateNext() {
    148         return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0
    149                 || imeAction() == EditorInfo.IME_ACTION_NEXT;
    150     }
    151 
    152     public boolean navigatePrevious() {
    153         return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0
    154                 || imeAction() == EditorInfo.IME_ACTION_PREVIOUS;
    155     }
    156 
    157     public boolean passwordInput() {
    158         final int inputType = mEditorInfo.inputType;
    159         return InputTypeUtils.isPasswordInputType(inputType)
    160                 || InputTypeUtils.isVisiblePasswordInputType(inputType);
    161     }
    162 
    163     public boolean isMultiLine() {
    164         return (mEditorInfo.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0;
    165     }
    166 
    167     public int imeAction() {
    168         final int actionId = mEditorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
    169         if ((mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
    170             return EditorInfo.IME_ACTION_NONE;
    171         } else if (mEditorInfo.actionLabel != null) {
    172             return IME_ACTION_CUSTOM_LABEL;
    173         } else {
    174             return actionId;
    175         }
    176     }
    177 
    178     public int imeActionId() {
    179         final int actionId = imeAction();
    180         return actionId == IME_ACTION_CUSTOM_LABEL ? mEditorInfo.actionId : actionId;
    181     }
    182 
    183     @Override
    184     public boolean equals(Object other) {
    185         return other instanceof KeyboardId && equals((KeyboardId) other);
    186     }
    187 
    188     @Override
    189     public int hashCode() {
    190         return mHashCode;
    191     }
    192 
    193     @Override
    194     public String toString() {
    195         return String.format("[%s %s:%s %s-%s:%d %s %s %s%s%s%s%s%s%s%s]",
    196                 elementIdToName(mElementId),
    197                 mLocale,
    198                 mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
    199                 deviceFormFactor(mDeviceFormFactor), (mOrientation == 1 ? "port" : "land"), mWidth,
    200                 modeName(mMode),
    201                 imeAction(),
    202                 (navigateNext() ? "navigateNext" : ""),
    203                 (navigatePrevious() ? "navigatePrevious" : ""),
    204                 (mClobberSettingsKey ? " clobberSettingsKey" : ""),
    205                 (passwordInput() ? " passwordInput" : ""),
    206                 (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""),
    207                 (mHasShortcutKey ? " hasShortcutKey" : ""),
    208                 (mLanguageSwitchKeyEnabled ? " languageSwitchKeyEnabled" : ""),
    209                 (isMultiLine() ? "isMultiLine" : "")
    210         );
    211     }
    212 
    213     public static boolean equivalentEditorInfoForKeyboard(EditorInfo a, EditorInfo b) {
    214         if (a == null && b == null) return true;
    215         if (a == null || b == null) return false;
    216         return a.inputType == b.inputType
    217                 && a.imeOptions == b.imeOptions
    218                 && TextUtils.equals(a.privateImeOptions, b.privateImeOptions);
    219     }
    220 
    221     public static String elementIdToName(int elementId) {
    222         switch (elementId) {
    223         case ELEMENT_ALPHABET: return "alphabet";
    224         case ELEMENT_ALPHABET_MANUAL_SHIFTED: return "alphabetManualShifted";
    225         case ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: return "alphabetAutomaticShifted";
    226         case ELEMENT_ALPHABET_SHIFT_LOCKED: return "alphabetShiftLocked";
    227         case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: return "alphabetShiftLockShifted";
    228         case ELEMENT_SYMBOLS: return "symbols";
    229         case ELEMENT_SYMBOLS_SHIFTED: return "symbolsShifted";
    230         case ELEMENT_PHONE: return "phone";
    231         case ELEMENT_PHONE_SYMBOLS: return "phoneSymbols";
    232         case ELEMENT_NUMBER: return "number";
    233         default: return null;
    234         }
    235     }
    236 
    237     public static String deviceFormFactor(int devoceFormFactor) {
    238         switch (devoceFormFactor) {
    239         case FORM_FACTOR_PHONE: return "phone";
    240         case FORM_FACTOR_TABLET7: return "tablet7";
    241         case FORM_FACTOR_TABLET10: return "tablet10";
    242         default: return null;
    243         }
    244     }
    245 
    246     public static String modeName(int mode) {
    247         switch (mode) {
    248         case MODE_TEXT: return "text";
    249         case MODE_URL: return "url";
    250         case MODE_EMAIL: return "email";
    251         case MODE_IM: return "im";
    252         case MODE_PHONE: return "phone";
    253         case MODE_NUMBER: return "number";
    254         case MODE_DATE: return "date";
    255         case MODE_TIME: return "time";
    256         case MODE_DATETIME: return "datetime";
    257         default: return null;
    258         }
    259     }
    260 
    261     public static String actionName(int actionId) {
    262         return (actionId == IME_ACTION_CUSTOM_LABEL) ? "actionCustomLabel"
    263                 : EditorInfoCompatUtils.imeActionName(actionId);
    264     }
    265 }
    266