001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package com.sun.midp.chameleon.input;
027:
028: import javax.microedition.lcdui.Canvas;
029: import javax.microedition.lcdui.TextField;
030: import com.sun.midp.i18n.Resource;
031: import com.sun.midp.i18n.ResourceConstants;
032: import com.sun.midp.log.Logging;
033: import com.sun.midp.log.LogChannels;
034:
035: /**
036: * An InputMode instance which processes the numeric 0-9 keys
037: * as their literal numeric values.
038: */
039: public class AlphaNumericInputMode extends BasicInputMode {
040:
041: /** set of chars for alpha upper-case input */
042: private static char[][] upperKeyMap;
043:
044: /** set of chars for alpha low-case input */
045: private static char[][] lowerKeyMap;
046:
047: /** set of chars for long key press */
048: private static char[][] longPressKeyMap;
049:
050: /** array of sub-inputModes supported by this inputMode */
051: protected static final int[] CAPS_MODES = { CAPS_SENTENCE,
052: CAPS_OFF, CAPS_ON };
053:
054: /** array of sub-inputModes labels, corresponding to CAPS_MODES array */
055: private static final String[] CAPS_MODES_LABELS = {
056: Resource
057: .getString(ResourceConstants.LCDUI_TF_CAPS_SENTENCE),
058: Resource.getString(ResourceConstants.LCDUI_TF_CAPS_OFF),
059: Resource.getString(ResourceConstants.LCDUI_TF_CAPS_ON) };
060:
061: /** the possible key maps for this input mode */
062: private static char[][][] keyMaps;
063:
064: /** points to an element of CAPS_MODES which is the current sub-inputMode */
065: protected int capsModePointer = 0;
066:
067: /** Default constructor. Init key maps for all constraints */
068: public AlphaNumericInputMode() {
069: String upperInLine = Resource
070: .getString(ResourceConstants.LCDUI_TF_CAPS_ALPHA_KEY_MAP);
071: upperKeyMap = getMapByLine(upperInLine);
072: String lowerInLine = Resource
073: .getString(ResourceConstants.LCDUI_TF_ALPHA_KEY_MAP);
074: lowerKeyMap = getMapByLine(lowerInLine);
075: String longInLine = Resource
076: .getString(ResourceConstants.LCDUI_TF_ALPHA_DIGIT_KEY_MAP);
077: longPressKeyMap = getMapByLine(longInLine);
078:
079: keyMaps = new char[3][][];
080: keyMaps[0] = upperKeyMap;
081: keyMaps[1] = lowerKeyMap;
082: keyMaps[2] = upperKeyMap;
083: }
084:
085: /**
086: * Set the corresponding key map.
087: *
088: * @param constraints text input constraints. The semantics of the
089: * constraints value are defined in the TextField API.
090: *
091: * @param longPress return true if it's long key press otherwise false
092: *
093: * @return true if the key map has been changed otherwise false
094: */
095: protected boolean setKeyMap(int constraints, boolean longPress) {
096: char[][] oldKeyMap = keyMap;
097:
098: keyMap = longPress ? longPressKeyMap : keyMaps[capsModePointer];
099:
100: return oldKeyMap != keyMap;
101: }
102:
103: /**
104: * This method is called to determine if this InputMode supports
105: * the given text input constraints. The semantics of the constraints
106: * value are defined in the javax.microedition.lcdui.TextField API.
107: * If this InputMode returns false, this InputMode must not be used
108: * to process key input for the selected text component.
109: *
110: * @param constraints text input constraints. The semantics of the
111: * constraints value are defined in the TextField API.
112: *
113: * @return true if this InputMode supports the given text component
114: * constraints, as defined in the MIDP TextField API
115: */
116: public boolean supportsConstraints(int constraints) {
117: switch (constraints & TextField.CONSTRAINT_MASK) {
118: case TextField.NUMERIC:
119: case TextField.DECIMAL:
120: case TextField.PHONENUMBER:
121: return false;
122: default:
123: return true;
124: }
125: }
126:
127: /**
128: * Returns the display name which will represent this InputMode to
129: * the user, such as in a selection list or the softbutton bar.
130: *
131: * @return the locale-appropriate name to represent this InputMode
132: * to the user
133: */
134: public String getName() {
135: return CAPS_MODES_LABELS[capsModePointer];
136: }
137:
138: /**
139: * Returns the command name which will represent this InputMode in
140: * the input menu
141: *
142: * @return the locale-appropriate name to represent this InputMode
143: * to the user
144: */
145: public String getCommandName() {
146: return getName();
147: }
148:
149: /**
150: * Set the next capital mode for this input method
151: */
152: protected void nextCapsMode() {
153: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
154: Logging.report(Logging.INFORMATION, LogChannels.LC_HIGHUI,
155: "[A.nextCapsMode]");
156: }
157: capsModePointer++;
158: if (capsModePointer == CAPS_MODES.length) {
159: capsModePointer = 0;
160: }
161: if (CAPS_MODES[capsModePointer] == CAPS_OFF) {
162: keyMap = lowerKeyMap;
163: } else {
164: keyMap = upperKeyMap;
165: }
166:
167: mediator.subInputModeChanged();
168: }
169:
170: /**
171: * Gets the possible matches for the key code
172: *
173: * @param lastKey the key code
174: *
175: * @return returns the set of options. Return null if matches are not found.
176: */
177: protected char[] getCharOptions(int lastKey) {
178: char[] chars = null;
179:
180: switch (lastKey) {
181: case Canvas.KEY_NUM0:
182: chars = keyMap[0];
183: break;
184: case Canvas.KEY_NUM1:
185: chars = keyMap[1];
186: break;
187: case Canvas.KEY_NUM2:
188: chars = keyMap[2];
189: break;
190: case Canvas.KEY_NUM3:
191: chars = keyMap[3];
192: break;
193: case Canvas.KEY_NUM4:
194: chars = keyMap[4];
195: break;
196: case Canvas.KEY_NUM5:
197: chars = keyMap[5];
198: break;
199: case Canvas.KEY_NUM6:
200: chars = keyMap[6];
201: break;
202: case Canvas.KEY_NUM7:
203: chars = keyMap[7];
204: break;
205: case Canvas.KEY_NUM8:
206: chars = keyMap[8];
207: break;
208: case Canvas.KEY_NUM9:
209: chars = keyMap[9];
210: break;
211: case Canvas.KEY_POUND:
212: chars = keyMap[10];
213: break;
214: case Canvas.KEY_STAR:
215: nextCapsMode();
216: break;
217:
218: default:
219: // This can actually happen if the Timer went off without
220: // a pending key, which can sometimes happen.
221: break;
222:
223: }
224:
225: return chars;
226: }
227:
228: /**
229: * This method is used to immediately commit the pending
230: * character because a new character is now pending.
231: *
232: * @return true if char has been committed otherwise false
233: */
234: protected boolean commitPendingChar() {
235: boolean committed = super .commitPendingChar();
236: if (committed) {
237: if (CAPS_MODES[capsModePointer] == CAPS_SENTENCE) {
238: nextCapsMode();
239: }
240: }
241: return committed;
242: }
243:
244: /** input subset x constraint map */
245: private static final boolean[][] isMap = {
246: // |ANY|EMAILADDR|NUMERIC|PHONENUMBER|URL|DECIMAL
247: { false, false, false, false, false, false }, // IS_FULLWIDTH_DIGITS
248: { true, true, false, false, true, false }, // IS_FULLWIDTH_LATIN
249: { false, false, false, false, false, false }, // IS_HALFWIDTH_KATAKANA
250: { false, false, false, false, false, false }, // IS_HANJA
251: { false, false, false, false, false, false }, // IS_KANJI
252: { true, true, false, false, true, false }, // IS_LATIN
253: { true, true, false, false, true, false }, // IS_LATIN_DIGITS
254: { false, false, false, false, false, false }, // IS_SIMPLIFIED_HANZI
255: { false, false, false, false, false, false }, // IS_TRADITIONAL_HANZI
256: { true, true, false, false, true, false }, // MIDP_UPPERCASE_LATIN
257: { true, true, false, false, true, false }, // MIDP_LOWERCASE_LATIN
258: { false, false, false, false, false, false } // NULL
259: };
260:
261: /**
262: * Returns the map specifying this input mode is proper one for the
263: * particular pair of input subset and constraint. The form of the map is
264: *
265: * |ANY|EMAILADDR|NUMERIC|PHONENUMBER|URL|DECIMAL|
266: * ---------------------------------------------------------------------
267: * IS_FULLWIDTH_DIGITS |t|f| t|f | t|f | t|f |t|f| t|f |
268: * IS_FULLWIDTH_LATIN |t|f| t|f | t|f | t|f |t|f| t|f |
269: * IS_HALFWIDTH_KATAKANA |t|f| t|f | t|f | t|f |t|f| t|f |
270: * IS_HANJA |t|f| t|f | t|f | t|f |t|f| t|f |
271: * IS_KANJI |t|f| t|f | t|f | t|f |t|f| t|f |
272: * IS_LATIN |t|f| t|f | t|f | t|f |t|f| t|f |
273: * IS_LATIN_DIGITS |t|f| t|f | t|f | t|f |t|f| t|f |
274: * IS_SIMPLIFIED_HANZI |t|f| t|f | t|f | t|f |t|f| t|f |
275: * IS_TRADITIONAL_HANZI |t|f| t|f | t|f | t|f |t|f| t|f |
276: * MIDP_UPPERCASE_LATIN |t|f| t|f | t|f | t|f |t|f| t|f |
277: * MIDP_LOWERCASE_LATIN |t|f| t|f | t|f | t|f |t|f| t|f |
278: * NULL |t|f| t|f | t|f | t|f |t|f| t|f |
279: *
280: * @return input subset x constraint map
281: */
282: public boolean[][] getIsConstraintsMap() {
283: return isMap;
284: }
285:
286: /**
287: * Notify about current input subset
288: * @param inputSubset current input subset
289: */
290: protected void setInputSubset(String inputSubset) {
291: int mode = -1;
292: if ("MIDP_UPPERCASE_LATIN".equals(inputSubset)) {
293: mode = CAPS_ON;
294: } else if ("MIDP_LOWERCASE_LATIN".equals(inputSubset)) {
295: mode = CAPS_OFF;
296: }
297: for (int i = CAPS_MODES.length - 1; i >= 0; i--) {
298: if (CAPS_MODES[i] == mode) {
299: capsModePointer = i;
300: break;
301: }
302: }
303: }
304: }
|