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