aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/inputmethod/latin/KeyboardSwitcher.java14
-rw-r--r--src/com/android/inputmethod/latin/LanguageSwitcher.java165
-rw-r--r--src/com/android/inputmethod/latin/LatinIME.java82
-rw-r--r--src/com/android/inputmethod/latin/LatinKeyboard.java319
-rw-r--r--src/com/android/inputmethod/latin/LatinKeyboardView.java35
-rw-r--r--src/com/android/inputmethod/latin/TextEntryState.java1
6 files changed, 534 insertions, 82 deletions
diff --git a/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/src/com/android/inputmethod/latin/KeyboardSwitcher.java
index ea473f223..0ebfe4a9a 100644
--- a/src/com/android/inputmethod/latin/KeyboardSwitcher.java
+++ b/src/com/android/inputmethod/latin/KeyboardSwitcher.java
@@ -77,6 +77,7 @@ public class KeyboardSwitcher {
private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
private int mLastDisplayWidth;
+ private LanguageSwitcher mLanguageSwitcher;
private Locale mInputLocale;
private boolean mEnableMultipleLanguages;
@@ -94,9 +95,10 @@ public class KeyboardSwitcher {
* @param locale the current input locale, or null for default locale with no locale
* button.
*/
- void setInputLocale(Locale locale, boolean enableMultipleLanguages) {
- mInputLocale = locale;
- mEnableMultipleLanguages = enableMultipleLanguages;
+ void setLanguageSwitcher(LanguageSwitcher languageSwitcher) {
+ mLanguageSwitcher = languageSwitcher;
+ mInputLocale = mLanguageSwitcher.getInputLocale();
+ mEnableMultipleLanguages = mLanguageSwitcher.getLocaleCount() > 1;
}
void setInputView(LatinKeyboardView inputView) {
@@ -195,11 +197,6 @@ public class KeyboardSwitcher {
}
mCurrentId = id;
- if (mEnableMultipleLanguages) {
- keyboard.setLanguage(mInputLocale);
- } else {
- keyboard.setLanguage(null);
- }
mInputView.setKeyboard(keyboard);
keyboard.setShifted(false);
keyboard.setShiftLocked(keyboard.isShiftLocked());
@@ -215,6 +212,7 @@ public class KeyboardSwitcher {
orig.updateConfiguration(conf, null);
LatinKeyboard keyboard = new LatinKeyboard(
mContext, id.mXml, id.mKeyboardMode, id.mHasVoice);
+ keyboard.setLanguageSwitcher(mLanguageSwitcher);
if (id.mKeyboardMode == KEYBOARDMODE_NORMAL
|| id.mKeyboardMode == KEYBOARDMODE_URL
|| id.mKeyboardMode == KEYBOARDMODE_IM
diff --git a/src/com/android/inputmethod/latin/LanguageSwitcher.java b/src/com/android/inputmethod/latin/LanguageSwitcher.java
new file mode 100644
index 000000000..97173533d
--- /dev/null
+++ b/src/com/android/inputmethod/latin/LanguageSwitcher.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import java.util.Locale;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.preference.PreferenceManager;
+
+/**
+ * Keeps track of list of selected input languages and the current
+ * input language that the user has selected.
+ */
+public class LanguageSwitcher {
+
+ private Locale[] mLocales;
+ private LatinIME mIme;
+ private String[] mSelectedLanguageArray;
+ private String mSelectedLanguages;
+ private int mCurrentIndex = 0;
+ private String mDefaultInputLanguage;
+ private Locale mDefaultInputLocale;
+
+ public LanguageSwitcher(LatinIME ime) {
+ mIme = ime;
+ mLocales = new Locale[0];
+ }
+
+ public Locale[] getLocales() {
+ return mLocales;
+ }
+
+ public int getLocaleCount() {
+ return mLocales.length;
+ }
+
+ /**
+ * Loads the currently selected input languages from shared preferences.
+ * @param sp
+ * @return whether there was any change
+ */
+ public boolean loadLocales(SharedPreferences sp) {
+ String selectedLanguages = sp.getString(LatinIME.PREF_SELECTED_LANGUAGES, null);
+ String currentLanguage = sp.getString(LatinIME.PREF_INPUT_LANGUAGE, null);
+ if (selectedLanguages == null || selectedLanguages.length() < 1) {
+ loadDefaults();
+ if (mLocales.length == 0) {
+ return false;
+ }
+ mLocales = new Locale[0];
+ return true;
+ }
+ if (selectedLanguages.equals(mSelectedLanguages)) {
+ return false;
+ }
+ mSelectedLanguageArray = selectedLanguages.split(",");
+ mSelectedLanguages = selectedLanguages; // Cache it for comparison later
+ constructLocales();
+ mCurrentIndex = 0;
+ if (currentLanguage != null) {
+ // Find the index
+ mCurrentIndex = 0;
+ for (int i = 0; i < mLocales.length; i++) {
+ if (mSelectedLanguageArray[i].equals(currentLanguage)) {
+ mCurrentIndex = i;
+ break;
+ }
+ }
+ // If we didn't find the index, use the first one
+ }
+ return true;
+ }
+
+ private void loadDefaults() {
+ mDefaultInputLocale = mIme.getResources().getConfiguration().locale;
+ mDefaultInputLanguage = mDefaultInputLocale.getLanguage() + "_"
+ + mDefaultInputLocale.getCountry();
+ }
+
+ private void constructLocales() {
+ mLocales = new Locale[mSelectedLanguageArray.length];
+ for (int i = 0; i < mLocales.length; i++) {
+ mLocales[i] = new Locale(mSelectedLanguageArray[i]);
+ }
+ }
+
+ /**
+ * Returns the currently selected input language code, or the display language code if
+ * no specific locale was selected for input.
+ */
+ public String getInputLanguage() {
+ if (getLocaleCount() == 0) return mDefaultInputLanguage;
+
+ return mSelectedLanguageArray[mCurrentIndex];
+ }
+
+ /**
+ * Returns the currently selected input locale, or the display locale if no specific
+ * locale was selected for input.
+ * @return
+ */
+ public Locale getInputLocale() {
+ if (getLocaleCount() == 0) return mDefaultInputLocale;
+
+ return mLocales[mCurrentIndex];
+ }
+
+ /**
+ * Returns the next input locale in the list. Wraps around to the beginning of the
+ * list if we're at the end of the list.
+ * @return
+ */
+ public Locale getNextInputLocale() {
+ if (getLocaleCount() == 0) return mDefaultInputLocale;
+
+ return mLocales[(mCurrentIndex + 1) % mLocales.length];
+ }
+
+ /**
+ * Returns the previous input locale in the list. Wraps around to the end of the
+ * list if we're at the beginning of the list.
+ * @return
+ */
+ public Locale getPrevInputLocale() {
+ if (getLocaleCount() == 0) return mDefaultInputLocale;
+
+ return mLocales[(mCurrentIndex - 1 + mLocales.length) % mLocales.length];
+ }
+
+ public void reset() {
+ mCurrentIndex = 0;
+ }
+
+ public void next() {
+ mCurrentIndex++;
+ if (mCurrentIndex >= mLocales.length) mCurrentIndex = 0; // Wrap around
+ }
+
+ public void prev() {
+ mCurrentIndex--;
+ if (mCurrentIndex < 0) mCurrentIndex = mLocales.length - 1; // Wrap around
+ }
+
+ public void persist() {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mIme);
+ Editor editor = sp.edit();
+ editor.putString(LatinIME.PREF_INPUT_LANGUAGE, getInputLanguage());
+ editor.commit();
+ }
+}
diff --git a/src/com/android/inputmethod/latin/LatinIME.java b/src/com/android/inputmethod/latin/LatinIME.java
index 8056030f6..ee525b495 100644
--- a/src/com/android/inputmethod/latin/LatinIME.java
+++ b/src/com/android/inputmethod/latin/LatinIME.java
@@ -178,6 +178,7 @@ public class LatinIME extends InputMethodService
Resources mResources;
private String mLocale;
+ private LanguageSwitcher mLanguageSwitcher;
private StringBuilder mComposing = new StringBuilder();
private WordComposer mWord = new WordComposer();
@@ -244,10 +245,6 @@ public class LatinIME extends InputMethodService
List<String> candidates;
Map<String, List<CharSequence>> alternatives;
}
- private int mCurrentInputLocale = 0;
- private String mInputLanguage;
- private String[] mSelectedLanguageArray;
- private String mSelectedLanguagesList;
private boolean mRefreshKeyboardRequired;
Handler mHandler = new Handler() {
@@ -285,18 +282,19 @@ public class LatinIME extends InputMethodService
@Override public void onCreate() {
super.onCreate();
//setStatusIcon(R.drawable.ime_qwerty);
- mKeyboardSwitcher = new KeyboardSwitcher(this, this);
mResources = getResources();
final Configuration conf = mResources.getConfiguration();
- mInputLanguage = getPersistedInputLanguage();
- mSelectedLanguagesList = getSelectedInputLanguages();
- boolean enableMultipleLanguages = mSelectedLanguagesList != null
- && mSelectedLanguagesList.split(",").length > 1;
- if (mInputLanguage == null) {
- mInputLanguage = conf.locale.toString();
- }
- initSuggest(mInputLanguage);
- mKeyboardSwitcher.setInputLocale(conf.locale, enableMultipleLanguages);
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ mLanguageSwitcher = new LanguageSwitcher(this);
+ mLanguageSwitcher.loadLocales(prefs);
+ mKeyboardSwitcher = new KeyboardSwitcher(this, this);
+ mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher);
+ boolean enableMultipleLanguages = mLanguageSwitcher.getLocaleCount() > 0;
+ String inputLanguage = mLanguageSwitcher.getInputLanguage();
+ if (inputLanguage == null) {
+ inputLanguage = conf.locale.toString();
+ }
+ initSuggest(inputLanguage);
mOrientation = conf.orientation;
mVibrateDuration = mResources.getInteger(R.integer.vibrate_duration_ms);
@@ -317,8 +315,7 @@ public class LatinIME extends InputMethodService
}
});
}
- PreferenceManager.getDefaultSharedPreferences(this)
- .registerOnSharedPreferenceChangeListener(this);
+ prefs.registerOnSharedPreferenceChangeListener(this);
}
private void initSuggest(String locale) {
@@ -429,7 +426,7 @@ public class LatinIME extends InputMethodService
if (mRefreshKeyboardRequired) {
mRefreshKeyboardRequired = false;
- toggleLanguage(true);
+ toggleLanguage(true, true);
}
mKeyboardSwitcher.makeKeyboards(false);
@@ -791,8 +788,7 @@ public class LatinIME extends InputMethodService
if (mKeyboardSwitcher == null) {
mKeyboardSwitcher = new KeyboardSwitcher(this, this);
}
- mKeyboardSwitcher.setInputLocale(new Locale(mInputLanguage),
- getSelectedInputLanguages() != null);
+ mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher);
if (mInputView != null) {
mKeyboardSwitcher.setVoiceMode(mEnableVoice, mVoiceOnPrimary);
}
@@ -919,7 +915,10 @@ public class LatinIME extends InputMethodService
showOptionsMenu();
break;
case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
- toggleLanguage(false);
+ toggleLanguage(false, true);
+ break;
+ case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
+ toggleLanguage(false, false);
break;
case LatinKeyboardView.KEYCODE_SHIFT_LONGPRESS:
if (mCapsLock) {
@@ -1514,27 +1513,30 @@ public class LatinIME extends InputMethodService
}
}
- private void toggleLanguage(boolean reset) {
- final String [] languages = mSelectedLanguageArray;
- if (reset) mCurrentInputLocale = -1;
- mCurrentInputLocale = (mCurrentInputLocale + 1)
- % (languages != null ? languages.length : 1);
- mInputLanguage = languages != null ? languages[mCurrentInputLocale] :
- getResources().getConfiguration().locale.getLanguage();
+ private void toggleLanguage(boolean reset, boolean next) {
+ if (reset) {
+ mLanguageSwitcher.reset();
+ } else {
+ if (next) {
+ mLanguageSwitcher.next();
+ } else {
+ mLanguageSwitcher.prev();
+ }
+ }
int currentKeyboardMode = mKeyboardSwitcher.getKeyboardMode();
reloadKeyboards();
mKeyboardSwitcher.makeKeyboards(true);
mKeyboardSwitcher.setKeyboardMode(currentKeyboardMode, 0,
mEnableVoiceButton && mEnableVoice);
- initSuggest(mInputLanguage);
- persistInputLanguage(mInputLanguage);
+ initSuggest(mLanguageSwitcher.getInputLanguage());
+ mLanguageSwitcher.persist();
updateShiftKeyState(getCurrentInputEditorInfo());
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (PREF_SELECTED_LANGUAGES.equals(key)) {
- updateSelectedLanguages(sharedPreferences.getString(key, null));
+ mLanguageSwitcher.loadLocales(sharedPreferences);
mRefreshKeyboardRequired = true;
}
}
@@ -1556,6 +1558,8 @@ public class LatinIME extends InputMethodService
}
public void onRelease(int primaryCode) {
+ // Reset any drag flags in the keyboard
+ ((LatinKeyboard) mInputView.getKeyboard()).keyReleased();
//vibrate();
}
@@ -1750,16 +1754,7 @@ public class LatinIME extends InputMethodService
mAutoCorrectEnabled = sp.getBoolean(PREF_AUTO_COMPLETE,
mResources.getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions;
updateCorrectionMode();
- String languageList = sp.getString(PREF_SELECTED_LANGUAGES, null);
- updateSelectedLanguages(languageList);
- }
-
- private void updateSelectedLanguages(String languageList) {
- if (languageList != null && languageList.length() > 1) {
- mSelectedLanguageArray = languageList.split(",");
- } else {
- mSelectedLanguageArray = null;
- }
+ mLanguageSwitcher.loadLocales(sp);
}
private String getPersistedInputLanguage() {
@@ -1767,13 +1762,6 @@ public class LatinIME extends InputMethodService
return sp.getString(PREF_INPUT_LANGUAGE, null);
}
- private void persistInputLanguage(String inputLanguage) {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
- Editor editor = sp.edit();
- editor.putString(PREF_INPUT_LANGUAGE, inputLanguage);
- editor.commit();
- }
-
private String getSelectedInputLanguages() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
return sp.getString(PREF_SELECTED_LANGUAGES, null);
diff --git a/src/com/android/inputmethod/latin/LatinKeyboard.java b/src/com/android/inputmethod/latin/LatinKeyboard.java
index f876af709..92f93b39c 100644
--- a/src/com/android/inputmethod/latin/LatinKeyboard.java
+++ b/src/com/android/inputmethod/latin/LatinKeyboard.java
@@ -16,19 +16,26 @@
package com.android.inputmethod.latin;
+import java.util.List;
import java.util.Locale;
import android.content.Context;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.ColorFilter;
import android.graphics.Paint;
+import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
+import android.graphics.Rect;
import android.graphics.Paint.Align;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.Keyboard;
+import android.text.TextPaint;
+import android.view.ViewConfiguration;
import android.view.inputmethod.EditorInfo;
public class LatinKeyboard extends Keyboard {
@@ -38,18 +45,29 @@ public class LatinKeyboard extends Keyboard {
private Drawable mOldShiftIcon;
private Drawable mOldShiftPreviewIcon;
private Drawable mSpaceIcon;
+ private Drawable mSpacePreviewIcon;
private Drawable mMicIcon;
private Drawable mMicPreviewIcon;
private Drawable m123MicIcon;
private Drawable m123MicPreviewIcon;
+ private Drawable mButtonArrowLeftIcon;
+ private Drawable mButtonArrowRightIcon;
private Key mShiftKey;
private Key mEnterKey;
private Key mF1Key;
private Key mSpaceKey;
+ private int mSpaceKeyIndex = -1;
+ private int mSpaceDragStartX;
+ private int mSpaceDragLastDiff;
/* package */ Locale mLocale;
+ private LanguageSwitcher mLanguageSwitcher;
private Resources mRes;
+ private Context mContext;
private int mMode;
private boolean mHasVoice;
+ private boolean mCurrentlyInSpace;
+ private SlidingLocaleDrawable mSlidingLocaleIcon;
+ private Rect mBounds = new Rect();
private int mExtensionResId;
@@ -59,6 +77,8 @@ public class LatinKeyboard extends Keyboard {
private int mShiftState = SHIFT_OFF;
+ private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f;
+
static int sSpacebarVerticalCorrection;
public LatinKeyboard(Context context, int xmlLayoutResId) {
@@ -68,6 +88,7 @@ public class LatinKeyboard extends Keyboard {
public LatinKeyboard(Context context, int xmlLayoutResId, int mode, boolean hasVoice) {
super(context, xmlLayoutResId, mode);
final Resources res = context.getResources();
+ mContext = context;
mMode = mode;
mRes = res;
mHasVoice = hasVoice;
@@ -77,11 +98,15 @@ public class LatinKeyboard extends Keyboard {
mShiftLockPreviewIcon.getIntrinsicWidth(),
mShiftLockPreviewIcon.getIntrinsicHeight());
mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space);
+ mSpacePreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_space);
mMicIcon = res.getDrawable(R.drawable.sym_keyboard_mic);
mMicPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_mic);
+ mButtonArrowLeftIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_left);
+ mButtonArrowRightIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_right);
sSpacebarVerticalCorrection = res.getDimensionPixelOffset(
R.dimen.spacebar_vertical_correction);
setF1Key();
+ mSpaceKeyIndex = indexOf((int) ' ');
}
public LatinKeyboard(Context context, int layoutTemplateResId,
@@ -237,7 +262,6 @@ public class LatinKeyboard extends Keyboard {
private void setF1Key() {
if (mF1Key == null) return;
- System.err.println("Setting F1 key");
if (!mHasVoice) {
mF1Key.label = ",";
mF1Key.codes = new int[] { ',' };
@@ -260,34 +284,179 @@ public class LatinKeyboard extends Keyboard {
canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
Paint paint = new Paint();
paint.setAntiAlias(true);
- // TODO: Make the text size a customizable attribute
- paint.setTextSize(18);
+ // Get the text size from the theme
+ paint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Small, 14));
paint.setTextAlign(Align.CENTER);
// Draw a drop shadow for the text
- paint.setShadowLayer(1f, 0, 0, 0xFF000000);
+ paint.setShadowLayer(2f, 0, 0, 0xFF000000);
paint.setColor(0xFF808080);
- canvas.drawText(mLocale.getDisplayLanguage(mLocale),
- buffer.getWidth() / 2, - paint.ascent() + 2, paint);
+ final String language = getInputLanguage(mSpaceKey.width, paint);
+ final int ascent = (int) -paint.ascent();
+ canvas.drawText(language,
+ buffer.getWidth() / 2, ascent, paint);
+ // Put arrows on either side of the text
+ if (mLanguageSwitcher.getLocaleCount() > 1) {
+ Rect bounds = new Rect();
+ paint.getTextBounds(language, 0, language.length(), bounds);
+ drawButtonArrow(mButtonArrowLeftIcon, canvas,
+ (mSpaceKey.width - bounds.right) / 2
+ - mButtonArrowLeftIcon.getIntrinsicWidth(),
+ (int) paint.getTextSize());
+ drawButtonArrow(mButtonArrowRightIcon, canvas,
+ (mSpaceKey.width + bounds.right) / 2, (int) paint.getTextSize());
+ }
+ // Draw the spacebar icon at the bottom
int x = (buffer.getWidth() - mSpaceIcon.getIntrinsicWidth()) / 2;
int y = buffer.getHeight() - mSpaceIcon.getIntrinsicHeight();
mSpaceIcon.setBounds(x, y,
x + mSpaceIcon.getIntrinsicWidth(), y + mSpaceIcon.getIntrinsicHeight());
mSpaceIcon.draw(canvas);
mSpaceKey.icon = new BitmapDrawable(mRes, buffer);
- mSpaceKey.repeatable = false;
+ mSpaceKey.repeatable = mLanguageSwitcher.getLocaleCount() < 2;
} else {
mSpaceKey.icon = mRes.getDrawable(R.drawable.sym_keyboard_space);
mSpaceKey.repeatable = true;
}
}
- public void setLanguage(Locale locale) {
+ private void drawButtonArrow(Drawable arrow, Canvas canvas, int x, int bottomY) {
+ arrow.setBounds(x, bottomY - arrow.getIntrinsicHeight(), x + arrow.getIntrinsicWidth(),
+ bottomY);
+ arrow.draw(canvas);
+ }
+
+ private String getInputLanguage(int widthAvail, Paint paint) {
+ return chooseDisplayName(mLanguageSwitcher.getInputLocale(), widthAvail, paint);
+ }
+
+ private String getNextInputLanguage(int widthAvail, Paint paint) {
+ return chooseDisplayName(mLanguageSwitcher.getNextInputLocale(), widthAvail, paint);
+ }
+
+ private String getPrevInputLanguage(int widthAvail, Paint paint) {
+ return chooseDisplayName(mLanguageSwitcher.getPrevInputLocale(), widthAvail, paint);
+ }
+
+ private String chooseDisplayName(Locale locale, int widthAvail, Paint paint) {
+ if (widthAvail < (int) (.35 * getMinWidth())) {
+ return locale.getLanguage().substring(0, 2).toUpperCase(locale);
+ } else {
+ return locale.getDisplayLanguage(locale);
+ }
+ }
+
+ private void updateLocaleDrag(int diff) {
+ if (mSlidingLocaleIcon == null) {
+ mSlidingLocaleIcon = new SlidingLocaleDrawable(mSpacePreviewIcon, mSpaceKey.width,
+ mSpacePreviewIcon.getIntrinsicHeight());
+ mSlidingLocaleIcon.setBounds(0, 0, mSpaceKey.width,
+ mSpacePreviewIcon.getIntrinsicHeight());
+ mSpaceKey.iconPreview = mSlidingLocaleIcon;
+ }
+ mSlidingLocaleIcon.setDiff(diff);
+ if (Math.abs(diff) == Integer.MAX_VALUE) {
+ mSpaceKey.iconPreview = mSpacePreviewIcon;
+ } else {
+ mSpaceKey.iconPreview = mSlidingLocaleIcon;
+ }
+ mSpaceKey.iconPreview.invalidateSelf();
+ }
+
+ public int getLanguageChangeDirection() {
+ if (mSpaceKey == null || mLanguageSwitcher.getLocaleCount() < 2
+ || Math.abs(mSpaceDragLastDiff) < mSpaceKey.width * SPACEBAR_DRAG_THRESHOLD ) {
+ return 0; // No change
+ }
+ return mSpaceDragLastDiff > 0 ? 1 : -1;
+ }
+
+ public void setLanguageSwitcher(LanguageSwitcher switcher) {
+ mLanguageSwitcher = switcher;
+ Locale locale = mLanguageSwitcher.getLocaleCount() > 0
+ ? mLanguageSwitcher.getInputLocale()
+ : null;
if (mLocale != null && mLocale.equals(locale)) return;
mLocale = locale;
updateSpaceBarForLocale();
}
- static class LatinKey extends Keyboard.Key {
+ boolean isCurrentlyInSpace() {
+ return mCurrentlyInSpace;
+ }
+
+ void keyReleased() {
+ mCurrentlyInSpace = false;
+ mSpaceDragLastDiff = 0;
+ if (mSpaceKey != null) {
+ updateLocaleDrag(Integer.MAX_VALUE);
+ }
+ }
+
+ /**
+ * Does the magic of locking the touch gesture into the spacebar when
+ * switching input languages.
+ */
+ boolean isInside(LatinKey key, int x, int y) {
+ final int code = key.codes[0];
+ if (code == KEYCODE_SHIFT ||
+ code == KEYCODE_DELETE) {
+ y -= key.height / 10;
+ if (code == KEYCODE_SHIFT) x += key.width / 6;
+ if (code == KEYCODE_DELETE) x -= key.width / 6;
+ } else if (code == LatinIME.KEYCODE_SPACE) {
+ y += LatinKeyboard.sSpacebarVerticalCorrection;
+ if (mLanguageSwitcher.getLocaleCount() > 1) {
+ if (mCurrentlyInSpace) {
+ int diff = x - mSpaceDragStartX;
+ if (Math.abs(diff - mSpaceDragLastDiff) > 0) {
+ updateLocaleDrag(diff);
+ }
+ mSpaceDragLastDiff = diff;
+ return true;
+ } else {
+ boolean insideSpace = key.isInsideSuper(x, y);
+ if (insideSpace) {
+ mCurrentlyInSpace = true;
+ mSpaceDragStartX = x;
+ updateLocaleDrag(0);
+ }
+ return insideSpace;
+ }
+ }
+ }
+
+ // Lock into the spacebar
+ if (mCurrentlyInSpace) return false;
+
+ return key.isInsideSuper(x, y);
+ }
+
+ @Override
+ public int[] getNearestKeys(int x, int y) {
+ if (mCurrentlyInSpace) {
+ return new int[] { mSpaceKeyIndex };
+ } else {
+ return super.getNearestKeys(x, y);
+ }
+ }
+
+ private int indexOf(int code) {
+ List<Key> keys = getKeys();
+ int count = keys.size();
+ for (int i = 0; i < count; i++) {
+ if (keys.get(i).codes[0] == code) return i;
+ }
+ return -1;
+ }
+
+ private int getTextSizeFromTheme(int style, int defValue) {
+ TypedArray array = mContext.getTheme().obtainStyledAttributes(
+ style, new int[] { android.R.attr.textSize });
+ int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
+ return textSize;
+ }
+
+ class LatinKey extends Keyboard.Key {
private boolean mShiftLockEnabled;
@@ -318,16 +487,130 @@ public class LatinKeyboard extends Keyboard {
*/
@Override
public boolean isInside(int x, int y) {
- final int code = codes[0];
- if (code == KEYCODE_SHIFT ||
- code == KEYCODE_DELETE) {
- y -= height / 10;
- if (code == KEYCODE_SHIFT) x += width / 6;
- if (code == KEYCODE_DELETE) x -= width / 6;
- } else if (code == LatinIME.KEYCODE_SPACE) {
- y += LatinKeyboard.sSpacebarVerticalCorrection;
- }
+ return LatinKeyboard.this.isInside(this, x, y);
+ }
+
+ boolean isInsideSuper(int x, int y) {
return super.isInside(x, y);
}
}
+
+ /**
+ * Animation to be displayed on the spacebar preview popup when switching
+ * languages by swiping the spacebar. It draws the current, previous and
+ * next languages and moves them by the delta of touch movement on the spacebar.
+ */
+ class SlidingLocaleDrawable extends Drawable {
+
+ private int mWidth;
+ private int mHeight;
+ private Drawable mBackground;
+ private int mDiff;
+ private TextPaint mTextPaint;
+ private int mMiddleX;
+ private int mAscent;
+ private Drawable mLeftDrawable;
+ private Drawable mRightDrawable;
+ private boolean mHitThreshold;
+ private int mThreshold;
+ private String mCurrentLanguage;
+ private String mNextLanguage;
+ private String mPrevLanguage;
+
+ public SlidingLocaleDrawable(Drawable background, int width, int height) {
+ mBackground = background;
+ mBackground.setBounds(0, 0,
+ mBackground.getIntrinsicWidth(), mBackground.getIntrinsicHeight());
+ mWidth = width;
+ mHeight = height;
+ mTextPaint = new TextPaint();
+ int textSize = getTextSizeFromTheme(android.R.style.TextAppearance_Medium, 18);
+ mTextPaint.setTextSize(textSize);
+ mTextPaint.setColor(0);
+ mTextPaint.setTextAlign(Align.CENTER);
+ mTextPaint.setAlpha(255);
+ mTextPaint.setAntiAlias(true);
+ mAscent = (int) mTextPaint.ascent();
+ mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2;
+ mLeftDrawable =
+ mRes.getDrawable(R.drawable.sym_keyboard_feedback_language_arrows_left);
+ mRightDrawable =
+ mRes.getDrawable(R.drawable.sym_keyboard_feedback_language_arrows_right);
+ mLeftDrawable.setBounds(0, 0,
+ mLeftDrawable.getIntrinsicWidth(), mLeftDrawable.getIntrinsicHeight());
+ mRightDrawable.setBounds(mWidth - mRightDrawable.getIntrinsicWidth(), 0,
+ mWidth, mRightDrawable.getIntrinsicHeight());
+ mThreshold = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ }
+
+ void setDiff(int diff) {
+ if (diff == Integer.MAX_VALUE) {
+ mHitThreshold = false;
+ mCurrentLanguage = null;
+ return;
+ }
+ mDiff = diff;
+ if (mDiff > mWidth) mDiff = mWidth;
+ if (mDiff < -mWidth) mDiff = -mWidth;
+ if (Math.abs(mDiff) > mThreshold) mHitThreshold = true;
+ invalidateSelf();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.save();
+ if (mHitThreshold) {
+ mTextPaint.setColor(0);
+ canvas.clipRect(0, 0, mWidth, mHeight);
+ int alpha = (255 * Math.max(0, mWidth / 2 - Math.abs(mDiff))) / (mWidth / 2);
+ mTextPaint.setAlpha(alpha);
+
+ if (mCurrentLanguage == null) {
+ mCurrentLanguage = getInputLanguage(mWidth, mTextPaint);
+ mNextLanguage = getNextInputLanguage(mWidth, mTextPaint);
+ mPrevLanguage = getPrevInputLanguage(mWidth, mTextPaint);
+ }
+
+ canvas.drawText(mCurrentLanguage,
+ mWidth / 2 + mDiff, -mAscent + 4, mTextPaint);
+ mTextPaint.setAlpha(255 - alpha);
+ canvas.drawText(mNextLanguage,
+ mDiff - mWidth / 2, -mAscent + 4, mTextPaint);
+ canvas.drawText(mPrevLanguage,
+ mDiff + mWidth + mWidth / 2, -mAscent + 4, mTextPaint);
+ mLeftDrawable.draw(canvas);
+ mRightDrawable.draw(canvas);
+ }
+ if (mBackground != null) {
+ canvas.translate(mMiddleX, 0);
+ mBackground.draw(canvas);
+ }
+ canvas.restore();
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // Ignore
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ // Ignore
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mWidth;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mHeight;
+ }
+ }
}
diff --git a/src/com/android/inputmethod/latin/LatinKeyboardView.java b/src/com/android/inputmethod/latin/LatinKeyboardView.java
index a88c1818c..05f8aff36 100644
--- a/src/com/android/inputmethod/latin/LatinKeyboardView.java
+++ b/src/com/android/inputmethod/latin/LatinKeyboardView.java
@@ -38,9 +38,15 @@ public class LatinKeyboardView extends KeyboardView {
static final int KEYCODE_VOICE = -102;
static final int KEYCODE_F1 = -103;
static final int KEYCODE_NEXT_LANGUAGE = -104;
+ static final int KEYCODE_PREV_LANGUAGE = -105;
private Keyboard mPhoneKeyboard;
+ private boolean mExtensionVisible;
+ private LatinKeyboardView mExtension;
+ private PopupWindow mExtensionPopup;
+ private boolean mFirstEvent;
+
public LatinKeyboardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -66,22 +72,33 @@ public class LatinKeyboardView extends KeyboardView {
// Long pressing on 0 in phone number keypad gives you a '+'.
getOnKeyboardActionListener().onKey('+', null);
return true;
- } else if (key.codes[0] == ' ' && ((LatinKeyboard)getKeyboard()).mLocale != null) {
- getOnKeyboardActionListener().onKey(KEYCODE_NEXT_LANGUAGE, null);
- return true;
} else {
return super.onLongPress(key);
}
}
- private boolean mExtensionVisible;
- private LatinKeyboardView mExtension;
- private PopupWindow mExtensionPopup;
- private boolean mFirstEvent;
-
@Override
public boolean onTouchEvent(MotionEvent me) {
- if (((LatinKeyboard) getKeyboard()).getExtension() == 0) {
+ LatinKeyboard keyboard = (LatinKeyboard) getKeyboard();
+ // Reset any bounding box controls in the keyboard
+ if (me.getAction() == MotionEvent.ACTION_DOWN) {
+ keyboard.keyReleased();
+ }
+
+ if (me.getAction() == MotionEvent.ACTION_UP) {
+ int languageDirection = keyboard.getLanguageChangeDirection();
+ if (languageDirection != 0) {
+ getOnKeyboardActionListener().onKey(
+ languageDirection == 1 ? KEYCODE_NEXT_LANGUAGE : KEYCODE_PREV_LANGUAGE,
+ null);
+ me.setAction(MotionEvent.ACTION_CANCEL);
+ keyboard.keyReleased();
+ return super.onTouchEvent(me);
+ }
+ }
+
+ // If we don't have an extension keyboard, don't go any further.
+ if (keyboard.getExtension() == 0) {
return super.onTouchEvent(me);
}
if (me.getY() < 0) {
diff --git a/src/com/android/inputmethod/latin/TextEntryState.java b/src/com/android/inputmethod/latin/TextEntryState.java
index 90c364a1c..c5e8ad9a1 100644
--- a/src/com/android/inputmethod/latin/TextEntryState.java
+++ b/src/com/android/inputmethod/latin/TextEntryState.java
@@ -123,6 +123,7 @@ public class TextEntryState {
}
public static void acceptedDefault(CharSequence typedWord, CharSequence actualWord) {
+ if (typedWord == null) return;
if (!typedWord.equals(actualWord)) {
sAutoSuggestCount++;
}