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