blob: 3c01c69519c5cb8022de5468eb406638c8e0af1c [file] [log] [blame]
Jim Miller0b319702010-02-05 18:51:59 -08001/*
2 * Copyright (C) 2010 Google Inc.
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.internal.widget;
18
19import java.util.Locale;
20import android.content.Context;
21import android.content.res.Resources;
22import android.content.res.XmlResourceParser;
Jim Miller0b319702010-02-05 18:51:59 -080023import android.graphics.drawable.Drawable;
24import android.inputmethodservice.Keyboard;
25import android.inputmethodservice.KeyboardView;
Jim Miller0b319702010-02-05 18:51:59 -080026import com.android.internal.R;
27
28/**
29 * A basic, embed-able keyboard designed for password entry. Allows entry of all Latin-1 characters.
30 *
31 * It has two modes: alpha and numeric. In alpha mode, it allows all Latin-1 characters and enables
32 * an additional keyboard with symbols. In numeric mode, it shows a 12-key DTMF dialer-like
33 * keypad with alpha characters hints.
34 */
35public class PasswordEntryKeyboard extends Keyboard {
Jim Miller0b319702010-02-05 18:51:59 -080036 private static final int SHIFT_OFF = 0;
37 private static final int SHIFT_ON = 1;
38 private static final int SHIFT_LOCKED = 2;
39 public static final int KEYCODE_SPACE = ' ';
40
41 private Drawable mShiftIcon;
42 private Drawable mShiftLockIcon;
Jim Miller6465f772011-01-19 22:01:25 -080043
44 // These two arrays must be the same length
45 private Drawable[] mOldShiftIcons = { null, null };
46 private Key[] mShiftKeys = { null, null };
47
Jim Miller0b319702010-02-05 18:51:59 -080048 private Key mEnterKey;
49 private Key mF1Key;
50 private Key mSpaceKey;
Jim Miller0b319702010-02-05 18:51:59 -080051 private int mShiftState = SHIFT_OFF;
52
53 static int sSpacebarVerticalCorrection;
54
55 public PasswordEntryKeyboard(Context context, int xmlLayoutResId) {
56 this(context, xmlLayoutResId, 0);
57 }
58
Jae Yong Sung8171b512010-08-05 10:44:27 -070059 public PasswordEntryKeyboard(Context context, int xmlLayoutResId, int width, int height) {
60 this(context, xmlLayoutResId, 0, width, height);
61 }
62
Jim Miller0b319702010-02-05 18:51:59 -080063 public PasswordEntryKeyboard(Context context, int xmlLayoutResId, int mode) {
64 super(context, xmlLayoutResId, mode);
Jae Yong Sung8171b512010-08-05 10:44:27 -070065 init(context);
66 }
67
68 public PasswordEntryKeyboard(Context context, int xmlLayoutResId, int mode,
69 int width, int height) {
70 super(context, xmlLayoutResId, mode, width, height);
71 init(context);
72 }
73
74 private void init(Context context) {
Jim Miller0b319702010-02-05 18:51:59 -080075 final Resources res = context.getResources();
Jim Miller0b319702010-02-05 18:51:59 -080076 mShiftIcon = res.getDrawable(R.drawable.sym_keyboard_shift);
77 mShiftLockIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked);
Jim Miller0b319702010-02-05 18:51:59 -080078 sSpacebarVerticalCorrection = res.getDimensionPixelOffset(
79 R.dimen.password_keyboard_spacebar_vertical_correction);
80 }
81
82 public PasswordEntryKeyboard(Context context, int layoutTemplateResId,
83 CharSequence characters, int columns, int horizontalPadding) {
84 super(context, layoutTemplateResId, characters, columns, horizontalPadding);
85 }
86
87 @Override
88 protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
89 XmlResourceParser parser) {
90 LatinKey key = new LatinKey(res, parent, x, y, parser);
91 final int code = key.codes[0];
92 if (code >=0 && code != '\n' && (code < 32 || code > 127)) {
Jim Millerec52eed2010-02-11 17:27:22 -080093 // Log.w(TAG, "Key code for " + key.label + " is not latin-1");
Jim Miller0b319702010-02-05 18:51:59 -080094 key.label = " ";
95 key.setEnabled(false);
96 }
97 switch (key.codes[0]) {
98 case 10:
99 mEnterKey = key;
100 break;
101 case PasswordEntryKeyboardView.KEYCODE_F1:
102 mF1Key = key;
103 break;
104 case 32:
105 mSpaceKey = key;
106 break;
107 }
108 return key;
109 }
110
111 /**
112 * Allows enter key resources to be overridden
113 * @param res resources to grab given items from
114 * @param previewId preview drawable shown on enter key
115 * @param iconId normal drawable shown on enter key
116 * @param labelId string shown on enter key
117 */
118 void setEnterKeyResources(Resources res, int previewId, int iconId, int labelId) {
119 if (mEnterKey != null) {
120 // Reset some of the rarely used attributes.
121 mEnterKey.popupCharacters = null;
122 mEnterKey.popupResId = 0;
123 mEnterKey.text = null;
124
125 mEnterKey.iconPreview = res.getDrawable(previewId);
126 mEnterKey.icon = res.getDrawable(iconId);
127 mEnterKey.label = res.getText(labelId);
128
129 // Set the initial size of the preview icon
130 if (mEnterKey.iconPreview != null) {
131 mEnterKey.iconPreview.setBounds(0, 0,
132 mEnterKey.iconPreview.getIntrinsicWidth(),
133 mEnterKey.iconPreview.getIntrinsicHeight());
134 }
135 }
136 }
137
138 /**
139 * Allows shiftlock to be turned on. See {@link #setShiftLocked(boolean)}
140 *
141 */
142 void enableShiftLock() {
Jim Miller6465f772011-01-19 22:01:25 -0800143 int i = 0;
144 for (int index : getShiftKeyIndices()) {
145 if (index >= 0 && i < mShiftKeys.length) {
146 mShiftKeys[i] = getKeys().get(index);
147 if (mShiftKeys[i] instanceof LatinKey) {
148 ((LatinKey)mShiftKeys[i]).enableShiftLock();
149 }
150 mOldShiftIcons[i] = mShiftKeys[i].icon;
151 i++;
Jim Miller0b319702010-02-05 18:51:59 -0800152 }
Jim Miller0b319702010-02-05 18:51:59 -0800153 }
154 }
155
156 /**
157 * Turn on shift lock. This turns on the LED for this key, if it has one.
158 * It should be followed by a call to {@link KeyboardView#invalidateKey(int)}
159 * or {@link KeyboardView#invalidateAllKeys()}
160 *
161 * @param shiftLocked
162 */
163 void setShiftLocked(boolean shiftLocked) {
Jim Miller6465f772011-01-19 22:01:25 -0800164 for (Key shiftKey : mShiftKeys) {
165 if (shiftKey != null) {
166 shiftKey.on = shiftLocked;
167 shiftKey.icon = mShiftLockIcon;
Jim Miller0b319702010-02-05 18:51:59 -0800168 }
169 }
Jim Miller6465f772011-01-19 22:01:25 -0800170 mShiftState = shiftLocked ? SHIFT_LOCKED : SHIFT_ON;
Jim Miller0b319702010-02-05 18:51:59 -0800171 }
172
173 /**
174 * Turn on shift mode. Sets shift mode and turns on icon for shift key.
175 * It should be followed by a call to {@link KeyboardView#invalidateKey(int)}
176 * or {@link KeyboardView#invalidateAllKeys()}
177 *
178 * @param shiftLocked
179 */
180 @Override
181 public boolean setShifted(boolean shiftState) {
182 boolean shiftChanged = false;
Jim Miller6465f772011-01-19 22:01:25 -0800183 if (shiftState == false) {
184 shiftChanged = mShiftState != SHIFT_OFF;
185 mShiftState = SHIFT_OFF;
186 } else if (mShiftState == SHIFT_OFF) {
187 shiftChanged = mShiftState == SHIFT_OFF;
188 mShiftState = SHIFT_ON;
189 }
190 for (int i = 0; i < mShiftKeys.length; i++) {
191 if (mShiftKeys[i] != null) {
192 if (shiftState == false) {
193 mShiftKeys[i].on = false;
194 mShiftKeys[i].icon = mOldShiftIcons[i];
195 } else if (mShiftState == SHIFT_OFF) {
196 mShiftKeys[i].on = false;
197 mShiftKeys[i].icon = mShiftIcon;
198 }
199 } else {
200 // return super.setShifted(shiftState);
Jim Miller0b319702010-02-05 18:51:59 -0800201 }
Jim Miller0b319702010-02-05 18:51:59 -0800202 }
203 return shiftChanged;
204 }
205
206 /**
207 * Whether or not keyboard is shifted.
208 * @return true if keyboard state is shifted.
209 */
210 @Override
211 public boolean isShifted() {
Jim Miller6465f772011-01-19 22:01:25 -0800212 if (mShiftKeys[0] != null) {
Jim Miller0b319702010-02-05 18:51:59 -0800213 return mShiftState != SHIFT_OFF;
214 } else {
215 return super.isShifted();
216 }
217 }
218
Jim Miller0b319702010-02-05 18:51:59 -0800219 static class LatinKey extends Keyboard.Key {
220 private boolean mShiftLockEnabled;
221 private boolean mEnabled = true;
222
223 public LatinKey(Resources res, Keyboard.Row parent, int x, int y,
224 XmlResourceParser parser) {
225 super(res, parent, x, y, parser);
226 if (popupCharacters != null && popupCharacters.length() == 0) {
227 // If there is a keyboard with no keys specified in popupCharacters
228 popupResId = 0;
229 }
230 }
231
232 void setEnabled(boolean enabled) {
233 mEnabled = enabled;
234 }
235
236 void enableShiftLock() {
237 mShiftLockEnabled = true;
238 }
239
240 @Override
241 public void onReleased(boolean inside) {
242 if (!mShiftLockEnabled) {
243 super.onReleased(inside);
244 } else {
245 pressed = !pressed;
246 }
247 }
248
249 /**
250 * Overriding this method so that we can reduce the target area for certain keys.
251 */
252 @Override
253 public boolean isInside(int x, int y) {
254 if (!mEnabled) {
255 return false;
256 }
257 final int code = codes[0];
258 if (code == KEYCODE_SHIFT || code == KEYCODE_DELETE) {
259 y -= height / 10;
260 if (code == KEYCODE_SHIFT) x += width / 6;
261 if (code == KEYCODE_DELETE) x -= width / 6;
262 } else if (code == KEYCODE_SPACE) {
263 y += PasswordEntryKeyboard.sSpacebarVerticalCorrection;
264 }
265 return super.isInside(x, y);
266 }
267 }
268}