KeyboardId.java revision 289544d6e45fa1f3f39bda2990ce0d9ad0c240d5
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    /* TODO: Implement alphabet variant shift keyboard.
43    public static final int ELEMENT_ALPHABET_MANUAL_TEMPORARY_SHIFT = 1;
44    public static final int ELEMENT_ALPHABET_AUTOMATIC_TEMPORARY_SHIFT = 2;
45    public static final int ELEMENT_ALPHABET_SHIFT_LOCK = 3;
46    public static final int ELEMENT_ALPHABET_SHIFT_LOCK_SHIFT = 4;
47    */
48    public static final int ELEMENT_SYMBOLS = 5;
49    public static final int ELEMENT_SYMBOLS_SHIFT = 6;
50    public static final int ELEMENT_PHONE = 7;
51    public static final int ELEMENT_PHONE_SHIFT = 8;
52    public static final int ELEMENT_NUMBER = 9;
53
54    private static final int F2KEY_MODE_NONE = 0;
55    private static final int F2KEY_MODE_SETTINGS = 1;
56    private static final int F2KEY_MODE_SHORTCUT_IME = 2;
57    private static final int F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS = 3;
58
59    public final Locale mLocale;
60    public final int mOrientation;
61    public final int mWidth;
62    public final int mMode;
63    // TODO: Remove this field.
64    private final int mXmlId;
65    public final int mElementState;
66    private final int mInputType;
67    private final int mImeOptions;
68    private final boolean mSettingsKeyEnabled;
69    public final boolean mClobberSettingsKey;
70    public final boolean mShortcutKeyEnabled;
71    public final boolean mHasShortcutKey;
72
73    private final int mHashCode;
74
75    public KeyboardId(int xmlId, int elementState, Locale locale, int orientation, int width,
76            int mode, int inputType, int imeOptions, boolean settingsKeyEnabled,
77            boolean clobberSettingsKey, boolean shortcutKeyEnabled, boolean hasShortcutKey) {
78        this.mLocale = locale;
79        this.mOrientation = orientation;
80        this.mWidth = width;
81        this.mMode = mode;
82        this.mXmlId = xmlId;
83        this.mElementState = elementState;
84        this.mInputType = inputType;
85        this.mImeOptions = imeOptions;
86        this.mSettingsKeyEnabled = settingsKeyEnabled;
87        this.mClobberSettingsKey = clobberSettingsKey;
88        this.mShortcutKeyEnabled = shortcutKeyEnabled;
89        this.mHasShortcutKey = hasShortcutKey;
90
91        this.mHashCode = hashCode(this);
92    }
93
94    private static int hashCode(KeyboardId id) {
95        return Arrays.hashCode(new Object[] {
96                id.mOrientation,
97                id.mElementState,
98                id.mMode,
99                id.mWidth,
100                id.mXmlId,
101                id.navigateAction(),
102                id.passwordInput(),
103                id.mSettingsKeyEnabled,
104                id.mClobberSettingsKey,
105                id.mShortcutKeyEnabled,
106                id.mHasShortcutKey,
107                id.imeAction(),
108                id.mLocale
109        });
110    }
111
112    private boolean equals(KeyboardId other) {
113        if (other == this)
114            return true;
115        return other.mOrientation == this.mOrientation
116                && other.mElementState == this.mElementState
117                && other.mMode == this.mMode
118                && other.mWidth == this.mWidth
119                && other.mXmlId == this.mXmlId
120                && other.navigateAction() == this.navigateAction()
121                && other.passwordInput() == this.passwordInput()
122                && other.mSettingsKeyEnabled == this.mSettingsKeyEnabled
123                && other.mClobberSettingsKey == this.mClobberSettingsKey
124                && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled
125                && other.mHasShortcutKey == this.mHasShortcutKey
126                && other.imeAction() == this.imeAction()
127                && other.mLocale.equals(this.mLocale);
128    }
129
130    public KeyboardId cloneWithNewXml(int xmlId) {
131        return new KeyboardId(xmlId, mElementState, mLocale, mOrientation, mWidth, mMode,
132                mInputType, mImeOptions, false, false, false, false);
133    }
134
135    // Remove this method.
136    public int getXmlId() {
137        return mXmlId;
138    }
139
140    public boolean isAlphabetKeyboard() {
141        return mElementState < ELEMENT_SYMBOLS;
142    }
143
144    public boolean isSymbolsKeyboard() {
145        return mElementState == ELEMENT_SYMBOLS || mElementState == ELEMENT_SYMBOLS_SHIFT;
146    }
147
148    public boolean isPhoneKeyboard() {
149        return mElementState == ELEMENT_PHONE || mElementState == ELEMENT_PHONE_SHIFT;
150    }
151
152    public boolean isPhoneShiftKeyboard() {
153        return mElementState == ELEMENT_PHONE_SHIFT;
154    }
155
156    public boolean navigateAction() {
157        // Note: Turn off checking navigation flag to show TAB key for now.
158        boolean navigateAction = InputTypeCompatUtils.isWebInputType(mInputType);
159//                || EditorInfoCompatUtils.hasFlagNavigateNext(mImeOptions)
160//                || EditorInfoCompatUtils.hasFlagNavigatePrevious(mImeOptions);
161        return navigateAction;
162    }
163
164    public boolean passwordInput() {
165        return InputTypeCompatUtils.isPasswordInputType(mInputType)
166                || InputTypeCompatUtils.isVisiblePasswordInputType(mInputType);
167    }
168
169    public int imeAction() {
170        // We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and
171        // {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}.
172        return mImeOptions & (
173                EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
174    }
175
176    public boolean hasSettingsKey() {
177        return mSettingsKeyEnabled && !mClobberSettingsKey;
178    }
179
180    public int f2KeyMode() {
181        if (mClobberSettingsKey) {
182            // Never shows the Settings key
183            return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
184        }
185
186        if (mSettingsKeyEnabled) {
187            return KeyboardId.F2KEY_MODE_SETTINGS;
188        } else {
189            // It should be alright to fall back to the Settings key on 7-inch layouts
190            // even when the Settings key is not explicitly enabled.
191            return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
192        }
193    }
194
195    @Override
196    public boolean equals(Object other) {
197        return other instanceof KeyboardId && equals((KeyboardId) other);
198    }
199
200    @Override
201    public int hashCode() {
202        return mHashCode;
203    }
204
205    @Override
206    public String toString() {
207        return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s]",
208                elementStateToString(mElementState),
209                mLocale,
210                (mOrientation == 1 ? "port" : "land"), mWidth,
211                modeName(mMode),
212                EditorInfoCompatUtils.imeOptionsName(imeAction()),
213                f2KeyModeName(f2KeyMode()),
214                (mClobberSettingsKey ? " clobberSettingsKey" : ""),
215                (navigateAction() ? " navigateAction" : ""),
216                (passwordInput() ? " passwordInput" : ""),
217                (hasSettingsKey() ? " hasSettingsKey" : ""),
218                (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""),
219                (mHasShortcutKey ? " hasShortcutKey" : "")
220        );
221    }
222
223    public static boolean equivalentEditorInfoForKeyboard(EditorInfo a, EditorInfo b) {
224        if (a == null && b == null) return true;
225        if (a == null || b == null) return false;
226        return a.inputType == b.inputType
227                && a.imeOptions == b.imeOptions
228                && TextUtils.equals(a.privateImeOptions, b.privateImeOptions);
229    }
230
231    public static String elementStateToString(int elementState) {
232        switch (elementState) {
233        case ELEMENT_ALPHABET: return "alphabet";
234        /* TODO: Implement alphabet variant shift keyboard.
235        case ELEMENT_ALPHABET_MANUAL_TEMPORARY_SHIFT: return "alphabetManualTemporaryShift";
236        case ELEMENT_ALPHABET_AUTOMATIC_TEMPORARY_SHIFT: return "alphabetAutomaticTemporaryShift";
237        case ELEMENT_ALPHABET_SHIFT_LOCK: return "alphabetShiftLock";
238        case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFT: return "alphabetShiftLockShift";
239        */
240        case ELEMENT_SYMBOLS: return "symbols";
241        case ELEMENT_SYMBOLS_SHIFT: return "symbolsShift";
242        case ELEMENT_PHONE: return "phone";
243        case ELEMENT_PHONE_SHIFT: return "phoneShift";
244        case ELEMENT_NUMBER: return "number";
245        default: return null;
246        }
247    }
248
249    public static String modeName(int mode) {
250        switch (mode) {
251        case MODE_TEXT: return "text";
252        case MODE_URL: return "url";
253        case MODE_EMAIL: return "email";
254        case MODE_IM: return "im";
255        case MODE_PHONE: return "phone";
256        case MODE_NUMBER: return "number";
257        default: return null;
258        }
259    }
260
261    public static String f2KeyModeName(int f2KeyMode) {
262        switch (f2KeyMode) {
263        case F2KEY_MODE_NONE: return "none";
264        case F2KEY_MODE_SETTINGS: return "settings";
265        case F2KEY_MODE_SHORTCUT_IME: return "shortcutIme";
266        case F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS: return "shortcutImeOrSettings";
267        default: return null;
268        }
269    }
270}
271