• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.graphics.drawable.Drawable;
20 import android.text.TextUtils;
21 
22 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
23 import com.android.inputmethod.keyboard.internal.KeyboardParams;
24 import com.android.inputmethod.keyboard.internal.KeyboardShiftState;
25 
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 
31 /**
32  * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
33  * consists of rows of keys.
34  * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p>
35  * <pre>
36  * &lt;Keyboard
37  *         latin:keyWidth="%10p"
38  *         latin:keyHeight="50px"
39  *         latin:horizontalGap="2px"
40  *         latin:verticalGap="2px" &gt;
41  *     &lt;Row latin:keyWidth="32px" &gt;
42  *         &lt;Key latin:keyLabel="A" /&gt;
43  *         ...
44  *     &lt;/Row&gt;
45  *     ...
46  * &lt;/Keyboard&gt;
47  * </pre>
48  */
49 public class Keyboard {
50     /** Some common keys code.  These should be aligned with values/keycodes.xml */
51     public static final int CODE_ENTER = '\n';
52     public static final int CODE_TAB = '\t';
53     public static final int CODE_SPACE = ' ';
54     public static final int CODE_PERIOD = '.';
55     public static final int CODE_DASH = '-';
56     public static final int CODE_SINGLE_QUOTE = '\'';
57     public static final int CODE_DOUBLE_QUOTE = '"';
58     // TODO: Check how this should work for right-to-left languages. It seems to stand
59     // that for rtl languages, a closing parenthesis is a left parenthesis. Is this
60     // managed by the font? Or is it a different char?
61     public static final int CODE_CLOSING_PARENTHESIS = ')';
62     public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
63     public static final int CODE_CLOSING_CURLY_BRACKET = '}';
64     public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
65     public static final int CODE_DIGIT0 = '0';
66     public static final int CODE_PLUS = '+';
67 
68 
69     /** Special keys code.  These should be aligned with values/keycodes.xml */
70     public static final int CODE_DUMMY = 0;
71     public static final int CODE_SHIFT = -1;
72     public static final int CODE_SWITCH_ALPHA_SYMBOL = -2;
73     public static final int CODE_CAPSLOCK = -3;
74     public static final int CODE_CANCEL = -4;
75     public static final int CODE_DELETE = -5;
76     public static final int CODE_SETTINGS = -6;
77     public static final int CODE_SHORTCUT = -7;
78     public static final int CODE_HAPTIC_AND_AUDIO_FEEDBACK_ONLY = -98;
79     // Code value representing the code is not specified.
80     public static final int CODE_UNSPECIFIED = -99;
81 
82     public final KeyboardId mId;
83     public final int mThemeId;
84 
85     /** Total height of the keyboard, including the padding and keys */
86     public final int mOccupiedHeight;
87     /** Total width of the keyboard, including the padding and keys */
88     public final int mOccupiedWidth;
89 
90     /** The padding above the keyboard */
91     public final int mTopPadding;
92     /** Default gap between rows */
93     public final int mVerticalGap;
94 
95     public final int mMostCommonKeyHeight;
96     public final int mMostCommonKeyWidth;
97 
98     /** More keys keyboard template */
99     public final int mMoreKeysTemplate;
100 
101     /** Maximum column for mini keyboard */
102     public final int mMaxMiniKeyboardColumn;
103 
104     /** True if Right-To-Left keyboard */
105     public final boolean mIsRtlKeyboard;
106 
107     /** List of keys and icons in this keyboard */
108     public final List<Key> mKeys;
109     public final List<Key> mShiftKeys;
110     public final Set<Key> mShiftLockKeys;
111     public final Map<Key, Drawable> mShiftedIcons;
112     public final Map<Key, Drawable> mUnshiftedIcons;
113     public final KeyboardIconsSet mIconsSet;
114 
115     private final KeyboardShiftState mShiftState = new KeyboardShiftState();
116 
117     private final ProximityInfo mProximityInfo;
118 
Keyboard(KeyboardParams params)119     public Keyboard(KeyboardParams params) {
120         mId = params.mId;
121         mThemeId = params.mThemeId;
122         mOccupiedHeight = params.mOccupiedHeight;
123         mOccupiedWidth = params.mOccupiedWidth;
124         mMostCommonKeyHeight = params.mMostCommonKeyHeight;
125         mMostCommonKeyWidth = params.mMostCommonKeyWidth;
126         mIsRtlKeyboard = params.mIsRtlKeyboard;
127         mMoreKeysTemplate = params.mMoreKeysTemplate;
128         mMaxMiniKeyboardColumn = params.mMaxMiniKeyboardColumn;
129 
130         mTopPadding = params.mTopPadding;
131         mVerticalGap = params.mVerticalGap;
132 
133         mKeys = Collections.unmodifiableList(params.mKeys);
134         mShiftKeys = Collections.unmodifiableList(params.mShiftKeys);
135         mShiftLockKeys = Collections.unmodifiableSet(params.mShiftLockKeys);
136         mShiftedIcons = Collections.unmodifiableMap(params.mShiftedIcons);
137         mUnshiftedIcons = Collections.unmodifiableMap(params.mUnshiftedIcons);
138         mIconsSet = params.mIconsSet;
139 
140         mProximityInfo = new ProximityInfo(
141                 params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,
142                 mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection);
143     }
144 
getProximityInfo()145     public ProximityInfo getProximityInfo() {
146         return mProximityInfo;
147     }
148 
hasShiftLockKey()149     public boolean hasShiftLockKey() {
150         return !mShiftLockKeys.isEmpty();
151     }
152 
setShiftLocked(boolean newShiftLockState)153     public boolean setShiftLocked(boolean newShiftLockState) {
154         for (final Key key : mShiftLockKeys) {
155             // To represent "shift locked" state. The highlight is handled by background image that
156             // might be a StateListDrawable.
157             key.setHighlightOn(newShiftLockState);
158             // To represent "shifted" state. The key might have a shifted icon.
159             if (newShiftLockState && mShiftedIcons.containsKey(key)) {
160                 key.setIcon(mShiftedIcons.get(key));
161             } else {
162                 key.setIcon(mUnshiftedIcons.get(key));
163             }
164         }
165         mShiftState.setShiftLocked(newShiftLockState);
166         return true;
167     }
168 
isShiftLocked()169     public boolean isShiftLocked() {
170         return mShiftState.isShiftLocked();
171     }
172 
setShifted(boolean newShiftState)173     public boolean setShifted(boolean newShiftState) {
174         for (final Key key : mShiftKeys) {
175             if (!newShiftState && !mShiftState.isShiftLocked()) {
176                 key.setIcon(mUnshiftedIcons.get(key));
177             } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) {
178                 key.setIcon(mShiftedIcons.get(key));
179             }
180         }
181         return mShiftState.setShifted(newShiftState);
182     }
183 
isShiftedOrShiftLocked()184     public boolean isShiftedOrShiftLocked() {
185         return mShiftState.isShiftedOrShiftLocked();
186     }
187 
setAutomaticTemporaryUpperCase()188     public void setAutomaticTemporaryUpperCase() {
189         setShifted(true);
190         mShiftState.setAutomaticTemporaryUpperCase();
191     }
192 
isAutomaticTemporaryUpperCase()193     public boolean isAutomaticTemporaryUpperCase() {
194         return isAlphaKeyboard() && mShiftState.isAutomaticTemporaryUpperCase();
195     }
196 
isManualTemporaryUpperCase()197     public boolean isManualTemporaryUpperCase() {
198         return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase();
199     }
200 
isManualTemporaryUpperCaseFromAuto()201     public boolean isManualTemporaryUpperCaseFromAuto() {
202         return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCaseFromAuto();
203     }
204 
getKeyboardShiftState()205     public KeyboardShiftState getKeyboardShiftState() {
206         return mShiftState;
207     }
208 
isAlphaKeyboard()209     public boolean isAlphaKeyboard() {
210         return mId.isAlphabetKeyboard();
211     }
212 
isPhoneKeyboard()213     public boolean isPhoneKeyboard() {
214         return mId.isPhoneKeyboard();
215     }
216 
isNumberKeyboard()217     public boolean isNumberKeyboard() {
218         return mId.isNumberKeyboard();
219     }
220 
adjustLabelCase(CharSequence label)221     public CharSequence adjustLabelCase(CharSequence label) {
222         if (isShiftedOrShiftLocked() && !TextUtils.isEmpty(label) && label.length() < 3
223                 && Character.isLowerCase(label.charAt(0))) {
224             return label.toString().toUpperCase(mId.mLocale);
225         }
226         return label;
227     }
228 
229     /**
230      * Returns the indices of the keys that are closest to the given point.
231      * @param x the x-coordinate of the point
232      * @param y the y-coordinate of the point
233      * @return the array of integer indices for the nearest keys to the given point. If the given
234      * point is out of range, then an array of size zero is returned.
235      */
getNearestKeys(int x, int y)236     public int[] getNearestKeys(int x, int y) {
237         return mProximityInfo.getNearestKeys(x, y);
238     }
239 
themeName(int themeId)240     public static String themeName(int themeId) {
241         // This should be aligned with theme-*.xml resource files' themeId attribute.
242         switch (themeId) {
243         case 0: return "Basic";
244         case 1: return "BasicHighContrast";
245         case 5: return "IceCreamSandwich";
246         case 6: return "Stone";
247         case 7: return "StoneBold";
248         case 8: return "GingerBread";
249         default: return null;
250         }
251     }
252 }
253