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