1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/*
2923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Copyright (C) 2008-2009 Google Inc.
3923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project *
4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of
6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at
7923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project *
8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0
9923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project *
10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under
14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License.
15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */
16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
17923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpackage com.android.inputmethod.latin;
18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
193f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasaniimport java.util.List;
2036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport java.util.Locale;
2136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
22923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context;
23923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.Resources;
243f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasaniimport android.content.res.TypedArray;
25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.XmlResourceParser;
2636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.graphics.Bitmap;
2736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.graphics.Canvas;
283f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasaniimport android.graphics.ColorFilter;
2936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.graphics.Paint;
303f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasaniimport android.graphics.PixelFormat;
3136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.graphics.PorterDuff;
323f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasaniimport android.graphics.Rect;
3336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.graphics.Paint.Align;
3436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.graphics.drawable.BitmapDrawable;
35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.graphics.drawable.Drawable;
36923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.Keyboard;
373f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasaniimport android.text.TextPaint;
381b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasaniimport android.util.Log;
393f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasaniimport android.view.ViewConfiguration;
40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo;
41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpublic class LatinKeyboard extends Keyboard {
43923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
441b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private static final boolean DEBUG_PREFERRED_LETTER = false;
451b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private static final String TAG = "LatinKeyboard";
461b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani
47923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private Drawable mShiftLockIcon;
48923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private Drawable mShiftLockPreviewIcon;
49923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private Drawable mOldShiftIcon;
50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private Drawable mOldShiftPreviewIcon;
5136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    private Drawable mSpaceIcon;
523f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private Drawable mSpacePreviewIcon;
53b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani    private Drawable mMicIcon;
54b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani    private Drawable mMicPreviewIcon;
55b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani    private Drawable m123MicIcon;
56b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani    private Drawable m123MicPreviewIcon;
573f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private Drawable mButtonArrowLeftIcon;
583f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private Drawable mButtonArrowRightIcon;
59923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private Key mShiftKey;
60923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private Key mEnterKey;
6136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    private Key mF1Key;
6236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    private Key mSpaceKey;
63cc03f196ad68fe564ec31199f0ffafa06caeccf3Amith Yamasani    private Key m123Key;
643f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private int mSpaceKeyIndex = -1;
653f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private int mSpaceDragStartX;
663f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private int mSpaceDragLastDiff;
678eb2e34d5b2def57c9548f88e37e5c9e5a0bea59Amith Yamasani    /* package */ Locale mLocale;
683f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private LanguageSwitcher mLanguageSwitcher;
6936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    private Resources mRes;
703f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private Context mContext;
7136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    private int mMode;
721ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani    // Whether this keyboard has voice icon on it
731ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani    private boolean mHasVoiceButton;
741ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani    // Whether voice icon is enabled at all
751ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani    private boolean mVoiceEnabled;
761ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani    private boolean mIsAlphaKeyboard;
771ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani    private CharSequence m123Label;
783f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private boolean mCurrentlyInSpace;
793f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private SlidingLocaleDrawable mSlidingLocaleIcon;
803f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private Rect mBounds = new Rect();
811b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private int[] mPrefLetterFrequencies;
821b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private boolean mPreemptiveCorrection;
831b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private int mPrefLetter;
841b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private int mPrefLetterX;
851b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private int mPrefLetterY;
861b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private int mPrefDistance;
87358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani
88358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani    private int mExtensionResId;
89923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
90923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final int SHIFT_OFF = 0;
91923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final int SHIFT_ON = 1;
92923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final int SHIFT_LOCKED = 2;
93923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
94923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private int mShiftState = SHIFT_OFF;
956a001f58da80b18bf9c6c4baa1936033f2674710Amith Yamasani
963f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f;
971b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private static final float OVERLAP_PERCENTAGE_LOW_PROB = 0.70f;
981b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private static final float OVERLAP_PERCENTAGE_HIGH_PROB = 0.85f;
993f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
1006a001f58da80b18bf9c6c4baa1936033f2674710Amith Yamasani    static int sSpacebarVerticalCorrection;
1016a001f58da80b18bf9c6c4baa1936033f2674710Amith Yamasani
102923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public LatinKeyboard(Context context, int xmlLayoutResId) {
1031ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani        this(context, xmlLayoutResId, 0);
104923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
105923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1061ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani    public LatinKeyboard(Context context, int xmlLayoutResId, int mode) {
107923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        super(context, xmlLayoutResId, mode);
10836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        final Resources res = context.getResources();
1093f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mContext = context;
11036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        mMode = mode;
11136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        mRes = res;
1126a001f58da80b18bf9c6c4baa1936033f2674710Amith Yamasani        mShiftLockIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked);
1136a001f58da80b18bf9c6c4baa1936033f2674710Amith Yamasani        mShiftLockPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_shift_locked);
114923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mShiftLockPreviewIcon.setBounds(0, 0,
115923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftLockPreviewIcon.getIntrinsicWidth(),
116923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftLockPreviewIcon.getIntrinsicHeight());
11736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space);
1183f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mSpacePreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_space);
119b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani        mMicIcon = res.getDrawable(R.drawable.sym_keyboard_mic);
120b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani        mMicPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_mic);
121f892861b7bf87efbbdbed8f911a715ca1614829bAmith Yamasani        setDefaultBounds(mMicPreviewIcon);
1223f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mButtonArrowLeftIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_left);
1233f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mButtonArrowRightIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_right);
124cc03f196ad68fe564ec31199f0ffafa06caeccf3Amith Yamasani        m123MicIcon = res.getDrawable(R.drawable.sym_keyboard_123_mic);
125cc03f196ad68fe564ec31199f0ffafa06caeccf3Amith Yamasani        m123MicPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_123_mic);
126f892861b7bf87efbbdbed8f911a715ca1614829bAmith Yamasani        setDefaultBounds(m123MicPreviewIcon);
1276a001f58da80b18bf9c6c4baa1936033f2674710Amith Yamasani        sSpacebarVerticalCorrection = res.getDimensionPixelOffset(
1286a001f58da80b18bf9c6c4baa1936033f2674710Amith Yamasani                R.dimen.spacebar_vertical_correction);
1291ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani        mIsAlphaKeyboard = xmlLayoutResId == R.xml.kbd_qwerty;
1303f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mSpaceKeyIndex = indexOf((int) ' ');
131923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
132923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
133923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public LatinKeyboard(Context context, int layoutTemplateResId,
134923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            CharSequence characters, int columns, int horizontalPadding) {
135923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        super(context, layoutTemplateResId, characters, columns, horizontalPadding);
136923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
139923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
140923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            XmlResourceParser parser) {
141923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        Key key = new LatinKey(res, parent, x, y, parser);
14236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        switch (key.codes[0]) {
14336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        case 10:
144923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mEnterKey = key;
14536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            break;
14636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        case LatinKeyboardView.KEYCODE_F1:
14736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            mF1Key = key;
14836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            break;
14936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        case 32:
15036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            mSpaceKey = key;
15136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            break;
152cc03f196ad68fe564ec31199f0ffafa06caeccf3Amith Yamasani        case KEYCODE_MODE_CHANGE:
153cc03f196ad68fe564ec31199f0ffafa06caeccf3Amith Yamasani            m123Key = key;
1541ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani            m123Label = key.label;
155cc03f196ad68fe564ec31199f0ffafa06caeccf3Amith Yamasani            break;
156923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
157923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return key;
158923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
15936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
160923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    void setImeOptions(Resources res, int mode, int options) {
161923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mEnterKey != null) {
162923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            // Reset some of the rarely used attributes.
163923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mEnterKey.popupCharacters = null;
164923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mEnterKey.popupResId = 0;
165923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mEnterKey.text = null;
166923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            switch (options&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) {
167923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                case EditorInfo.IME_ACTION_GO:
168923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.iconPreview = null;
169923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.icon = null;
170923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.label = res.getText(R.string.label_go_key);
171923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
172923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                case EditorInfo.IME_ACTION_NEXT:
173923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.iconPreview = null;
174923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.icon = null;
175923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.label = res.getText(R.string.label_next_key);
176923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
177923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                case EditorInfo.IME_ACTION_DONE:
178923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.iconPreview = null;
179923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.icon = null;
180923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.label = res.getText(R.string.label_done_key);
181923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
182923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                case EditorInfo.IME_ACTION_SEARCH:
183923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.iconPreview = res.getDrawable(
184923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                            R.drawable.sym_keyboard_feedback_search);
185923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.icon = res.getDrawable(
186923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                            R.drawable.sym_keyboard_search);
187923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.label = null;
188923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
189923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                case EditorInfo.IME_ACTION_SEND:
190923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.iconPreview = null;
191923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.icon = null;
192923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mEnterKey.label = res.getText(R.string.label_send_key);
193923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
194923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                default:
195923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    if (mode == KeyboardSwitcher.MODE_IM) {
196923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        mEnterKey.icon = null;
197923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        mEnterKey.iconPreview = null;
198923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        mEnterKey.label = ":-)";
199923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        mEnterKey.text = ":-) ";
200923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        mEnterKey.popupResId = R.xml.popup_smileys;
201923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    } else {
202923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        mEnterKey.iconPreview = res.getDrawable(
203923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                                R.drawable.sym_keyboard_feedback_return);
204923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        mEnterKey.icon = res.getDrawable(
205923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                                R.drawable.sym_keyboard_return);
206923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        mEnterKey.label = null;
207923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    }
208923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
209923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
210923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            // Set the initial size of the preview icon
211923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (mEnterKey.iconPreview != null) {
212923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mEnterKey.iconPreview.setBounds(0, 0,
213923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        mEnterKey.iconPreview.getIntrinsicWidth(),
214923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        mEnterKey.iconPreview.getIntrinsicHeight());
215923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
216923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
217923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
218923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
219923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    void enableShiftLock() {
220923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        int index = getShiftKeyIndex();
221923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (index >= 0) {
222923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mShiftKey = getKeys().get(index);
223923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (mShiftKey instanceof LatinKey) {
224923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                ((LatinKey)mShiftKey).enableShiftLock();
225923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
226923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mOldShiftIcon = mShiftKey.icon;
227923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mOldShiftPreviewIcon = mShiftKey.iconPreview;
228923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
229923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
230923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
231923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    void setShiftLocked(boolean shiftLocked) {
232923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mShiftKey != null) {
233923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (shiftLocked) {
234923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftKey.on = true;
235923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftKey.icon = mShiftLockIcon;
236923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftState = SHIFT_LOCKED;
237923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            } else {
238923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftKey.on = false;
239923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftKey.icon = mShiftLockIcon;
240923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftState = SHIFT_ON;
241923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
243923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
244923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
245923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    boolean isShiftLocked() {
246923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return mShiftState == SHIFT_LOCKED;
247923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
248923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
249923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
250923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public boolean setShifted(boolean shiftState) {
251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        boolean shiftChanged = false;
252923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mShiftKey != null) {
253923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (shiftState == false) {
254923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                shiftChanged = mShiftState != SHIFT_OFF;
255923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftState = SHIFT_OFF;
256923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftKey.on = false;
257923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mShiftKey.icon = mOldShiftIcon;
258923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            } else {
259923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (mShiftState == SHIFT_OFF) {
260923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    shiftChanged = mShiftState == SHIFT_OFF;
261923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mShiftState = SHIFT_ON;
262923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mShiftKey.icon = mShiftLockIcon;
263923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
264923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
265923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        } else {
266923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return super.setShifted(shiftState);
267923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
268923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return shiftChanged;
269923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
27036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
271923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
272923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public boolean isShifted() {
273923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mShiftKey != null) {
274923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return mShiftState != SHIFT_OFF;
275923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        } else {
276923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return super.isShifted();
277923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
278923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
279923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
280358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani    public void setExtension(int resId) {
281358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani        mExtensionResId = resId;
282358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani    }
283358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani
284358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani    public int getExtension() {
285358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani        return mExtensionResId;
286358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani    }
287358e485b14938fbcb5af5be75aa29f2b73674100Amith Yamasani
288f892861b7bf87efbbdbed8f911a715ca1614829bAmith Yamasani    private void setDefaultBounds(Drawable drawable) {
289f892861b7bf87efbbdbed8f911a715ca1614829bAmith Yamasani        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
290f892861b7bf87efbbdbed8f911a715ca1614829bAmith Yamasani    }
291f892861b7bf87efbbdbed8f911a715ca1614829bAmith Yamasani
2921ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani    public void setVoiceMode(boolean hasVoiceButton, boolean hasVoice) {
2931ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani        mHasVoiceButton = hasVoiceButton;
2941ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani        mVoiceEnabled = hasVoice;
2951ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani        updateF1Key();
2961ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani    }
2971ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani
2981ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani    private void updateF1Key() {
299b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani        if (mF1Key == null) return;
3001ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani        if (m123Key != null && mIsAlphaKeyboard) {
3011ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani            if (mVoiceEnabled && !mHasVoiceButton) {
302cc03f196ad68fe564ec31199f0ffafa06caeccf3Amith Yamasani                m123Key.icon = m123MicIcon;
303cc03f196ad68fe564ec31199f0ffafa06caeccf3Amith Yamasani                m123Key.iconPreview = m123MicPreviewIcon;
304f892861b7bf87efbbdbed8f911a715ca1614829bAmith Yamasani                m123Key.label = null;
3051ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani            } else {
3061ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani                m123Key.icon = null;
3071ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani                m123Key.iconPreview = null;
3081ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani                m123Key.label = m123Label;
309cc03f196ad68fe564ec31199f0ffafa06caeccf3Amith Yamasani            }
3101ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani        }
3111ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani
3121ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani        if (mHasVoiceButton && mVoiceEnabled) {
313b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani            mF1Key.codes = new int[] { LatinKeyboardView.KEYCODE_VOICE };
314b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani            mF1Key.label = null;
315b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani            mF1Key.icon = mMicIcon;
316b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani            mF1Key.iconPreview = mMicPreviewIcon;
3171ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani        } else {
3181ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani            mF1Key.label = ",";
3191ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani            mF1Key.codes = new int[] { ',' };
3201ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani            mF1Key.icon = null;
3211ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani            mF1Key.iconPreview = null;
322b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani        }
3238eb2e34d5b2def57c9548f88e37e5c9e5a0bea59Amith Yamasani    }
3248eb2e34d5b2def57c9548f88e37e5c9e5a0bea59Amith Yamasani
3258eb2e34d5b2def57c9548f88e37e5c9e5a0bea59Amith Yamasani    private void updateSpaceBarForLocale() {
32636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        if (mLocale != null) {
32736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            // Create the graphic for spacebar
32836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            Bitmap buffer = Bitmap.createBitmap(mSpaceKey.width, mSpaceIcon.getIntrinsicHeight(),
32936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani                    Bitmap.Config.ARGB_8888);
33036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            Canvas canvas = new Canvas(buffer);
331676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani            drawSpaceBar(canvas, buffer.getWidth(), buffer.getHeight(), 255);
3328eb2e34d5b2def57c9548f88e37e5c9e5a0bea59Amith Yamasani            mSpaceKey.icon = new BitmapDrawable(mRes, buffer);
3333f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mSpaceKey.repeatable = mLanguageSwitcher.getLocaleCount() < 2;
33436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        } else {
33536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            mSpaceKey.icon = mRes.getDrawable(R.drawable.sym_keyboard_space);
3368eb2e34d5b2def57c9548f88e37e5c9e5a0bea59Amith Yamasani            mSpaceKey.repeatable = true;
33736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        }
33836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    }
33936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
340676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani    private void drawSpaceBar(Canvas canvas, int width, int height, int opacity) {
341676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
342676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        Paint paint = new Paint();
343676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        paint.setAntiAlias(true);
344676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        paint.setAlpha(opacity);
345676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        // Get the text size from the theme
346676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        paint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Small, 14));
347676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        paint.setTextAlign(Align.CENTER);
348676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        //// Draw a drop shadow for the text
349676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        //paint.setShadowLayer(2f, 0, 0, 0xFF000000);
350676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        final String language = getInputLanguage(mSpaceKey.width, paint);
351676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        final int ascent = (int) -paint.ascent();
352676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        paint.setColor(0x80000000);
353676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        canvas.drawText(language,
354676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani                width / 2, ascent - 1, paint);
355676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        paint.setColor(0xFF808080);
356676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        canvas.drawText(language,
357676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani                width / 2, ascent, paint);
358676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        // Put arrows on either side of the text
359676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        if (mLanguageSwitcher.getLocaleCount() > 1) {
360676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani            Rect bounds = new Rect();
361676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani            paint.getTextBounds(language, 0, language.length(), bounds);
362676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani            drawButtonArrow(mButtonArrowLeftIcon, canvas,
363676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani                    (mSpaceKey.width - bounds.right) / 2
364676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani                    - mButtonArrowLeftIcon.getIntrinsicWidth(),
365676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani                    (int) paint.getTextSize());
366676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani            drawButtonArrow(mButtonArrowRightIcon, canvas,
367676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani                    (mSpaceKey.width + bounds.right) / 2, (int) paint.getTextSize());
368676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        }
369676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        // Draw the spacebar icon at the bottom
370676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        int x = (width - mSpaceIcon.getIntrinsicWidth()) / 2;
371676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        int y = height - mSpaceIcon.getIntrinsicHeight();
372676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        mSpaceIcon.setBounds(x, y,
373676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani                x + mSpaceIcon.getIntrinsicWidth(), y + mSpaceIcon.getIntrinsicHeight());
374676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani        mSpaceIcon.draw(canvas);
375676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani    }
376676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani
3773f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private void drawButtonArrow(Drawable arrow, Canvas canvas, int x, int bottomY) {
3783f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        arrow.setBounds(x, bottomY - arrow.getIntrinsicHeight(), x + arrow.getIntrinsicWidth(),
3793f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                bottomY);
3803f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        arrow.draw(canvas);
3813f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
3823f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
3833f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private String getInputLanguage(int widthAvail, Paint paint) {
3843f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        return chooseDisplayName(mLanguageSwitcher.getInputLocale(), widthAvail, paint);
3853f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
3863f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
3873f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private String getNextInputLanguage(int widthAvail, Paint paint) {
3883f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        return chooseDisplayName(mLanguageSwitcher.getNextInputLocale(), widthAvail, paint);
3893f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
3903f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
3913f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private String getPrevInputLanguage(int widthAvail, Paint paint) {
3923f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        return chooseDisplayName(mLanguageSwitcher.getPrevInputLocale(), widthAvail, paint);
3933f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
3943f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
3953f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private String chooseDisplayName(Locale locale, int widthAvail, Paint paint) {
3963f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        if (widthAvail < (int) (.35 * getMinWidth())) {
397676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani            return LanguageSwitcher.toTitleCase(locale.getLanguage().substring(0, 2));
3983f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        } else {
399676fb5b665127f43b7062dfa5ebeb36b1e9f9280Amith Yamasani            return LanguageSwitcher.toTitleCase(locale.getDisplayLanguage(locale));
4003f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
4013f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
4023f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
4033f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private void updateLocaleDrag(int diff) {
4043f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        if (mSlidingLocaleIcon == null) {
4053f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mSlidingLocaleIcon = new SlidingLocaleDrawable(mSpacePreviewIcon, mSpaceKey.width,
4063f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mSpacePreviewIcon.getIntrinsicHeight());
4073f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mSlidingLocaleIcon.setBounds(0, 0, mSpaceKey.width,
4083f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mSpacePreviewIcon.getIntrinsicHeight());
4093f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mSpaceKey.iconPreview = mSlidingLocaleIcon;
4103f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
4113f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mSlidingLocaleIcon.setDiff(diff);
4123f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        if (Math.abs(diff) == Integer.MAX_VALUE) {
4133f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mSpaceKey.iconPreview = mSpacePreviewIcon;
4143f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        } else {
4153f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mSpaceKey.iconPreview = mSlidingLocaleIcon;
4163f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
4173f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mSpaceKey.iconPreview.invalidateSelf();
4183f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
4193f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
4203f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    public int getLanguageChangeDirection() {
4213f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        if (mSpaceKey == null || mLanguageSwitcher.getLocaleCount() < 2
4223f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                || Math.abs(mSpaceDragLastDiff) < mSpaceKey.width * SPACEBAR_DRAG_THRESHOLD ) {
4233f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            return 0; // No change
4243f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
4253f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        return mSpaceDragLastDiff > 0 ? 1 : -1;
4263f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
4273f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
4283f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    public void setLanguageSwitcher(LanguageSwitcher switcher) {
4293f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mLanguageSwitcher = switcher;
4303f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        Locale locale = mLanguageSwitcher.getLocaleCount() > 0
4313f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                ? mLanguageSwitcher.getInputLocale()
4323f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                : null;
433f02964264f196447b03a88591a2964b67c318718Amith Yamasani        // If the language count is 1 and is the same as the system language, don't show it.
434f02964264f196447b03a88591a2964b67c318718Amith Yamasani        if (locale != null
435f02964264f196447b03a88591a2964b67c318718Amith Yamasani                && mLanguageSwitcher.getLocaleCount() == 1
436f02964264f196447b03a88591a2964b67c318718Amith Yamasani                && mLanguageSwitcher.getSystemLocale().getLanguage()
437f02964264f196447b03a88591a2964b67c318718Amith Yamasani                   .equalsIgnoreCase(locale.getLanguage())) {
438f02964264f196447b03a88591a2964b67c318718Amith Yamasani            locale = null;
439f02964264f196447b03a88591a2964b67c318718Amith Yamasani        }
44036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        if (mLocale != null && mLocale.equals(locale)) return;
44136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        mLocale = locale;
4428eb2e34d5b2def57c9548f88e37e5c9e5a0bea59Amith Yamasani        updateSpaceBarForLocale();
44336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    }
44436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
4453f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    boolean isCurrentlyInSpace() {
4463f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        return mCurrentlyInSpace;
4473f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
4483f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
4491b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    void setPreferredLetters(int[] frequencies) {
4501b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        mPrefLetterFrequencies = frequencies;
4511b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        mPrefLetter = 0;
4521b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    }
4531b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani
4543f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    void keyReleased() {
4553f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mCurrentlyInSpace = false;
4563f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mSpaceDragLastDiff = 0;
4571b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        mPrefLetter = 0;
4581b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        mPrefLetterX = 0;
4591b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        mPrefLetterY = 0;
4601b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        mPrefDistance = Integer.MAX_VALUE;
4613f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        if (mSpaceKey != null) {
4623f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            updateLocaleDrag(Integer.MAX_VALUE);
4633f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
4643f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
4653f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
4663f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    /**
4673f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani     * Does the magic of locking the touch gesture into the spacebar when
4683f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani     * switching input languages.
4693f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani     */
4703f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    boolean isInside(LatinKey key, int x, int y) {
4713f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        final int code = key.codes[0];
4723f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        if (code == KEYCODE_SHIFT ||
4733f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                code == KEYCODE_DELETE) {
4743f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            y -= key.height / 10;
4753f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (code == KEYCODE_SHIFT) x += key.width / 6;
4763f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (code == KEYCODE_DELETE) x -= key.width / 6;
4773f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        } else if (code == LatinIME.KEYCODE_SPACE) {
4783f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            y += LatinKeyboard.sSpacebarVerticalCorrection;
4793f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (mLanguageSwitcher.getLocaleCount() > 1) {
4803f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                if (mCurrentlyInSpace) {
4813f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    int diff = x - mSpaceDragStartX;
4823f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    if (Math.abs(diff - mSpaceDragLastDiff) > 0) {
4833f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                        updateLocaleDrag(diff);
4843f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    }
4853f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mSpaceDragLastDiff = diff;
4863f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    return true;
4873f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                } else {
4883f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    boolean insideSpace = key.isInsideSuper(x, y);
4893f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    if (insideSpace) {
4903f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                        mCurrentlyInSpace = true;
4913f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                        mSpaceDragStartX = x;
4923f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                        updateLocaleDrag(0);
4933f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    }
4943f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    return insideSpace;
4953f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                }
4963f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            }
4971b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        } else if (mPrefLetterFrequencies != null) {
4981b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            // New coordinate? Reset
4991b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            if (mPrefLetterX != x || mPrefLetterY != y) {
5001b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                mPrefLetter = 0;
5011b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                mPrefDistance = Integer.MAX_VALUE;
5021b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            }
5031b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            // Handle preferred next letter
5041b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            final int[] pref = mPrefLetterFrequencies;
5051b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            if (mPrefLetter > 0) {
5061b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                if (DEBUG_PREFERRED_LETTER && mPrefLetter == code
5071b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        && !key.isInsideSuper(x, y)) {
5081b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                    Log.d(TAG, "CORRECTED !!!!!!");
5091b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                }
5101b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                return mPrefLetter == code;
5111b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            } else {
5121b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                final boolean inside = key.isInsideSuper(x, y);
5131b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                int[] nearby = getNearestKeys(x, y);
5141b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                List<Key> nearbyKeys = getKeys();
5151b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                if (inside) {
5161b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                    // If it's a preferred letter
5171b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                    if (inPrefList(code, pref)) {
5181b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        // Check if its frequency is much lower than a nearby key
5191b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        mPrefLetter = code;
5201b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        mPrefLetterX = x;
5211b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        mPrefLetterY = y;
5221b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        for (int i = 0; i < nearby.length; i++) {
5231b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                            Key k = nearbyKeys.get(nearby[i]);
5241b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                            if (k != key && inPrefList(k.codes[0], pref)) {
5251b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                final int dist = distanceFrom(k, x, y);
5261b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                if (dist < (int) (k.width * OVERLAP_PERCENTAGE_LOW_PROB) &&
5271b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                        (pref[k.codes[0]] > pref[mPrefLetter] * 3))  {
5281b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                    mPrefLetter = k.codes[0];
5291b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                    mPrefDistance = dist;
5301b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                    if (DEBUG_PREFERRED_LETTER) {
5311b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                        Log.d(TAG, "CORRECTED ALTHOUGH PREFERRED !!!!!!");
5321b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                    }
5331b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                    break;
5341b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                }
5351b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                            }
5361b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        }
5371b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani
5381b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        return mPrefLetter == code;
5391b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                    }
5401b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                }
5411b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani
5421b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                // Get the surrounding keys and intersect with the preferred list
5431b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                // For all in the intersection
5441b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                //   if distance from touch point is within a reasonable distance
5451b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                //       make this the pref letter
5461b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                // If no pref letter
5471b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                //   return inside;
5481b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                // else return thiskey == prefletter;
5491b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani
5501b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                for (int i = 0; i < nearby.length; i++) {
5511b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                    Key k = nearbyKeys.get(nearby[i]);
5521b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                    if (inPrefList(k.codes[0], pref)) {
5531b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        final int dist = distanceFrom(k, x, y);
5541b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        if (dist < (int) (k.width * OVERLAP_PERCENTAGE_HIGH_PROB)
5551b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                                && dist < mPrefDistance)  {
5561b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                            mPrefLetter = k.codes[0];
5571b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                            mPrefLetterX = x;
5581b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                            mPrefLetterY = y;
5591b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                            mPrefDistance = dist;
5601b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                        }
5611b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                    }
5621b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                }
5631b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                // Didn't find any
5641b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                if (mPrefLetter == 0) {
5651b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                    return inside;
5661b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                } else {
5671b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                    return mPrefLetter == code;
5681b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani                }
5691b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            }
5703f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
5713f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
5723f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        // Lock into the spacebar
5733f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        if (mCurrentlyInSpace) return false;
5743f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
5753f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        return key.isInsideSuper(x, y);
5763f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
5773f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
5781b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private boolean inPrefList(int code, int[] pref) {
5791b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        if (code < pref.length && code >= 0) return pref[code] > 0;
5801b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        return false;
5811b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    }
5821b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani
5831b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    private int distanceFrom(Key k, int x, int y) {
5841b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        if (y > k.y && y < k.y + k.height) {
5851b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            return Math.abs(k.x + k.width / 2 - x);
5861b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        } else {
5871b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            return Integer.MAX_VALUE;
5881b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        }
5891b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani    }
5901b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani
5913f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    @Override
5923f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    public int[] getNearestKeys(int x, int y) {
5933f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        if (mCurrentlyInSpace) {
5943f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            return new int[] { mSpaceKeyIndex };
5953f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        } else {
5963f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            return super.getNearestKeys(x, y);
5973f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
5983f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
5993f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
6003f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private int indexOf(int code) {
6013f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        List<Key> keys = getKeys();
6023f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        int count = keys.size();
6033f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        for (int i = 0; i < count; i++) {
6043f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (keys.get(i).codes[0] == code) return i;
6053f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
6063f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        return -1;
6073f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
6083f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
6093f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private int getTextSizeFromTheme(int style, int defValue) {
6103f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        TypedArray array = mContext.getTheme().obtainStyledAttributes(
6113f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                style, new int[] { android.R.attr.textSize });
6123f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
6133f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        return textSize;
6143f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
6153f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
6163f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    class LatinKey extends Keyboard.Key {
617923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
618923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        private boolean mShiftLockEnabled;
619923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
620923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        public LatinKey(Resources res, Keyboard.Row parent, int x, int y,
621923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                XmlResourceParser parser) {
622923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            super(res, parent, x, y, parser);
623808202b60fca5615220c98fbf0672bb34f32c1bbAmith Yamasani            if (popupCharacters != null && popupCharacters.length() == 0) {
624808202b60fca5615220c98fbf0672bb34f32c1bbAmith Yamasani                // If there is a keyboard with no keys specified in popupCharacters
625808202b60fca5615220c98fbf0672bb34f32c1bbAmith Yamasani                popupResId = 0;
626808202b60fca5615220c98fbf0672bb34f32c1bbAmith Yamasani            }
627923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
628923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
629923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        void enableShiftLock() {
630923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mShiftLockEnabled = true;
631923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
632923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
633923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        @Override
634923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        public void onReleased(boolean inside) {
635923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (!mShiftLockEnabled) {
636923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                super.onReleased(inside);
637923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            } else {
638923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                pressed = !pressed;
639923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
640923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
6415e8a2fc5d5661eda6c2eee34b339705544403a49Amith Yamasani
642923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        /**
643923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project         * Overriding this method so that we can reduce the target area for certain keys.
644923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project         */
645923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        @Override
646923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        public boolean isInside(int x, int y) {
6471b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            boolean result = LatinKeyboard.this.isInside(this, x, y);
6481b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani            return result;
6493f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
6503f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
6513f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        boolean isInsideSuper(int x, int y) {
652923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return super.isInside(x, y);
653923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
654923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
6553f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
6563f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    /**
6573f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani     * Animation to be displayed on the spacebar preview popup when switching
6583f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani     * languages by swiping the spacebar. It draws the current, previous and
6593f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani     * next languages and moves them by the delta of touch movement on the spacebar.
6603f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani     */
6613f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    class SlidingLocaleDrawable extends Drawable {
6623f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
6633f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private int mWidth;
6643f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private int mHeight;
6653f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private Drawable mBackground;
6663f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private int mDiff;
6673f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private TextPaint mTextPaint;
6683f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private int mMiddleX;
6693f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private int mAscent;
6703f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private Drawable mLeftDrawable;
6713f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private Drawable mRightDrawable;
6723f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private boolean mHitThreshold;
6733f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private int     mThreshold;
6743f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private String mCurrentLanguage;
6753f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private String mNextLanguage;
6763f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        private String mPrevLanguage;
6773f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
6783f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        public SlidingLocaleDrawable(Drawable background, int width, int height) {
6793f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mBackground = background;
6803f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mBackground.setBounds(0, 0,
6813f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mBackground.getIntrinsicWidth(), mBackground.getIntrinsicHeight());
6823f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mWidth = width;
6833f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mHeight = height;
6843f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mTextPaint = new TextPaint();
6853f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            int textSize = getTextSizeFromTheme(android.R.style.TextAppearance_Medium, 18);
6863f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mTextPaint.setTextSize(textSize);
6873f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mTextPaint.setColor(0);
6883f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mTextPaint.setTextAlign(Align.CENTER);
6893f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mTextPaint.setAlpha(255);
6903f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mTextPaint.setAntiAlias(true);
6913f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mAscent = (int) mTextPaint.ascent();
6923f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2;
6933f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mLeftDrawable =
6943f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mRes.getDrawable(R.drawable.sym_keyboard_feedback_language_arrows_left);
6953f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mRightDrawable =
6963f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mRes.getDrawable(R.drawable.sym_keyboard_feedback_language_arrows_right);
6973f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mLeftDrawable.setBounds(0, 0,
6983f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mLeftDrawable.getIntrinsicWidth(), mLeftDrawable.getIntrinsicHeight());
6993f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mRightDrawable.setBounds(mWidth - mRightDrawable.getIntrinsicWidth(), 0,
7003f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mWidth, mRightDrawable.getIntrinsicHeight());
7013f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mThreshold = ViewConfiguration.get(mContext).getScaledTouchSlop();
7023f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
7033f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
7043f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        void setDiff(int diff) {
7053f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (diff == Integer.MAX_VALUE) {
7063f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                mHitThreshold = false;
7073f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                mCurrentLanguage = null;
7083f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                return;
7093f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            }
7103f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mDiff = diff;
7113f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (mDiff > mWidth) mDiff = mWidth;
7123f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (mDiff < -mWidth) mDiff = -mWidth;
7133f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (Math.abs(mDiff) > mThreshold) mHitThreshold = true;
7143f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            invalidateSelf();
7153f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
7163f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
7173f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        @Override
7183f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        public void draw(Canvas canvas) {
7193f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            canvas.save();
7203f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (mHitThreshold) {
721cc03f196ad68fe564ec31199f0ffafa06caeccf3Amith Yamasani                mTextPaint.setColor(0xFF000000);
7223f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                canvas.clipRect(0, 0, mWidth, mHeight);
7233f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                if (mCurrentLanguage == null) {
7243f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mCurrentLanguage = getInputLanguage(mWidth, mTextPaint);
7253f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mNextLanguage = getNextInputLanguage(mWidth, mTextPaint);
7263f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                    mPrevLanguage = getPrevInputLanguage(mWidth, mTextPaint);
7273f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                }
7283f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                canvas.drawText(mCurrentLanguage,
7293f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                        mWidth / 2 + mDiff, -mAscent + 4, mTextPaint);
7303f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                canvas.drawText(mNextLanguage,
7313f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                        mDiff - mWidth / 2, -mAscent + 4, mTextPaint);
7323f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                canvas.drawText(mPrevLanguage,
7333f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                        mDiff + mWidth + mWidth / 2, -mAscent + 4, mTextPaint);
7343f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                mLeftDrawable.draw(canvas);
7353f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                mRightDrawable.draw(canvas);
7363f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            }
7373f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (mBackground != null) {
7383f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                canvas.translate(mMiddleX, 0);
7393f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                mBackground.draw(canvas);
7403f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            }
7413f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            canvas.restore();
7423f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
7433f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
7443f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        @Override
7453f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        public int getOpacity() {
7463f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            return PixelFormat.TRANSLUCENT;
7473f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
7483f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
7493f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        @Override
7503f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        public void setAlpha(int alpha) {
7513f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            // Ignore
7523f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
7533f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
7543f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        @Override
7553f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        public void setColorFilter(ColorFilter cf) {
7563f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            // Ignore
7573f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
7583f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
7593f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        @Override
7603f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        public int getIntrinsicWidth() {
7613f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            return mWidth;
7623f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
7633f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani
7643f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        @Override
7653f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        public int getIntrinsicHeight() {
7663f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            return mHeight;
7673f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
7683f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    }
769923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project}
770