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