PageRenderTime 54ms CodeModel.GetById 12ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 1ms

/ime/latinime/src/com/googlecode/eyesfree/inputmethod/latin/LatinKeyboardView.java

http://eyes-free.googlecode.com/
Java | 327 lines | 269 code | 30 blank | 28 comment | 49 complexity | bccfcdb040517fdfa0983acb1a9312c5 MD5 | raw file
  1/*
  2 * Copyright (C) 2008 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
 17package com.googlecode.eyesfree.inputmethod.latin;
 18
 19import android.content.Context;
 20import android.graphics.Canvas;
 21import android.graphics.Paint;
 22import android.inputmethodservice.Keyboard;
 23import android.inputmethodservice.Keyboard.Key;
 24import android.os.Handler;
 25import android.os.Message;
 26import android.os.SystemClock;
 27import android.text.TextUtils;
 28import android.util.AttributeSet;
 29import android.view.KeyEvent;
 30import android.view.MotionEvent;
 31
 32import java.util.List;
 33
 34public class LatinKeyboardView extends LatinKeyboardBaseView {
 35    public static final int KEYCODE_TAB = 9;
 36    public static final int KEYCODE_RETURN = 10;
 37    public static final int KEYCODE_SPACE = 32;
 38    public static final int KEYCODE_SHIFT = -1;
 39    public static final int KEYCODE_SYMBOL = -2;
 40    public static final int KEYCODE_DELETE = -5;
 41    public static final int KEYCODE_OPTIONS = -100;
 42    public static final int KEYCODE_OPTIONS_LONGPRESS = -101;
 43    public static final int KEYCODE_VOICE = -102;
 44    public static final int KEYCODE_F1 = -103;
 45    public static final int KEYCODE_NEXT_LANGUAGE = -104;
 46    public static final int KEYCODE_PREV_LANGUAGE = -105;
 47    public static final int KEYCODE_BACK = -106;
 48    public static final int KEYCODE_SEARCH = -107;
 49    public static final int KEYCODE_HOME = -108;
 50    public static final int KEYCODE_MENU = -109;
 51    public static final int KEYCODE_CALL = -110;
 52    public static final int KEYCODE_ENDCALL = -111;
 53    public static final int KEYCODE_ALT = -112;
 54    public static final int KEYCODE_DPAD_UP = -113;
 55    public static final int KEYCODE_DPAD_LEFT = -114;
 56    public static final int KEYCODE_DPAD_CENTER = -115;
 57    public static final int KEYCODE_DPAD_RIGHT = -116;
 58    public static final int KEYCODE_DPAD_DOWN = -117;
 59    public static final int KEYCODE_UNKNOWN = Integer.MIN_VALUE;
 60
 61    /**
 62     * Returns the key code from {@link KeyEvent} for a given internal key code.
 63     *
 64     * @param internalKeyCode The internal key code.
 65     * @return the key code from {@link KeyEvent}
 66     */
 67    static int getKeyCode(int internalKeyCode) {
 68        switch (internalKeyCode) {
 69            case KEYCODE_BACK:
 70                return KeyEvent.KEYCODE_BACK;
 71            case KEYCODE_SEARCH:
 72                return KeyEvent.KEYCODE_SEARCH;
 73            case KEYCODE_MENU:
 74                return KeyEvent.KEYCODE_MENU;
 75            case KEYCODE_CALL:
 76                return KeyEvent.KEYCODE_CALL;
 77            case KEYCODE_ENDCALL:
 78                return KeyEvent.KEYCODE_ENDCALL;
 79            case KEYCODE_ALT:
 80                return KeyEvent.KEYCODE_ALT_LEFT;
 81            case KEYCODE_DPAD_UP:
 82                return KeyEvent.KEYCODE_DPAD_UP;
 83            case KEYCODE_DPAD_LEFT:
 84                return KeyEvent.KEYCODE_DPAD_LEFT;
 85            case KEYCODE_DPAD_CENTER:
 86                return KeyEvent.KEYCODE_DPAD_CENTER;
 87            case KEYCODE_DPAD_RIGHT:
 88                return KeyEvent.KEYCODE_DPAD_RIGHT;
 89            case KEYCODE_DPAD_DOWN:
 90                return KeyEvent.KEYCODE_DPAD_DOWN;
 91            default:
 92                return KeyEvent.KEYCODE_UNKNOWN;
 93        }
 94    }
 95
 96    private Keyboard mPhoneKeyboard;
 97
 98    public LatinKeyboardView(Context context, AttributeSet attrs) {
 99        this(context, attrs, 0);
100    }
101
102    public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
103        super(context, attrs, defStyle);
104    }
105
106    public void setPhoneKeyboard(Keyboard phoneKeyboard) {
107        mPhoneKeyboard = phoneKeyboard;
108    }
109
110    @Override
111    public void setPreviewEnabled(boolean previewEnabled) {
112        if (getKeyboard() == mPhoneKeyboard) {
113            // Phone keyboard never shows popup preview (except language switch).
114            super.setPreviewEnabled(false);
115        } else {
116            super.setPreviewEnabled(previewEnabled);
117        }
118    }
119
120    @Override
121    public void setKeyboard(Keyboard k) {
122        super.setKeyboard(k);
123        setKeyboardLocal(k);
124    }
125
126    @Override
127    protected boolean onLongPress(Key key) {
128        int primaryCode = key.codes[0];
129        if (primaryCode == KEYCODE_OPTIONS) {
130            return invokeOnKey(KEYCODE_OPTIONS_LONGPRESS);
131        } else if (primaryCode == '0' && getKeyboard() == mPhoneKeyboard) {
132            // Long pressing on 0 in phone number keypad gives you a '+'.
133            return invokeOnKey('+');
134        } else {
135            return super.onLongPress(key);
136        }
137    }
138
139    private boolean invokeOnKey(int primaryCode) {
140        getOnKeyboardActionListener().onKey(primaryCode, null,
141                LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE,
142                LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE);
143        return true;
144    }
145
146    @Override
147    protected CharSequence adjustCase(CharSequence label) {
148        Keyboard keyboard = getKeyboard();
149        if (keyboard.isShifted()
150                && keyboard instanceof LatinKeyboard
151                && ((LatinKeyboard) keyboard).isAlphaKeyboard()
152                && !TextUtils.isEmpty(label) && label.length() < 3
153                && Character.isLowerCase(label.charAt(0))) {
154            label = label.toString().toUpperCase();
155        }
156        return label;
157    }
158
159    public boolean setShiftLocked(boolean shiftLocked) {
160        Keyboard keyboard = getKeyboard();
161        if (keyboard instanceof LatinKeyboard) {
162            ((LatinKeyboard)keyboard).setShiftLocked(shiftLocked);
163            invalidateAllKeys();
164            return true;
165        }
166        return false;
167    }
168
169    public boolean isShiftLocked() {
170        Keyboard keyboard = getKeyboard();
171        if (keyboard instanceof LatinKeyboard) {
172            return ((LatinKeyboard)keyboard).isShiftLocked();
173        }
174        return false;
175    }
176
177    @Override
178    public boolean onTouchEvent(MotionEvent me) {
179        LatinKeyboard keyboard = (LatinKeyboard) getKeyboard();
180        if (DEBUG_LINE) {
181            mLastX = (int) me.getX();
182            mLastY = (int) me.getY();
183            invalidate();
184        }
185
186        // Reset any bounding box controls in the keyboard
187        if (me.getAction() == MotionEvent.ACTION_DOWN) {
188            keyboard.keyReleased();
189        }
190
191        return super.onTouchEvent(me);
192    }
193
194    /****************************  INSTRUMENTATION  *******************************/
195
196    static final boolean DEBUG_AUTO_PLAY = false;
197    static final boolean DEBUG_LINE = false;
198    private static final int MSG_TOUCH_DOWN = 1;
199    private static final int MSG_TOUCH_UP = 2;
200
201    Handler mHandler2;
202
203    private String mStringToPlay;
204    private int mStringIndex;
205    private boolean mDownDelivered;
206    private Key[] mAsciiKeys = new Key[256];
207    private boolean mPlaying;
208    private int mLastX;
209    private int mLastY;
210    private Paint mPaint;
211
212    private void setKeyboardLocal(Keyboard k) {
213        if (DEBUG_AUTO_PLAY) {
214            findKeys();
215            if (mHandler2 == null) {
216                mHandler2 = new Handler() {
217                    @Override
218                    public void handleMessage(Message msg) {
219                        removeMessages(MSG_TOUCH_DOWN);
220                        removeMessages(MSG_TOUCH_UP);
221                        if (mPlaying == false) return;
222
223                        switch (msg.what) {
224                            case MSG_TOUCH_DOWN:
225                                if (mStringIndex >= mStringToPlay.length()) {
226                                    mPlaying = false;
227                                    return;
228                                }
229                                char c = mStringToPlay.charAt(mStringIndex);
230                                while (c > 255 || mAsciiKeys[c] == null) {
231                                    mStringIndex++;
232                                    if (mStringIndex >= mStringToPlay.length()) {
233                                        mPlaying = false;
234                                        return;
235                                    }
236                                    c = mStringToPlay.charAt(mStringIndex);
237                                }
238                                int x = mAsciiKeys[c].x + 10;
239                                int y = mAsciiKeys[c].y + 26;
240                                MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(),
241                                        SystemClock.uptimeMillis(),
242                                        MotionEvent.ACTION_DOWN, x, y, 0);
243                                LatinKeyboardView.this.dispatchTouchEvent(me);
244                                me.recycle();
245                                sendEmptyMessageDelayed(MSG_TOUCH_UP, 500); // Deliver up in 500ms if nothing else
246                                // happens
247                                mDownDelivered = true;
248                                break;
249                            case MSG_TOUCH_UP:
250                                char cUp = mStringToPlay.charAt(mStringIndex);
251                                int x2 = mAsciiKeys[cUp].x + 10;
252                                int y2 = mAsciiKeys[cUp].y + 26;
253                                mStringIndex++;
254
255                                MotionEvent me2 = MotionEvent.obtain(SystemClock.uptimeMillis(),
256                                        SystemClock.uptimeMillis(),
257                                        MotionEvent.ACTION_UP, x2, y2, 0);
258                                LatinKeyboardView.this.dispatchTouchEvent(me2);
259                                me2.recycle();
260                                sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 500); // Deliver up in 500ms if nothing else
261                                // happens
262                                mDownDelivered = false;
263                                break;
264                        }
265                    }
266                };
267
268            }
269        }
270    }
271
272    private void findKeys() {
273        List<Key> keys = getKeyboard().getKeys();
274        // Get the keys on this keyboard
275        for (int i = 0; i < keys.size(); i++) {
276            int code = keys.get(i).codes[0];
277            if (code >= 0 && code <= 255) {
278                mAsciiKeys[code] = keys.get(i);
279            }
280        }
281    }
282
283    public void startPlaying(String s) {
284        if (DEBUG_AUTO_PLAY) {
285            if (s == null) return;
286            mStringToPlay = s.toLowerCase();
287            mPlaying = true;
288            mDownDelivered = false;
289            mStringIndex = 0;
290            mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 10);
291        }
292    }
293
294    @Override
295    public void draw(Canvas c) {
296        LatinIMEUtil.GCUtils.getInstance().reset();
297        boolean tryGC = true;
298        for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
299            try {
300                super.draw(c);
301                tryGC = false;
302            } catch (OutOfMemoryError e) {
303                tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait("LatinKeyboardView", e);
304            }
305        }
306        if (DEBUG_AUTO_PLAY) {
307            if (mPlaying) {
308                mHandler2.removeMessages(MSG_TOUCH_DOWN);
309                mHandler2.removeMessages(MSG_TOUCH_UP);
310                if (mDownDelivered) {
311                    mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_UP, 20);
312                } else {
313                    mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 20);
314                }
315            }
316        }
317        if (DEBUG_LINE) {
318            if (mPaint == null) {
319                mPaint = new Paint();
320                mPaint.setColor(0x80FFFFFF);
321                mPaint.setAntiAlias(false);
322            }
323            c.drawLine(mLastX, 0, mLastX, getHeight(), mPaint);
324            c.drawLine(0, mLastY, getWidth(), mLastY, mPaint);
325        }
326    }
327}