KeyboardSwitcher.java revision b19668cfc17ad30afcc3c8c0407d47238ce1a90d
1/* 2 * Copyright (C) 2008 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.inputmethod.latin; 18 19import java.util.HashMap; 20import java.util.Map; 21 22public class KeyboardSwitcher { 23 24 public static final int MODE_TEXT = 1; 25 public static final int MODE_SYMBOLS = 2; 26 public static final int MODE_PHONE = 3; 27 public static final int MODE_URL = 4; 28 public static final int MODE_EMAIL = 5; 29 public static final int MODE_IM = 6; 30 31 public static final int MODE_TEXT_QWERTY = 0; 32 public static final int MODE_TEXT_ALPHA = 1; 33 public static final int MODE_TEXT_COUNT = 2; 34 35 public static final int KEYBOARDMODE_NORMAL = R.id.mode_normal; 36 public static final int KEYBOARDMODE_URL = R.id.mode_url; 37 public static final int KEYBOARDMODE_EMAIL = R.id.mode_email; 38 public static final int KEYBOARDMODE_IM = R.id.mode_im; 39 40 private static final int SYMBOLS_MODE_STATE_NONE = 0; 41 private static final int SYMBOLS_MODE_STATE_BEGIN = 1; 42 private static final int SYMBOLS_MODE_STATE_SYMBOL = 2; 43 44 LatinKeyboardView mInputView; 45 LatinIME mContext; 46 47 private KeyboardId mSymbolsId; 48 private KeyboardId mSymbolsShiftedId; 49 50 private KeyboardId mCurrentId; 51 private Map<KeyboardId, LatinKeyboard> mKeyboards; 52 53 private int mMode; 54 private int mImeOptions; 55 private int mTextMode = MODE_TEXT_QWERTY; 56 private boolean mIsSymbols; 57 private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; 58 59 private int mLastDisplayWidth; 60 61 KeyboardSwitcher(LatinIME context) { 62 mContext = context; 63 mKeyboards = new HashMap<KeyboardId, LatinKeyboard>(); 64 mSymbolsId = new KeyboardId(R.xml.kbd_symbols); 65 mSymbolsShiftedId = new KeyboardId(R.xml.kbd_symbols_shift); 66 } 67 68 void setInputView(LatinKeyboardView inputView) { 69 mInputView = inputView; 70 } 71 72 void makeKeyboards() { 73 // Configuration change is coming after the keyboard gets recreated. So don't rely on that. 74 // If keyboards have already been made, check if we have a screen width change and 75 // create the keyboard layouts again at the correct orientation 76 int displayWidth = mContext.getMaxWidth(); 77 if (displayWidth == mLastDisplayWidth) return; 78 mLastDisplayWidth = displayWidth; 79 mKeyboards.clear(); 80 mSymbolsId = new KeyboardId(R.xml.kbd_symbols); 81 mSymbolsShiftedId = new KeyboardId(R.xml.kbd_symbols_shift); 82 } 83 84 /** 85 * Represents the parameters necessary to construct a new LatinKeyboard, 86 * which also serve as a unique identifier for each keyboard type. 87 */ 88 private static class KeyboardId { 89 public int mXml; 90 public int mMode; 91 public boolean mEnableShiftLock; 92 93 public KeyboardId(int xml, int mode, boolean enableShiftLock) { 94 this.mXml = xml; 95 this.mMode = mode; 96 this.mEnableShiftLock = enableShiftLock; 97 } 98 99 public KeyboardId(int xml) { 100 this(xml, 0, false); 101 } 102 103 public boolean equals(Object other) { 104 return other instanceof KeyboardId && equals((KeyboardId) other); 105 } 106 107 public boolean equals(KeyboardId other) { 108 return other.mXml == this.mXml && other.mMode == this.mMode; 109 } 110 111 public int hashCode() { 112 return (mXml + 1) * (mMode + 1) * (mEnableShiftLock ? 2 : 1); 113 } 114 } 115 116 void setKeyboardMode(int mode, int imeOptions) { 117 setKeyboardMode(mode, imeOptions, false); 118 } 119 120 void setKeyboardMode(int mode, int imeOptions, boolean isSymbols) { 121 mMode = mode; 122 mImeOptions = imeOptions; 123 mIsSymbols = isSymbols; 124 mInputView.setPreviewEnabled(true); 125 KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols); 126 LatinKeyboard keyboard = getKeyboard(id); 127 128 if (mode == MODE_PHONE) { 129 mInputView.setPhoneKeyboard(keyboard); 130 mInputView.setPreviewEnabled(false); 131 } 132 133 mCurrentId = id; 134 mInputView.setKeyboard(keyboard); 135 keyboard.setShifted(false); 136 keyboard.setShiftLocked(keyboard.isShiftLocked()); 137 keyboard.setImeOptions(mContext.getResources(), mMode, imeOptions); 138 139 } 140 141 private LatinKeyboard getKeyboard(KeyboardId id) { 142 if (!mKeyboards.containsKey(id)) { 143 LatinKeyboard keyboard = new LatinKeyboard( 144 mContext, id.mXml, id.mMode); 145 if (id.mEnableShiftLock) { 146 keyboard.enableShiftLock(); 147 } 148 mKeyboards.put(id, keyboard); 149 } 150 return mKeyboards.get(id); 151 } 152 153 private KeyboardId getKeyboardId(int mode, int imeOptions, boolean isSymbols) { 154 if (isSymbols) { 155 return (mode == MODE_PHONE) 156 ? new KeyboardId(R.xml.kbd_phone_symbols) : new KeyboardId(R.xml.kbd_symbols); 157 } 158 159 switch (mode) { 160 case MODE_TEXT: 161 if (mTextMode == MODE_TEXT_QWERTY) { 162 return new KeyboardId(R.xml.kbd_qwerty, KEYBOARDMODE_NORMAL, true); 163 } else if (mTextMode == MODE_TEXT_ALPHA) { 164 return new KeyboardId(R.xml.kbd_alpha, KEYBOARDMODE_NORMAL, true); 165 } 166 break; 167 case MODE_SYMBOLS: 168 return new KeyboardId(R.xml.kbd_symbols); 169 case MODE_PHONE: 170 return new KeyboardId(R.xml.kbd_phone); 171 case MODE_URL: 172 return new KeyboardId(R.xml.kbd_qwerty, KEYBOARDMODE_URL, true); 173 case MODE_EMAIL: 174 return new KeyboardId(R.xml.kbd_qwerty, KEYBOARDMODE_EMAIL, true); 175 case MODE_IM: 176 return new KeyboardId(R.xml.kbd_qwerty, KEYBOARDMODE_IM, true); 177 } 178 return null; 179 } 180 181 int getKeyboardMode() { 182 return mMode; 183 } 184 185 boolean isTextMode() { 186 return mMode == MODE_TEXT; 187 } 188 189 int getTextMode() { 190 return mTextMode; 191 } 192 193 void setTextMode(int position) { 194 if (position < MODE_TEXT_COUNT && position >= 0) { 195 mTextMode = position; 196 } 197 if (isTextMode()) { 198 setKeyboardMode(MODE_TEXT, mImeOptions); 199 } 200 } 201 202 int getTextModeCount() { 203 return MODE_TEXT_COUNT; 204 } 205 206 boolean isAlphabetMode() { 207 KeyboardId current = mCurrentId; 208 return current.mMode == KEYBOARDMODE_NORMAL 209 || current.mMode == KEYBOARDMODE_URL 210 || current.mMode == KEYBOARDMODE_EMAIL 211 || current.mMode == KEYBOARDMODE_IM; 212 } 213 214 void toggleShift() { 215 if (mCurrentId.equals(mSymbolsId)) { 216 LatinKeyboard symbolsKeyboard = getKeyboard(mSymbolsId); 217 LatinKeyboard symbolsShiftedKeyboard = getKeyboard(mSymbolsShiftedId); 218 symbolsKeyboard.setShifted(true); 219 mCurrentId = mSymbolsShiftedId; 220 mInputView.setKeyboard(symbolsShiftedKeyboard); 221 symbolsShiftedKeyboard.setShifted(true); 222 symbolsShiftedKeyboard.setImeOptions(mContext.getResources(), mMode, mImeOptions); 223 } else if (mCurrentId.equals(mSymbolsShiftedId)) { 224 LatinKeyboard symbolsKeyboard = getKeyboard(mSymbolsId); 225 LatinKeyboard symbolsShiftedKeyboard = getKeyboard(mSymbolsShiftedId); 226 symbolsShiftedKeyboard.setShifted(false); 227 mCurrentId = mSymbolsId; 228 mInputView.setKeyboard(getKeyboard(mSymbolsId)); 229 symbolsKeyboard.setShifted(false); 230 symbolsKeyboard.setImeOptions(mContext.getResources(), mMode, mImeOptions); 231 } 232 } 233 234 void toggleSymbols() { 235 setKeyboardMode(mMode, mImeOptions, !mIsSymbols); 236 if (mIsSymbols) { 237 mSymbolsModeState = SYMBOLS_MODE_STATE_BEGIN; 238 } else { 239 mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; 240 } 241 } 242 243 /** 244 * Updates state machine to figure out when to automatically switch back to alpha mode. 245 * Returns true if the keyboard needs to switch back 246 */ 247 boolean onKey(int key) { 248 // Switch back to alpha mode if user types one or more non-space characters followed by 249 // a space. 250 switch (mSymbolsModeState) { 251 case SYMBOLS_MODE_STATE_BEGIN: 252 if (key != ' ' && key > 0) mSymbolsModeState = SYMBOLS_MODE_STATE_SYMBOL; 253 break; 254 case SYMBOLS_MODE_STATE_SYMBOL: 255 if (key == ' ') return true; 256 break; 257 } 258 return false; 259 } 260} 261