KeyboardId.java revision 117c124c13f0e6af737b1858bd5c4d9e6e7eb353
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
17package com.android.inputmethod.keyboard;
18
19import android.text.TextUtils;
20import android.view.inputmethod.EditorInfo;
21
22import com.android.inputmethod.compat.EditorInfoCompatUtils;
23import com.android.inputmethod.compat.InputTypeCompatUtils;
24
25import java.util.Arrays;
26import java.util.Locale;
27
28// TODO: Move to com.android.inputmethod.keyboard.internal package.
29/**
30 * Represents the parameters necessary to construct a new LatinKeyboard,
31 * which also serve as a unique identifier for each keyboard type.
32 */
33public class KeyboardId {
34    public static final int MODE_TEXT = 0;
35    public static final int MODE_URL = 1;
36    public static final int MODE_EMAIL = 2;
37    public static final int MODE_IM = 3;
38    public static final int MODE_PHONE = 4;
39    public static final int MODE_NUMBER = 5;
40
41    public static final int ELEMENT_ALPHABET = 0;
42    public static final int ELEMENT_ALPHABET_MANUAL_SHIFTED = 1;
43    public static final int ELEMENT_ALPHABET_AUTOMATIC_SHIFTED = 2;
44    public static final int ELEMENT_ALPHABET_SHIFT_LOCKED = 3;
45    public static final int ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED = 4;
46    public static final int ELEMENT_SYMBOLS = 5;
47    public static final int ELEMENT_SYMBOLS_SHIFTED = 6;
48    public static final int ELEMENT_PHONE = 7;
49    public static final int ELEMENT_PHONE_SHIFTED = 8;
50    public static final int ELEMENT_NUMBER = 9;
51
52    private static final int F2KEY_MODE_NONE = 0;
53    private static final int F2KEY_MODE_SETTINGS = 1;
54    private static final int F2KEY_MODE_SHORTCUT_IME = 2;
55    private static final int F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS = 3;
56
57    public final Locale mLocale;
58    public final int mOrientation;
59    public final int mWidth;
60    public final int mMode;
61    public final int mElementId;
62    private final int mInputType;
63    private final int mImeOptions;
64    private final boolean mSettingsKeyEnabled;
65    public final boolean mClobberSettingsKey;
66    public final boolean mShortcutKeyEnabled;
67    public final boolean mHasShortcutKey;
68
69    private final int mHashCode;
70
71    public KeyboardId(int elementId, Locale locale, int orientation, int width, int mode,
72            int inputType, int imeOptions, boolean settingsKeyEnabled, boolean clobberSettingsKey,
73            boolean shortcutKeyEnabled, boolean hasShortcutKey) {
74        this.mLocale = locale;
75        this.mOrientation = orientation;
76        this.mWidth = width;
77        this.mMode = mode;
78        this.mElementId = elementId;
79        this.mInputType = inputType;
80        this.mImeOptions = imeOptions;
81        this.mSettingsKeyEnabled = settingsKeyEnabled;
82        this.mClobberSettingsKey = clobberSettingsKey;
83        this.mShortcutKeyEnabled = shortcutKeyEnabled;
84        this.mHasShortcutKey = hasShortcutKey;
85
86        this.mHashCode = hashCode(this);
87    }
88
89    private static int hashCode(KeyboardId id) {
90        return Arrays.hashCode(new Object[] {
91                id.mOrientation,
92                id.mElementId,
93                id.mMode,
94                id.mWidth,
95                id.navigateAction(),
96                id.passwordInput(),
97                id.mSettingsKeyEnabled,
98                id.mClobberSettingsKey,
99                id.mShortcutKeyEnabled,
100                id.mHasShortcutKey,
101                id.imeAction(),
102                id.mLocale
103        });
104    }
105
106    private boolean equals(KeyboardId other) {
107        if (other == this)
108            return true;
109        return other.mOrientation == this.mOrientation
110                && other.mElementId == this.mElementId
111                && other.mMode == this.mMode
112                && other.mWidth == this.mWidth
113                && other.navigateAction() == this.navigateAction()
114                && other.passwordInput() == this.passwordInput()
115                && other.mSettingsKeyEnabled == this.mSettingsKeyEnabled
116                && other.mClobberSettingsKey == this.mClobberSettingsKey
117                && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled
118                && other.mHasShortcutKey == this.mHasShortcutKey
119                && other.imeAction() == this.imeAction()
120                && other.mLocale.equals(this.mLocale);
121    }
122
123    public boolean isAlphabetKeyboard() {
124        return mElementId < ELEMENT_SYMBOLS;
125    }
126
127    public boolean isSymbolsKeyboard() {
128        return mElementId == ELEMENT_SYMBOLS || mElementId == ELEMENT_SYMBOLS_SHIFTED;
129    }
130
131    public boolean isPhoneKeyboard() {
132        return mElementId == ELEMENT_PHONE || mElementId == ELEMENT_PHONE_SHIFTED;
133    }
134
135    public boolean isPhoneShiftKeyboard() {
136        return mElementId == ELEMENT_PHONE_SHIFTED;
137    }
138
139    public boolean navigateAction() {
140        // Note: Turn off checking navigation flag to show TAB key for now.
141        boolean navigateAction = InputTypeCompatUtils.isWebInputType(mInputType);
142//                || EditorInfoCompatUtils.hasFlagNavigateNext(mImeOptions)
143//                || EditorInfoCompatUtils.hasFlagNavigatePrevious(mImeOptions);
144        return navigateAction;
145    }
146
147    public boolean passwordInput() {
148        return InputTypeCompatUtils.isPasswordInputType(mInputType)
149                || InputTypeCompatUtils.isVisiblePasswordInputType(mInputType);
150    }
151
152    public int imeAction() {
153        // We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and
154        // {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}.
155        return mImeOptions & (
156                EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
157    }
158
159    public boolean hasSettingsKey() {
160        return mSettingsKeyEnabled && !mClobberSettingsKey;
161    }
162
163    public int f2KeyMode() {
164        if (mClobberSettingsKey) {
165            // Never shows the Settings key
166            return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
167        }
168
169        if (mSettingsKeyEnabled) {
170            return KeyboardId.F2KEY_MODE_SETTINGS;
171        } else {
172            // It should be alright to fall back to the Settings key on 7-inch layouts
173            // even when the Settings key is not explicitly enabled.
174            return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
175        }
176    }
177
178    @Override
179    public boolean equals(Object other) {
180        return other instanceof KeyboardId && equals((KeyboardId) other);
181    }
182
183    @Override
184    public int hashCode() {
185        return mHashCode;
186    }
187
188    @Override
189    public String toString() {
190        return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s]",
191                elementIdToName(mElementId),
192                mLocale,
193                (mOrientation == 1 ? "port" : "land"), mWidth,
194                modeName(mMode),
195                EditorInfoCompatUtils.imeOptionsName(imeAction()),
196                f2KeyModeName(f2KeyMode()),
197                (mClobberSettingsKey ? " clobberSettingsKey" : ""),
198                (navigateAction() ? " navigateAction" : ""),
199                (passwordInput() ? " passwordInput" : ""),
200                (hasSettingsKey() ? " hasSettingsKey" : ""),
201                (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""),
202                (mHasShortcutKey ? " hasShortcutKey" : "")
203        );
204    }
205
206    public static boolean equivalentEditorInfoForKeyboard(EditorInfo a, EditorInfo b) {
207        if (a == null && b == null) return true;
208        if (a == null || b == null) return false;
209        return a.inputType == b.inputType
210                && a.imeOptions == b.imeOptions
211                && TextUtils.equals(a.privateImeOptions, b.privateImeOptions);
212    }
213
214    public static String elementIdToName(int elementId) {
215        switch (elementId) {
216        case ELEMENT_ALPHABET: return "alphabet";
217        case ELEMENT_ALPHABET_MANUAL_SHIFTED: return "alphabetManualShifted";
218        case ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: return "alphabetAutomaticShifted";
219        case ELEMENT_ALPHABET_SHIFT_LOCKED: return "alphabetShiftLocked";
220        case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: return "alphabetShiftLockShifted";
221        case ELEMENT_SYMBOLS: return "symbols";
222        case ELEMENT_SYMBOLS_SHIFTED: return "symbolsShifted";
223        case ELEMENT_PHONE: return "phone";
224        case ELEMENT_PHONE_SHIFTED: return "phoneShifted";
225        case ELEMENT_NUMBER: return "number";
226        default: return null;
227        }
228    }
229
230    public static String modeName(int mode) {
231        switch (mode) {
232        case MODE_TEXT: return "text";
233        case MODE_URL: return "url";
234        case MODE_EMAIL: return "email";
235        case MODE_IM: return "im";
236        case MODE_PHONE: return "phone";
237        case MODE_NUMBER: return "number";
238        default: return null;
239        }
240    }
241
242    public static String f2KeyModeName(int f2KeyMode) {
243        switch (f2KeyMode) {
244        case F2KEY_MODE_NONE: return "none";
245        case F2KEY_MODE_SETTINGS: return "settings";
246        case F2KEY_MODE_SHORTCUT_IME: return "shortcutIme";
247        case F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS: return "shortcutImeOrSettings";
248        default: return null;
249        }
250    }
251}
252