aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/inputmethod/latin/AutoDictionary.java217
-rw-r--r--src/com/android/inputmethod/latin/BinaryDictionary.java151
-rwxr-xr-xsrc/com/android/inputmethod/latin/CandidateView.java533
-rw-r--r--src/com/android/inputmethod/latin/CandidateViewContainer.java83
-rw-r--r--src/com/android/inputmethod/latin/ContactsDictionary.java176
-rw-r--r--src/com/android/inputmethod/latin/Dictionary.java99
-rw-r--r--src/com/android/inputmethod/latin/ExpandableDictionary.java465
-rw-r--r--src/com/android/inputmethod/latin/Hints.java188
-rw-r--r--src/com/android/inputmethod/latin/InputLanguageSelection.java183
-rw-r--r--src/com/android/inputmethod/latin/KeyboardSwitcher.java351
-rw-r--r--src/com/android/inputmethod/latin/LanguageSwitcher.java182
-rw-r--r--src/com/android/inputmethod/latin/LatinIME.java1949
-rw-r--r--src/com/android/inputmethod/latin/LatinIMEBackupAgent.java31
-rw-r--r--src/com/android/inputmethod/latin/LatinIMESettings.java200
-rw-r--r--src/com/android/inputmethod/latin/LatinKeyboard.java762
-rw-r--r--src/com/android/inputmethod/latin/LatinKeyboardView.java332
-rwxr-xr-xsrc/com/android/inputmethod/latin/Suggest.java378
-rw-r--r--src/com/android/inputmethod/latin/TextEntryState.java233
-rw-r--r--src/com/android/inputmethod/latin/Tutorial.java251
-rw-r--r--src/com/android/inputmethod/latin/UserDictionary.java138
-rw-r--r--src/com/android/inputmethod/latin/WordComposer.java174
-rw-r--r--src/com/android/inputmethod/voice/EditingUtil.java162
-rw-r--r--src/com/android/inputmethod/voice/FieldContext.java102
-rw-r--r--src/com/android/inputmethod/voice/LatinIMEWithVoice.java28
-rw-r--r--src/com/android/inputmethod/voice/LatinIMEWithVoiceSettings.java21
-rw-r--r--src/com/android/inputmethod/voice/RecognitionView.java324
-rw-r--r--src/com/android/inputmethod/voice/SettingsUtil.java113
-rw-r--r--src/com/android/inputmethod/voice/VoiceInput.java508
-rw-r--r--src/com/android/inputmethod/voice/VoiceInputLogger.java177
-rw-r--r--src/com/android/inputmethod/voice/WaveformImage.java90
-rw-r--r--src/com/android/inputmethod/voice/Whitelist.java67
-rw-r--r--src/com/google/android/voicesearch/LatinIMEWithVoice.java29
-rw-r--r--src/com/google/android/voicesearch/LatinIMEWithVoiceSettings.java5
33 files changed, 0 insertions, 8702 deletions
diff --git a/src/com/android/inputmethod/latin/AutoDictionary.java b/src/com/android/inputmethod/latin/AutoDictionary.java
deleted file mode 100644
index 3d76dc301..000000000
--- a/src/com/android/inputmethod/latin/AutoDictionary.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * 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.HashMap;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.provider.BaseColumns;
-import android.provider.UserDictionary.Words;
-import android.util.Log;
-
-/**
- * Stores new words temporarily until they are promoted to the user dictionary
- * for longevity. Words in the auto dictionary are used to determine if it's ok
- * to accept a word that's not in the main or user dictionary. Using a new word
- * repeatedly will promote it to the user dictionary.
- */
-public class AutoDictionary extends ExpandableDictionary {
- // Weight added to a user picking a new word from the suggestion strip
- static final int FREQUENCY_FOR_PICKED = 3;
- // Weight added to a user typing a new word that doesn't get corrected (or is reverted)
- static final int FREQUENCY_FOR_TYPED = 1;
- // A word that is frequently typed and gets promoted to the user dictionary, uses this
- // frequency.
- static final int FREQUENCY_FOR_AUTO_ADD = 250;
- // If the user touches a typed word 2 times or more, it will become valid.
- private static final int VALIDITY_THRESHOLD = 2 * FREQUENCY_FOR_PICKED;
- // If the user touches a typed word 4 times or more, it will be added to the user dict.
- private static final int PROMOTION_THRESHOLD = 4 * FREQUENCY_FOR_PICKED;
-
- private LatinIME mIme;
- // Locale for which this auto dictionary is storing words
- private String mLocale;
-
- private static final String DATABASE_NAME = "auto_dict.db";
- private static final int DATABASE_VERSION = 1;
-
- // These are the columns in the dictionary
- // TODO: Consume less space by using a unique id for locale instead of the whole
- // 2-5 character string.
- private static final String COLUMN_ID = BaseColumns._ID;
- private static final String COLUMN_WORD = "word";
- private static final String COLUMN_FREQUENCY = "freq";
- private static final String COLUMN_LOCALE = "locale";
-
- /** Sort by descending order of frequency. */
- public static final String DEFAULT_SORT_ORDER = COLUMN_FREQUENCY + " DESC";
-
- /** Name of the words table in the auto_dict.db */
- private static final String AUTODICT_TABLE_NAME = "words";
-
- private static HashMap<String, String> sDictProjectionMap;
-
- static {
- sDictProjectionMap = new HashMap<String, String>();
- sDictProjectionMap.put(COLUMN_ID, COLUMN_ID);
- sDictProjectionMap.put(COLUMN_WORD, COLUMN_WORD);
- sDictProjectionMap.put(COLUMN_FREQUENCY, COLUMN_FREQUENCY);
- sDictProjectionMap.put(COLUMN_LOCALE, COLUMN_LOCALE);
- }
-
- private DatabaseHelper mOpenHelper;
-
- public AutoDictionary(Context context, LatinIME ime, String locale) {
- super(context);
- mIme = ime;
- mLocale = locale;
- mOpenHelper = new DatabaseHelper(getContext());
- if (mLocale != null && mLocale.length() > 1) {
- loadDictionary();
- }
- }
-
- @Override
- public boolean isValidWord(CharSequence word) {
- final int frequency = getWordFrequency(word);
- return frequency >= VALIDITY_THRESHOLD;
- }
-
- public void close() {
- mOpenHelper.close();
- }
-
- private void loadDictionary() {
- // Load the words that correspond to the current input locale
- Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale });
- if (cursor.moveToFirst()) {
- int wordIndex = cursor.getColumnIndex(COLUMN_WORD);
- int frequencyIndex = cursor.getColumnIndex(COLUMN_FREQUENCY);
- while (!cursor.isAfterLast()) {
- String word = cursor.getString(wordIndex);
- int frequency = cursor.getInt(frequencyIndex);
- // Safeguard against adding really long words. Stack may overflow due
- // to recursive lookup
- if (word.length() < getMaxWordLength()) {
- super.addWord(word, frequency);
- }
- cursor.moveToNext();
- }
- }
- cursor.close();
- }
-
- @Override
- public void addWord(String word, int addFrequency) {
- final int length = word.length();
- // Don't add very short or very long words.
- if (length < 2 || length > getMaxWordLength()) return;
- if (mIme.getCurrentWord().isAutoCapitalized()) {
- // Remove caps before adding
- word = Character.toLowerCase(word.charAt(0)) + word.substring(1);
- }
- int freq = getWordFrequency(word);
- freq = freq < 0 ? addFrequency : freq + addFrequency;
- super.addWord(word, freq);
- if (freq >= PROMOTION_THRESHOLD) {
- mIme.promoteToUserDictionary(word, FREQUENCY_FOR_AUTO_ADD);
- // Delete the word (for input locale) from the auto dictionary db, as it
- // is now in the user dictionary provider.
- delete(COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?",
- new String[] { word, mLocale });
- } else {
- update(word, freq, mLocale);
- }
- }
-
- /**
- * This class helps open, create, and upgrade the database file.
- */
- private static class DatabaseHelper extends SQLiteOpenHelper {
-
- DatabaseHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE " + AUTODICT_TABLE_NAME + " ("
- + COLUMN_ID + " INTEGER PRIMARY KEY,"
- + COLUMN_WORD + " TEXT,"
- + COLUMN_FREQUENCY + " INTEGER,"
- + COLUMN_LOCALE + " TEXT"
- + ");");
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- Log.w("AutoDictionary", "Upgrading database from version " + oldVersion + " to "
- + newVersion + ", which will destroy all old data");
- db.execSQL("DROP TABLE IF EXISTS " + AUTODICT_TABLE_NAME);
- onCreate(db);
- }
- }
-
- private Cursor query(String selection, String[] selectionArgs) {
- SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
- qb.setTables(AUTODICT_TABLE_NAME);
- qb.setProjectionMap(sDictProjectionMap);
-
- // Get the database and run the query
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- Cursor c = qb.query(db, null, selection, selectionArgs, null, null,
- DEFAULT_SORT_ORDER);
- return c;
- }
-
- private boolean insert(ContentValues values) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- long rowId = db.insert(AUTODICT_TABLE_NAME, Words.WORD, values);
- if (rowId > 0) {
- return true;
- }
- return false;
- }
-
- private int delete(String where, String[] whereArgs) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- int count = db.delete(AUTODICT_TABLE_NAME, where, whereArgs);
- return count;
- }
-
- private int update(String word, int frequency, String locale) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- long count = db.delete(AUTODICT_TABLE_NAME, COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?",
- new String[] { word, locale });
- count = db.insert(AUTODICT_TABLE_NAME, null,
- getContentValues(word, frequency, locale));
- return (int) count;
- }
-
- private ContentValues getContentValues(String word, int frequency, String locale) {
- ContentValues values = new ContentValues(4);
- values.put(COLUMN_WORD, word);
- values.put(COLUMN_FREQUENCY, frequency);
- values.put(COLUMN_LOCALE, locale);
- return values;
- }
-}
diff --git a/src/com/android/inputmethod/latin/BinaryDictionary.java b/src/com/android/inputmethod/latin/BinaryDictionary.java
deleted file mode 100644
index 43f4c4cb6..000000000
--- a/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.Arrays;
-
-import android.content.Context;
-import android.content.res.AssetManager;
-import android.util.Log;
-
-/**
- * Implements a static, compacted, binary dictionary of standard words.
- */
-public class BinaryDictionary extends Dictionary {
-
- public static final int MAX_WORD_LENGTH = 48;
- private static final int MAX_ALTERNATIVES = 16;
- private static final int MAX_WORDS = 16;
-
- private static final int TYPED_LETTER_MULTIPLIER = 2;
- private static final boolean ENABLE_MISSED_CHARACTERS = true;
-
- private int mNativeDict;
- private int mDictLength; // This value is set from native code, don't change the name!!!!
- private int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_ALTERNATIVES];
- private char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS];
- private int[] mFrequencies = new int[MAX_WORDS];
-
- static {
- try {
- System.loadLibrary("jni_latinime");
- } catch (UnsatisfiedLinkError ule) {
- Log.e("BinaryDictionary", "Could not load native library jni_latinime");
- }
- }
-
- /**
- * Create a dictionary from a raw resource file
- * @param context application context for reading resources
- * @param resId the resource containing the raw binary dictionary
- */
- public BinaryDictionary(Context context, int resId) {
- if (resId != 0) {
- loadDictionary(context, resId);
- }
- }
-
- private native int openNative(AssetManager am, String resourcePath, int typedLetterMultiplier,
- int fullWordMultiplier);
- private native void closeNative(int dict);
- private native boolean isValidWordNative(int nativeData, char[] word, int wordLength);
- private native int getSuggestionsNative(int dict, int[] inputCodes, int codesSize,
- char[] outputChars, int[] frequencies,
- int maxWordLength, int maxWords, int maxAlternatives, int skipPos,
- int[] nextLettersFrequencies, int nextLettersSize);
-
- private final void loadDictionary(Context context, int resId) {
- AssetManager am = context.getResources().getAssets();
- String assetName = context.getResources().getString(resId);
- mNativeDict = openNative(am, assetName, TYPED_LETTER_MULTIPLIER, FULL_WORD_FREQ_MULTIPLIER);
- }
-
- @Override
- public void getWords(final WordComposer codes, final WordCallback callback,
- int[] nextLettersFrequencies) {
- final int codesSize = codes.size();
- // Wont deal with really long words.
- if (codesSize > MAX_WORD_LENGTH - 1) return;
-
- Arrays.fill(mInputCodes, -1);
- for (int i = 0; i < codesSize; i++) {
- int[] alternatives = codes.getCodesAt(i);
- System.arraycopy(alternatives, 0, mInputCodes, i * MAX_ALTERNATIVES,
- Math.min(alternatives.length, MAX_ALTERNATIVES));
- }
- Arrays.fill(mOutputChars, (char) 0);
- Arrays.fill(mFrequencies, 0);
-
- int count = getSuggestionsNative(mNativeDict, mInputCodes, codesSize,
- mOutputChars, mFrequencies,
- MAX_WORD_LENGTH, MAX_WORDS, MAX_ALTERNATIVES, -1,
- nextLettersFrequencies,
- nextLettersFrequencies != null ? nextLettersFrequencies.length : 0);
-
- // If there aren't sufficient suggestions, search for words by allowing wild cards at
- // the different character positions. This feature is not ready for prime-time as we need
- // to figure out the best ranking for such words compared to proximity corrections and
- // completions.
- if (ENABLE_MISSED_CHARACTERS && count < 5) {
- for (int skip = 0; skip < codesSize; skip++) {
- int tempCount = getSuggestionsNative(mNativeDict, mInputCodes, codesSize,
- mOutputChars, mFrequencies,
- MAX_WORD_LENGTH, MAX_WORDS, MAX_ALTERNATIVES, skip,
- null, 0);
- count = Math.max(count, tempCount);
- if (tempCount > 0) break;
- }
- }
-
- for (int j = 0; j < count; j++) {
- if (mFrequencies[j] < 1) break;
- int start = j * MAX_WORD_LENGTH;
- int len = 0;
- while (mOutputChars[start + len] != 0) {
- len++;
- }
- if (len > 0) {
- callback.addWord(mOutputChars, start, len, mFrequencies[j]);
- }
- }
- }
-
- @Override
- public boolean isValidWord(CharSequence word) {
- if (word == null) return false;
- char[] chars = word.toString().toCharArray();
- return isValidWordNative(mNativeDict, chars, chars.length);
- }
-
- public int getSize() {
- return mDictLength; // This value is initialized on the call to openNative()
- }
-
- @Override
- public synchronized void close() {
- if (mNativeDict != 0) {
- closeNative(mNativeDict);
- mNativeDict = 0;
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- close();
- super.finalize();
- }
-}
diff --git a/src/com/android/inputmethod/latin/CandidateView.java b/src/com/android/inputmethod/latin/CandidateView.java
deleted file mode 100755
index 0c0373b3b..000000000
--- a/src/com/android/inputmethod/latin/CandidateView.java
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import android.graphics.Paint.Align;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.PopupWindow;
-import android.widget.TextView;
-
-public class CandidateView extends View {
-
- private static final int OUT_OF_BOUNDS = -1;
- private static final List<CharSequence> EMPTY_LIST = new ArrayList<CharSequence>();
-
- private LatinIME mService;
- private List<CharSequence> mSuggestions = EMPTY_LIST;
- private boolean mShowingCompletions;
- private CharSequence mSelectedString;
- private int mSelectedIndex;
- private int mTouchX = OUT_OF_BOUNDS;
- private Drawable mSelectionHighlight;
- private boolean mTypedWordValid;
-
- private boolean mHaveMinimalSuggestion;
-
- private Rect mBgPadding;
-
- private TextView mPreviewText;
- private PopupWindow mPreviewPopup;
- private int mCurrentWordIndex;
- private Drawable mDivider;
-
- private static final int MAX_SUGGESTIONS = 32;
- private static final int SCROLL_PIXELS = 20;
-
- private static final int MSG_REMOVE_PREVIEW = 1;
- private static final int MSG_REMOVE_THROUGH_PREVIEW = 2;
-
- private int[] mWordWidth = new int[MAX_SUGGESTIONS];
- private int[] mWordX = new int[MAX_SUGGESTIONS];
- private int mPopupPreviewX;
- private int mPopupPreviewY;
-
- private static final int X_GAP = 10;
-
- private int mColorNormal;
- private int mColorRecommended;
- private int mColorOther;
- private Paint mPaint;
- private int mDescent;
- private boolean mScrolled;
- private boolean mShowingAddToDictionary;
- private CharSequence mWordToAddToDictionary;
- private CharSequence mAddToDictionaryHint;
-
- private int mTargetScrollX;
-
- private int mMinTouchableWidth;
-
- private int mTotalWidth;
-
- private GestureDetector mGestureDetector;
-
- Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_REMOVE_PREVIEW:
- mPreviewText.setVisibility(GONE);
- break;
- case MSG_REMOVE_THROUGH_PREVIEW:
- mPreviewText.setVisibility(GONE);
- if (mTouchX != OUT_OF_BOUNDS) {
- removeHighlight();
- }
- break;
- }
-
- }
- };
-
- /**
- * Construct a CandidateView for showing suggested words for completion.
- * @param context
- * @param attrs
- */
- public CandidateView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mSelectionHighlight = context.getResources().getDrawable(
- R.drawable.list_selector_background_pressed);
-
- LayoutInflater inflate =
- (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- Resources res = context.getResources();
- mPreviewPopup = new PopupWindow(context);
- mPreviewText = (TextView) inflate.inflate(R.layout.candidate_preview, null);
- mPreviewPopup.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- mPreviewPopup.setContentView(mPreviewText);
- mPreviewPopup.setBackgroundDrawable(null);
- mColorNormal = res.getColor(R.color.candidate_normal);
- mColorRecommended = res.getColor(R.color.candidate_recommended);
- mColorOther = res.getColor(R.color.candidate_other);
- mDivider = res.getDrawable(R.drawable.keyboard_suggest_strip_divider);
- mAddToDictionaryHint = res.getString(R.string.hint_add_to_dictionary);
-
- mPaint = new Paint();
- mPaint.setColor(mColorNormal);
- mPaint.setAntiAlias(true);
- mPaint.setTextSize(mPreviewText.getTextSize());
- mPaint.setStrokeWidth(0);
- mPaint.setTextAlign(Align.CENTER);
- mDescent = (int) mPaint.descent();
- // 80 pixels for a 160dpi device would mean half an inch
- mMinTouchableWidth = (int) (getResources().getDisplayMetrics().density * 50);
-
- mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
- @Override
- public void onLongPress(MotionEvent me) {
- if (mSuggestions.size() > 0) {
- if (me.getX() + getScrollX() < mWordWidth[0] && getScrollX() < 10) {
- longPressFirstWord();
- }
- }
- }
-
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2,
- float distanceX, float distanceY) {
- final int width = getWidth();
- mScrolled = true;
- int scrollX = getScrollX();
- scrollX += (int) distanceX;
- if (scrollX < 0) {
- scrollX = 0;
- }
- if (distanceX > 0 && scrollX + width > mTotalWidth) {
- scrollX -= (int) distanceX;
- }
- mTargetScrollX = scrollX;
- scrollTo(scrollX, getScrollY());
- hidePreview();
- invalidate();
- return true;
- }
- });
- setHorizontalFadingEdgeEnabled(true);
- setWillNotDraw(false);
- setHorizontalScrollBarEnabled(false);
- setVerticalScrollBarEnabled(false);
- scrollTo(0, getScrollY());
- }
-
- /**
- * A connection back to the service to communicate with the text field
- * @param listener
- */
- public void setService(LatinIME listener) {
- mService = listener;
- }
-
- @Override
- public int computeHorizontalScrollRange() {
- return mTotalWidth;
- }
-
- /**
- * If the canvas is null, then only touch calculations are performed to pick the target
- * candidate.
- */
- @Override
- protected void onDraw(Canvas canvas) {
- if (canvas != null) {
- super.onDraw(canvas);
- }
- mTotalWidth = 0;
- if (mSuggestions == null) return;
-
- final int height = getHeight();
- if (mBgPadding == null) {
- mBgPadding = new Rect(0, 0, 0, 0);
- if (getBackground() != null) {
- getBackground().getPadding(mBgPadding);
- }
- mDivider.setBounds(0, 0, mDivider.getIntrinsicWidth(),
- mDivider.getIntrinsicHeight());
- }
- int x = 0;
- final int count = mSuggestions.size();
- final int width = getWidth();
- final Rect bgPadding = mBgPadding;
- final Paint paint = mPaint;
- final int touchX = mTouchX;
- final int scrollX = getScrollX();
- final boolean scrolled = mScrolled;
- final boolean typedWordValid = mTypedWordValid;
- final int y = (int) (height + mPaint.getTextSize() - mDescent) / 2;
-
- for (int i = 0; i < count; i++) {
- CharSequence suggestion = mSuggestions.get(i);
- if (suggestion == null) continue;
- paint.setColor(mColorNormal);
- if (mHaveMinimalSuggestion
- && ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid))) {
- paint.setTypeface(Typeface.DEFAULT_BOLD);
- paint.setColor(mColorRecommended);
- } else if (i != 0) {
- paint.setColor(mColorOther);
- }
- final int wordWidth;
- if (mWordWidth[i] != 0) {
- wordWidth = mWordWidth[i];
- } else {
- float textWidth = paint.measureText(suggestion, 0, suggestion.length());
- wordWidth = Math.max(mMinTouchableWidth, (int) textWidth + X_GAP * 2);
- mWordWidth[i] = wordWidth;
- }
-
- mWordX[i] = x;
-
- if (touchX + scrollX >= x && touchX + scrollX < x + wordWidth && !scrolled &&
- touchX != OUT_OF_BOUNDS) {
- if (canvas != null && !mShowingAddToDictionary) {
- canvas.translate(x, 0);
- mSelectionHighlight.setBounds(0, bgPadding.top, wordWidth, height);
- mSelectionHighlight.draw(canvas);
- canvas.translate(-x, 0);
- showPreview(i, null);
- }
- mSelectedString = suggestion;
- mSelectedIndex = i;
- }
-
- if (canvas != null) {
- canvas.drawText(suggestion, 0, suggestion.length(), x + wordWidth / 2, y, paint);
- paint.setColor(mColorOther);
- canvas.translate(x + wordWidth, 0);
- // Draw a divider unless it's after the hint
- if (!(mShowingAddToDictionary && i == 1)) {
- mDivider.draw(canvas);
- }
- canvas.translate(-x - wordWidth, 0);
- }
- paint.setTypeface(Typeface.DEFAULT);
- x += wordWidth;
- }
- mTotalWidth = x;
- if (mTargetScrollX != scrollX) {
- scrollToTarget();
- }
- }
-
- private void scrollToTarget() {
- int scrollX = getScrollX();
- if (mTargetScrollX > scrollX) {
- scrollX += SCROLL_PIXELS;
- if (scrollX >= mTargetScrollX) {
- scrollX = mTargetScrollX;
- scrollTo(scrollX, getScrollY());
- requestLayout();
- } else {
- scrollTo(scrollX, getScrollY());
- }
- } else {
- scrollX -= SCROLL_PIXELS;
- if (scrollX <= mTargetScrollX) {
- scrollX = mTargetScrollX;
- scrollTo(scrollX, getScrollY());
- requestLayout();
- } else {
- scrollTo(scrollX, getScrollY());
- }
- }
- invalidate();
- }
-
- public void setSuggestions(List<CharSequence> suggestions, boolean completions,
- boolean typedWordValid, boolean haveMinimalSuggestion) {
- clear();
- if (suggestions != null) {
- mSuggestions = new ArrayList<CharSequence>(suggestions);
- }
- mShowingCompletions = completions;
- mTypedWordValid = typedWordValid;
- scrollTo(0, getScrollY());
- mTargetScrollX = 0;
- mHaveMinimalSuggestion = haveMinimalSuggestion;
- // Compute the total width
- onDraw(null);
- invalidate();
- requestLayout();
- }
-
- public void showAddToDictionaryHint(CharSequence word) {
- mWordToAddToDictionary = word;
- ArrayList<CharSequence> suggestions = new ArrayList<CharSequence>();
- suggestions.add(word);
- suggestions.add(mAddToDictionaryHint);
- setSuggestions(suggestions, false, false, false);
- mShowingAddToDictionary = true;
- }
-
- public void scrollPrev() {
- int i = 0;
- final int count = mSuggestions.size();
- int firstItem = 0; // Actually just before the first item, if at the boundary
- while (i < count) {
- if (mWordX[i] < getScrollX()
- && mWordX[i] + mWordWidth[i] >= getScrollX() - 1) {
- firstItem = i;
- break;
- }
- i++;
- }
- int leftEdge = mWordX[firstItem] + mWordWidth[firstItem] - getWidth();
- if (leftEdge < 0) leftEdge = 0;
- updateScrollPosition(leftEdge);
- }
-
- public void scrollNext() {
- int i = 0;
- int scrollX = getScrollX();
- int targetX = scrollX;
- final int count = mSuggestions.size();
- int rightEdge = scrollX + getWidth();
- while (i < count) {
- if (mWordX[i] <= rightEdge &&
- mWordX[i] + mWordWidth[i] >= rightEdge) {
- targetX = Math.min(mWordX[i], mTotalWidth - getWidth());
- break;
- }
- i++;
- }
- updateScrollPosition(targetX);
- }
-
- private void updateScrollPosition(int targetX) {
- if (targetX != getScrollX()) {
- // TODO: Animate
- mTargetScrollX = targetX;
- requestLayout();
- invalidate();
- mScrolled = true;
- }
- }
-
- public void clear() {
- mSuggestions = EMPTY_LIST;
- mTouchX = OUT_OF_BOUNDS;
- mSelectedString = null;
- mSelectedIndex = -1;
- mShowingAddToDictionary = false;
- invalidate();
- Arrays.fill(mWordWidth, 0);
- Arrays.fill(mWordX, 0);
- if (mPreviewPopup.isShowing()) {
- mPreviewPopup.dismiss();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent me) {
-
- if (mGestureDetector.onTouchEvent(me)) {
- return true;
- }
-
- int action = me.getAction();
- int x = (int) me.getX();
- int y = (int) me.getY();
- mTouchX = x;
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mScrolled = false;
- invalidate();
- break;
- case MotionEvent.ACTION_MOVE:
- if (y <= 0) {
- // Fling up!?
- if (mSelectedString != null) {
- if (!mShowingCompletions) {
- TextEntryState.acceptedSuggestion(mSuggestions.get(0),
- mSelectedString);
- }
- mService.pickSuggestionManually(mSelectedIndex, mSelectedString);
- mSelectedString = null;
- mSelectedIndex = -1;
- }
- }
- invalidate();
- break;
- case MotionEvent.ACTION_UP:
- if (!mScrolled) {
- if (mSelectedString != null) {
- if (mShowingAddToDictionary) {
- longPressFirstWord();
- clear();
- } else {
- if (!mShowingCompletions) {
- TextEntryState.acceptedSuggestion(mSuggestions.get(0),
- mSelectedString);
- }
- mService.pickSuggestionManually(mSelectedIndex, mSelectedString);
- }
- }
- }
- mSelectedString = null;
- mSelectedIndex = -1;
- removeHighlight();
- hidePreview();
- requestLayout();
- break;
- }
- return true;
- }
-
- /**
- * For flick through from keyboard, call this method with the x coordinate of the flick
- * gesture.
- * @param x
- */
- public void takeSuggestionAt(float x) {
- mTouchX = (int) x;
- // To detect candidate
- onDraw(null);
- if (mSelectedString != null) {
- if (!mShowingCompletions) {
- TextEntryState.acceptedSuggestion(mSuggestions.get(0), mSelectedString);
- }
- mService.pickSuggestionManually(mSelectedIndex, mSelectedString);
- }
- invalidate();
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_REMOVE_THROUGH_PREVIEW), 200);
- }
-
- private void hidePreview() {
- mCurrentWordIndex = OUT_OF_BOUNDS;
- if (mPreviewPopup.isShowing()) {
- mHandler.sendMessageDelayed(mHandler
- .obtainMessage(MSG_REMOVE_PREVIEW), 60);
- }
- }
-
- private void showPreview(int wordIndex, String altText) {
- int oldWordIndex = mCurrentWordIndex;
- mCurrentWordIndex = wordIndex;
- // If index changed or changing text
- if (oldWordIndex != mCurrentWordIndex || altText != null) {
- if (wordIndex == OUT_OF_BOUNDS) {
- hidePreview();
- } else {
- CharSequence word = altText != null? altText : mSuggestions.get(wordIndex);
- mPreviewText.setText(word);
- mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- int wordWidth = (int) (mPaint.measureText(word, 0, word.length()) + X_GAP * 2);
- final int popupWidth = wordWidth
- + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight();
- final int popupHeight = mPreviewText.getMeasuredHeight();
- //mPreviewText.setVisibility(INVISIBLE);
- mPopupPreviewX = mWordX[wordIndex] - mPreviewText.getPaddingLeft() - getScrollX()
- + (mWordWidth[wordIndex] - wordWidth) / 2;
- mPopupPreviewY = - popupHeight;
- mHandler.removeMessages(MSG_REMOVE_PREVIEW);
- int [] offsetInWindow = new int[2];
- getLocationInWindow(offsetInWindow);
- if (mPreviewPopup.isShowing()) {
- mPreviewPopup.update(mPopupPreviewX, mPopupPreviewY + offsetInWindow[1],
- popupWidth, popupHeight);
- } else {
- mPreviewPopup.setWidth(popupWidth);
- mPreviewPopup.setHeight(popupHeight);
- mPreviewPopup.showAtLocation(this, Gravity.NO_GRAVITY, mPopupPreviewX,
- mPopupPreviewY + offsetInWindow[1]);
- }
- mPreviewText.setVisibility(VISIBLE);
- }
- }
- }
-
- private void removeHighlight() {
- mTouchX = OUT_OF_BOUNDS;
- invalidate();
- }
-
- private void longPressFirstWord() {
- CharSequence word = mSuggestions.get(0);
- if (word.length() < 2) return;
- if (mService.addWordToDictionary(word.toString())) {
- showPreview(0, getContext().getResources().getString(R.string.added_word, word));
- }
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- hidePreview();
- }
-}
diff --git a/src/com/android/inputmethod/latin/CandidateViewContainer.java b/src/com/android/inputmethod/latin/CandidateViewContainer.java
deleted file mode 100644
index e13f2738c..000000000
--- a/src/com/android/inputmethod/latin/CandidateViewContainer.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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 android.content.Context;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.widget.LinearLayout;
-
-public class CandidateViewContainer extends LinearLayout implements OnTouchListener {
-
- private View mButtonLeft;
- private View mButtonRight;
- private View mButtonLeftLayout;
- private View mButtonRightLayout;
- private CandidateView mCandidates;
-
- public CandidateViewContainer(Context screen, AttributeSet attrs) {
- super(screen, attrs);
- }
-
- public void initViews() {
- if (mCandidates == null) {
- mButtonLeftLayout = findViewById(R.id.candidate_left_parent);
- mButtonLeft = findViewById(R.id.candidate_left);
- if (mButtonLeft != null) {
- mButtonLeft.setOnTouchListener(this);
- }
- mButtonRightLayout = findViewById(R.id.candidate_right_parent);
- mButtonRight = findViewById(R.id.candidate_right);
- if (mButtonRight != null) {
- mButtonRight.setOnTouchListener(this);
- }
- mCandidates = (CandidateView) findViewById(R.id.candidates);
- }
- }
-
- @Override
- public void requestLayout() {
- if (mCandidates != null) {
- int availableWidth = mCandidates.getWidth();
- int neededWidth = mCandidates.computeHorizontalScrollRange();
- int x = mCandidates.getScrollX();
- boolean leftVisible = x > 0;
- boolean rightVisible = x + availableWidth < neededWidth;
- if (mButtonLeftLayout != null) {
- mButtonLeftLayout.setVisibility(leftVisible ? VISIBLE : GONE);
- }
- if (mButtonRightLayout != null) {
- mButtonRightLayout.setVisibility(rightVisible ? VISIBLE : GONE);
- }
- }
- super.requestLayout();
- }
-
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- if (v == mButtonRight) {
- mCandidates.scrollNext();
- } else if (v == mButtonLeft) {
- mCandidates.scrollPrev();
- }
- }
- return false;
- }
-
-}
diff --git a/src/com/android/inputmethod/latin/ContactsDictionary.java b/src/com/android/inputmethod/latin/ContactsDictionary.java
deleted file mode 100644
index f53ebf3f5..000000000
--- a/src/com/android/inputmethod/latin/ContactsDictionary.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * 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 android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.os.AsyncTask;
-import android.os.SystemClock;
-import android.provider.ContactsContract.Contacts;
-
-public class ContactsDictionary extends ExpandableDictionary {
-
- private static final String[] PROJECTION = {
- Contacts._ID,
- Contacts.DISPLAY_NAME,
- };
-
- private static final int INDEX_NAME = 1;
-
- private ContentObserver mObserver;
-
- private boolean mRequiresReload;
-
- private long mLastLoadedContacts;
-
- private boolean mUpdatingContacts;
-
- // Use this lock before touching mUpdatingContacts & mRequiresDownload
- private Object mUpdatingLock = new Object();
-
- public ContactsDictionary(Context context) {
- super(context);
- // Perform a managed query. The Activity will handle closing and requerying the cursor
- // when needed.
- ContentResolver cres = context.getContentResolver();
-
- cres.registerContentObserver(Contacts.CONTENT_URI, true, mObserver = new ContentObserver(null) {
- @Override
- public void onChange(boolean self) {
- synchronized (mUpdatingLock) {
- mRequiresReload = true;
- }
- }
- });
-
- synchronized (mUpdatingLock) {
- loadDictionaryAsyncLocked();
- }
- }
-
- public synchronized void close() {
- if (mObserver != null) {
- getContext().getContentResolver().unregisterContentObserver(mObserver);
- mObserver = null;
- }
- }
-
- private synchronized void loadDictionaryAsyncLocked() {
- long now = SystemClock.uptimeMillis();
- if (mLastLoadedContacts == 0
- || now - mLastLoadedContacts > 30 * 60 * 1000 /* 30 minutes */) {
- if (!mUpdatingContacts) {
- mUpdatingContacts = true;
- mRequiresReload = false;
- new LoadContactsTask().execute();
- }
- }
- }
-
- @Override
- public synchronized void getWords(final WordComposer codes, final WordCallback callback,
- int[] nextLettersFrequencies) {
- synchronized (mUpdatingLock) {
- // If we need to update, start off a background task
- if (mRequiresReload) loadDictionaryAsyncLocked();
- // Currently updating contacts, don't return any results.
- if (mUpdatingContacts) return;
- }
- super.getWords(codes, callback, nextLettersFrequencies);
- }
-
- @Override
- public synchronized boolean isValidWord(CharSequence word) {
- synchronized (mUpdatingLock) {
- // If we need to update, start off a background task
- if (mRequiresReload) loadDictionaryAsyncLocked();
- if (mUpdatingContacts) return false;
- }
-
- return super.isValidWord(word);
- }
-
- private void addWords(Cursor cursor) {
- clearDictionary();
-
- final int maxWordLength = getMaxWordLength();
- if (cursor.moveToFirst()) {
- while (!cursor.isAfterLast()) {
- String name = cursor.getString(INDEX_NAME);
-
- if (name != null) {
- int len = name.length();
-
- // TODO: Better tokenization for non-Latin writing systems
- for (int i = 0; i < len; i++) {
- if (Character.isLetter(name.charAt(i))) {
- int j;
- for (j = i + 1; j < len; j++) {
- char c = name.charAt(j);
-
- if (!(c == '-' || c == '\'' ||
- Character.isLetter(c))) {
- break;
- }
- }
-
- String word = name.substring(i, j);
- i = j - 1;
-
- // Safeguard against adding really long words. Stack
- // may overflow due to recursion
- // Also don't add single letter words, possibly confuses
- // capitalization of i.
- final int wordLen = word.length();
- if (wordLen < maxWordLength && wordLen > 1) {
- super.addWord(word, 128);
- }
- }
- }
- }
-
- cursor.moveToNext();
- }
- }
- cursor.close();
- }
-
- private class LoadContactsTask extends AsyncTask<Void, Void, Void> {
- @Override
- protected Void doInBackground(Void... v) {
- Cursor cursor = getContext().getContentResolver()
- .query(Contacts.CONTENT_URI, PROJECTION, null, null, null);
- if (cursor != null) {
- addWords(cursor);
- }
- mLastLoadedContacts = SystemClock.uptimeMillis();
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- // TODO Auto-generated method stub
- synchronized (mUpdatingLock) {
- mUpdatingContacts = false;
- }
- super.onPostExecute(result);
- }
-
- }
-}
diff --git a/src/com/android/inputmethod/latin/Dictionary.java b/src/com/android/inputmethod/latin/Dictionary.java
deleted file mode 100644
index b656d04dc..000000000
--- a/src/com/android/inputmethod/latin/Dictionary.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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;
-
-/**
- * Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
- * strokes.
- */
-abstract public class Dictionary {
-
- /**
- * Whether or not to replicate the typed word in the suggested list, even if it's valid.
- */
- protected static final boolean INCLUDE_TYPED_WORD_IF_VALID = false;
-
- /**
- * The weight to give to a word if it's length is the same as the number of typed characters.
- */
- protected static final int FULL_WORD_FREQ_MULTIPLIER = 2;
-
- /**
- * Interface to be implemented by classes requesting words to be fetched from the dictionary.
- * @see #getWords(WordComposer, WordCallback)
- */
- public interface WordCallback {
- /**
- * Adds a word to a list of suggestions. The word is expected to be ordered based on
- * the provided frequency.
- * @param word the character array containing the word
- * @param wordOffset starting offset of the word in the character array
- * @param wordLength length of valid characters in the character array
- * @param frequency the frequency of occurence. This is normalized between 1 and 255, but
- * can exceed those limits
- * @return true if the word was added, false if no more words are required
- */
- boolean addWord(char[] word, int wordOffset, int wordLength, int frequency);
- }
-
- /**
- * Searches for words in the dictionary that match the characters in the composer. Matched
- * words are added through the callback object.
- * @param composer the key sequence to match
- * @param callback the callback object to send matched words to as possible candidates
- * @param nextLettersFrequencies array of frequencies of next letters that could follow the
- * word so far. For instance, "bracke" can be followed by "t", so array['t'] will have
- * a non-zero value on returning from this method.
- * Pass in null if you don't want the dictionary to look up next letters.
- * @see WordCallback#addWord(char[], int, int)
- */
- abstract public void getWords(final WordComposer composer, final WordCallback callback,
- int[] nextLettersFrequencies);
-
- /**
- * Checks if the given word occurs in the dictionary
- * @param word the word to search for. The search should be case-insensitive.
- * @return true if the word exists, false otherwise
- */
- abstract public boolean isValidWord(CharSequence word);
-
- /**
- * Compares the contents of the character array with the typed word and returns true if they
- * are the same.
- * @param word the array of characters that make up the word
- * @param length the number of valid characters in the character array
- * @param typedWord the word to compare with
- * @return true if they are the same, false otherwise.
- */
- protected boolean same(final char[] word, final int length, final CharSequence typedWord) {
- if (typedWord.length() != length) {
- return false;
- }
- for (int i = 0; i < length; i++) {
- if (word[i] != typedWord.charAt(i)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Override to clean up any resources.
- */
- public void close() {
- }
-}
diff --git a/src/com/android/inputmethod/latin/ExpandableDictionary.java b/src/com/android/inputmethod/latin/ExpandableDictionary.java
deleted file mode 100644
index 006593700..000000000
--- a/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * 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 android.content.Context;
-
-/**
- * Base class for an in-memory dictionary that can grow dynamically and can
- * be searched for suggestions and valid words.
- */
-public class ExpandableDictionary extends Dictionary {
- private Context mContext;
- private char[] mWordBuilder = new char[MAX_WORD_LENGTH];
- private int mMaxDepth;
- private int mInputLength;
- private int[] mNextLettersFrequencies;
-
- public static final int MAX_WORD_LENGTH = 32;
- private static final char QUOTE = '\'';
-
- static class Node {
- char code;
- int frequency;
- boolean terminal;
- NodeArray children;
- }
-
- static class NodeArray {
- Node[] data;
- int length = 0;
- private static final int INCREMENT = 2;
-
- NodeArray() {
- data = new Node[INCREMENT];
- }
-
- void add(Node n) {
- if (length + 1 > data.length) {
- Node[] tempData = new Node[length + INCREMENT];
- if (length > 0) {
- System.arraycopy(data, 0, tempData, 0, length);
- }
- data = tempData;
- }
- data[length++] = n;
- }
- }
-
- private NodeArray mRoots;
-
- private int[][] mCodes;
-
- ExpandableDictionary(Context context) {
- mContext = context;
- clearDictionary();
- mCodes = new int[MAX_WORD_LENGTH][];
- }
-
- Context getContext() {
- return mContext;
- }
-
- int getMaxWordLength() {
- return MAX_WORD_LENGTH;
- }
-
- public void addWord(String word, int frequency) {
- addWordRec(mRoots, word, 0, frequency);
- }
-
- private void addWordRec(NodeArray children, final String word,
- final int depth, final int frequency) {
-
- final int wordLength = word.length();
- final char c = word.charAt(depth);
- // Does children have the current character?
- final int childrenLength = children.length;
- Node childNode = null;
- boolean found = false;
- for (int i = 0; i < childrenLength; i++) {
- childNode = children.data[i];
- if (childNode.code == c) {
- found = true;
- break;
- }
- }
- if (!found) {
- childNode = new Node();
- childNode.code = c;
- children.add(childNode);
- }
- if (wordLength == depth + 1) {
- // Terminate this word
- childNode.terminal = true;
- childNode.frequency = Math.max(frequency, childNode.frequency);
- if (childNode.frequency > 255) childNode.frequency = 255;
- return;
- }
- if (childNode.children == null) {
- childNode.children = new NodeArray();
- }
- addWordRec(childNode.children, word, depth + 1, frequency);
- }
-
- @Override
- public void getWords(final WordComposer codes, final WordCallback callback,
- int[] nextLettersFrequencies) {
- mInputLength = codes.size();
- mNextLettersFrequencies = nextLettersFrequencies;
- if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
- // Cache the codes so that we don't have to lookup an array list
- for (int i = 0; i < mInputLength; i++) {
- mCodes[i] = codes.getCodesAt(i);
- }
- mMaxDepth = mInputLength * 3;
- getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, callback);
- for (int i = 0; i < mInputLength; i++) {
- getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, i, callback);
- }
- }
-
- @Override
- public synchronized boolean isValidWord(CharSequence word) {
- final int freq = getWordFrequencyRec(mRoots, word, 0, word.length());
- return freq > -1;
- }
-
- /**
- * Returns the word's frequency or -1 if not found
- */
- public int getWordFrequency(CharSequence word) {
- return getWordFrequencyRec(mRoots, word, 0, word.length());
- }
-
- /**
- * Returns the word's frequency or -1 if not found
- */
- private int getWordFrequencyRec(final NodeArray children, final CharSequence word,
- final int offset, final int length) {
- final int count = children.length;
- char currentChar = word.charAt(offset);
- for (int j = 0; j < count; j++) {
- final Node node = children.data[j];
- if (node.code == currentChar) {
- if (offset == length - 1) {
- if (node.terminal) {
- return node.frequency;
- }
- } else {
- if (node.children != null) {
- int freq = getWordFrequencyRec(node.children, word, offset + 1, length);
- if (freq > -1) return freq;
- }
- }
- }
- }
- return -1;
- }
-
- /**
- * Recursively traverse the tree for words that match the input. Input consists of
- * a list of arrays. Each item in the list is one input character position. An input
- * character is actually an array of multiple possible candidates. This function is not
- * optimized for speed, assuming that the user dictionary will only be a few hundred words in
- * size.
- * @param roots node whose children have to be search for matches
- * @param codes the input character codes
- * @param word the word being composed as a possible match
- * @param depth the depth of traversal - the length of the word being composed thus far
- * @param completion whether the traversal is now in completion mode - meaning that we've
- * exhausted the input and we're looking for all possible suffixes.
- * @param snr current weight of the word being formed
- * @param inputIndex position in the input characters. This can be off from the depth in
- * case we skip over some punctuations such as apostrophe in the traversal. That is, if you type
- * "wouldve", it could be matching "would've", so the depth will be one more than the
- * inputIndex
- * @param callback the callback class for adding a word
- */
- protected void getWordsRec(NodeArray roots, final WordComposer codes, final char[] word,
- final int depth, boolean completion, int snr, int inputIndex, int skipPos,
- WordCallback callback) {
- final int count = roots.length;
- final int codeSize = mInputLength;
- // Optimization: Prune out words that are too long compared to how much was typed.
- if (depth > mMaxDepth) {
- return;
- }
- int[] currentChars = null;
- if (codeSize <= inputIndex) {
- completion = true;
- } else {
- currentChars = mCodes[inputIndex];
- }
-
- for (int i = 0; i < count; i++) {
- final Node node = roots.data[i];
- final char c = node.code;
- final char lowerC = toLowerCase(c);
- final boolean terminal = node.terminal;
- final NodeArray children = node.children;
- final int freq = node.frequency;
- if (completion) {
- word[depth] = c;
- if (terminal) {
- if (!callback.addWord(word, 0, depth + 1, freq * snr)) {
- return;
- }
- // Add to frequency of next letters for predictive correction
- if (mNextLettersFrequencies != null && depth >= inputIndex && skipPos < 0
- && mNextLettersFrequencies.length > word[inputIndex]) {
- mNextLettersFrequencies[word[inputIndex]]++;
- }
- }
- if (children != null) {
- getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex,
- skipPos, callback);
- }
- } else if ((c == QUOTE && currentChars[0] != QUOTE) || depth == skipPos) {
- // Skip the ' and continue deeper
- word[depth] = c;
- if (children != null) {
- getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex,
- skipPos, callback);
- }
- } else {
- // Don't use alternatives if we're looking for missing characters
- final int alternativesSize = skipPos >= 0? 1 : currentChars.length;
- for (int j = 0; j < alternativesSize; j++) {
- final int addedAttenuation = (j > 0 ? 1 : 2);
- final int currentChar = currentChars[j];
- if (currentChar == -1) {
- break;
- }
- if (currentChar == lowerC || currentChar == c) {
- word[depth] = c;
-
- if (codeSize == inputIndex + 1) {
- if (terminal) {
- if (INCLUDE_TYPED_WORD_IF_VALID
- || !same(word, depth + 1, codes.getTypedWord())) {
- int finalFreq = freq * snr * addedAttenuation;
- if (skipPos < 0) finalFreq *= FULL_WORD_FREQ_MULTIPLIER;
- callback.addWord(word, 0, depth + 1, finalFreq);
- }
- }
- if (children != null) {
- getWordsRec(children, codes, word, depth + 1,
- true, snr * addedAttenuation, inputIndex + 1,
- skipPos, callback);
- }
- } else if (children != null) {
- getWordsRec(children, codes, word, depth + 1,
- false, snr * addedAttenuation, inputIndex + 1,
- skipPos, callback);
- }
- }
- }
- }
- }
- }
-
- protected void clearDictionary() {
- mRoots = new NodeArray();
- }
-
- static char toLowerCase(char c) {
- if (c < BASE_CHARS.length) {
- c = BASE_CHARS[c];
- }
- if (c >= 'A' && c <= 'Z') {
- c = (char) (c | 32);
- } else if (c > 127) {
- c = Character.toLowerCase(c);
- }
- return c;
- }
-
- /**
- * Table mapping most combined Latin, Greek, and Cyrillic characters
- * to their base characters. If c is in range, BASE_CHARS[c] == c
- * if c is not a combined character, or the base character if it
- * is combined.
- */
- static final char BASE_CHARS[] = {
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
- 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
- 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
- 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
- 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
- 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
- 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
- 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
- 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
- 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
- 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
- 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
- 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
- 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
- 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
- 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
- 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
- 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
- 0x0020, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
- 0x0020, 0x00a9, 0x0061, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0020,
- 0x00b0, 0x00b1, 0x0032, 0x0033, 0x0020, 0x03bc, 0x00b6, 0x00b7,
- 0x0020, 0x0031, 0x006f, 0x00bb, 0x0031, 0x0031, 0x0033, 0x00bf,
- 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x00c6, 0x0043,
- 0x0045, 0x0045, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049,
- 0x00d0, 0x004e, 0x004f, 0x004f, 0x004f, 0x004f, 0x004f, 0x00d7,
- 0x004f, 0x0055, 0x0055, 0x0055, 0x0055, 0x0059, 0x00de, 0x0073, // Manually changed d8 to 4f
- // Manually changed df to 73
- 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x00e6, 0x0063,
- 0x0065, 0x0065, 0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069,
- 0x00f0, 0x006e, 0x006f, 0x006f, 0x006f, 0x006f, 0x006f, 0x00f7,
- 0x006f, 0x0075, 0x0075, 0x0075, 0x0075, 0x0079, 0x00fe, 0x0079, // Manually changed f8 to 6f
- 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0043, 0x0063,
- 0x0043, 0x0063, 0x0043, 0x0063, 0x0043, 0x0063, 0x0044, 0x0064,
- 0x0110, 0x0111, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065,
- 0x0045, 0x0065, 0x0045, 0x0065, 0x0047, 0x0067, 0x0047, 0x0067,
- 0x0047, 0x0067, 0x0047, 0x0067, 0x0048, 0x0068, 0x0126, 0x0127,
- 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069,
- 0x0049, 0x0131, 0x0049, 0x0069, 0x004a, 0x006a, 0x004b, 0x006b,
- 0x0138, 0x004c, 0x006c, 0x004c, 0x006c, 0x004c, 0x006c, 0x004c,
- 0x006c, 0x0141, 0x0142, 0x004e, 0x006e, 0x004e, 0x006e, 0x004e,
- 0x006e, 0x02bc, 0x014a, 0x014b, 0x004f, 0x006f, 0x004f, 0x006f,
- 0x004f, 0x006f, 0x0152, 0x0153, 0x0052, 0x0072, 0x0052, 0x0072,
- 0x0052, 0x0072, 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073,
- 0x0053, 0x0073, 0x0054, 0x0074, 0x0054, 0x0074, 0x0166, 0x0167,
- 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075,
- 0x0055, 0x0075, 0x0055, 0x0075, 0x0057, 0x0077, 0x0059, 0x0079,
- 0x0059, 0x005a, 0x007a, 0x005a, 0x007a, 0x005a, 0x007a, 0x0073,
- 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185, 0x0186, 0x0187,
- 0x0188, 0x0189, 0x018a, 0x018b, 0x018c, 0x018d, 0x018e, 0x018f,
- 0x0190, 0x0191, 0x0192, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197,
- 0x0198, 0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e, 0x019f,
- 0x004f, 0x006f, 0x01a2, 0x01a3, 0x01a4, 0x01a5, 0x01a6, 0x01a7,
- 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x0055,
- 0x0075, 0x01b1, 0x01b2, 0x01b3, 0x01b4, 0x01b5, 0x01b6, 0x01b7,
- 0x01b8, 0x01b9, 0x01ba, 0x01bb, 0x01bc, 0x01bd, 0x01be, 0x01bf,
- 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x0044, 0x0044, 0x0064, 0x004c,
- 0x004c, 0x006c, 0x004e, 0x004e, 0x006e, 0x0041, 0x0061, 0x0049,
- 0x0069, 0x004f, 0x006f, 0x0055, 0x0075, 0x00dc, 0x00fc, 0x00dc,
- 0x00fc, 0x00dc, 0x00fc, 0x00dc, 0x00fc, 0x01dd, 0x00c4, 0x00e4,
- 0x0226, 0x0227, 0x00c6, 0x00e6, 0x01e4, 0x01e5, 0x0047, 0x0067,
- 0x004b, 0x006b, 0x004f, 0x006f, 0x01ea, 0x01eb, 0x01b7, 0x0292,
- 0x006a, 0x0044, 0x0044, 0x0064, 0x0047, 0x0067, 0x01f6, 0x01f7,
- 0x004e, 0x006e, 0x00c5, 0x00e5, 0x00c6, 0x00e6, 0x00d8, 0x00f8,
- 0x0041, 0x0061, 0x0041, 0x0061, 0x0045, 0x0065, 0x0045, 0x0065,
- 0x0049, 0x0069, 0x0049, 0x0069, 0x004f, 0x006f, 0x004f, 0x006f,
- 0x0052, 0x0072, 0x0052, 0x0072, 0x0055, 0x0075, 0x0055, 0x0075,
- 0x0053, 0x0073, 0x0054, 0x0074, 0x021c, 0x021d, 0x0048, 0x0068,
- 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0041, 0x0061,
- 0x0045, 0x0065, 0x00d6, 0x00f6, 0x00d5, 0x00f5, 0x004f, 0x006f,
- 0x022e, 0x022f, 0x0059, 0x0079, 0x0234, 0x0235, 0x0236, 0x0237,
- 0x0238, 0x0239, 0x023a, 0x023b, 0x023c, 0x023d, 0x023e, 0x023f,
- 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247,
- 0x0248, 0x0249, 0x024a, 0x024b, 0x024c, 0x024d, 0x024e, 0x024f,
- 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257,
- 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x025e, 0x025f,
- 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267,
- 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, 0x026f,
- 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277,
- 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f,
- 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287,
- 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, 0x028e, 0x028f,
- 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,
- 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f,
- 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7,
- 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af,
- 0x0068, 0x0266, 0x006a, 0x0072, 0x0279, 0x027b, 0x0281, 0x0077,
- 0x0079, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf,
- 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7,
- 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf,
- 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7,
- 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x02de, 0x02df,
- 0x0263, 0x006c, 0x0073, 0x0078, 0x0295, 0x02e5, 0x02e6, 0x02e7,
- 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef,
- 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7,
- 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff,
- 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
- 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f,
- 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
- 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f,
- 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
- 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f,
- 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
- 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f,
- 0x0300, 0x0301, 0x0342, 0x0313, 0x0308, 0x0345, 0x0346, 0x0347,
- 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f,
- 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
- 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f,
- 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
- 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f,
- 0x0370, 0x0371, 0x0372, 0x0373, 0x02b9, 0x0375, 0x0376, 0x0377,
- 0x0378, 0x0379, 0x0020, 0x037b, 0x037c, 0x037d, 0x003b, 0x037f,
- 0x0380, 0x0381, 0x0382, 0x0383, 0x0020, 0x00a8, 0x0391, 0x00b7,
- 0x0395, 0x0397, 0x0399, 0x038b, 0x039f, 0x038d, 0x03a5, 0x03a9,
- 0x03ca, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
- 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
- 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
- 0x03a8, 0x03a9, 0x0399, 0x03a5, 0x03b1, 0x03b5, 0x03b7, 0x03b9,
- 0x03cb, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
- 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
- 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
- 0x03c8, 0x03c9, 0x03b9, 0x03c5, 0x03bf, 0x03c5, 0x03c9, 0x03cf,
- 0x03b2, 0x03b8, 0x03a5, 0x03d2, 0x03d2, 0x03c6, 0x03c0, 0x03d7,
- 0x03d8, 0x03d9, 0x03da, 0x03db, 0x03dc, 0x03dd, 0x03de, 0x03df,
- 0x03e0, 0x03e1, 0x03e2, 0x03e3, 0x03e4, 0x03e5, 0x03e6, 0x03e7,
- 0x03e8, 0x03e9, 0x03ea, 0x03eb, 0x03ec, 0x03ed, 0x03ee, 0x03ef,
- 0x03ba, 0x03c1, 0x03c2, 0x03f3, 0x0398, 0x03b5, 0x03f6, 0x03f7,
- 0x03f8, 0x03a3, 0x03fa, 0x03fb, 0x03fc, 0x03fd, 0x03fe, 0x03ff,
- 0x0415, 0x0415, 0x0402, 0x0413, 0x0404, 0x0405, 0x0406, 0x0406,
- 0x0408, 0x0409, 0x040a, 0x040b, 0x041a, 0x0418, 0x0423, 0x040f,
- 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
- 0x0418, 0x0418, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
- 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
- 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
- 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
- 0x0438, 0x0438, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
- 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
- 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
- 0x0435, 0x0435, 0x0452, 0x0433, 0x0454, 0x0455, 0x0456, 0x0456,
- 0x0458, 0x0459, 0x045a, 0x045b, 0x043a, 0x0438, 0x0443, 0x045f,
- 0x0460, 0x0461, 0x0462, 0x0463, 0x0464, 0x0465, 0x0466, 0x0467,
- 0x0468, 0x0469, 0x046a, 0x046b, 0x046c, 0x046d, 0x046e, 0x046f,
- 0x0470, 0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0474, 0x0475,
- 0x0478, 0x0479, 0x047a, 0x047b, 0x047c, 0x047d, 0x047e, 0x047f,
- 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
- 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f,
- 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497,
- 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x049f,
- 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7,
- 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af,
- 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7,
- 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x04be, 0x04bf,
- 0x04c0, 0x0416, 0x0436, 0x04c3, 0x04c4, 0x04c5, 0x04c6, 0x04c7,
- 0x04c8, 0x04c9, 0x04ca, 0x04cb, 0x04cc, 0x04cd, 0x04ce, 0x04cf,
- 0x0410, 0x0430, 0x0410, 0x0430, 0x04d4, 0x04d5, 0x0415, 0x0435,
- 0x04d8, 0x04d9, 0x04d8, 0x04d9, 0x0416, 0x0436, 0x0417, 0x0437,
- 0x04e0, 0x04e1, 0x0418, 0x0438, 0x0418, 0x0438, 0x041e, 0x043e,
- 0x04e8, 0x04e9, 0x04e8, 0x04e9, 0x042d, 0x044d, 0x0423, 0x0443,
- 0x0423, 0x0443, 0x0423, 0x0443, 0x0427, 0x0447, 0x04f6, 0x04f7,
- 0x042b, 0x044b, 0x04fa, 0x04fb, 0x04fc, 0x04fd, 0x04fe, 0x04ff,
- };
-
- // generated with:
- // cat UnicodeData.txt | perl -e 'while (<>) { @foo = split(/;/); $foo[5] =~ s/<.*> //; $base[hex($foo[0])] = hex($foo[5]);} for ($i = 0; $i < 0x500; $i += 8) { for ($j = $i; $j < $i + 8; $j++) { printf("0x%04x, ", $base[$j] ? $base[$j] : $j)}; print "\n"; }'
-
-}
diff --git a/src/com/android/inputmethod/latin/Hints.java b/src/com/android/inputmethod/latin/Hints.java
deleted file mode 100644
index 689c8d852..000000000
--- a/src/com/android/inputmethod/latin/Hints.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2009 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 com.android.inputmethod.voice.SettingsUtil;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import android.view.inputmethod.InputConnection;
-
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Logic to determine when to display hints on usage to the user.
- */
-public class Hints {
- public interface Display {
- public void showHint(int viewResource);
- }
-
- private static final String TAG = "Hints";
- private static final String PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN =
- "voice_hint_num_unique_days_shown";
- private static final String PREF_VOICE_HINT_LAST_TIME_SHOWN =
- "voice_hint_last_time_shown";
- private static final String PREF_VOICE_INPUT_LAST_TIME_USED =
- "voice_input_last_time_used";
- private static final String PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT =
- "voice_punctuation_hint_view_count";
- private static final int DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW = 7;
- private static final int DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS = 7;
-
- private Context mContext;
- private Display mDisplay;
- private boolean mVoiceResultContainedPunctuation;
- private int mSwipeHintMaxDaysToShow;
- private int mPunctuationHintMaxDisplays;
-
- // Only show punctuation hint if voice result did not contain punctuation.
- static final Map<CharSequence, String> SPEAKABLE_PUNCTUATION
- = new HashMap<CharSequence, String>();
- static {
- SPEAKABLE_PUNCTUATION.put(",", "comma");
- SPEAKABLE_PUNCTUATION.put(".", "period");
- SPEAKABLE_PUNCTUATION.put("?", "question mark");
- }
-
- public Hints(Context context, Display display) {
- mContext = context;
- mDisplay = display;
-
- ContentResolver cr = mContext.getContentResolver();
- mSwipeHintMaxDaysToShow = SettingsUtil.getSettingsInt(
- cr,
- SettingsUtil.LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS,
- DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW);
- mPunctuationHintMaxDisplays = SettingsUtil.getSettingsInt(
- cr,
- SettingsUtil.LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS,
- DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS);
- }
-
- public boolean showSwipeHintIfNecessary(boolean fieldRecommended) {
- if (fieldRecommended && shouldShowSwipeHint()) {
- showHint(R.layout.voice_swipe_hint);
- return true;
- }
-
- return false;
- }
-
- public boolean showPunctuationHintIfNecessary(InputConnection ic) {
- if (!mVoiceResultContainedPunctuation
- && ic != null
- && getAndIncrementPref(PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT)
- < mPunctuationHintMaxDisplays) {
- CharSequence charBeforeCursor = ic.getTextBeforeCursor(1, 0);
- if (SPEAKABLE_PUNCTUATION.containsKey(charBeforeCursor)) {
- showHint(R.layout.voice_punctuation_hint);
- return true;
- }
- }
-
- return false;
- }
-
- public void registerVoiceResult(String text) {
- // Update the current time as the last time voice input was used.
- SharedPreferences.Editor editor =
- PreferenceManager.getDefaultSharedPreferences(mContext).edit();
- editor.putLong(PREF_VOICE_INPUT_LAST_TIME_USED, System.currentTimeMillis());
- editor.commit();
-
- mVoiceResultContainedPunctuation = false;
- for (CharSequence s : SPEAKABLE_PUNCTUATION.keySet()) {
- if (text.indexOf(s.toString()) >= 0) {
- mVoiceResultContainedPunctuation = true;
- break;
- }
- }
- }
-
- private boolean shouldShowSwipeHint() {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
-
- int numUniqueDaysShown = sp.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0);
-
- // If we've already shown the hint for enough days, we'll return false.
- if (numUniqueDaysShown < mSwipeHintMaxDaysToShow) {
-
- long lastTimeVoiceWasUsed = sp.getLong(PREF_VOICE_INPUT_LAST_TIME_USED, 0);
-
- // If the user has used voice today, we'll return false. (We don't show the hint on
- // any day that the user has already used voice.)
- if (!isFromToday(lastTimeVoiceWasUsed)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Determines whether the provided time is from some time today (i.e., this day, month,
- * and year).
- */
- private boolean isFromToday(long timeInMillis) {
- if (timeInMillis == 0) return false;
-
- Calendar today = Calendar.getInstance();
- today.setTimeInMillis(System.currentTimeMillis());
-
- Calendar timestamp = Calendar.getInstance();
- timestamp.setTimeInMillis(timeInMillis);
-
- return (today.get(Calendar.YEAR) == timestamp.get(Calendar.YEAR) &&
- today.get(Calendar.DAY_OF_MONTH) == timestamp.get(Calendar.DAY_OF_MONTH) &&
- today.get(Calendar.MONTH) == timestamp.get(Calendar.MONTH));
- }
-
- private void showHint(int hintViewResource) {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
-
- int numUniqueDaysShown = sp.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0);
- long lastTimeHintWasShown = sp.getLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, 0);
-
- // If this is the first time the hint is being shown today, increase the saved values
- // to represent that. We don't need to increase the last time the hint was shown unless
- // it is a different day from the current value.
- if (!isFromToday(lastTimeHintWasShown)) {
- SharedPreferences.Editor editor = sp.edit();
- editor.putInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, numUniqueDaysShown + 1);
- editor.putLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, System.currentTimeMillis());
- editor.commit();
- }
-
- if (mDisplay != null) {
- mDisplay.showHint(hintViewResource);
- }
- }
-
- private int getAndIncrementPref(String pref) {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
- int value = sp.getInt(pref, 0);
- SharedPreferences.Editor editor = sp.edit();
- editor.putInt(pref, value + 1);
- editor.commit();
- return value;
- }
-}
diff --git a/src/com/android/inputmethod/latin/InputLanguageSelection.java b/src/com/android/inputmethod/latin/InputLanguageSelection.java
deleted file mode 100644
index b1ddb2175..000000000
--- a/src/com/android/inputmethod/latin/InputLanguageSelection.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.text.Collator;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Locale;
-
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceGroup;
-import android.preference.PreferenceManager;
-import android.text.TextUtils;
-
-public class InputLanguageSelection extends PreferenceActivity {
-
- private String mSelectedLanguages;
- private ArrayList<Loc> mAvailableLanguages = new ArrayList<Loc>();
- private static final String[] BLACKLIST_LANGUAGES = {
- "ko", "ja", "zh"
- };
-
- private static class Loc implements Comparable {
- static Collator sCollator = Collator.getInstance();
-
- String label;
- Locale locale;
-
- public Loc(String label, Locale locale) {
- this.label = label;
- this.locale = locale;
- }
-
- @Override
- public String toString() {
- return this.label;
- }
-
- public int compareTo(Object o) {
- return sCollator.compare(this.label, ((Loc) o).label);
- }
- }
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- addPreferencesFromResource(R.xml.language_prefs);
- // Get the settings preferences
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
- mSelectedLanguages = sp.getString(LatinIME.PREF_SELECTED_LANGUAGES, "");
- String[] languageList = mSelectedLanguages.split(",");
- mAvailableLanguages = getUniqueLocales();
- PreferenceGroup parent = getPreferenceScreen();
- for (int i = 0; i < mAvailableLanguages.size(); i++) {
- CheckBoxPreference pref = new CheckBoxPreference(this);
- Locale locale = mAvailableLanguages.get(i).locale;
- pref.setTitle(LanguageSwitcher.toTitleCase(locale.getDisplayName(locale)));
- boolean checked = isLocaleIn(locale, languageList);
- pref.setChecked(checked);
- parent.addPreference(pref);
- }
- }
-
- private boolean isLocaleIn(Locale locale, String[] list) {
- String lang = get5Code(locale);
- for (int i = 0; i < list.length; i++) {
- if (lang.equalsIgnoreCase(list[i])) return true;
- }
- // If it matches the current locale
- Locale displayLocale = getResources().getConfiguration().locale;
- if (lang.equalsIgnoreCase(get5Code(displayLocale))) {
- return true;
- }
- return false;
- }
-
- private String get5Code(Locale locale) {
- String country = locale.getCountry();
- return locale.getLanguage()
- + (TextUtils.isEmpty(country) ? "" : "_" + country);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- // Save the selected languages
- String checkedLanguages = "";
- PreferenceGroup parent = getPreferenceScreen();
- int count = parent.getPreferenceCount();
- for (int i = 0; i < count; i++) {
- CheckBoxPreference pref = (CheckBoxPreference) parent.getPreference(i);
- if (pref.isChecked()) {
- Locale locale = mAvailableLanguages.get(i).locale;
- checkedLanguages += get5Code(locale) + ",";
- }
- }
- if (checkedLanguages.length() < 1) checkedLanguages = null; // Save null
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
- Editor editor = sp.edit();
- editor.putString(LatinIME.PREF_SELECTED_LANGUAGES, checkedLanguages);
- editor.commit();
- }
-
- ArrayList<Loc> getUniqueLocales() {
- String[] locales = getAssets().getLocales();
- Arrays.sort(locales);
- ArrayList<Loc> uniqueLocales = new ArrayList<Loc>();
-
- final int origSize = locales.length;
- Loc[] preprocess = new Loc[origSize];
- int finalSize = 0;
- for (int i = 0 ; i < origSize; i++ ) {
- String s = locales[i];
- int len = s.length();
- if (len == 5) {
- String language = s.substring(0, 2);
- String country = s.substring(3, 5);
- Locale l = new Locale(language, country);
-
- // Exclude languages that are not relevant to LatinIME
- if (arrayContains(BLACKLIST_LANGUAGES, language)) continue;
-
- if (finalSize == 0) {
- preprocess[finalSize++] =
- new Loc(LanguageSwitcher.toTitleCase(l.getDisplayName(l)), l);
- } else {
- // check previous entry:
- // same lang and a country -> upgrade to full name and
- // insert ours with full name
- // diff lang -> insert ours with lang-only name
- if (preprocess[finalSize-1].locale.getLanguage().equals(
- language)) {
- preprocess[finalSize-1].label = LanguageSwitcher.toTitleCase(
- preprocess[finalSize-1].locale.getDisplayName());
- preprocess[finalSize++] =
- new Loc(LanguageSwitcher.toTitleCase(l.getDisplayName()), l);
- } else {
- String displayName;
- if (s.equals("zz_ZZ")) {
- } else {
- displayName = LanguageSwitcher.toTitleCase(l.getDisplayName(l));
- preprocess[finalSize++] = new Loc(displayName, l);
- }
- }
- }
- }
- }
- for (int i = 0; i < finalSize ; i++) {
- uniqueLocales.add(preprocess[i]);
- }
- return uniqueLocales;
- }
-
- private boolean arrayContains(String[] array, String value) {
- for (int i = 0; i < array.length; i++) {
- if (array[i].equalsIgnoreCase(value)) return true;
- }
- return false;
- }
-}
diff --git a/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/src/com/android/inputmethod/latin/KeyboardSwitcher.java
deleted file mode 100644
index 438680cf8..000000000
--- a/src/com/android/inputmethod/latin/KeyboardSwitcher.java
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (C) 2008 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.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.inputmethodservice.InputMethodService;
-
-public class KeyboardSwitcher {
-
- public static final int MODE_TEXT = 1;
- public static final int MODE_SYMBOLS = 2;
- public static final int MODE_PHONE = 3;
- public static final int MODE_URL = 4;
- public static final int MODE_EMAIL = 5;
- public static final int MODE_IM = 6;
- public static final int MODE_WEB = 7;
-
- public static final int MODE_TEXT_QWERTY = 0;
- public static final int MODE_TEXT_ALPHA = 1;
- public static final int MODE_TEXT_COUNT = 2;
-
- public static final int KEYBOARDMODE_NORMAL = R.id.mode_normal;
- public static final int KEYBOARDMODE_URL = R.id.mode_url;
- public static final int KEYBOARDMODE_EMAIL = R.id.mode_email;
- public static final int KEYBOARDMODE_IM = R.id.mode_im;
- public static final int KEYBOARDMODE_WEB = R.id.mode_webentry;
-
- private static final int SYMBOLS_MODE_STATE_NONE = 0;
- private static final int SYMBOLS_MODE_STATE_BEGIN = 1;
- private static final int SYMBOLS_MODE_STATE_SYMBOL = 2;
-
- LatinKeyboardView mInputView;
- private static final int[] ALPHABET_MODES = {
- KEYBOARDMODE_NORMAL,
- KEYBOARDMODE_URL,
- KEYBOARDMODE_EMAIL,
- KEYBOARDMODE_IM,
- KEYBOARDMODE_WEB};
-
- //LatinIME mContext;
- Context mContext;
- InputMethodService mInputMethodService;
-
- private KeyboardId mSymbolsId;
- private KeyboardId mSymbolsShiftedId;
-
- private KeyboardId mCurrentId;
- private Map<KeyboardId, LatinKeyboard> mKeyboards;
-
- private int mMode; /** One of the MODE_XXX values */
- private int mImeOptions;
- private int mTextMode = MODE_TEXT_QWERTY;
- private boolean mIsSymbols;
- private boolean mHasVoice;
- private boolean mVoiceOnPrimary;
- private boolean mPreferSymbols;
- private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
-
- private int mLastDisplayWidth;
- private LanguageSwitcher mLanguageSwitcher;
- private Locale mInputLocale;
- private boolean mEnableMultipleLanguages;
-
- KeyboardSwitcher(Context context, InputMethodService ims) {
- mContext = context;
- mKeyboards = new HashMap<KeyboardId, LatinKeyboard>();
- mSymbolsId = new KeyboardId(R.xml.kbd_symbols, false);
- mSymbolsShiftedId = new KeyboardId(R.xml.kbd_symbols_shift, false);
- mInputMethodService = ims;
- }
-
- /**
- * Sets the input locale, when there are multiple locales for input.
- * If no locale switching is required, then the locale should be set to null.
- * @param locale the current input locale, or null for default locale with no locale
- * button.
- */
- void setLanguageSwitcher(LanguageSwitcher languageSwitcher) {
- mLanguageSwitcher = languageSwitcher;
- mInputLocale = mLanguageSwitcher.getInputLocale();
- mEnableMultipleLanguages = mLanguageSwitcher.getLocaleCount() > 1;
- }
-
- void setInputView(LatinKeyboardView inputView) {
- mInputView = inputView;
- }
-
- void makeKeyboards(boolean forceCreate) {
- if (forceCreate) mKeyboards.clear();
- // Configuration change is coming after the keyboard gets recreated. So don't rely on that.
- // If keyboards have already been made, check if we have a screen width change and
- // create the keyboard layouts again at the correct orientation
- int displayWidth = mInputMethodService.getMaxWidth();
- if (displayWidth == mLastDisplayWidth) return;
- mLastDisplayWidth = displayWidth;
- if (!forceCreate) mKeyboards.clear();
- mSymbolsId = new KeyboardId(R.xml.kbd_symbols, mHasVoice && !mVoiceOnPrimary);
- mSymbolsShiftedId = new KeyboardId(R.xml.kbd_symbols_shift,
- mHasVoice && !mVoiceOnPrimary);
- }
-
- /**
- * Represents the parameters necessary to construct a new LatinKeyboard,
- * which also serve as a unique identifier for each keyboard type.
- */
- private static class KeyboardId {
- public int mXml;
- public int mKeyboardMode; /** A KEYBOARDMODE_XXX value */
- public boolean mEnableShiftLock;
- public boolean mHasVoice;
-
- public KeyboardId(int xml, int mode, boolean enableShiftLock, boolean hasVoice) {
- this.mXml = xml;
- this.mKeyboardMode = mode;
- this.mEnableShiftLock = enableShiftLock;
- this.mHasVoice = hasVoice;
- }
-
- public KeyboardId(int xml, boolean hasVoice) {
- this(xml, 0, false, hasVoice);
- }
-
- public boolean equals(Object other) {
- return other instanceof KeyboardId && equals((KeyboardId) other);
- }
-
- public boolean equals(KeyboardId other) {
- return other.mXml == this.mXml
- && other.mKeyboardMode == this.mKeyboardMode
- && other.mEnableShiftLock == this.mEnableShiftLock;
- }
-
- public int hashCode() {
- return (mXml + 1) * (mKeyboardMode + 1) * (mEnableShiftLock ? 2 : 1)
- * (mHasVoice ? 4 : 8);
- }
- }
-
- void setVoiceMode(boolean enableVoice, boolean voiceOnPrimary) {
- if (enableVoice != mHasVoice || voiceOnPrimary != mVoiceOnPrimary) {
- mKeyboards.clear();
- }
- mHasVoice = enableVoice;
- mVoiceOnPrimary = voiceOnPrimary;
- setKeyboardMode(mMode, mImeOptions, mHasVoice,
- mIsSymbols);
- }
-
- boolean hasVoiceButton(boolean isSymbols) {
- return mHasVoice && (isSymbols != mVoiceOnPrimary);
- }
-
- void setKeyboardMode(int mode, int imeOptions, boolean enableVoice) {
- mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
- mPreferSymbols = mode == MODE_SYMBOLS;
- setKeyboardMode(mode == MODE_SYMBOLS ? MODE_TEXT : mode, imeOptions, enableVoice,
- mPreferSymbols);
- }
-
- void setKeyboardMode(int mode, int imeOptions, boolean enableVoice, boolean isSymbols) {
- if (mInputView == null) return;
- mMode = mode;
- mImeOptions = imeOptions;
- if (enableVoice != mHasVoice) {
- setVoiceMode(mHasVoice, mVoiceOnPrimary);
- }
- mIsSymbols = isSymbols;
-
- mInputView.setPreviewEnabled(true);
- KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols);
-
- LatinKeyboard keyboard = getKeyboard(id);
-
- if (mode == MODE_PHONE) {
- mInputView.setPhoneKeyboard(keyboard);
- mInputView.setPreviewEnabled(false);
- }
-
- mCurrentId = id;
- mInputView.setKeyboard(keyboard);
- keyboard.setShifted(false);
- keyboard.setShiftLocked(keyboard.isShiftLocked());
- keyboard.setImeOptions(mContext.getResources(), mMode, imeOptions);
- }
-
- private LatinKeyboard getKeyboard(KeyboardId id) {
- if (!mKeyboards.containsKey(id)) {
- Resources orig = mContext.getResources();
- Configuration conf = orig.getConfiguration();
- Locale saveLocale = conf.locale;
- conf.locale = mInputLocale;
- orig.updateConfiguration(conf, null);
- LatinKeyboard keyboard = new LatinKeyboard(
- mContext, id.mXml, id.mKeyboardMode);
- keyboard.setVoiceMode(hasVoiceButton(id.mXml == R.xml.kbd_symbols), mHasVoice);
- keyboard.setLanguageSwitcher(mLanguageSwitcher);
- if (id.mKeyboardMode == KEYBOARDMODE_NORMAL
- || id.mKeyboardMode == KEYBOARDMODE_URL
- || id.mKeyboardMode == KEYBOARDMODE_IM
- || id.mKeyboardMode == KEYBOARDMODE_EMAIL
- || id.mKeyboardMode == KEYBOARDMODE_WEB
- ) {
- keyboard.setExtension(R.xml.kbd_extension);
- }
-
- if (id.mEnableShiftLock) {
- keyboard.enableShiftLock();
- }
- mKeyboards.put(id, keyboard);
-
- conf.locale = saveLocale;
- orig.updateConfiguration(conf, null);
- }
- return mKeyboards.get(id);
- }
-
- private KeyboardId getKeyboardId(int mode, int imeOptions, boolean isSymbols) {
- boolean hasVoice = hasVoiceButton(isSymbols);
- if (isSymbols) {
- return (mode == MODE_PHONE)
- ? new KeyboardId(R.xml.kbd_phone_symbols, hasVoice)
- : new KeyboardId(R.xml.kbd_symbols, hasVoice);
- }
- switch (mode) {
- case MODE_TEXT:
- if (mTextMode == MODE_TEXT_QWERTY) {
- return new KeyboardId(R.xml.kbd_qwerty, KEYBOARDMODE_NORMAL, true, hasVoice);
- } else if (mTextMode == MODE_TEXT_ALPHA) {
- return new KeyboardId(R.xml.kbd_alpha, KEYBOARDMODE_NORMAL, true, hasVoice);
- }
- break;
- case MODE_SYMBOLS:
- return new KeyboardId(R.xml.kbd_symbols, hasVoice);
- case MODE_PHONE:
- return new KeyboardId(R.xml.kbd_phone, hasVoice);
- case MODE_URL:
- return new KeyboardId(R.xml.kbd_qwerty, KEYBOARDMODE_URL, true, hasVoice);
- case MODE_EMAIL:
- return new KeyboardId(R.xml.kbd_qwerty, KEYBOARDMODE_EMAIL, true, hasVoice);
- case MODE_IM:
- return new KeyboardId(R.xml.kbd_qwerty, KEYBOARDMODE_IM, true, hasVoice);
- case MODE_WEB:
- return new KeyboardId(R.xml.kbd_qwerty, KEYBOARDMODE_WEB, true, hasVoice);
- }
- return null;
- }
-
- int getKeyboardMode() {
- return mMode;
- }
-
- boolean isTextMode() {
- return mMode == MODE_TEXT;
- }
-
- int getTextMode() {
- return mTextMode;
- }
-
- void setTextMode(int position) {
- if (position < MODE_TEXT_COUNT && position >= 0) {
- mTextMode = position;
- }
- if (isTextMode()) {
- setKeyboardMode(MODE_TEXT, mImeOptions, mHasVoice);
- }
- }
-
- int getTextModeCount() {
- return MODE_TEXT_COUNT;
- }
-
- boolean isAlphabetMode() {
- int currentMode = mCurrentId.mKeyboardMode;
- for (Integer mode : ALPHABET_MODES) {
- if (currentMode == mode) {
- return true;
- }
- }
- return false;
- }
-
- void toggleShift() {
- if (mCurrentId.equals(mSymbolsId)) {
- LatinKeyboard symbolsKeyboard = getKeyboard(mSymbolsId);
- LatinKeyboard symbolsShiftedKeyboard = getKeyboard(mSymbolsShiftedId);
- symbolsKeyboard.setShifted(true);
- mCurrentId = mSymbolsShiftedId;
- mInputView.setKeyboard(symbolsShiftedKeyboard);
- symbolsShiftedKeyboard.setShifted(true);
- symbolsShiftedKeyboard.setImeOptions(mContext.getResources(), mMode, mImeOptions);
- } else if (mCurrentId.equals(mSymbolsShiftedId)) {
- LatinKeyboard symbolsKeyboard = getKeyboard(mSymbolsId);
- LatinKeyboard symbolsShiftedKeyboard = getKeyboard(mSymbolsShiftedId);
- symbolsShiftedKeyboard.setShifted(false);
- mCurrentId = mSymbolsId;
- mInputView.setKeyboard(getKeyboard(mSymbolsId));
- symbolsKeyboard.setShifted(false);
- symbolsKeyboard.setImeOptions(mContext.getResources(), mMode, mImeOptions);
- }
- }
-
- void toggleSymbols() {
- setKeyboardMode(mMode, mImeOptions, mHasVoice, !mIsSymbols);
- if (mIsSymbols && !mPreferSymbols) {
- mSymbolsModeState = SYMBOLS_MODE_STATE_BEGIN;
- } else {
- mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
- }
- }
-
- /**
- * Updates state machine to figure out when to automatically switch back to alpha mode.
- * Returns true if the keyboard needs to switch back
- */
- boolean onKey(int key) {
- // Switch back to alpha mode if user types one or more non-space/enter characters
- // followed by a space/enter
- switch (mSymbolsModeState) {
- case SYMBOLS_MODE_STATE_BEGIN:
- if (key != LatinIME.KEYCODE_SPACE && key != LatinIME.KEYCODE_ENTER && key > 0) {
- mSymbolsModeState = SYMBOLS_MODE_STATE_SYMBOL;
- }
- break;
- case SYMBOLS_MODE_STATE_SYMBOL:
- if (key == LatinIME.KEYCODE_ENTER || key == LatinIME.KEYCODE_SPACE) return true;
- break;
- }
- return false;
- }
-}
diff --git a/src/com/android/inputmethod/latin/LanguageSwitcher.java b/src/com/android/inputmethod/latin/LanguageSwitcher.java
deleted file mode 100644
index 12045125f..000000000
--- a/src/com/android/inputmethod/latin/LanguageSwitcher.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 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;
-import android.text.TextUtils;
-
-/**
- * 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;
- String country = mDefaultInputLocale.getCountry();
- mDefaultInputLanguage = mDefaultInputLocale.getLanguage() +
- (TextUtils.isEmpty(country) ? "" : "_" + country);
- }
-
- 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 list of enabled language codes.
- */
- public String[] getEnabledLanguages() {
- return mSelectedLanguageArray;
- }
-
- /**
- * 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();
- }
-
- static String toTitleCase(String s) {
- if (s.length() == 0) {
- return s;
- }
-
- return Character.toUpperCase(s.charAt(0)) + s.substring(1);
- }
-}
diff --git a/src/com/android/inputmethod/latin/LatinIME.java b/src/com/android/inputmethod/latin/LatinIME.java
deleted file mode 100644
index 43972d98b..000000000
--- a/src/com/android/inputmethod/latin/LatinIME.java
+++ /dev/null
@@ -1,1949 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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 com.android.inputmethod.voice.EditingUtil;
-import com.android.inputmethod.voice.FieldContext;
-import com.android.inputmethod.voice.SettingsUtil;
-import com.android.inputmethod.voice.VoiceInput;
-
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.inputmethodservice.InputMethodService;
-import android.inputmethodservice.Keyboard;
-import android.inputmethodservice.KeyboardView;
-import android.media.AudioManager;
-import android.os.Debug;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.preference.PreferenceManager;
-import android.speech.RecognitionManager;
-import android.text.AutoText;
-import android.text.ClipboardManager;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.PrintWriterPrinter;
-import android.util.Printer;
-import android.view.HapticFeedbackConstants;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewParent;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Input method implementation for Qwerty'ish keyboard.
- */
-public class LatinIME extends InputMethodService
- implements KeyboardView.OnKeyboardActionListener,
- VoiceInput.UiListener,
- SharedPreferences.OnSharedPreferenceChangeListener {
- private static final String TAG = "LatinIME";
- static final boolean DEBUG = false;
- static final boolean TRACE = false;
- static final boolean VOICE_INSTALLED = true;
- static final boolean ENABLE_VOICE_BUTTON = true;
-
- private static final String PREF_VIBRATE_ON = "vibrate_on";
- private static final String PREF_SOUND_ON = "sound_on";
- private static final String PREF_AUTO_CAP = "auto_cap";
- private static final String PREF_QUICK_FIXES = "quick_fixes";
- private static final String PREF_SHOW_SUGGESTIONS = "show_suggestions";
- private static final String PREF_AUTO_COMPLETE = "auto_complete";
- private static final String PREF_VOICE_MODE = "voice_mode";
-
- // Whether or not the user has used voice input before (and thus, whether to show the
- // first-run warning dialog or not).
- private static final String PREF_HAS_USED_VOICE_INPUT = "has_used_voice_input";
-
- // Whether or not the user has used voice input from an unsupported locale UI before.
- // For example, the user has a Chinese UI but activates voice input.
- private static final String PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE =
- "has_used_voice_input_unsupported_locale";
-
- // A list of locales which are supported by default for voice input, unless we get a
- // different list from Gservices.
- public static final String DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES =
- "en " +
- "en_US " +
- "en_GB " +
- "en_AU " +
- "en_CA " +
- "en_IE " +
- "en_IN " +
- "en_NZ " +
- "en_SG " +
- "en_ZA ";
-
- // The private IME option used to indicate that no microphone should be shown for a
- // given text field. For instance this is specified by the search dialog when the
- // dialog is already showing a voice search button.
- private static final String IME_OPTION_NO_MICROPHONE = "nm";
-
- public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
- public static final String PREF_INPUT_LANGUAGE = "input_language";
-
- private static final int MSG_UPDATE_SUGGESTIONS = 0;
- private static final int MSG_START_TUTORIAL = 1;
- private static final int MSG_UPDATE_SHIFT_STATE = 2;
- private static final int MSG_VOICE_RESULTS = 3;
- private static final int MSG_START_LISTENING_AFTER_SWIPE = 4;
-
- // If we detect a swipe gesture within N ms of typing, then swipe is
- // ignored, since it may in fact be two key presses in quick succession.
- private static final long MIN_MILLIS_AFTER_TYPING_BEFORE_SWIPE = 1000;
-
- // How many continuous deletes at which to start deleting at a higher speed.
- private static final int DELETE_ACCELERATE_AT = 20;
- // Key events coming any faster than this are long-presses.
- private static final int QUICK_PRESS = 200;
-
- static final int KEYCODE_ENTER = '\n';
- static final int KEYCODE_SPACE = ' ';
- static final int KEYCODE_PERIOD = '.';
-
- // Contextual menu positions
- private static final int POS_SETTINGS = 0;
- private static final int POS_METHOD = 1;
-
- private LatinKeyboardView mInputView;
- private CandidateViewContainer mCandidateViewContainer;
- private CandidateView mCandidateView;
- private Suggest mSuggest;
- private CompletionInfo[] mCompletions;
-
- private AlertDialog mOptionsDialog;
- private AlertDialog mVoiceWarningDialog;
-
- KeyboardSwitcher mKeyboardSwitcher;
-
- private UserDictionary mUserDictionary;
- private ContactsDictionary mContactsDictionary;
- private ExpandableDictionary mAutoDictionary;
-
- private Hints mHints;
-
- Resources mResources;
-
- private String mLocale;
- private LanguageSwitcher mLanguageSwitcher;
-
- private StringBuilder mComposing = new StringBuilder();
- private WordComposer mWord = new WordComposer();
- private int mCommittedLength;
- private boolean mPredicting;
- private boolean mRecognizing;
- private boolean mAfterVoiceInput;
- private boolean mImmediatelyAfterVoiceInput;
- private boolean mShowingVoiceSuggestions;
- private boolean mImmediatelyAfterVoiceSuggestions;
- private boolean mVoiceInputHighlighted;
- private boolean mEnableVoiceButton;
- private CharSequence mBestWord;
- private boolean mPredictionOn;
- private boolean mCompletionOn;
- private boolean mHasDictionary;
- private boolean mAutoSpace;
- private boolean mJustAddedAutoSpace;
- private boolean mAutoCorrectEnabled;
- private boolean mAutoCorrectOn;
- private boolean mCapsLock;
- private boolean mPasswordText;
- private boolean mEmailText;
- private boolean mVibrateOn;
- private boolean mSoundOn;
- private boolean mAutoCap;
- private boolean mQuickFixes;
- private boolean mHasUsedVoiceInput;
- private boolean mHasUsedVoiceInputUnsupportedLocale;
- private boolean mLocaleSupportedForVoiceInput;
- private boolean mShowSuggestions;
- private boolean mSuggestionShouldReplaceCurrentWord;
- private boolean mIsShowingHint;
- private int mCorrectionMode;
- private boolean mEnableVoice = true;
- private boolean mVoiceOnPrimary;
- private int mOrientation;
- private List<CharSequence> mSuggestPuncList;
-
- // Indicates whether the suggestion strip is to be on in landscape
- private boolean mJustAccepted;
- private CharSequence mJustRevertedSeparator;
- private int mDeleteCount;
- private long mLastKeyTime;
-
- private Tutorial mTutorial;
-
- private AudioManager mAudioManager;
- // Align sound effect volume on music volume
- private final float FX_VOLUME = -1.0f;
- private boolean mSilentMode;
-
- private String mWordSeparators;
- private String mSentenceSeparators;
- private VoiceInput mVoiceInput;
- private VoiceResults mVoiceResults = new VoiceResults();
- private long mSwipeTriggerTimeMillis;
- private boolean mConfigurationChanging;
-
- // For each word, a list of potential replacements, usually from voice.
- private Map<String, List<CharSequence>> mWordToSuggestions =
- new HashMap<String, List<CharSequence>>();
-
- private class VoiceResults {
- List<String> candidates;
- Map<String, List<CharSequence>> alternatives;
- }
- private boolean mRefreshKeyboardRequired;
-
- Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_UPDATE_SUGGESTIONS:
- updateSuggestions();
- break;
- case MSG_START_TUTORIAL:
- if (mTutorial == null) {
- if (mInputView.isShown()) {
- mTutorial = new Tutorial(LatinIME.this, mInputView);
- mTutorial.start();
- } else {
- // Try again soon if the view is not yet showing
- sendMessageDelayed(obtainMessage(MSG_START_TUTORIAL), 100);
- }
- }
- break;
- case MSG_UPDATE_SHIFT_STATE:
- updateShiftKeyState(getCurrentInputEditorInfo());
- break;
- case MSG_VOICE_RESULTS:
- handleVoiceResults();
- break;
- case MSG_START_LISTENING_AFTER_SWIPE:
- if (mLastKeyTime < mSwipeTriggerTimeMillis) {
- startListening(true);
- }
- }
- }
- };
-
- @Override public void onCreate() {
- super.onCreate();
- //setStatusIcon(R.drawable.ime_qwerty);
- mResources = getResources();
- final Configuration conf = mResources.getConfiguration();
- 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;
- initSuggestPuncList();
-
- // register to receive ringer mode changes for silent mode
- IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
- registerReceiver(mReceiver, filter);
- if (VOICE_INSTALLED) {
- mVoiceInput = new VoiceInput(this, this);
- mHints = new Hints(this, new Hints.Display() {
- public void showHint(int viewResource) {
- LayoutInflater inflater = (LayoutInflater) getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(viewResource, null);
- setCandidatesView(view);
- setCandidatesViewShown(true);
- mIsShowingHint = true;
- }
- });
- }
- prefs.registerOnSharedPreferenceChangeListener(this);
- }
-
- private void initSuggest(String locale) {
- mLocale = locale;
-
- Resources orig = getResources();
- Configuration conf = orig.getConfiguration();
- Locale saveLocale = conf.locale;
- conf.locale = new Locale(locale);
- orig.updateConfiguration(conf, orig.getDisplayMetrics());
- if (mSuggest != null) {
- mSuggest.close();
- }
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
- mQuickFixes = sp.getBoolean(PREF_QUICK_FIXES, true);
- mSuggest = new Suggest(this, R.raw.main);
- updateAutoTextEnabled(saveLocale);
- if (mUserDictionary != null) mUserDictionary.close();
- mUserDictionary = new UserDictionary(this, mLocale);
- if (mContactsDictionary == null) {
- mContactsDictionary = new ContactsDictionary(this);
- }
- if (mAutoDictionary != null) {
- mAutoDictionary.close();
- }
- mAutoDictionary = new AutoDictionary(this, this, mLocale);
- mSuggest.setUserDictionary(mUserDictionary);
- mSuggest.setContactsDictionary(mContactsDictionary);
- mSuggest.setAutoDictionary(mAutoDictionary);
- updateCorrectionMode();
- mWordSeparators = mResources.getString(R.string.word_separators);
- mSentenceSeparators = mResources.getString(R.string.sentence_separators);
-
- conf.locale = saveLocale;
- orig.updateConfiguration(conf, orig.getDisplayMetrics());
- }
-
- @Override
- public void onDestroy() {
- mUserDictionary.close();
- mContactsDictionary.close();
- unregisterReceiver(mReceiver);
- if (VOICE_INSTALLED) {
- mVoiceInput.destroy();
- }
- super.onDestroy();
- }
-
- @Override
- public void onConfigurationChanged(Configuration conf) {
- // If the system locale changes and is different from the saved
- // locale (mLocale), then reload the input locale list from the
- // latin ime settings (shared prefs) and reset the input locale
- // to the first one.
- if (!TextUtils.equals(conf.locale.toString(), mLocale)) {
- if (mLanguageSwitcher != null) {
- mLanguageSwitcher.loadLocales(
- PreferenceManager.getDefaultSharedPreferences(this));
- toggleLanguage(true, true);
- } else {
- reloadKeyboards();
- }
- }
- // If orientation changed while predicting, commit the change
- if (conf.orientation != mOrientation) {
- InputConnection ic = getCurrentInputConnection();
- commitTyped(ic);
- if (ic != null) ic.finishComposingText(); // For voice input
- mOrientation = conf.orientation;
- reloadKeyboards();
- }
- mConfigurationChanging = true;
- super.onConfigurationChanged(conf);
- if (mRecognizing) {
- switchToRecognitionStatusView();
- }
- mConfigurationChanging = false;
- }
-
- @Override
- public View onCreateInputView() {
- mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
- R.layout.input, null);
- mKeyboardSwitcher.setInputView(mInputView);
- mKeyboardSwitcher.makeKeyboards(true);
- mInputView.setOnKeyboardActionListener(this);
- mKeyboardSwitcher.setKeyboardMode(
- KeyboardSwitcher.MODE_TEXT, 0,
- shouldShowVoiceButton(makeFieldContext(), getCurrentInputEditorInfo()));
- return mInputView;
- }
-
- @Override
- public View onCreateCandidatesView() {
- mKeyboardSwitcher.makeKeyboards(true);
- mCandidateViewContainer = (CandidateViewContainer) getLayoutInflater().inflate(
- R.layout.candidates, null);
- mCandidateViewContainer.initViews();
- mCandidateView = (CandidateView) mCandidateViewContainer.findViewById(R.id.candidates);
- mCandidateView.setService(this);
- setCandidatesViewShown(true);
- return mCandidateViewContainer;
- }
-
- @Override
- public void onStartInputView(EditorInfo attribute, boolean restarting) {
- // In landscape mode, this method gets called without the input view being created.
- if (mInputView == null) {
- return;
- }
-
- if (mRefreshKeyboardRequired) {
- mRefreshKeyboardRequired = false;
- toggleLanguage(true, true);
- }
-
- mKeyboardSwitcher.makeKeyboards(false);
-
- TextEntryState.newSession(this);
-
- // Most such things we decide below in the switch statement, but we need to know
- // now whether this is a password text field, because we need to know now (before
- // the switch statement) whether we want to enable the voice button.
- mPasswordText = false;
- int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION;
- if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD ||
- variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
- mPasswordText = true;
- }
-
- mEnableVoiceButton = shouldShowVoiceButton(makeFieldContext(), attribute);
- final boolean enableVoiceButton = mEnableVoiceButton && mEnableVoice;
-
- mAfterVoiceInput = false;
- mImmediatelyAfterVoiceInput = false;
- mShowingVoiceSuggestions = false;
- mImmediatelyAfterVoiceSuggestions = false;
- mVoiceInputHighlighted = false;
- mWordToSuggestions.clear();
- mInputTypeNoAutoCorrect = false;
- mPredictionOn = false;
- mCompletionOn = false;
- mCompletions = null;
- mCapsLock = false;
- mEmailText = false;
- switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) {
- case EditorInfo.TYPE_CLASS_NUMBER:
- case EditorInfo.TYPE_CLASS_DATETIME:
- mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_SYMBOLS,
- attribute.imeOptions, enableVoiceButton);
- break;
- case EditorInfo.TYPE_CLASS_PHONE:
- mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_PHONE,
- attribute.imeOptions, enableVoiceButton);
- break;
- case EditorInfo.TYPE_CLASS_TEXT:
- mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT,
- attribute.imeOptions, enableVoiceButton);
- //startPrediction();
- mPredictionOn = true;
- // Make sure that passwords are not displayed in candidate view
- if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD ||
- variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD ) {
- mPredictionOn = false;
- }
- if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) {
- mEmailText = true;
- }
- if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
- || variation == EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME) {
- mAutoSpace = false;
- } else {
- mAutoSpace = true;
- }
- if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) {
- mPredictionOn = false;
- mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_EMAIL,
- attribute.imeOptions, enableVoiceButton);
- } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
- mPredictionOn = false;
- mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_URL,
- attribute.imeOptions, enableVoiceButton);
- } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
- mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_IM,
- attribute.imeOptions, enableVoiceButton);
- } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) {
- mPredictionOn = false;
- } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) {
- mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_WEB,
- attribute.imeOptions, enableVoiceButton);
- // If it's a browser edit field and auto correct is not ON explicitly, then
- // disable auto correction, but keep suggestions on.
- if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
- mInputTypeNoAutoCorrect = true;
- }
- }
-
- // If NO_SUGGESTIONS is set, don't do prediction.
- if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) {
- mPredictionOn = false;
- mInputTypeNoAutoCorrect = true;
- }
- // If it's not multiline and the autoCorrect flag is not set, then don't correct
- if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 &&
- (attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) == 0) {
- mInputTypeNoAutoCorrect = true;
- }
- if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
- mPredictionOn = false;
- mCompletionOn = true && isFullscreenMode();
- }
- updateShiftKeyState(attribute);
- break;
- default:
- mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT,
- attribute.imeOptions, enableVoiceButton);
- updateShiftKeyState(attribute);
- }
- mInputView.closing();
- mComposing.setLength(0);
- mPredicting = false;
- mDeleteCount = 0;
- mJustAddedAutoSpace = false;
- loadSettings();
- updateShiftKeyState(attribute);
-
- setCandidatesViewShown(false);
- setSuggestions(null, false, false, false);
-
- // If the dictionary is not big enough, don't auto correct
- mHasDictionary = mSuggest.hasMainDictionary();
-
- updateCorrectionMode();
-
- mInputView.setProximityCorrectionEnabled(true);
- mPredictionOn = mPredictionOn && (mCorrectionMode > 0 || mShowSuggestions);
- checkTutorial(attribute.privateImeOptions);
- if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
- }
-
- @Override
- public void onFinishInput() {
- super.onFinishInput();
-
- if (VOICE_INSTALLED && !mConfigurationChanging) {
- if (mAfterVoiceInput) {
- mVoiceInput.logInputEnded();
- }
- mVoiceInput.flushLogs();
- mVoiceInput.cancel();
- }
- if (mInputView != null) {
- mInputView.closing();
- }
- }
-
- @Override
- public void onUpdateExtractedText(int token, ExtractedText text) {
- super.onUpdateExtractedText(token, text);
- InputConnection ic = getCurrentInputConnection();
- if (!mImmediatelyAfterVoiceInput && mAfterVoiceInput && ic != null) {
- mVoiceInput.logTextModified();
-
- if (mHints.showPunctuationHintIfNecessary(ic)) {
- mVoiceInput.logPunctuationHintDisplayed();
- }
- }
- mImmediatelyAfterVoiceInput = false;
- }
-
- @Override
- public void onUpdateSelection(int oldSelStart, int oldSelEnd,
- int newSelStart, int newSelEnd,
- int candidatesStart, int candidatesEnd) {
- super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
- candidatesStart, candidatesEnd);
-
- if (DEBUG) {
- Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
- + ", ose=" + oldSelEnd
- + ", nss=" + newSelStart
- + ", nse=" + newSelEnd
- + ", cs=" + candidatesStart
- + ", ce=" + candidatesEnd);
- }
-
- mSuggestionShouldReplaceCurrentWord = false;
- // If the current selection in the text view changes, we should
- // clear whatever candidate text we have.
- if ((((mComposing.length() > 0 && mPredicting) || mVoiceInputHighlighted)
- && (newSelStart != candidatesEnd
- || newSelEnd != candidatesEnd))) {
- mComposing.setLength(0);
- mPredicting = false;
- updateSuggestions();
- TextEntryState.reset();
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.finishComposingText();
- }
- mVoiceInputHighlighted = false;
- } else if (!mPredicting && !mJustAccepted) {
- switch (TextEntryState.getState()) {
- case TextEntryState.STATE_ACCEPTED_DEFAULT:
- TextEntryState.reset();
- // fall through
- case TextEntryState.STATE_SPACE_AFTER_PICKED:
- mJustAddedAutoSpace = false; // The user moved the cursor.
- break;
- }
- }
- mJustAccepted = false;
- postUpdateShiftKeyState();
-
- if (VOICE_INSTALLED) {
- if (mShowingVoiceSuggestions) {
- if (mImmediatelyAfterVoiceSuggestions) {
- mImmediatelyAfterVoiceSuggestions = false;
- } else {
- updateSuggestions();
- mShowingVoiceSuggestions = false;
- }
- }
- if (VoiceInput.ENABLE_WORD_CORRECTIONS) {
- // If we have alternatives for the current word, then show them.
- String word = EditingUtil.getWordAtCursor(
- getCurrentInputConnection(), getWordSeparators());
- if (word != null && mWordToSuggestions.containsKey(word.trim())) {
- mSuggestionShouldReplaceCurrentWord = true;
- final List<CharSequence> suggestions = mWordToSuggestions.get(word.trim());
-
- setSuggestions(suggestions, false, true, true);
- setCandidatesViewShown(true);
- }
- }
- }
- }
-
- @Override
- public void hideWindow() {
- if (TRACE) Debug.stopMethodTracing();
- if (mOptionsDialog != null && mOptionsDialog.isShowing()) {
- mOptionsDialog.dismiss();
- mOptionsDialog = null;
- }
- if (!mConfigurationChanging) {
- if (mAfterVoiceInput) mVoiceInput.logInputEnded();
- if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
- mVoiceInput.logKeyboardWarningDialogDismissed();
- mVoiceWarningDialog.dismiss();
- mVoiceWarningDialog = null;
- }
- if (VOICE_INSTALLED & mRecognizing) {
- mVoiceInput.cancel();
- }
- }
- super.hideWindow();
- TextEntryState.endSession();
- }
-
- @Override
- public void onDisplayCompletions(CompletionInfo[] completions) {
- if (false) {
- Log.i("foo", "Received completions:");
- for (int i=0; i<(completions != null ? completions.length : 0); i++) {
- Log.i("foo", " #" + i + ": " + completions[i]);
- }
- }
- if (mCompletionOn) {
- mCompletions = completions;
- if (completions == null) {
- setSuggestions(null, false, false, false);
- return;
- }
-
- List<CharSequence> stringList = new ArrayList<CharSequence>();
- for (int i=0; i<(completions != null ? completions.length : 0); i++) {
- CompletionInfo ci = completions[i];
- if (ci != null) stringList.add(ci.getText());
- }
- //CharSequence typedWord = mWord.getTypedWord();
- setSuggestions(stringList, true, true, true);
- mBestWord = null;
- setCandidatesViewShown(isCandidateStripVisible() || mCompletionOn);
- }
- }
-
- @Override
- public void setCandidatesViewShown(boolean shown) {
- // TODO: Remove this if we support candidates with hard keyboard
- if (onEvaluateInputViewShown()) {
- super.setCandidatesViewShown(shown);
- }
- }
-
- @Override
- public void onComputeInsets(InputMethodService.Insets outInsets) {
- super.onComputeInsets(outInsets);
- if (!isFullscreenMode()) {
- outInsets.contentTopInsets = outInsets.visibleTopInsets;
- }
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_BACK:
- if (event.getRepeatCount() == 0 && mInputView != null) {
- if (mInputView.handleBack()) {
- return true;
- } else if (mTutorial != null) {
- mTutorial.close();
- mTutorial = null;
- }
- }
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- // If tutorial is visible, don't allow dpad to work
- if (mTutorial != null) {
- return true;
- }
- break;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- // If tutorial is visible, don't allow dpad to work
- if (mTutorial != null) {
- return true;
- }
- // Enable shift key and DPAD to do selections
- if (mInputView != null && mInputView.isShown() && mInputView.isShifted()) {
- event = new KeyEvent(event.getDownTime(), event.getEventTime(),
- event.getAction(), event.getKeyCode(), event.getRepeatCount(),
- event.getDeviceId(), event.getScanCode(),
- KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON);
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) ic.sendKeyEvent(event);
- return true;
- }
- break;
- }
- return super.onKeyUp(keyCode, event);
- }
-
- private void revertVoiceInput() {
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) ic.commitText("", 1);
- updateSuggestions();
- mVoiceInputHighlighted = false;
- }
-
- private void commitVoiceInput() {
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) ic.finishComposingText();
- updateSuggestions();
- mVoiceInputHighlighted = false;
- }
-
- private void reloadKeyboards() {
- if (mKeyboardSwitcher == null) {
- mKeyboardSwitcher = new KeyboardSwitcher(this, this);
- }
- mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher);
- if (mInputView != null) {
- mKeyboardSwitcher.setVoiceMode(mEnableVoice && mEnableVoiceButton, mVoiceOnPrimary);
- }
- mKeyboardSwitcher.makeKeyboards(true);
- }
-
- private void commitTyped(InputConnection inputConnection) {
- if (mPredicting) {
- mPredicting = false;
- if (mComposing.length() > 0) {
- if (inputConnection != null) {
- inputConnection.commitText(mComposing, 1);
- }
- mCommittedLength = mComposing.length();
- TextEntryState.acceptedTyped(mComposing);
- checkAddToDictionary(mComposing, AutoDictionary.FREQUENCY_FOR_TYPED);
- }
- updateSuggestions();
- }
- }
-
- private void postUpdateShiftKeyState() {
- mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SHIFT_STATE), 300);
- }
-
- public void updateShiftKeyState(EditorInfo attr) {
- InputConnection ic = getCurrentInputConnection();
- if (attr != null && mInputView != null && mKeyboardSwitcher.isAlphabetMode()
- && ic != null) {
- mInputView.setShifted(mCapsLock || getCursorCapsMode(ic, attr) != 0);
- }
- }
-
- private int getCursorCapsMode(InputConnection ic, EditorInfo attr) {
- int caps = 0;
- EditorInfo ei = getCurrentInputEditorInfo();
- if (mAutoCap && ei != null && ei.inputType != EditorInfo.TYPE_NULL) {
- caps = ic.getCursorCapsMode(attr.inputType);
- }
- return caps;
- }
-
- private void swapPunctuationAndSpace() {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- CharSequence lastTwo = ic.getTextBeforeCursor(2, 0);
- if (lastTwo != null && lastTwo.length() == 2
- && lastTwo.charAt(0) == KEYCODE_SPACE && isSentenceSeparator(lastTwo.charAt(1))) {
- ic.beginBatchEdit();
- ic.deleteSurroundingText(2, 0);
- ic.commitText(lastTwo.charAt(1) + " ", 1);
- ic.endBatchEdit();
- updateShiftKeyState(getCurrentInputEditorInfo());
- mJustAddedAutoSpace = true;
- }
- }
-
- private void reswapPeriodAndSpace() {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- CharSequence lastThree = ic.getTextBeforeCursor(3, 0);
- if (lastThree != null && lastThree.length() == 3
- && lastThree.charAt(0) == KEYCODE_PERIOD
- && lastThree.charAt(1) == KEYCODE_SPACE
- && lastThree.charAt(2) == KEYCODE_PERIOD) {
- ic.beginBatchEdit();
- ic.deleteSurroundingText(3, 0);
- ic.commitText(" ..", 1);
- ic.endBatchEdit();
- updateShiftKeyState(getCurrentInputEditorInfo());
- }
- }
-
- private void doubleSpace() {
- //if (!mAutoPunctuate) return;
- if (mCorrectionMode == Suggest.CORRECTION_NONE) return;
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- CharSequence lastThree = ic.getTextBeforeCursor(3, 0);
- if (lastThree != null && lastThree.length() == 3
- && Character.isLetterOrDigit(lastThree.charAt(0))
- && lastThree.charAt(1) == KEYCODE_SPACE && lastThree.charAt(2) == KEYCODE_SPACE) {
- ic.beginBatchEdit();
- ic.deleteSurroundingText(2, 0);
- ic.commitText(". ", 1);
- ic.endBatchEdit();
- updateShiftKeyState(getCurrentInputEditorInfo());
- mJustAddedAutoSpace = true;
- }
- }
-
- private void maybeRemovePreviousPeriod(CharSequence text) {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
-
- // When the text's first character is '.', remove the previous period
- // if there is one.
- CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
- if (lastOne != null && lastOne.length() == 1
- && lastOne.charAt(0) == KEYCODE_PERIOD
- && text.charAt(0) == KEYCODE_PERIOD) {
- ic.deleteSurroundingText(1, 0);
- }
- }
-
- private void removeTrailingSpace() {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
-
- CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
- if (lastOne != null && lastOne.length() == 1
- && lastOne.charAt(0) == KEYCODE_SPACE) {
- ic.deleteSurroundingText(1, 0);
- }
- }
-
- public boolean addWordToDictionary(String word) {
- mUserDictionary.addWord(word, 128);
- return true;
- }
-
- private boolean isAlphabet(int code) {
- if (Character.isLetter(code)) {
- return true;
- } else {
- return false;
- }
- }
-
- // Implementation of KeyboardViewListener
-
- public void onKey(int primaryCode, int[] keyCodes) {
- long when = SystemClock.uptimeMillis();
- if (primaryCode != Keyboard.KEYCODE_DELETE ||
- when > mLastKeyTime + QUICK_PRESS) {
- mDeleteCount = 0;
- }
- mLastKeyTime = when;
- switch (primaryCode) {
- case Keyboard.KEYCODE_DELETE:
- handleBackspace();
- mDeleteCount++;
- break;
- case Keyboard.KEYCODE_SHIFT:
- handleShift();
- break;
- case Keyboard.KEYCODE_CANCEL:
- if (mOptionsDialog == null || !mOptionsDialog.isShowing()) {
- handleClose();
- }
- break;
- case LatinKeyboardView.KEYCODE_OPTIONS:
- showOptionsMenu();
- break;
- case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
- toggleLanguage(false, true);
- break;
- case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
- toggleLanguage(false, false);
- break;
- case LatinKeyboardView.KEYCODE_SHIFT_LONGPRESS:
- if (mCapsLock) {
- handleShift();
- } else {
- toggleCapsLock();
- }
- break;
- case Keyboard.KEYCODE_MODE_CHANGE:
- changeKeyboardMode();
- break;
- case LatinKeyboardView.KEYCODE_VOICE:
- if (VOICE_INSTALLED) {
- startListening(false /* was a button press, was not a swipe */);
- }
- break;
- case 9 /*Tab*/:
- sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
- break;
- default:
- if (primaryCode != KEYCODE_ENTER) {
- mJustAddedAutoSpace = false;
- }
- if (isWordSeparator(primaryCode)) {
- handleSeparator(primaryCode);
- } else {
- handleCharacter(primaryCode, keyCodes);
- }
- // Cancel the just reverted state
- mJustRevertedSeparator = null;
- }
- if (mKeyboardSwitcher.onKey(primaryCode)) {
- changeKeyboardMode();
- }
- }
-
- public void onText(CharSequence text) {
- if (VOICE_INSTALLED && mVoiceInputHighlighted) {
- commitVoiceInput();
- }
- InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- ic.beginBatchEdit();
- if (mPredicting) {
- commitTyped(ic);
- }
- maybeRemovePreviousPeriod(text);
- ic.commitText(text, 1);
- ic.endBatchEdit();
- updateShiftKeyState(getCurrentInputEditorInfo());
- mJustRevertedSeparator = null;
- mJustAddedAutoSpace = false;
- }
-
- private void handleBackspace() {
- if (VOICE_INSTALLED && mVoiceInputHighlighted) {
- revertVoiceInput();
- return;
- }
- boolean deleteChar = false;
- InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- if (mPredicting) {
- final int length = mComposing.length();
- if (length > 0) {
- mComposing.delete(length - 1, length);
- mWord.deleteLast();
- ic.setComposingText(mComposing, 1);
- if (mComposing.length() == 0) {
- mPredicting = false;
- }
- postUpdateSuggestions();
- } else {
- ic.deleteSurroundingText(1, 0);
- }
- } else {
- deleteChar = true;
- }
- postUpdateShiftKeyState();
- TextEntryState.backspace();
- if (TextEntryState.getState() == TextEntryState.STATE_UNDO_COMMIT) {
- revertLastWord(deleteChar);
- return;
- } else if (deleteChar) {
- sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
- if (mDeleteCount > DELETE_ACCELERATE_AT) {
- sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
- }
- }
- mJustRevertedSeparator = null;
- }
-
- private void handleShift() {
- mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
- if (mKeyboardSwitcher.isAlphabetMode()) {
- // Alphabet keyboard
- checkToggleCapsLock();
- mInputView.setShifted(mCapsLock || !mInputView.isShifted());
- } else {
- mKeyboardSwitcher.toggleShift();
- }
- }
-
- private void handleCharacter(int primaryCode, int[] keyCodes) {
- if (VOICE_INSTALLED && mVoiceInputHighlighted) {
- commitVoiceInput();
- }
- if (isAlphabet(primaryCode) && isPredictionOn() && !isCursorTouchingWord()) {
- if (!mPredicting) {
- mPredicting = true;
- mComposing.setLength(0);
- mWord.reset();
- }
- }
- if (mInputView.isShifted()) {
- // TODO: This doesn't work with ß, need to fix it in the next release.
- if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT
- || keyCodes[0] > Character.MAX_CODE_POINT) {
- return;
- }
- primaryCode = new String(keyCodes, 0, 1).toUpperCase().charAt(0);
- }
- if (mPredicting) {
- if (mInputView.isShifted() && mComposing.length() == 0) {
- mWord.setCapitalized(true);
- }
- mComposing.append((char) primaryCode);
- mWord.add(primaryCode, keyCodes);
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- // If it's the first letter, make note of auto-caps state
- if (mWord.size() == 1) {
- mWord.setAutoCapitalized(
- getCursorCapsMode(ic, getCurrentInputEditorInfo()) != 0);
- }
- ic.setComposingText(mComposing, 1);
- }
- postUpdateSuggestions();
- } else {
- sendKeyChar((char)primaryCode);
- }
- updateShiftKeyState(getCurrentInputEditorInfo());
- measureCps();
- TextEntryState.typedCharacter((char) primaryCode, isWordSeparator(primaryCode));
- }
-
- private void handleSeparator(int primaryCode) {
- if (VOICE_INSTALLED && mVoiceInputHighlighted) {
- commitVoiceInput();
- }
- boolean pickedDefault = false;
- // Handle separator
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.beginBatchEdit();
- }
- if (mPredicting) {
- // In certain languages where single quote is a separator, it's better
- // not to auto correct, but accept the typed word. For instance,
- // in Italian dov' should not be expanded to dove' because the elision
- // requires the last vowel to be removed.
- if (mAutoCorrectOn && primaryCode != '\'' &&
- (mJustRevertedSeparator == null
- || mJustRevertedSeparator.length() == 0
- || mJustRevertedSeparator.charAt(0) != primaryCode)) {
- pickDefaultSuggestion();
- pickedDefault = true;
- // Picked the suggestion by the space key. We consider this
- // as "added an auto space".
- if (primaryCode == KEYCODE_SPACE) {
- mJustAddedAutoSpace = true;
- }
- } else {
- commitTyped(ic);
- }
- }
- if (mJustAddedAutoSpace && primaryCode == KEYCODE_ENTER) {
- removeTrailingSpace();
- mJustAddedAutoSpace = false;
- }
- sendKeyChar((char)primaryCode);
-
- // Handle the case of ". ." -> " .." with auto-space if necessary
- // before changing the TextEntryState.
- if (TextEntryState.getState() == TextEntryState.STATE_PUNCTUATION_AFTER_ACCEPTED
- && primaryCode == KEYCODE_PERIOD) {
- reswapPeriodAndSpace();
- }
-
- TextEntryState.typedCharacter((char) primaryCode, true);
- if (TextEntryState.getState() == TextEntryState.STATE_PUNCTUATION_AFTER_ACCEPTED
- && primaryCode != KEYCODE_ENTER) {
- swapPunctuationAndSpace();
- } else if (isPredictionOn() && primaryCode == KEYCODE_SPACE) {
- //else if (TextEntryState.STATE_SPACE_AFTER_ACCEPTED) {
- doubleSpace();
- }
- if (pickedDefault && mBestWord != null) {
- TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord);
- }
- updateShiftKeyState(getCurrentInputEditorInfo());
- if (ic != null) {
- ic.endBatchEdit();
- }
- }
-
- private void handleClose() {
- commitTyped(getCurrentInputConnection());
- if (VOICE_INSTALLED & mRecognizing) {
- mVoiceInput.cancel();
- }
- requestHideSelf(0);
- mInputView.closing();
- TextEntryState.endSession();
- }
-
- private void checkToggleCapsLock() {
- if (mInputView.getKeyboard().isShifted()) {
- toggleCapsLock();
- }
- }
-
- private void toggleCapsLock() {
- mCapsLock = !mCapsLock;
- if (mKeyboardSwitcher.isAlphabetMode()) {
- ((LatinKeyboard) mInputView.getKeyboard()).setShiftLocked(mCapsLock);
- }
- }
-
- private void postUpdateSuggestions() {
- mHandler.removeMessages(MSG_UPDATE_SUGGESTIONS);
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SUGGESTIONS), 100);
- }
-
- private boolean isPredictionOn() {
- boolean predictionOn = mPredictionOn;
- return predictionOn;
- }
-
- private boolean isCandidateStripVisible() {
- return isPredictionOn() && mShowSuggestions;
- }
-
- public void onCancelVoice() {
- if (mRecognizing) {
- switchToKeyboardView();
- }
- }
-
- private void switchToKeyboardView() {
- mHandler.post(new Runnable() {
- public void run() {
- mRecognizing = false;
- if (mInputView != null) {
- setInputView(mInputView);
- }
- updateInputViewShown();
- }});
- }
-
- private void switchToRecognitionStatusView() {
- final boolean configChanged = mConfigurationChanging;
- mHandler.post(new Runnable() {
- public void run() {
- mRecognizing = true;
- View v = mVoiceInput.getView();
- ViewParent p = v.getParent();
- if (p != null && p instanceof ViewGroup) {
- ((ViewGroup)v.getParent()).removeView(v);
- }
- setInputView(v);
- updateInputViewShown();
- if (configChanged) {
- mVoiceInput.onConfigurationChanged();
- }
- }});
- }
-
- private void startListening(boolean swipe) {
- if (!mHasUsedVoiceInput ||
- (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale)) {
- // Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel.
- showVoiceWarningDialog(swipe);
- } else {
- reallyStartListening(swipe);
- }
- }
-
- private void reallyStartListening(boolean swipe) {
- if (!mHasUsedVoiceInput) {
- // The user has started a voice input, so remember that in the
- // future (so we don't show the warning dialog after the first run).
- SharedPreferences.Editor editor =
- PreferenceManager.getDefaultSharedPreferences(this).edit();
- editor.putBoolean(PREF_HAS_USED_VOICE_INPUT, true);
- editor.commit();
- mHasUsedVoiceInput = true;
- }
-
- if (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale) {
- // The user has started a voice input from an unsupported locale, so remember that
- // in the future (so we don't show the warning dialog the next time they do this).
- SharedPreferences.Editor editor =
- PreferenceManager.getDefaultSharedPreferences(this).edit();
- editor.putBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, true);
- editor.commit();
- mHasUsedVoiceInputUnsupportedLocale = true;
- }
-
- // Clear N-best suggestions
- setSuggestions(null, false, false, true);
-
- FieldContext context = new FieldContext(
- getCurrentInputConnection(),
- getCurrentInputEditorInfo(),
- mLanguageSwitcher.getInputLanguage(),
- mLanguageSwitcher.getEnabledLanguages());
- mVoiceInput.startListening(context, swipe);
- switchToRecognitionStatusView();
- }
-
- private void showVoiceWarningDialog(final boolean swipe) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setCancelable(true);
- builder.setIcon(R.drawable.ic_mic_dialog);
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- mVoiceInput.logKeyboardWarningDialogOk();
- reallyStartListening(swipe);
- }
- });
- builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- mVoiceInput.logKeyboardWarningDialogCancel();
- }
- });
-
- if (mLocaleSupportedForVoiceInput) {
- String message = getString(R.string.voice_warning_may_not_understand) + "\n\n" +
- getString(R.string.voice_warning_how_to_turn_off);
- builder.setMessage(message);
- } else {
- String message = getString(R.string.voice_warning_locale_not_supported) + "\n\n" +
- getString(R.string.voice_warning_may_not_understand) + "\n\n" +
- getString(R.string.voice_warning_how_to_turn_off);
- builder.setMessage(message);
- }
-
- builder.setTitle(R.string.voice_warning_title);
- mVoiceWarningDialog = builder.create();
-
- Window window = mVoiceWarningDialog.getWindow();
- WindowManager.LayoutParams lp = window.getAttributes();
- lp.token = mInputView.getWindowToken();
- lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
- window.setAttributes(lp);
- window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
- mVoiceInput.logKeyboardWarningDialogShown();
- mVoiceWarningDialog.show();
- }
-
- public void onVoiceResults(List<String> candidates,
- Map<String, List<CharSequence>> alternatives) {
- if (!mRecognizing) {
- return;
- }
- mVoiceResults.candidates = candidates;
- mVoiceResults.alternatives = alternatives;
- mHandler.sendMessage(mHandler.obtainMessage(MSG_VOICE_RESULTS));
- }
-
- private void handleVoiceResults() {
- mAfterVoiceInput = true;
- mImmediatelyAfterVoiceInput = true;
-
- InputConnection ic = getCurrentInputConnection();
- if (!isFullscreenMode()) {
- // Start listening for updates to the text from typing, etc.
- if (ic != null) {
- ExtractedTextRequest req = new ExtractedTextRequest();
- ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR);
- }
- }
-
- vibrate();
- switchToKeyboardView();
-
- final List<CharSequence> nBest = new ArrayList<CharSequence>();
- boolean capitalizeFirstWord = preferCapitalization()
- || (mKeyboardSwitcher.isAlphabetMode() && mInputView.isShifted());
- for (String c : mVoiceResults.candidates) {
- if (capitalizeFirstWord) {
- c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length());
- }
- nBest.add(c);
- }
-
- if (nBest.size() == 0) {
- return;
- }
-
- String bestResult = nBest.get(0).toString();
-
- mVoiceInput.logVoiceInputDelivered();
-
- mHints.registerVoiceResult(bestResult);
-
- if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text
-
- commitTyped(ic);
- EditingUtil.appendText(ic, bestResult);
-
- if (ic != null) ic.endBatchEdit();
-
- // Show N-Best alternates, if there is more than one choice.
- if (nBest.size() > 1) {
- mImmediatelyAfterVoiceSuggestions = true;
- mShowingVoiceSuggestions = true;
- setSuggestions(nBest.subList(1, nBest.size()), false, true, true);
- setCandidatesViewShown(true);
- }
- mVoiceInputHighlighted = true;
- mWordToSuggestions.putAll(mVoiceResults.alternatives);
-
- }
-
- private void setSuggestions(
- List<CharSequence> suggestions,
- boolean completions,
-
- boolean typedWordValid,
- boolean haveMinimalSuggestion) {
-
- if (mIsShowingHint) {
- setCandidatesView(mCandidateViewContainer);
- mIsShowingHint = false;
- }
-
- if (mCandidateView != null) {
- mCandidateView.setSuggestions(
- suggestions, completions, typedWordValid, haveMinimalSuggestion);
- }
- }
-
- private void updateSuggestions() {
- mSuggestionShouldReplaceCurrentWord = false;
-
- ((LatinKeyboard) mInputView.getKeyboard()).setPreferredLetters(null);
-
- // Check if we have a suggestion engine attached.
- if ((mSuggest == null || !isPredictionOn()) && !mVoiceInputHighlighted) {
- return;
- }
-
- if (!mPredicting) {
- setNextSuggestions();
- return;
- }
-
- List<CharSequence> stringList = mSuggest.getSuggestions(mInputView, mWord, false);
- int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies();
-
- ((LatinKeyboard) mInputView.getKeyboard()).setPreferredLetters(nextLettersFrequencies);
-
- boolean correctionAvailable = mSuggest.hasMinimalCorrection();
- //|| mCorrectionMode == mSuggest.CORRECTION_FULL;
- CharSequence typedWord = mWord.getTypedWord();
- // If we're in basic correct
- boolean typedWordValid = mSuggest.isValidWord(typedWord) ||
- (preferCapitalization() && mSuggest.isValidWord(typedWord.toString().toLowerCase()));
- if (mCorrectionMode == Suggest.CORRECTION_FULL) {
- correctionAvailable |= typedWordValid;
- }
- // Don't auto-correct words with multiple capital letter
- correctionAvailable &= !mWord.isMostlyCaps();
-
- setSuggestions(stringList, false, typedWordValid, correctionAvailable);
- if (stringList.size() > 0) {
- if (correctionAvailable && !typedWordValid && stringList.size() > 1) {
- mBestWord = stringList.get(1);
- } else {
- mBestWord = typedWord;
- }
- } else {
- mBestWord = null;
- }
- setCandidatesViewShown(isCandidateStripVisible() || mCompletionOn);
- }
-
- private void pickDefaultSuggestion() {
- // Complete any pending candidate query first
- if (mHandler.hasMessages(MSG_UPDATE_SUGGESTIONS)) {
- mHandler.removeMessages(MSG_UPDATE_SUGGESTIONS);
- updateSuggestions();
- }
- if (mBestWord != null) {
- TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord);
- mJustAccepted = true;
- pickSuggestion(mBestWord);
- // Add the word to the auto dictionary if it's not a known word
- checkAddToDictionary(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED);
- }
- }
-
- public void pickSuggestionManually(int index, CharSequence suggestion) {
- if (mAfterVoiceInput && mShowingVoiceSuggestions) mVoiceInput.logNBestChoose(index);
-
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.beginBatchEdit();
- }
- if (mCompletionOn && mCompletions != null && index >= 0
- && index < mCompletions.length) {
- CompletionInfo ci = mCompletions[index];
- if (ic != null) {
- ic.commitCompletion(ci);
- }
- mCommittedLength = suggestion.length();
- if (mCandidateView != null) {
- mCandidateView.clear();
- }
- updateShiftKeyState(getCurrentInputEditorInfo());
- if (ic != null) {
- ic.endBatchEdit();
- }
- return;
- }
-
- // If this is a punctuation, apply it through the normal key press
- if (suggestion.length() == 1 && isWordSeparator(suggestion.charAt(0))) {
- onKey(suggestion.charAt(0), null);
- if (ic != null) {
- ic.endBatchEdit();
- }
- return;
- }
- mJustAccepted = true;
- pickSuggestion(suggestion);
- // Add the word to the auto dictionary if it's not a known word
- checkAddToDictionary(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED);
- TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion);
- // Follow it with a space
- if (mAutoSpace) {
- sendSpace();
- mJustAddedAutoSpace = true;
- }
- // Fool the state watcher so that a subsequent backspace will not do a revert
- TextEntryState.typedCharacter((char) KEYCODE_SPACE, true);
- if (index == 0 && mCorrectionMode > 0 && !mSuggest.isValidWord(suggestion)) {
- mCandidateView.showAddToDictionaryHint(suggestion);
- }
- if (ic != null) {
- ic.endBatchEdit();
- }
- }
-
- private void pickSuggestion(CharSequence suggestion) {
- if (mCapsLock) {
- suggestion = suggestion.toString().toUpperCase();
- } else if (preferCapitalization()
- || (mKeyboardSwitcher.isAlphabetMode() && mInputView.isShifted())) {
- suggestion = suggestion.toString().toUpperCase().charAt(0)
- + suggestion.subSequence(1, suggestion.length()).toString();
- }
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- if (mSuggestionShouldReplaceCurrentWord) {
- EditingUtil.deleteWordAtCursor(ic, getWordSeparators());
- }
- if (!VoiceInput.DELETE_SYMBOL.equals(suggestion)) {
- ic.commitText(suggestion, 1);
- }
- }
- mPredicting = false;
- mCommittedLength = suggestion.length();
- ((LatinKeyboard) mInputView.getKeyboard()).setPreferredLetters(null);
- setNextSuggestions();
- updateShiftKeyState(getCurrentInputEditorInfo());
- }
-
- private void setNextSuggestions() {
- setSuggestions(mSuggestPuncList, false, false, false);
- }
-
- private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta) {
- if (mAutoDictionary.isValidWord(suggestion)
- || !mSuggest.isValidWord(suggestion.toString().toLowerCase())) {
- mAutoDictionary.addWord(suggestion.toString(), frequencyDelta);
- }
- }
-
- private boolean isCursorTouchingWord() {
- InputConnection ic = getCurrentInputConnection();
- if (ic == null) return false;
- CharSequence toLeft = ic.getTextBeforeCursor(1, 0);
- CharSequence toRight = ic.getTextAfterCursor(1, 0);
- if (!TextUtils.isEmpty(toLeft)
- && !isWordSeparator(toLeft.charAt(0))) {
- return true;
- }
- if (!TextUtils.isEmpty(toRight)
- && !isWordSeparator(toRight.charAt(0))) {
- return true;
- }
- return false;
- }
-
- public void revertLastWord(boolean deleteChar) {
- final int length = mComposing.length();
- if (!mPredicting && length > 0) {
- final InputConnection ic = getCurrentInputConnection();
- mPredicting = true;
- ic.beginBatchEdit();
- mJustRevertedSeparator = ic.getTextBeforeCursor(1, 0);
- if (deleteChar) ic.deleteSurroundingText(1, 0);
- int toDelete = mCommittedLength;
- CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0);
- if (toTheLeft != null && toTheLeft.length() > 0
- && isWordSeparator(toTheLeft.charAt(0))) {
- toDelete--;
- }
- ic.deleteSurroundingText(toDelete, 0);
- ic.setComposingText(mComposing, 1);
- TextEntryState.backspace();
- ic.endBatchEdit();
- postUpdateSuggestions();
- } else {
- sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
- mJustRevertedSeparator = null;
- }
- }
-
- protected String getWordSeparators() {
- return mWordSeparators;
- }
-
- public boolean isWordSeparator(int code) {
- String separators = getWordSeparators();
- return separators.contains(String.valueOf((char)code));
- }
-
- public boolean isSentenceSeparator(int code) {
- return mSentenceSeparators.contains(String.valueOf((char)code));
- }
-
- private void sendSpace() {
- sendKeyChar((char)KEYCODE_SPACE);
- updateShiftKeyState(getCurrentInputEditorInfo());
- //onKey(KEY_SPACE[0], KEY_SPACE);
- }
-
- public boolean preferCapitalization() {
- return mWord.isCapitalized();
- }
-
- public void swipeRight() {
- if (userHasNotTypedRecently() && VOICE_INSTALLED && mEnableVoice &&
- fieldCanDoVoice(makeFieldContext())) {
- startListening(true /* was a swipe */);
- }
-
- if (LatinKeyboardView.DEBUG_AUTO_PLAY) {
- ClipboardManager cm = ((ClipboardManager)getSystemService(CLIPBOARD_SERVICE));
- CharSequence text = cm.getText();
- if (!TextUtils.isEmpty(text)) {
- mInputView.startPlaying(text.toString());
- }
- }
- }
-
- 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(mLanguageSwitcher.getInputLanguage());
- mLanguageSwitcher.persist();
- updateShiftKeyState(getCurrentInputEditorInfo());
- }
-
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
- String key) {
- if (PREF_SELECTED_LANGUAGES.equals(key)) {
- mLanguageSwitcher.loadLocales(sharedPreferences);
- mRefreshKeyboardRequired = true;
- }
- }
-
- public void swipeLeft() {
- }
-
- public void swipeDown() {
- handleClose();
- }
-
- public void swipeUp() {
- //launchSettings();
- }
-
- public void onPress(int primaryCode) {
- vibrate();
- playKeyClick(primaryCode);
- }
-
- public void onRelease(int primaryCode) {
- // Reset any drag flags in the keyboard
- ((LatinKeyboard) mInputView.getKeyboard()).keyReleased();
- //vibrate();
- }
-
- private FieldContext makeFieldContext() {
- return new FieldContext(
- getCurrentInputConnection(),
- getCurrentInputEditorInfo(),
- mLanguageSwitcher.getInputLanguage(),
- mLanguageSwitcher.getEnabledLanguages());
- }
-
- private boolean fieldCanDoVoice(FieldContext fieldContext) {
- return !mPasswordText
- && mVoiceInput != null
- && !mVoiceInput.isBlacklistedField(fieldContext);
- }
-
- private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo attribute) {
- return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext)
- && !(attribute != null && attribute.privateImeOptions != null
- && attribute.privateImeOptions.equals(IME_OPTION_NO_MICROPHONE))
- && RecognitionManager.isRecognitionAvailable(this);
- }
-
- // receive ringer mode changes to detect silent mode
- private BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- updateRingerMode();
- }
- };
-
- // update flags for silent mode
- private void updateRingerMode() {
- if (mAudioManager == null) {
- mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- }
- if (mAudioManager != null) {
- mSilentMode = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL);
- }
- }
-
- private boolean userHasNotTypedRecently() {
- return (SystemClock.uptimeMillis() - mLastKeyTime)
- > MIN_MILLIS_AFTER_TYPING_BEFORE_SWIPE;
- }
-
- private void playKeyClick(int primaryCode) {
- // if mAudioManager is null, we don't have the ringer state yet
- // mAudioManager will be set by updateRingerMode
- if (mAudioManager == null) {
- if (mInputView != null) {
- updateRingerMode();
- }
- }
- if (mSoundOn && !mSilentMode) {
- // FIXME: Volume and enable should come from UI settings
- // FIXME: These should be triggered after auto-repeat logic
- int sound = AudioManager.FX_KEYPRESS_STANDARD;
- switch (primaryCode) {
- case Keyboard.KEYCODE_DELETE:
- sound = AudioManager.FX_KEYPRESS_DELETE;
- break;
- case KEYCODE_ENTER:
- sound = AudioManager.FX_KEYPRESS_RETURN;
- break;
- case KEYCODE_SPACE:
- sound = AudioManager.FX_KEYPRESS_SPACEBAR;
- break;
- }
- mAudioManager.playSoundEffect(sound, FX_VOLUME);
- }
- }
-
- private void vibrate() {
- if (!mVibrateOn) {
- return;
- }
- if (mInputView != null) {
- mInputView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP,
- HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
- }
- }
-
- private void checkTutorial(String privateImeOptions) {
- if (privateImeOptions == null) return;
- if (privateImeOptions.equals("com.android.setupwizard:ShowTutorial")) {
- if (mTutorial == null) startTutorial();
- } else if (privateImeOptions.equals("com.android.setupwizard:HideTutorial")) {
- if (mTutorial != null) {
- if (mTutorial.close()) {
- mTutorial = null;
- }
- }
- }
- }
-
- private void startTutorial() {
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_TUTORIAL), 500);
- }
-
- void tutorialDone() {
- mTutorial = null;
- }
-
- void promoteToUserDictionary(String word, int frequency) {
- if (mUserDictionary.isValidWord(word)) return;
- mUserDictionary.addWord(word, frequency);
- }
-
- WordComposer getCurrentWord() {
- return mWord;
- }
-
- private void updateCorrectionMode() {
- mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false;
- mAutoCorrectOn = (mAutoCorrectEnabled || mQuickFixes)
- && !mInputTypeNoAutoCorrect && mHasDictionary;
- mCorrectionMode = (mAutoCorrectOn && mAutoCorrectEnabled)
- ? Suggest.CORRECTION_FULL
- : (mAutoCorrectOn ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE);
- if (mSuggest != null) {
- mSuggest.setCorrectionMode(mCorrectionMode);
- }
- }
-
- private void updateAutoTextEnabled(Locale systemLocale) {
- if (mSuggest == null) return;
- boolean different = !systemLocale.getLanguage().equalsIgnoreCase(mLocale.substring(0, 2));
- mSuggest.setAutoTextEnabled(!different && mQuickFixes);
- }
-
- protected void launchSettings() {
- launchSettings(LatinIMESettings.class);
- }
-
- protected void launchSettings(Class settingsClass) {
- handleClose();
- Intent intent = new Intent();
- intent.setClass(LatinIME.this, settingsClass);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
- }
-
- private void loadSettings() {
- // Get the settings preferences
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
- mVibrateOn = sp.getBoolean(PREF_VIBRATE_ON, false);
- mSoundOn = sp.getBoolean(PREF_SOUND_ON, false);
- mAutoCap = sp.getBoolean(PREF_AUTO_CAP, true);
- mQuickFixes = sp.getBoolean(PREF_QUICK_FIXES, true);
- mHasUsedVoiceInput = sp.getBoolean(PREF_HAS_USED_VOICE_INPUT, false);
- mHasUsedVoiceInputUnsupportedLocale =
- sp.getBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, false);
-
- // Get the current list of supported locales and check the current locale against that
- // list. We cache this value so as not to check it every time the user starts a voice
- // input. Because this method is called by onStartInputView, this should mean that as
- // long as the locale doesn't change while the user is keeping the IME open, the
- // value should never be stale.
- String supportedLocalesString = SettingsUtil.getSettingsString(
- getContentResolver(),
- SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
- DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
- ArrayList<String> voiceInputSupportedLocales =
- newArrayList(supportedLocalesString.split("\\s+"));
-
- mLocaleSupportedForVoiceInput = voiceInputSupportedLocales.contains(mLocale);
-
- mShowSuggestions = sp.getBoolean(PREF_SHOW_SUGGESTIONS, true);
-
- if (VOICE_INSTALLED) {
- final String voiceMode = sp.getString(PREF_VOICE_MODE,
- getString(R.string.voice_mode_main));
- boolean enableVoice = !voiceMode.equals(getString(R.string.voice_mode_off))
- && mEnableVoiceButton;
- boolean voiceOnPrimary = voiceMode.equals(getString(R.string.voice_mode_main));
- if (mKeyboardSwitcher != null &&
- (enableVoice != mEnableVoice || voiceOnPrimary != mVoiceOnPrimary)) {
- mKeyboardSwitcher.setVoiceMode(enableVoice, voiceOnPrimary);
- }
- mEnableVoice = enableVoice;
- mVoiceOnPrimary = voiceOnPrimary;
- }
- mAutoCorrectEnabled = sp.getBoolean(PREF_AUTO_COMPLETE,
- mResources.getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions;
- updateCorrectionMode();
- updateAutoTextEnabled(mResources.getConfiguration().locale);
- mLanguageSwitcher.loadLocales(sp);
- }
-
- private void initSuggestPuncList() {
- mSuggestPuncList = new ArrayList<CharSequence>();
- String suggestPuncs = mResources.getString(R.string.suggested_punctuations);
- if (suggestPuncs != null) {
- for (int i = 0; i < suggestPuncs.length(); i++) {
- mSuggestPuncList.add(suggestPuncs.subSequence(i, i + 1));
- }
- }
- }
-
- private void showOptionsMenu() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setCancelable(true);
- builder.setIcon(R.drawable.ic_dialog_keyboard);
- builder.setNegativeButton(android.R.string.cancel, null);
- CharSequence itemSettings = getString(R.string.english_ime_settings);
- CharSequence itemInputMethod = getString(R.string.inputMethod);
- builder.setItems(new CharSequence[] {
- itemSettings, itemInputMethod},
- new DialogInterface.OnClickListener() {
-
- public void onClick(DialogInterface di, int position) {
- di.dismiss();
- switch (position) {
- case POS_SETTINGS:
- launchSettings();
- break;
- case POS_METHOD:
- ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
- .showInputMethodPicker();
- break;
- }
- }
- });
- builder.setTitle(mResources.getString(R.string.english_ime_name));
- mOptionsDialog = builder.create();
- Window window = mOptionsDialog.getWindow();
- WindowManager.LayoutParams lp = window.getAttributes();
- lp.token = mInputView.getWindowToken();
- lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
- window.setAttributes(lp);
- window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
- mOptionsDialog.show();
- }
-
- private void changeKeyboardMode() {
- mKeyboardSwitcher.toggleSymbols();
- if (mCapsLock && mKeyboardSwitcher.isAlphabetMode()) {
- ((LatinKeyboard) mInputView.getKeyboard()).setShiftLocked(mCapsLock);
- }
-
- updateShiftKeyState(getCurrentInputEditorInfo());
- }
-
- public static <E> ArrayList<E> newArrayList(E... elements) {
- int capacity = (elements.length * 110) / 100 + 5;
- ArrayList<E> list = new ArrayList<E>(capacity);
- Collections.addAll(list, elements);
- return list;
- }
-
- @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- super.dump(fd, fout, args);
-
- final Printer p = new PrintWriterPrinter(fout);
- p.println("LatinIME state :");
- p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode());
- p.println(" mCapsLock=" + mCapsLock);
- p.println(" mComposing=" + mComposing.toString());
- p.println(" mPredictionOn=" + mPredictionOn);
- p.println(" mCorrectionMode=" + mCorrectionMode);
- p.println(" mPredicting=" + mPredicting);
- p.println(" mAutoCorrectOn=" + mAutoCorrectOn);
- p.println(" mAutoSpace=" + mAutoSpace);
- p.println(" mCompletionOn=" + mCompletionOn);
- p.println(" TextEntryState.state=" + TextEntryState.getState());
- p.println(" mSoundOn=" + mSoundOn);
- p.println(" mVibrateOn=" + mVibrateOn);
- }
-
- // Characters per second measurement
-
- private static final boolean PERF_DEBUG = false;
- private long mLastCpsTime;
- private static final int CPS_BUFFER_SIZE = 16;
- private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE];
- private int mCpsIndex;
- private boolean mInputTypeNoAutoCorrect;
-
- private void measureCps() {
- if (!LatinIME.PERF_DEBUG) return;
- long now = System.currentTimeMillis();
- if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial
- mCpsIntervals[mCpsIndex] = now - mLastCpsTime;
- mLastCpsTime = now;
- mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE;
- long total = 0;
- for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i];
- System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total));
- }
-
-}
diff --git a/src/com/android/inputmethod/latin/LatinIMEBackupAgent.java b/src/com/android/inputmethod/latin/LatinIMEBackupAgent.java
deleted file mode 100644
index 62da86cd4..000000000
--- a/src/com/android/inputmethod/latin/LatinIMEBackupAgent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2009 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 android.app.backup.BackupHelperAgent;
-import android.app.backup.SharedPreferencesBackupHelper;
-
-/**
- * Backs up the Latin IME shared preferences.
- */
-public class LatinIMEBackupAgent extends BackupHelperAgent {
-
- public void onCreate() {
- addHelper("shared_pref", new SharedPreferencesBackupHelper(this,
- getPackageName() + "_preferences"));
- }
-}
diff --git a/src/com/android/inputmethod/latin/LatinIMESettings.java b/src/com/android/inputmethod/latin/LatinIMESettings.java
deleted file mode 100644
index f76ec99b6..000000000
--- a/src/com/android/inputmethod/latin/LatinIMESettings.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.ArrayList;
-import java.util.Locale;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.backup.BackupManager;
-import android.content.DialogInterface;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceGroup;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.speech.RecognitionManager;
-import android.text.AutoText;
-import android.util.Log;
-
-import com.android.inputmethod.voice.SettingsUtil;
-import com.android.inputmethod.voice.VoiceInputLogger;
-
-public class LatinIMESettings extends PreferenceActivity
- implements SharedPreferences.OnSharedPreferenceChangeListener,
- DialogInterface.OnDismissListener {
-
- private static final String QUICK_FIXES_KEY = "quick_fixes";
- private static final String SHOW_SUGGESTIONS_KEY = "show_suggestions";
- private static final String PREDICTION_SETTINGS_KEY = "prediction_settings";
- private static final String VOICE_SETTINGS_KEY = "voice_mode";
- private static final String VOICE_ON_PRIMARY_KEY = "voice_on_main";
- private static final String VOICE_SERVER_KEY = "voice_server_url";
-
- private static final String TAG = "LatinIMESettings";
-
- // Dialog ids
- private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
-
- private CheckBoxPreference mQuickFixes;
- private CheckBoxPreference mShowSuggestions;
- private ListPreference mVoicePreference;
- private boolean mVoiceOn;
-
- private VoiceInputLogger mLogger;
-
- private boolean mOkClicked = false;
- private String mVoiceModeOff;
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- addPreferencesFromResource(R.xml.prefs);
- mQuickFixes = (CheckBoxPreference) findPreference(QUICK_FIXES_KEY);
- mShowSuggestions = (CheckBoxPreference) findPreference(SHOW_SUGGESTIONS_KEY);
- mVoicePreference = (ListPreference) findPreference(VOICE_SETTINGS_KEY);
- SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
- prefs.registerOnSharedPreferenceChangeListener(this);
-
- mVoiceModeOff = getString(R.string.voice_mode_off);
- mVoiceOn = !(prefs.getString(VOICE_SETTINGS_KEY, mVoiceModeOff).equals(mVoiceModeOff));
- mLogger = VoiceInputLogger.getLogger(this);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- int autoTextSize = AutoText.getSize(getListView());
- if (autoTextSize < 1) {
- ((PreferenceGroup) findPreference(PREDICTION_SETTINGS_KEY))
- .removePreference(mQuickFixes);
- }
- if (!LatinIME.VOICE_INSTALLED
- || !RecognitionManager.isRecognitionAvailable(this)) {
- getPreferenceScreen().removePreference(mVoicePreference);
- } else {
- updateVoiceModeSummary();
- }
- }
-
- @Override
- protected void onDestroy() {
- getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
- this);
- super.onDestroy();
- }
-
- public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
- (new BackupManager(this)).dataChanged();
- // If turning on voice input, show dialog
- if (key.equals(VOICE_SETTINGS_KEY) && !mVoiceOn) {
- if (! prefs.getString(VOICE_SETTINGS_KEY, mVoiceModeOff)
- .equals(mVoiceModeOff)) {
- showVoiceConfirmation();
- }
- }
- mVoiceOn = !(prefs.getString(VOICE_SETTINGS_KEY, mVoiceModeOff).equals(mVoiceModeOff));
- updateVoiceModeSummary();
- }
-
- private void showVoiceConfirmation() {
- mOkClicked = false;
- showDialog(VOICE_INPUT_CONFIRM_DIALOG);
- }
-
- private void updateVoiceModeSummary() {
- mVoicePreference.setSummary(
- getResources().getStringArray(R.array.voice_input_modes_summary)
- [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
- }
-
- @Override
- protected Dialog onCreateDialog(int id) {
- switch (id) {
- case VOICE_INPUT_CONFIRM_DIALOG:
- DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
- mVoicePreference.setValue(mVoiceModeOff);
- mLogger.settingsWarningDialogCancel();
- } else if (whichButton == DialogInterface.BUTTON_POSITIVE) {
- mOkClicked = true;
- mLogger.settingsWarningDialogOk();
- }
- updateVoicePreference();
- }
- };
- AlertDialog.Builder builder = new AlertDialog.Builder(this)
- .setTitle(R.string.voice_warning_title)
- .setPositiveButton(android.R.string.ok, listener)
- .setNegativeButton(android.R.string.cancel, listener);
-
- // Get the current list of supported locales and check the current locale against
- // that list, to decide whether to put a warning that voice input will not work in
- // the current language as part of the pop-up confirmation dialog.
- String supportedLocalesString = SettingsUtil.getSettingsString(
- getContentResolver(),
- SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
- LatinIME.DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
- ArrayList<String> voiceInputSupportedLocales =
- LatinIME.newArrayList(supportedLocalesString.split("\\s+"));
- boolean localeSupported = voiceInputSupportedLocales.contains(
- Locale.getDefault().toString());
-
- if (localeSupported) {
- String message = getString(R.string.voice_warning_may_not_understand) + "\n\n" +
- getString(R.string.voice_hint_dialog_message);
- builder.setMessage(message);
- } else {
- String message = getString(R.string.voice_warning_locale_not_supported) +
- "\n\n" + getString(R.string.voice_warning_may_not_understand) + "\n\n" +
- getString(R.string.voice_hint_dialog_message);
- builder.setMessage(message);
- }
-
- AlertDialog dialog = builder.create();
- dialog.setOnDismissListener(this);
- mLogger.settingsWarningDialogShown();
- return dialog;
- default:
- Log.e(TAG, "unknown dialog " + id);
- return null;
- }
- }
-
- public void onDismiss(DialogInterface dialog) {
- mLogger.settingsWarningDialogDismissed();
- if (!mOkClicked) {
- // This assumes that onPreferenceClick gets called first, and this if the user
- // agreed after the warning, we set the mOkClicked value to true.
- mVoicePreference.setValue(mVoiceModeOff);
- }
- }
-
- private void updateVoicePreference() {
- boolean isChecked = !mVoicePreference.getValue().equals(mVoiceModeOff);
- if (isChecked) {
- mLogger.voiceInputSettingEnabled();
- } else {
- mLogger.voiceInputSettingDisabled();
- }
- }
-}
diff --git a/src/com/android/inputmethod/latin/LatinKeyboard.java b/src/com/android/inputmethod/latin/LatinKeyboard.java
deleted file mode 100644
index 58e1dc767..000000000
--- a/src/com/android/inputmethod/latin/LatinKeyboard.java
+++ /dev/null
@@ -1,762 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.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.util.Log;
-import android.view.ViewConfiguration;
-import android.view.inputmethod.EditorInfo;
-
-public class LatinKeyboard extends Keyboard {
-
- private static final boolean DEBUG_PREFERRED_LETTER = false;
- private static final String TAG = "LatinKeyboard";
-
- private Drawable mShiftLockIcon;
- private Drawable mShiftLockPreviewIcon;
- 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 Key m123Key;
- 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;
- // Whether this keyboard has voice icon on it
- private boolean mHasVoiceButton;
- // Whether voice icon is enabled at all
- private boolean mVoiceEnabled;
- private boolean mIsAlphaKeyboard;
- private CharSequence m123Label;
- private boolean mCurrentlyInSpace;
- private SlidingLocaleDrawable mSlidingLocaleIcon;
- private Rect mBounds = new Rect();
- private int[] mPrefLetterFrequencies;
- private boolean mPreemptiveCorrection;
- private int mPrefLetter;
- private int mPrefLetterX;
- private int mPrefLetterY;
- private int mPrefDistance;
-
- private int mExtensionResId;
-
- private static final int SHIFT_OFF = 0;
- private static final int SHIFT_ON = 1;
- private static final int SHIFT_LOCKED = 2;
-
- private int mShiftState = SHIFT_OFF;
-
- private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f;
- private static final float OVERLAP_PERCENTAGE_LOW_PROB = 0.70f;
- private static final float OVERLAP_PERCENTAGE_HIGH_PROB = 0.85f;
-
- static int sSpacebarVerticalCorrection;
-
- public LatinKeyboard(Context context, int xmlLayoutResId) {
- this(context, xmlLayoutResId, 0);
- }
-
- public LatinKeyboard(Context context, int xmlLayoutResId, int mode) {
- super(context, xmlLayoutResId, mode);
- final Resources res = context.getResources();
- mContext = context;
- mMode = mode;
- mRes = res;
- mShiftLockIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked);
- mShiftLockPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_shift_locked);
- mShiftLockPreviewIcon.setBounds(0, 0,
- 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);
- setDefaultBounds(mMicPreviewIcon);
- mButtonArrowLeftIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_left);
- mButtonArrowRightIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_right);
- m123MicIcon = res.getDrawable(R.drawable.sym_keyboard_123_mic);
- m123MicPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_123_mic);
- setDefaultBounds(m123MicPreviewIcon);
- sSpacebarVerticalCorrection = res.getDimensionPixelOffset(
- R.dimen.spacebar_vertical_correction);
- mIsAlphaKeyboard = xmlLayoutResId == R.xml.kbd_qwerty;
- mSpaceKeyIndex = indexOf((int) ' ');
- }
-
- public LatinKeyboard(Context context, int layoutTemplateResId,
- CharSequence characters, int columns, int horizontalPadding) {
- super(context, layoutTemplateResId, characters, columns, horizontalPadding);
- }
-
- @Override
- protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
- XmlResourceParser parser) {
- Key key = new LatinKey(res, parent, x, y, parser);
- switch (key.codes[0]) {
- case 10:
- mEnterKey = key;
- break;
- case LatinKeyboardView.KEYCODE_F1:
- mF1Key = key;
- break;
- case 32:
- mSpaceKey = key;
- break;
- case KEYCODE_MODE_CHANGE:
- m123Key = key;
- m123Label = key.label;
- break;
- }
- return key;
- }
-
- void setImeOptions(Resources res, int mode, int options) {
- if (mEnterKey != null) {
- // Reset some of the rarely used attributes.
- mEnterKey.popupCharacters = null;
- mEnterKey.popupResId = 0;
- mEnterKey.text = null;
- switch (options&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) {
- case EditorInfo.IME_ACTION_GO:
- mEnterKey.iconPreview = null;
- mEnterKey.icon = null;
- mEnterKey.label = res.getText(R.string.label_go_key);
- break;
- case EditorInfo.IME_ACTION_NEXT:
- mEnterKey.iconPreview = null;
- mEnterKey.icon = null;
- mEnterKey.label = res.getText(R.string.label_next_key);
- break;
- case EditorInfo.IME_ACTION_DONE:
- mEnterKey.iconPreview = null;
- mEnterKey.icon = null;
- mEnterKey.label = res.getText(R.string.label_done_key);
- break;
- case EditorInfo.IME_ACTION_SEARCH:
- mEnterKey.iconPreview = res.getDrawable(
- R.drawable.sym_keyboard_feedback_search);
- mEnterKey.icon = res.getDrawable(
- R.drawable.sym_keyboard_search);
- mEnterKey.label = null;
- break;
- case EditorInfo.IME_ACTION_SEND:
- mEnterKey.iconPreview = null;
- mEnterKey.icon = null;
- mEnterKey.label = res.getText(R.string.label_send_key);
- break;
- default:
- if (mode == KeyboardSwitcher.MODE_IM) {
- mEnterKey.icon = null;
- mEnterKey.iconPreview = null;
- mEnterKey.label = ":-)";
- mEnterKey.text = ":-) ";
- mEnterKey.popupResId = R.xml.popup_smileys;
- } else {
- mEnterKey.iconPreview = res.getDrawable(
- R.drawable.sym_keyboard_feedback_return);
- mEnterKey.icon = res.getDrawable(
- R.drawable.sym_keyboard_return);
- mEnterKey.label = null;
- }
- break;
- }
- // Set the initial size of the preview icon
- if (mEnterKey.iconPreview != null) {
- mEnterKey.iconPreview.setBounds(0, 0,
- mEnterKey.iconPreview.getIntrinsicWidth(),
- mEnterKey.iconPreview.getIntrinsicHeight());
- }
- }
- }
-
- void enableShiftLock() {
- int index = getShiftKeyIndex();
- if (index >= 0) {
- mShiftKey = getKeys().get(index);
- if (mShiftKey instanceof LatinKey) {
- ((LatinKey)mShiftKey).enableShiftLock();
- }
- mOldShiftIcon = mShiftKey.icon;
- mOldShiftPreviewIcon = mShiftKey.iconPreview;
- }
- }
-
- void setShiftLocked(boolean shiftLocked) {
- if (mShiftKey != null) {
- if (shiftLocked) {
- mShiftKey.on = true;
- mShiftKey.icon = mShiftLockIcon;
- mShiftState = SHIFT_LOCKED;
- } else {
- mShiftKey.on = false;
- mShiftKey.icon = mShiftLockIcon;
- mShiftState = SHIFT_ON;
- }
- }
- }
-
- boolean isShiftLocked() {
- return mShiftState == SHIFT_LOCKED;
- }
-
- @Override
- public boolean setShifted(boolean shiftState) {
- boolean shiftChanged = false;
- if (mShiftKey != null) {
- if (shiftState == false) {
- shiftChanged = mShiftState != SHIFT_OFF;
- mShiftState = SHIFT_OFF;
- mShiftKey.on = false;
- mShiftKey.icon = mOldShiftIcon;
- } else {
- if (mShiftState == SHIFT_OFF) {
- shiftChanged = mShiftState == SHIFT_OFF;
- mShiftState = SHIFT_ON;
- mShiftKey.icon = mShiftLockIcon;
- }
- }
- } else {
- return super.setShifted(shiftState);
- }
- return shiftChanged;
- }
-
- @Override
- public boolean isShifted() {
- if (mShiftKey != null) {
- return mShiftState != SHIFT_OFF;
- } else {
- return super.isShifted();
- }
- }
-
- public void setExtension(int resId) {
- mExtensionResId = resId;
- }
-
- public int getExtension() {
- return mExtensionResId;
- }
-
- private void setDefaultBounds(Drawable drawable) {
- drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
- }
-
- public void setVoiceMode(boolean hasVoiceButton, boolean hasVoice) {
- mHasVoiceButton = hasVoiceButton;
- mVoiceEnabled = hasVoice;
- updateF1Key();
- }
-
- private void updateF1Key() {
- if (mF1Key == null) return;
- if (m123Key != null && mIsAlphaKeyboard) {
- if (mVoiceEnabled && !mHasVoiceButton) {
- m123Key.icon = m123MicIcon;
- m123Key.iconPreview = m123MicPreviewIcon;
- m123Key.label = null;
- } else {
- m123Key.icon = null;
- m123Key.iconPreview = null;
- m123Key.label = m123Label;
- }
- }
-
- if (mHasVoiceButton && mVoiceEnabled) {
- mF1Key.codes = new int[] { LatinKeyboardView.KEYCODE_VOICE };
- mF1Key.label = null;
- mF1Key.icon = mMicIcon;
- mF1Key.iconPreview = mMicPreviewIcon;
- } else {
- mF1Key.label = ",";
- mF1Key.codes = new int[] { ',' };
- mF1Key.icon = null;
- mF1Key.iconPreview = null;
- }
- }
-
- private void updateSpaceBarForLocale() {
- if (mLocale != null) {
- // Create the graphic for spacebar
- Bitmap buffer = Bitmap.createBitmap(mSpaceKey.width, mSpaceIcon.getIntrinsicHeight(),
- Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(buffer);
- drawSpaceBar(canvas, buffer.getWidth(), buffer.getHeight(), 255);
- mSpaceKey.icon = new BitmapDrawable(mRes, buffer);
- mSpaceKey.repeatable = mLanguageSwitcher.getLocaleCount() < 2;
- } else {
- mSpaceKey.icon = mRes.getDrawable(R.drawable.sym_keyboard_space);
- mSpaceKey.repeatable = true;
- }
- }
-
- private void drawSpaceBar(Canvas canvas, int width, int height, int opacity) {
- canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
- Paint paint = new Paint();
- paint.setAntiAlias(true);
- paint.setAlpha(opacity);
- // 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(2f, 0, 0, 0xFF000000);
- final String language = getInputLanguage(mSpaceKey.width, paint);
- final int ascent = (int) -paint.ascent();
- paint.setColor(0x80000000);
- canvas.drawText(language,
- width / 2, ascent - 1, paint);
- paint.setColor(0xFF808080);
- canvas.drawText(language,
- width / 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 = (width - mSpaceIcon.getIntrinsicWidth()) / 2;
- int y = height - mSpaceIcon.getIntrinsicHeight();
- mSpaceIcon.setBounds(x, y,
- x + mSpaceIcon.getIntrinsicWidth(), y + mSpaceIcon.getIntrinsicHeight());
- mSpaceIcon.draw(canvas);
- }
-
- 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 LanguageSwitcher.toTitleCase(locale.getLanguage().substring(0, 2));
- } else {
- return LanguageSwitcher.toTitleCase(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();
- }
-
- boolean isCurrentlyInSpace() {
- return mCurrentlyInSpace;
- }
-
- void setPreferredLetters(int[] frequencies) {
- mPrefLetterFrequencies = frequencies;
- mPrefLetter = 0;
- }
-
- void keyReleased() {
- mCurrentlyInSpace = false;
- mSpaceDragLastDiff = 0;
- mPrefLetter = 0;
- mPrefLetterX = 0;
- mPrefLetterY = 0;
- mPrefDistance = Integer.MAX_VALUE;
- 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;
- }
- }
- } else if (mPrefLetterFrequencies != null) {
- // New coordinate? Reset
- if (mPrefLetterX != x || mPrefLetterY != y) {
- mPrefLetter = 0;
- mPrefDistance = Integer.MAX_VALUE;
- }
- // Handle preferred next letter
- final int[] pref = mPrefLetterFrequencies;
- if (mPrefLetter > 0) {
- if (DEBUG_PREFERRED_LETTER && mPrefLetter == code
- && !key.isInsideSuper(x, y)) {
- Log.d(TAG, "CORRECTED !!!!!!");
- }
- return mPrefLetter == code;
- } else {
- final boolean inside = key.isInsideSuper(x, y);
- int[] nearby = getNearestKeys(x, y);
- List<Key> nearbyKeys = getKeys();
- if (inside) {
- // If it's a preferred letter
- if (inPrefList(code, pref)) {
- // Check if its frequency is much lower than a nearby key
- mPrefLetter = code;
- mPrefLetterX = x;
- mPrefLetterY = y;
- for (int i = 0; i < nearby.length; i++) {
- Key k = nearbyKeys.get(nearby[i]);
- if (k != key && inPrefList(k.codes[0], pref)) {
- final int dist = distanceFrom(k, x, y);
- if (dist < (int) (k.width * OVERLAP_PERCENTAGE_LOW_PROB) &&
- (pref[k.codes[0]] > pref[mPrefLetter] * 3)) {
- mPrefLetter = k.codes[0];
- mPrefDistance = dist;
- if (DEBUG_PREFERRED_LETTER) {
- Log.d(TAG, "CORRECTED ALTHOUGH PREFERRED !!!!!!");
- }
- break;
- }
- }
- }
-
- return mPrefLetter == code;
- }
- }
-
- // Get the surrounding keys and intersect with the preferred list
- // For all in the intersection
- // if distance from touch point is within a reasonable distance
- // make this the pref letter
- // If no pref letter
- // return inside;
- // else return thiskey == prefletter;
-
- for (int i = 0; i < nearby.length; i++) {
- Key k = nearbyKeys.get(nearby[i]);
- if (inPrefList(k.codes[0], pref)) {
- final int dist = distanceFrom(k, x, y);
- if (dist < (int) (k.width * OVERLAP_PERCENTAGE_HIGH_PROB)
- && dist < mPrefDistance) {
- mPrefLetter = k.codes[0];
- mPrefLetterX = x;
- mPrefLetterY = y;
- mPrefDistance = dist;
- }
- }
- }
- // Didn't find any
- if (mPrefLetter == 0) {
- return inside;
- } else {
- return mPrefLetter == code;
- }
- }
- }
-
- // Lock into the spacebar
- if (mCurrentlyInSpace) return false;
-
- return key.isInsideSuper(x, y);
- }
-
- private boolean inPrefList(int code, int[] pref) {
- if (code < pref.length && code >= 0) return pref[code] > 0;
- return false;
- }
-
- private int distanceFrom(Key k, int x, int y) {
- if (y > k.y && y < k.y + k.height) {
- return Math.abs(k.x + k.width / 2 - x);
- } else {
- return Integer.MAX_VALUE;
- }
- }
-
- @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;
-
- public LatinKey(Resources res, Keyboard.Row parent, int x, int y,
- XmlResourceParser parser) {
- super(res, parent, x, y, parser);
- if (popupCharacters != null && popupCharacters.length() == 0) {
- // If there is a keyboard with no keys specified in popupCharacters
- popupResId = 0;
- }
- }
-
- void enableShiftLock() {
- mShiftLockEnabled = true;
- }
-
- @Override
- public void onReleased(boolean inside) {
- if (!mShiftLockEnabled) {
- super.onReleased(inside);
- } else {
- pressed = !pressed;
- }
- }
-
- /**
- * Overriding this method so that we can reduce the target area for certain keys.
- */
- @Override
- public boolean isInside(int x, int y) {
- boolean result = LatinKeyboard.this.isInside(this, x, y);
- return result;
- }
-
- 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(0xFF000000);
- canvas.clipRect(0, 0, mWidth, mHeight);
- if (mCurrentLanguage == null) {
- mCurrentLanguage = getInputLanguage(mWidth, mTextPaint);
- mNextLanguage = getNextInputLanguage(mWidth, mTextPaint);
- mPrevLanguage = getPrevInputLanguage(mWidth, mTextPaint);
- }
- canvas.drawText(mCurrentLanguage,
- mWidth / 2 + mDiff, -mAscent + 4, mTextPaint);
- 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
deleted file mode 100644
index 2686a93c6..000000000
--- a/src/com/android/inputmethod/latin/LatinKeyboardView.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.List;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.inputmethodservice.Keyboard;
-import android.inputmethodservice.KeyboardView;
-import android.inputmethodservice.Keyboard.Key;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.widget.PopupWindow;
-
-public class LatinKeyboardView extends KeyboardView {
-
- static final int KEYCODE_OPTIONS = -100;
- static final int KEYCODE_SHIFT_LONGPRESS = -101;
- 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);
- }
-
- public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public void setPhoneKeyboard(Keyboard phoneKeyboard) {
- mPhoneKeyboard = phoneKeyboard;
- }
-
- @Override
- protected boolean onLongPress(Key key) {
- if (key.codes[0] == Keyboard.KEYCODE_MODE_CHANGE) {
- getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS, null);
- return true;
- } else if (key.codes[0] == Keyboard.KEYCODE_SHIFT) {
- getOnKeyboardActionListener().onKey(KEYCODE_SHIFT_LONGPRESS, null);
- invalidateAllKeys();
- return true;
- } else if (key.codes[0] == '0' && getKeyboard() == mPhoneKeyboard) {
- // Long pressing on 0 in phone number keypad gives you a '+'.
- getOnKeyboardActionListener().onKey('+', null);
- return true;
- } else {
- return super.onLongPress(key);
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent me) {
- LatinKeyboard keyboard = (LatinKeyboard) getKeyboard();
- if (DEBUG_LINE) {
- mLastX = (int) me.getX();
- mLastY = (int) me.getY();
- invalidate();
- }
- // 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) {
- if (mExtensionVisible) {
- int action = me.getAction();
- if (mFirstEvent) action = MotionEvent.ACTION_DOWN;
- mFirstEvent = false;
- MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(),
- action,
- me.getX(), me.getY() + mExtension.getHeight(), me.getMetaState());
- boolean result = mExtension.onTouchEvent(translated);
- translated.recycle();
- if (me.getAction() == MotionEvent.ACTION_UP
- || me.getAction() == MotionEvent.ACTION_CANCEL) {
- closeExtension();
- }
- return result;
- } else {
- if (openExtension()) {
- MotionEvent cancel = MotionEvent.obtain(me.getDownTime(), me.getEventTime(),
- MotionEvent.ACTION_CANCEL, me.getX() - 100, me.getY() - 100, 0);
- super.onTouchEvent(cancel);
- cancel.recycle();
- if (mExtension.getHeight() > 0) {
- MotionEvent translated = MotionEvent.obtain(me.getEventTime(),
- me.getEventTime(),
- MotionEvent.ACTION_DOWN,
- me.getX(), me.getY() + mExtension.getHeight(),
- me.getMetaState());
- mExtension.onTouchEvent(translated);
- translated.recycle();
- } else {
- mFirstEvent = true;
- }
- }
- return true;
- }
- } else if (mExtensionVisible) {
- closeExtension();
- // Send a down event into the main keyboard first
- MotionEvent down = MotionEvent.obtain(me.getEventTime(), me.getEventTime(),
- MotionEvent.ACTION_DOWN,
- me.getX(), me.getY(), me.getMetaState());
- super.onTouchEvent(down);
- down.recycle();
- // Send the actual event
- return super.onTouchEvent(me);
- } else {
- return super.onTouchEvent(me);
- }
- }
-
- private boolean openExtension() {
- if (((LatinKeyboard) getKeyboard()).getExtension() == 0) return false;
- makePopupWindow();
- mExtensionVisible = true;
- return true;
- }
-
- private void makePopupWindow() {
- if (mExtensionPopup == null) {
- int[] windowLocation = new int[2];
- mExtensionPopup = new PopupWindow(getContext());
- mExtensionPopup.setBackgroundDrawable(null);
- LayoutInflater li = (LayoutInflater) getContext().getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- mExtension = (LatinKeyboardView) li.inflate(R.layout.input_trans, null);
- mExtension.setOnKeyboardActionListener((LatinIME) getContext());
- mExtension.setPopupParent(this);
- mExtension.setPopupOffset(0, -windowLocation[1]);
- Keyboard keyboard;
- mExtension.setKeyboard(keyboard = new LatinKeyboard(getContext(),
- ((LatinKeyboard) getKeyboard()).getExtension()));
- mExtensionPopup.setContentView(mExtension);
- mExtensionPopup.setWidth(getWidth());
- mExtensionPopup.setHeight(keyboard.getHeight());
- getLocationInWindow(windowLocation);
- // TODO: Fix the "- 30".
- mExtension.setPopupOffset(0, -windowLocation[1] - 30);
- mExtensionPopup.showAtLocation(this, 0, 0, -keyboard.getHeight()
- + windowLocation[1]);
- } else {
- mExtension.setVisibility(VISIBLE);
- }
- }
-
- @Override
- public void closing() {
- super.closing();
- if (mExtensionPopup != null && mExtensionPopup.isShowing()) {
- mExtensionPopup.dismiss();
- mExtensionPopup = null;
- }
- }
-
- private void closeExtension() {
- mExtension.setVisibility(INVISIBLE);
- mExtension.closing();
- mExtensionVisible = false;
- }
-
- /**************************** INSTRUMENTATION *******************************/
-
- static final boolean DEBUG_AUTO_PLAY = false;
- static final boolean DEBUG_LINE = false;
- private static final int MSG_TOUCH_DOWN = 1;
- private static final int MSG_TOUCH_UP = 2;
-
- Handler mHandler2;
-
- private String mStringToPlay;
- private int mStringIndex;
- private boolean mDownDelivered;
- private Key[] mAsciiKeys = new Key[256];
- private boolean mPlaying;
- private int mLastX;
- private int mLastY;
- private Paint mPaint;
-
- @Override
- public void setKeyboard(Keyboard k) {
- super.setKeyboard(k);
- if (DEBUG_AUTO_PLAY) {
- findKeys();
- if (mHandler2 == null) {
- mHandler2 = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- removeMessages(MSG_TOUCH_DOWN);
- removeMessages(MSG_TOUCH_UP);
- if (mPlaying == false) return;
-
- switch (msg.what) {
- case MSG_TOUCH_DOWN:
- if (mStringIndex >= mStringToPlay.length()) {
- mPlaying = false;
- return;
- }
- char c = mStringToPlay.charAt(mStringIndex);
- while (c > 255 || mAsciiKeys[(int) c] == null) {
- mStringIndex++;
- if (mStringIndex >= mStringToPlay.length()) {
- mPlaying = false;
- return;
- }
- c = mStringToPlay.charAt(mStringIndex);
- }
- int x = mAsciiKeys[c].x + 10;
- int y = mAsciiKeys[c].y + 26;
- MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(),
- SystemClock.uptimeMillis(),
- MotionEvent.ACTION_DOWN, x, y, 0);
- LatinKeyboardView.this.dispatchTouchEvent(me);
- me.recycle();
- sendEmptyMessageDelayed(MSG_TOUCH_UP, 500); // Deliver up in 500ms if nothing else
- // happens
- mDownDelivered = true;
- break;
- case MSG_TOUCH_UP:
- char cUp = mStringToPlay.charAt(mStringIndex);
- int x2 = mAsciiKeys[cUp].x + 10;
- int y2 = mAsciiKeys[cUp].y + 26;
- mStringIndex++;
-
- MotionEvent me2 = MotionEvent.obtain(SystemClock.uptimeMillis(),
- SystemClock.uptimeMillis(),
- MotionEvent.ACTION_UP, x2, y2, 0);
- LatinKeyboardView.this.dispatchTouchEvent(me2);
- me2.recycle();
- sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 500); // Deliver up in 500ms if nothing else
- // happens
- mDownDelivered = false;
- break;
- }
- }
- };
-
- }
- }
- }
-
- private void findKeys() {
- List<Key> keys = getKeyboard().getKeys();
- // Get the keys on this keyboard
- for (int i = 0; i < keys.size(); i++) {
- int code = keys.get(i).codes[0];
- if (code >= 0 && code <= 255) {
- mAsciiKeys[code] = keys.get(i);
- }
- }
- }
-
- void startPlaying(String s) {
- if (!DEBUG_AUTO_PLAY) return;
- if (s == null) return;
- mStringToPlay = s.toLowerCase();
- mPlaying = true;
- mDownDelivered = false;
- mStringIndex = 0;
- mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 10);
- }
-
- @Override
- public void draw(Canvas c) {
- super.draw(c);
- if (DEBUG_AUTO_PLAY && mPlaying) {
- mHandler2.removeMessages(MSG_TOUCH_DOWN);
- mHandler2.removeMessages(MSG_TOUCH_UP);
- if (mDownDelivered) {
- mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_UP, 20);
- } else {
- mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 20);
- }
- }
- if (DEBUG_LINE) {
- if (mPaint == null) {
- mPaint = new Paint();
- mPaint.setColor(0x80FFFFFF);
- mPaint.setAntiAlias(false);
- }
- c.drawLine(mLastX, 0, mLastX, getHeight(), mPaint);
- c.drawLine(0, mLastY, getWidth(), mLastY, mPaint);
- }
- }
-}
diff --git a/src/com/android/inputmethod/latin/Suggest.java b/src/com/android/inputmethod/latin/Suggest.java
deleted file mode 100755
index 712b9cf37..000000000
--- a/src/com/android/inputmethod/latin/Suggest.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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 android.content.Context;
-import android.text.AutoText;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.View;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import com.android.inputmethod.latin.WordComposer;
-
-/**
- * This class loads a dictionary and provides a list of suggestions for a given sequence of
- * characters. This includes corrections and completions.
- * @hide pending API Council Approval
- */
-public class Suggest implements Dictionary.WordCallback {
-
- public static final int CORRECTION_NONE = 0;
- public static final int CORRECTION_BASIC = 1;
- public static final int CORRECTION_FULL = 2;
-
- private static final int LARGE_DICTIONARY_THRESHOLD = 200 * 1000;
-
- private BinaryDictionary mMainDict;
-
- private Dictionary mUserDictionary;
-
- private Dictionary mAutoDictionary;
-
- private Dictionary mContactsDictionary;
-
- private int mPrefMaxSuggestions = 12;
-
- private boolean mAutoTextEnabled;
-
- private int[] mPriorities = new int[mPrefMaxSuggestions];
- // Handle predictive correction for only the first 1280 characters for performance reasons
- // If we support scripts that need latin characters beyond that, we should probably use some
- // kind of a sparse array or language specific list with a mapping lookup table.
- // 1280 is the size of the BASE_CHARS array in ExpandableDictionary, which is a basic set of
- // latin characters.
- private int[] mNextLettersFrequencies = new int[1280];
- private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
- private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>();
- private boolean mHaveCorrection;
- private CharSequence mOriginalWord;
- private String mLowerOriginalWord;
- private boolean mCapitalize;
-
- private int mCorrectionMode = CORRECTION_BASIC;
-
-
- public Suggest(Context context, int dictionaryResId) {
- mMainDict = new BinaryDictionary(context, dictionaryResId);
- for (int i = 0; i < mPrefMaxSuggestions; i++) {
- StringBuilder sb = new StringBuilder(32);
- mStringPool.add(sb);
- }
- }
-
- public void setAutoTextEnabled(boolean enabled) {
- mAutoTextEnabled = enabled;
- }
-
- public int getCorrectionMode() {
- return mCorrectionMode;
- }
-
- public void setCorrectionMode(int mode) {
- mCorrectionMode = mode;
- }
-
- public boolean hasMainDictionary() {
- return mMainDict.getSize() > LARGE_DICTIONARY_THRESHOLD;
- }
-
- /**
- * Sets an optional user dictionary resource to be loaded. The user dictionary is consulted
- * before the main dictionary, if set.
- */
- public void setUserDictionary(Dictionary userDictionary) {
- mUserDictionary = userDictionary;
- }
-
- /**
- * Sets an optional contacts dictionary resource to be loaded.
- */
- public void setContactsDictionary(Dictionary userDictionary) {
- mContactsDictionary = userDictionary;
- }
-
- public void setAutoDictionary(Dictionary autoDictionary) {
- mAutoDictionary = autoDictionary;
- }
-
- /**
- * Number of suggestions to generate from the input key sequence. This has
- * to be a number between 1 and 100 (inclusive).
- * @param maxSuggestions
- * @throws IllegalArgumentException if the number is out of range
- */
- public void setMaxSuggestions(int maxSuggestions) {
- if (maxSuggestions < 1 || maxSuggestions > 100) {
- throw new IllegalArgumentException("maxSuggestions must be between 1 and 100");
- }
- mPrefMaxSuggestions = maxSuggestions;
- mPriorities = new int[mPrefMaxSuggestions];
- collectGarbage();
- while (mStringPool.size() < mPrefMaxSuggestions) {
- StringBuilder sb = new StringBuilder(32);
- mStringPool.add(sb);
- }
- }
-
- private boolean haveSufficientCommonality(String original, CharSequence suggestion) {
- final int originalLength = original.length();
- final int suggestionLength = suggestion.length();
- final int minLength = Math.min(originalLength, suggestionLength);
- if (minLength <= 2) return true;
- int matching = 0;
- int lessMatching = 0; // Count matches if we skip one character
- int i;
- for (i = 0; i < minLength; i++) {
- final char origChar = ExpandableDictionary.toLowerCase(original.charAt(i));
- if (origChar == ExpandableDictionary.toLowerCase(suggestion.charAt(i))) {
- matching++;
- lessMatching++;
- } else if (i + 1 < suggestionLength
- && origChar == ExpandableDictionary.toLowerCase(suggestion.charAt(i + 1))) {
- lessMatching++;
- }
- }
- matching = Math.max(matching, lessMatching);
-
- if (minLength <= 4) {
- return matching >= 2;
- } else {
- return matching > minLength / 2;
- }
- }
-
- /**
- * Returns a list of words that match the list of character codes passed in.
- * This list will be overwritten the next time this function is called.
- * @param a view for retrieving the context for AutoText
- * @param codes the list of codes. Each list item contains an array of character codes
- * in order of probability where the character at index 0 in the array has the highest
- * probability.
- * @return list of suggestions.
- */
- public List<CharSequence> getSuggestions(View view, WordComposer wordComposer,
- boolean includeTypedWordIfValid) {
- mHaveCorrection = false;
- mCapitalize = wordComposer.isCapitalized();
- collectGarbage();
- Arrays.fill(mPriorities, 0);
- Arrays.fill(mNextLettersFrequencies, 0);
-
- // Save a lowercase version of the original word
- mOriginalWord = wordComposer.getTypedWord();
- if (mOriginalWord != null) {
- mOriginalWord = mOriginalWord.toString();
- mLowerOriginalWord = mOriginalWord.toString().toLowerCase();
- } else {
- mLowerOriginalWord = "";
- }
- // Search the dictionary only if there are at least 2 characters
- if (wordComposer.size() > 1) {
- if (mUserDictionary != null || mContactsDictionary != null) {
- if (mUserDictionary != null) {
- mUserDictionary.getWords(wordComposer, this, mNextLettersFrequencies);
- }
- if (mContactsDictionary != null) {
- mContactsDictionary.getWords(wordComposer, this, mNextLettersFrequencies);
- }
-
- if (mSuggestions.size() > 0 && isValidWord(mOriginalWord)
- && mCorrectionMode == CORRECTION_FULL) {
- mHaveCorrection = true;
- }
- }
- mMainDict.getWords(wordComposer, this, mNextLettersFrequencies);
- if (mCorrectionMode == CORRECTION_FULL && mSuggestions.size() > 0) {
- mHaveCorrection = true;
- }
- }
- if (mOriginalWord != null) {
- mSuggestions.add(0, mOriginalWord.toString());
- }
-
- // Check if the first suggestion has a minimum number of characters in common
- if (mCorrectionMode == CORRECTION_FULL && mSuggestions.size() > 1) {
- if (!haveSufficientCommonality(mLowerOriginalWord, mSuggestions.get(1))) {
- mHaveCorrection = false;
- }
- }
-
- if (mAutoTextEnabled) {
- int i = 0;
- int max = 6;
- // Don't autotext the suggestions from the dictionaries
- if (mCorrectionMode == CORRECTION_BASIC) max = 1;
- while (i < mSuggestions.size() && i < max) {
- String suggestedWord = mSuggestions.get(i).toString().toLowerCase();
- CharSequence autoText =
- AutoText.get(suggestedWord, 0, suggestedWord.length(), view);
- // Is there an AutoText correction?
- boolean canAdd = autoText != null;
- // Is that correction already the current prediction (or original word)?
- canAdd &= !TextUtils.equals(autoText, mSuggestions.get(i));
- // Is that correction already the next predicted word?
- if (canAdd && i + 1 < mSuggestions.size() && mCorrectionMode != CORRECTION_BASIC) {
- canAdd &= !TextUtils.equals(autoText, mSuggestions.get(i + 1));
- }
- if (canAdd) {
- mHaveCorrection = true;
- mSuggestions.add(i + 1, autoText);
- i++;
- }
- i++;
- }
- }
-
- removeDupes();
- return mSuggestions;
- }
-
- public int[] getNextLettersFrequencies() {
- return mNextLettersFrequencies;
- }
-
- private void removeDupes() {
- final ArrayList<CharSequence> suggestions = mSuggestions;
- if (suggestions.size() < 2) return;
- int i = 1;
- // Don't cache suggestions.size(), since we may be removing items
- while (i < suggestions.size()) {
- final CharSequence cur = suggestions.get(i);
- // Compare each candidate with each previous candidate
- for (int j = 0; j < i; j++) {
- CharSequence previous = suggestions.get(j);
- if (TextUtils.equals(cur, previous)) {
- removeFromSuggestions(i);
- i--;
- break;
- }
- }
- i++;
- }
- }
-
- private void removeFromSuggestions(int index) {
- CharSequence garbage = mSuggestions.remove(index);
- if (garbage != null && garbage instanceof StringBuilder) {
- mStringPool.add(garbage);
- }
- }
-
- public boolean hasMinimalCorrection() {
- return mHaveCorrection;
- }
-
- private boolean compareCaseInsensitive(final String mLowerOriginalWord,
- final char[] word, final int offset, final int length) {
- final int originalLength = mLowerOriginalWord.length();
- if (originalLength == length && Character.isUpperCase(word[offset])) {
- for (int i = 0; i < originalLength; i++) {
- if (mLowerOriginalWord.charAt(i) != Character.toLowerCase(word[offset+i])) {
- return false;
- }
- }
- return true;
- }
- return false;
- }
-
- public boolean addWord(final char[] word, final int offset, final int length, final int freq) {
- int pos = 0;
- final int[] priorities = mPriorities;
- final int prefMaxSuggestions = mPrefMaxSuggestions;
- // Check if it's the same word, only caps are different
- if (compareCaseInsensitive(mLowerOriginalWord, word, offset, length)) {
- pos = 0;
- } else {
- // Check the last one's priority and bail
- if (priorities[prefMaxSuggestions - 1] >= freq) return true;
- while (pos < prefMaxSuggestions) {
- if (priorities[pos] < freq
- || (priorities[pos] == freq && length < mSuggestions
- .get(pos).length())) {
- break;
- }
- pos++;
- }
- }
-
- if (pos >= prefMaxSuggestions) {
- return true;
- }
- System.arraycopy(priorities, pos, priorities, pos + 1,
- prefMaxSuggestions - pos - 1);
- priorities[pos] = freq;
- int poolSize = mStringPool.size();
- StringBuilder sb = poolSize > 0 ? (StringBuilder) mStringPool.remove(poolSize - 1)
- : new StringBuilder(32);
- sb.setLength(0);
- if (mCapitalize) {
- sb.append(Character.toUpperCase(word[offset]));
- if (length > 1) {
- sb.append(word, offset + 1, length - 1);
- }
- } else {
- sb.append(word, offset, length);
- }
- mSuggestions.add(pos, sb);
- if (mSuggestions.size() > prefMaxSuggestions) {
- CharSequence garbage = mSuggestions.remove(prefMaxSuggestions);
- if (garbage instanceof StringBuilder) {
- mStringPool.add(garbage);
- }
- }
- return true;
- }
-
- public boolean isValidWord(final CharSequence word) {
- if (word == null || word.length() == 0) {
- return false;
- }
- return (mCorrectionMode == CORRECTION_FULL && mMainDict.isValidWord(word))
- || (mCorrectionMode > CORRECTION_NONE &&
- ((mUserDictionary != null && mUserDictionary.isValidWord(word)))
- || (mAutoDictionary != null && mAutoDictionary.isValidWord(word))
- || (mContactsDictionary != null && mContactsDictionary.isValidWord(word)));
- }
-
- private void collectGarbage() {
- int poolSize = mStringPool.size();
- int garbageSize = mSuggestions.size();
- while (poolSize < mPrefMaxSuggestions && garbageSize > 0) {
- CharSequence garbage = mSuggestions.get(garbageSize - 1);
- if (garbage != null && garbage instanceof StringBuilder) {
- mStringPool.add(garbage);
- poolSize++;
- }
- garbageSize--;
- }
- if (poolSize == mPrefMaxSuggestions + 1) {
- Log.w("Suggest", "String pool got too big: " + poolSize);
- }
- mSuggestions.clear();
- }
-
- public void close() {
- if (mMainDict != null) {
- mMainDict.close();
- }
- }
-}
diff --git a/src/com/android/inputmethod/latin/TextEntryState.java b/src/com/android/inputmethod/latin/TextEntryState.java
deleted file mode 100644
index c5e8ad9a1..000000000
--- a/src/com/android/inputmethod/latin/TextEntryState.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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 android.content.Context;
-import android.text.format.DateFormat;
-import android.util.Log;
-
-import android.inputmethodservice.Keyboard.Key;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Calendar;
-
-public class TextEntryState {
-
- private static boolean LOGGING = false;
-
- private static int sBackspaceCount = 0;
-
- private static int sAutoSuggestCount = 0;
-
- private static int sAutoSuggestUndoneCount = 0;
-
- private static int sManualSuggestCount = 0;
-
- private static int sWordNotInDictionaryCount = 0;
-
- private static int sSessionCount = 0;
-
- private static int sTypedChars;
-
- private static int sActualChars;
-
- private static final String[] STATES = {
- "Unknown",
- "Start",
- "In word",
- "Accepted default",
- "Picked suggestion",
- "Punc. after word",
- "Punc. after accepted",
- "Space after accepted",
- "Space after picked",
- "Undo commit"
- };
-
- public static final int STATE_UNKNOWN = 0;
- public static final int STATE_START = 1;
- public static final int STATE_IN_WORD = 2;
- public static final int STATE_ACCEPTED_DEFAULT = 3;
- public static final int STATE_PICKED_SUGGESTION = 4;
- public static final int STATE_PUNCTUATION_AFTER_WORD = 5;
- public static final int STATE_PUNCTUATION_AFTER_ACCEPTED = 6;
- public static final int STATE_SPACE_AFTER_ACCEPTED = 7;
- public static final int STATE_SPACE_AFTER_PICKED = 8;
- public static final int STATE_UNDO_COMMIT = 9;
-
- private static int sState = STATE_UNKNOWN;
-
- private static FileOutputStream sKeyLocationFile;
- private static FileOutputStream sUserActionFile;
-
- public static void newSession(Context context) {
- sSessionCount++;
- sAutoSuggestCount = 0;
- sBackspaceCount = 0;
- sAutoSuggestUndoneCount = 0;
- sManualSuggestCount = 0;
- sWordNotInDictionaryCount = 0;
- sTypedChars = 0;
- sActualChars = 0;
- sState = STATE_START;
-
- if (LOGGING) {
- try {
- sKeyLocationFile = context.openFileOutput("key.txt", Context.MODE_APPEND);
- sUserActionFile = context.openFileOutput("action.txt", Context.MODE_APPEND);
- } catch (IOException ioe) {
- Log.e("TextEntryState", "Couldn't open file for output: " + ioe);
- }
- }
- }
-
- public static void endSession() {
- if (sKeyLocationFile == null) {
- return;
- }
- try {
- sKeyLocationFile.close();
- // Write to log file
- // Write timestamp, settings,
- String out = DateFormat.format("MM:dd hh:mm:ss", Calendar.getInstance().getTime())
- .toString()
- + " BS: " + sBackspaceCount
- + " auto: " + sAutoSuggestCount
- + " manual: " + sManualSuggestCount
- + " typed: " + sWordNotInDictionaryCount
- + " undone: " + sAutoSuggestUndoneCount
- + " saved: " + ((float) (sActualChars - sTypedChars) / sActualChars)
- + "\n";
- sUserActionFile.write(out.getBytes());
- sUserActionFile.close();
- sKeyLocationFile = null;
- sUserActionFile = null;
- } catch (IOException ioe) {
-
- }
- }
-
- public static void acceptedDefault(CharSequence typedWord, CharSequence actualWord) {
- if (typedWord == null) return;
- if (!typedWord.equals(actualWord)) {
- sAutoSuggestCount++;
- }
- sTypedChars += typedWord.length();
- sActualChars += actualWord.length();
- sState = STATE_ACCEPTED_DEFAULT;
- }
-
- public static void acceptedTyped(CharSequence typedWord) {
- sWordNotInDictionaryCount++;
- sState = STATE_PICKED_SUGGESTION;
- }
-
- public static void acceptedSuggestion(CharSequence typedWord, CharSequence actualWord) {
- sManualSuggestCount++;
- if (typedWord.equals(actualWord)) {
- acceptedTyped(typedWord);
- }
- sState = STATE_PICKED_SUGGESTION;
- }
-
- public static void typedCharacter(char c, boolean isSeparator) {
- boolean isSpace = c == ' ';
- switch (sState) {
- case STATE_IN_WORD:
- if (isSpace || isSeparator) {
- sState = STATE_START;
- } else {
- // State hasn't changed.
- }
- break;
- case STATE_ACCEPTED_DEFAULT:
- case STATE_SPACE_AFTER_PICKED:
- if (isSpace) {
- sState = STATE_SPACE_AFTER_ACCEPTED;
- } else if (isSeparator) {
- sState = STATE_PUNCTUATION_AFTER_ACCEPTED;
- } else {
- sState = STATE_IN_WORD;
- }
- break;
- case STATE_PICKED_SUGGESTION:
- if (isSpace) {
- sState = STATE_SPACE_AFTER_PICKED;
- } else if (isSeparator) {
- // Swap
- sState = STATE_PUNCTUATION_AFTER_ACCEPTED;
- } else {
- sState = STATE_IN_WORD;
- }
- break;
- case STATE_START:
- case STATE_UNKNOWN:
- case STATE_SPACE_AFTER_ACCEPTED:
- case STATE_PUNCTUATION_AFTER_ACCEPTED:
- case STATE_PUNCTUATION_AFTER_WORD:
- if (!isSpace && !isSeparator) {
- sState = STATE_IN_WORD;
- } else {
- sState = STATE_START;
- }
- break;
- case STATE_UNDO_COMMIT:
- if (isSpace || isSeparator) {
- sState = STATE_ACCEPTED_DEFAULT;
- } else {
- sState = STATE_IN_WORD;
- }
- }
- }
-
- public static void backspace() {
- if (sState == STATE_ACCEPTED_DEFAULT) {
- sState = STATE_UNDO_COMMIT;
- sAutoSuggestUndoneCount++;
- } else if (sState == STATE_UNDO_COMMIT) {
- sState = STATE_IN_WORD;
- }
- sBackspaceCount++;
- }
-
- public static void reset() {
- sState = STATE_START;
- }
-
- public static int getState() {
- return sState;
- }
-
- public static void keyPressedAt(Key key, int x, int y) {
- if (LOGGING && sKeyLocationFile != null && key.codes[0] >= 32) {
- String out =
- "KEY: " + (char) key.codes[0]
- + " X: " + x
- + " Y: " + y
- + " MX: " + (key.x + key.width / 2)
- + " MY: " + (key.y + key.height / 2)
- + "\n";
- try {
- sKeyLocationFile.write(out.getBytes());
- } catch (IOException ioe) {
- // TODO: May run out of space
- }
- }
- }
-}
-
diff --git a/src/com/android/inputmethod/latin/Tutorial.java b/src/com/android/inputmethod/latin/Tutorial.java
deleted file mode 100644
index 03d4858c4..000000000
--- a/src/com/android/inputmethod/latin/Tutorial.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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 android.content.Context;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Message;
-import android.text.Layout;
-import android.text.SpannableStringBuilder;
-import android.text.StaticLayout;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.widget.PopupWindow;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class Tutorial implements OnTouchListener {
-
- private List<Bubble> mBubbles = new ArrayList<Bubble>();
- private long mStartTime;
- private static final long MINIMUM_TIME = 6000;
- private static final long MAXIMUM_TIME = 20000;
- private View mInputView;
- private LatinIME mIme;
- private int[] mLocation = new int[2];
- private int mBubblePointerOffset;
-
- private static final int MSG_SHOW_BUBBLE = 0;
-
- private int mBubbleIndex;
-
- Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SHOW_BUBBLE:
- Bubble bubba = (Bubble) msg.obj;
- bubba.show(mLocation[0], mLocation[1]);
- break;
- }
- }
- };
-
- class Bubble {
- Drawable bubbleBackground;
- int x;
- int y;
- int width;
- int gravity;
- CharSequence text;
- boolean dismissOnTouch;
- boolean dismissOnClose;
- PopupWindow window;
- TextView textView;
- View inputView;
-
- Bubble(Context context, View inputView,
- int backgroundResource, int bx, int by, int textResource1, int textResource2) {
- bubbleBackground = context.getResources().getDrawable(backgroundResource);
- x = bx;
- y = by;
- width = (int) (inputView.getWidth() * 0.9);
- this.gravity = Gravity.TOP | Gravity.LEFT;
- text = new SpannableStringBuilder()
- .append(context.getResources().getText(textResource1))
- .append("\n")
- .append(context.getResources().getText(textResource2));
- this.dismissOnTouch = true;
- this.dismissOnClose = false;
- this.inputView = inputView;
- window = new PopupWindow(context);
- window.setBackgroundDrawable(null);
- LayoutInflater inflate =
- (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- textView = (TextView) inflate.inflate(R.layout.bubble_text, null);
- textView.setBackgroundDrawable(bubbleBackground);
- textView.setText(text);
- //textView.setText(textResource1);
- window.setContentView(textView);
- window.setFocusable(false);
- window.setTouchable(true);
- window.setOutsideTouchable(false);
- }
-
- private int chooseSize(PopupWindow pop, View parentView, CharSequence text, TextView tv) {
- int wid = tv.getPaddingLeft() + tv.getPaddingRight();
- int ht = tv.getPaddingTop() + tv.getPaddingBottom();
-
- /*
- * Figure out how big the text would be if we laid it out to the
- * full width of this view minus the border.
- */
- int cap = width - wid;
-
- Layout l = new StaticLayout(text, tv.getPaint(), cap,
- Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
- float max = 0;
- for (int i = 0; i < l.getLineCount(); i++) {
- max = Math.max(max, l.getLineWidth(i));
- }
-
- /*
- * Now set the popup size to be big enough for the text plus the border.
- */
- pop.setWidth(width);
- pop.setHeight(ht + l.getHeight());
- return l.getHeight();
- }
-
- void show(int offx, int offy) {
- int textHeight = chooseSize(window, inputView, text, textView);
- offy -= textView.getPaddingTop() + textHeight;
- if (inputView.getVisibility() == View.VISIBLE
- && inputView.getWindowVisibility() == View.VISIBLE) {
- try {
- if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) offy -= window.getHeight();
- if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) offx -= window.getWidth();
- textView.setOnTouchListener(new View.OnTouchListener() {
- public boolean onTouch(View view, MotionEvent me) {
- Tutorial.this.next();
- return true;
- }
- });
- window.showAtLocation(inputView, Gravity.NO_GRAVITY, x + offx, y + offy);
- } catch (Exception e) {
- // Input view is not valid
- }
- }
- }
-
- void hide() {
- if (window.isShowing()) {
- textView.setOnTouchListener(null);
- window.dismiss();
- }
- }
-
- boolean isShowing() {
- return window.isShowing();
- }
- }
-
- public Tutorial(LatinIME ime, LatinKeyboardView inputView) {
- Context context = inputView.getContext();
- mIme = ime;
- int inputWidth = inputView.getWidth();
- final int x = inputWidth / 20; // Half of 1/10th
- mBubblePointerOffset = inputView.getContext().getResources()
- .getDimensionPixelOffset(R.dimen.bubble_pointer_offset);
- Bubble bWelcome = new Bubble(context, inputView,
- R.drawable.dialog_bubble_step02, x, 0,
- R.string.tip_to_open_keyboard, R.string.touch_to_continue);
- mBubbles.add(bWelcome);
- Bubble bAccents = new Bubble(context, inputView,
- R.drawable.dialog_bubble_step02, x, 0,
- R.string.tip_to_view_accents, R.string.touch_to_continue);
- mBubbles.add(bAccents);
- Bubble b123 = new Bubble(context, inputView,
- R.drawable.dialog_bubble_step07, x, 0,
- R.string.tip_to_open_symbols, R.string.touch_to_continue);
- mBubbles.add(b123);
- Bubble bABC = new Bubble(context, inputView,
- R.drawable.dialog_bubble_step07, x, 0,
- R.string.tip_to_close_symbols, R.string.touch_to_continue);
- mBubbles.add(bABC);
- Bubble bSettings = new Bubble(context, inputView,
- R.drawable.dialog_bubble_step07, x, 0,
- R.string.tip_to_launch_settings, R.string.touch_to_continue);
- mBubbles.add(bSettings);
- Bubble bDone = new Bubble(context, inputView,
- R.drawable.dialog_bubble_step02, x, 0,
- R.string.tip_to_start_typing, R.string.touch_to_finish);
- mBubbles.add(bDone);
- mInputView = inputView;
- }
-
- void start() {
- mInputView.getLocationInWindow(mLocation);
- mBubbleIndex = -1;
- mInputView.setOnTouchListener(this);
- next();
- }
-
- boolean next() {
- if (mBubbleIndex >= 0) {
- // If the bubble is not yet showing, don't move to the next.
- if (!mBubbles.get(mBubbleIndex).isShowing()) {
- return true;
- }
- // Hide all previous bubbles as well, as they may have had a delayed show
- for (int i = 0; i <= mBubbleIndex; i++) {
- mBubbles.get(i).hide();
- }
- }
- mBubbleIndex++;
- if (mBubbleIndex >= mBubbles.size()) {
- mInputView.setOnTouchListener(null);
- mIme.sendDownUpKeyEvents(-1); // Inform the setupwizard that tutorial is in last bubble
- mIme.tutorialDone();
- return false;
- }
- if (mBubbleIndex == 3 || mBubbleIndex == 4) {
- mIme.mKeyboardSwitcher.toggleSymbols();
- }
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(mBubbleIndex)), 500);
- return true;
- }
-
- void hide() {
- for (int i = 0; i < mBubbles.size(); i++) {
- mBubbles.get(i).hide();
- }
- mInputView.setOnTouchListener(null);
- }
-
- boolean close() {
- mHandler.removeMessages(MSG_SHOW_BUBBLE);
- hide();
- return true;
- }
-
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- next();
- }
- return true;
- }
-}
diff --git a/src/com/android/inputmethod/latin/UserDictionary.java b/src/com/android/inputmethod/latin/UserDictionary.java
deleted file mode 100644
index 4b98eacce..000000000
--- a/src/com/android/inputmethod/latin/UserDictionary.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.UserDictionary.Words;
-
-public class UserDictionary extends ExpandableDictionary {
-
- private static final String[] PROJECTION = {
- Words._ID,
- Words.WORD,
- Words.FREQUENCY
- };
-
- private static final int INDEX_WORD = 1;
- private static final int INDEX_FREQUENCY = 2;
-
- private ContentObserver mObserver;
-
- private boolean mRequiresReload;
- private String mLocale;
-
- public UserDictionary(Context context, String locale) {
- super(context);
- mLocale = locale;
- // Perform a managed query. The Activity will handle closing and requerying the cursor
- // when needed.
- ContentResolver cres = context.getContentResolver();
-
- cres.registerContentObserver(Words.CONTENT_URI, true, mObserver = new ContentObserver(null) {
- @Override
- public void onChange(boolean self) {
- mRequiresReload = true;
- }
- });
-
- loadDictionary();
- }
-
- public synchronized void close() {
- if (mObserver != null) {
- getContext().getContentResolver().unregisterContentObserver(mObserver);
- mObserver = null;
- }
- }
-
- private synchronized void loadDictionary() {
- Cursor cursor = getContext().getContentResolver()
- .query(Words.CONTENT_URI, PROJECTION, "(locale IS NULL) or (locale=?)",
- new String[] { mLocale }, null);
- addWords(cursor);
- mRequiresReload = false;
- }
-
- /**
- * Adds a word to the dictionary and makes it persistent.
- * @param word the word to add. If the word is capitalized, then the dictionary will
- * recognize it as a capitalized word when searched.
- * @param frequency the frequency of occurrence of the word. A frequency of 255 is considered
- * the highest.
- * @TODO use a higher or float range for frequency
- */
- @Override
- public synchronized void addWord(String word, int frequency) {
- if (mRequiresReload) loadDictionary();
- // Safeguard against adding long words. Can cause stack overflow.
- if (word.length() >= getMaxWordLength()) return;
-
- super.addWord(word, frequency);
-
- // Update the user dictionary provider
- ContentValues values = new ContentValues(5);
- values.put(Words.WORD, word);
- values.put(Words.FREQUENCY, frequency);
- values.put(Words.LOCALE, mLocale);
- values.put(Words.APP_ID, 0);
-
- getContext().getContentResolver().insert(Words.CONTENT_URI, values);
- // In case the above does a synchronous callback of the change observer
- mRequiresReload = false;
- }
-
- @Override
- public synchronized void getWords(final WordComposer codes, final WordCallback callback,
- int[] nextLettersFrequencies) {
- if (mRequiresReload) loadDictionary();
- super.getWords(codes, callback, nextLettersFrequencies);
- }
-
- @Override
- public synchronized boolean isValidWord(CharSequence word) {
- if (mRequiresReload) loadDictionary();
- return super.isValidWord(word);
- }
-
- private void addWords(Cursor cursor) {
- clearDictionary();
-
- final int maxWordLength = getMaxWordLength();
- if (cursor.moveToFirst()) {
- while (!cursor.isAfterLast()) {
- String word = cursor.getString(INDEX_WORD);
- int frequency = cursor.getInt(INDEX_FREQUENCY);
- // Safeguard against adding really long words. Stack may overflow due
- // to recursion
- if (word.length() < maxWordLength) {
- super.addWord(word, frequency);
- }
- cursor.moveToNext();
- }
- }
- cursor.close();
- }
-}
diff --git a/src/com/android/inputmethod/latin/WordComposer.java b/src/com/android/inputmethod/latin/WordComposer.java
deleted file mode 100644
index e97cb24ba..000000000
--- a/src/com/android/inputmethod/latin/WordComposer.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.ArrayList;
-import java.util.List;
-
-/**
- * A place to store the currently composing word with information such as adjacent key codes as well
- */
-public class WordComposer {
- /**
- * The list of unicode values for each keystroke (including surrounding keys)
- */
- private ArrayList<int[]> mCodes;
-
- /**
- * The word chosen from the candidate list, until it is committed.
- */
- private String mPreferredWord;
-
- private StringBuilder mTypedWord;
-
- private int mCapsCount;
-
- private boolean mAutoCapitalized;
-
- /**
- * Whether the user chose to capitalize the word.
- */
- private boolean mIsCapitalized;
-
- WordComposer() {
- mCodes = new ArrayList<int[]>(12);
- mTypedWord = new StringBuilder(20);
- }
-
- /**
- * Clear out the keys registered so far.
- */
- public void reset() {
- mCodes.clear();
- mIsCapitalized = false;
- mPreferredWord = null;
- mTypedWord.setLength(0);
- mCapsCount = 0;
- }
-
- /**
- * Number of keystrokes in the composing word.
- * @return the number of keystrokes
- */
- public int size() {
- return mCodes.size();
- }
-
- /**
- * Returns the codes at a particular position in the word.
- * @param index the position in the word
- * @return the unicode for the pressed and surrounding keys
- */
- public int[] getCodesAt(int index) {
- return mCodes.get(index);
- }
-
- /**
- * Add a new keystroke, with codes[0] containing the pressed key's unicode and the rest of
- * the array containing unicode for adjacent keys, sorted by reducing probability/proximity.
- * @param codes the array of unicode values
- */
- public void add(int primaryCode, int[] codes) {
- mTypedWord.append((char) primaryCode);
- mCodes.add(codes);
- if (Character.isUpperCase((char) primaryCode)) mCapsCount++;
- }
-
- /**
- * Delete the last keystroke as a result of hitting backspace.
- */
- public void deleteLast() {
- mCodes.remove(mCodes.size() - 1);
- final int lastPos = mTypedWord.length() - 1;
- char last = mTypedWord.charAt(lastPos);
- mTypedWord.deleteCharAt(lastPos);
- if (Character.isUpperCase(last)) mCapsCount--;
- }
-
- /**
- * Returns the word as it was typed, without any correction applied.
- * @return the word that was typed so far
- */
- public CharSequence getTypedWord() {
- int wordSize = mCodes.size();
- if (wordSize == 0) {
- return null;
- }
-// StringBuffer sb = new StringBuffer(wordSize);
-// for (int i = 0; i < wordSize; i++) {
-// char c = (char) mCodes.get(i)[0];
-// if (i == 0 && mIsCapitalized) {
-// c = Character.toUpperCase(c);
-// }
-// sb.append(c);
-// }
-// return sb;
- return mTypedWord;
- }
-
- public void setCapitalized(boolean capitalized) {
- mIsCapitalized = capitalized;
- }
-
- /**
- * Whether or not the user typed a capital letter as the first letter in the word
- * @return capitalization preference
- */
- public boolean isCapitalized() {
- return mIsCapitalized;
- }
-
- /**
- * Stores the user's selected word, before it is actually committed to the text field.
- * @param preferred
- */
- public void setPreferredWord(String preferred) {
- mPreferredWord = preferred;
- }
-
- /**
- * Return the word chosen by the user, or the typed word if no other word was chosen.
- * @return the preferred word
- */
- public CharSequence getPreferredWord() {
- return mPreferredWord != null ? mPreferredWord : getTypedWord();
- }
-
- /**
- * Returns true if more than one character is upper case, otherwise returns false.
- */
- public boolean isMostlyCaps() {
- return mCapsCount > 1;
- }
-
- /**
- * Saves the reason why the word is capitalized - whether it was automatic or
- * due to the user hitting shift in the middle of a sentence.
- * @param auto whether it was an automatic capitalization due to start of sentence
- */
- public void setAutoCapitalized(boolean auto) {
- mAutoCapitalized = auto;
- }
-
- /**
- * Returns whether the word was automatically capitalized.
- * @return whether the word was automatically capitalized
- */
- public boolean isAutoCapitalized() {
- return mAutoCapitalized;
- }
-}
diff --git a/src/com/android/inputmethod/voice/EditingUtil.java b/src/com/android/inputmethod/voice/EditingUtil.java
deleted file mode 100644
index 6316d8ccf..000000000
--- a/src/com/android/inputmethod/voice/EditingUtil.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2009 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.voice;
-
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-
-/**
- * Utility methods to deal with editing text through an InputConnection.
- */
-public class EditingUtil {
- private EditingUtil() {};
-
- /**
- * Append newText to the text field represented by connection.
- * The new text becomes selected.
- */
- public static void appendText(InputConnection connection, String newText) {
- if (connection == null) {
- return;
- }
-
- // Commit the composing text
- connection.finishComposingText();
-
- // Add a space if the field already has text.
- CharSequence charBeforeCursor = connection.getTextBeforeCursor(1, 0);
- if (charBeforeCursor != null
- && !charBeforeCursor.equals(" ")
- && (charBeforeCursor.length() > 0)) {
- newText = " " + newText;
- }
-
- connection.setComposingText(newText, 1);
- }
-
- private static int getCursorPosition(InputConnection connection) {
- ExtractedText extracted = connection.getExtractedText(
- new ExtractedTextRequest(), 0);
- if (extracted == null) {
- return -1;
- }
- return extracted.startOffset + extracted.selectionStart;
- }
-
- private static int getSelectionEnd(InputConnection connection) {
- ExtractedText extracted = connection.getExtractedText(
- new ExtractedTextRequest(), 0);
- if (extracted == null) {
- return -1;
- }
- return extracted.startOffset + extracted.selectionEnd;
- }
-
- /**
- * @param connection connection to the current text field.
- * @param sep characters which may separate words
- * @return the word that surrounds the cursor, including up to one trailing
- * separator. For example, if the field contains "he|llo world", where |
- * represents the cursor, then "hello " will be returned.
- */
- public static String getWordAtCursor(
- InputConnection connection, String separators) {
- Range range = getWordRangeAtCursor(connection, separators);
- return (range == null) ? null : range.word;
- }
-
- /**
- * Removes the word surrounding the cursor. Parameters are identical to
- * getWordAtCursor.
- */
- public static void deleteWordAtCursor(
- InputConnection connection, String separators) {
-
- Range range = getWordRangeAtCursor(connection, separators);
- if (range == null) return;
-
- connection.finishComposingText();
- // Move cursor to beginning of word, to avoid crash when cursor is outside
- // of valid range after deleting text.
- int newCursor = getCursorPosition(connection) - range.charsBefore;
- connection.setSelection(newCursor, newCursor);
- connection.deleteSurroundingText(0, range.charsBefore + range.charsAfter);
- }
-
- /**
- * Represents a range of text, relative to the current cursor position.
- */
- private static class Range {
- /** Characters before selection start */
- int charsBefore;
-
- /**
- * Characters after selection start, including one trailing word
- * separator.
- */
- int charsAfter;
-
- /** The actual characters that make up a word */
- String word;
-
- public Range(int charsBefore, int charsAfter, String word) {
- if (charsBefore < 0 || charsAfter < 0) {
- throw new IndexOutOfBoundsException();
- }
- this.charsBefore = charsBefore;
- this.charsAfter = charsAfter;
- this.word = word;
- }
- }
-
- private static Range getWordRangeAtCursor(
- InputConnection connection, String sep) {
- if (connection == null || sep == null) {
- return null;
- }
- CharSequence before = connection.getTextBeforeCursor(1000, 0);
- CharSequence after = connection.getTextAfterCursor(1000, 0);
- if (before == null || after == null) {
- return null;
- }
-
- // Find first word separator before the cursor
- int start = before.length();
- while (--start > 0 && !isWhitespace(before.charAt(start - 1), sep));
-
- // Find last word separator after the cursor
- int end = -1;
- while (++end < after.length() && !isWhitespace(after.charAt(end), sep));
- if (end < after.length() - 1) {
- end++; // Include trailing space, if it exists, in word
- }
-
- int cursor = getCursorPosition(connection);
- if (start >= 0 && cursor + end <= after.length() + before.length()) {
- String word = before.toString().substring(start, before.length())
- + after.toString().substring(0, end);
- return new Range(before.length() - start, end, word);
- }
-
- return null;
- }
-
- private static boolean isWhitespace(int code, String whitespace) {
- return whitespace.contains(String.valueOf((char) code));
- }
-}
diff --git a/src/com/android/inputmethod/voice/FieldContext.java b/src/com/android/inputmethod/voice/FieldContext.java
deleted file mode 100644
index 5fbacfb6c..000000000
--- a/src/com/android/inputmethod/voice/FieldContext.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2009 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.voice;
-
-import android.os.Bundle;
-import android.util.Log;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-
-/**
- * Represents information about a given text field, which can be passed
- * to the speech recognizer as context information.
- */
-public class FieldContext {
- private static final boolean DBG = false;
-
- static final String LABEL = "label";
- static final String HINT = "hint";
- static final String PACKAGE_NAME = "packageName";
- static final String FIELD_ID = "fieldId";
- static final String FIELD_NAME = "fieldName";
- static final String SINGLE_LINE = "singleLine";
- static final String INPUT_TYPE = "inputType";
- static final String IME_OPTIONS = "imeOptions";
- static final String SELECTED_LANGUAGE = "selectedLanguage";
- static final String ENABLED_LANGUAGES = "enabledLanguages";
-
- Bundle mFieldInfo;
-
- public FieldContext(InputConnection conn, EditorInfo info,
- String selectedLanguage, String[] enabledLanguages) {
- mFieldInfo = new Bundle();
- addEditorInfoToBundle(info, mFieldInfo);
- addInputConnectionToBundle(conn, mFieldInfo);
- addLanguageInfoToBundle(selectedLanguage, enabledLanguages, mFieldInfo);
- if (DBG) Log.i("FieldContext", "Bundle = " + mFieldInfo.toString());
- }
-
- private static String safeToString(Object o) {
- if (o == null) {
- return "";
- }
- return o.toString();
- }
-
- private static void addEditorInfoToBundle(EditorInfo info, Bundle bundle) {
- if (info == null) {
- return;
- }
-
- bundle.putString(LABEL, safeToString(info.label));
- bundle.putString(HINT, safeToString(info.hintText));
- bundle.putString(PACKAGE_NAME, safeToString(info.packageName));
- bundle.putInt(FIELD_ID, info.fieldId);
- bundle.putString(FIELD_NAME, safeToString(info.fieldName));
- bundle.putInt(INPUT_TYPE, info.inputType);
- bundle.putInt(IME_OPTIONS, info.imeOptions);
- }
-
- private static void addInputConnectionToBundle(
- InputConnection conn, Bundle bundle) {
- if (conn == null) {
- return;
- }
-
- ExtractedText et = conn.getExtractedText(new ExtractedTextRequest(), 0);
- if (et == null) {
- return;
- }
- bundle.putBoolean(SINGLE_LINE, (et.flags & et.FLAG_SINGLE_LINE) > 0);
- }
-
- private static void addLanguageInfoToBundle(
- String selectedLanguage, String[] enabledLanguages, Bundle bundle) {
- bundle.putString(SELECTED_LANGUAGE, selectedLanguage);
- bundle.putStringArray(ENABLED_LANGUAGES, enabledLanguages);
- }
-
- public Bundle getBundle() {
- return mFieldInfo;
- }
-
- public String toString() {
- return mFieldInfo.toString();
- }
-}
diff --git a/src/com/android/inputmethod/voice/LatinIMEWithVoice.java b/src/com/android/inputmethod/voice/LatinIMEWithVoice.java
deleted file mode 100644
index ccbf5b6bc..000000000
--- a/src/com/android/inputmethod/voice/LatinIMEWithVoice.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2009 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.voice;
-
-import android.content.Intent;
-
-import com.android.inputmethod.latin.LatinIME;
-
-public class LatinIMEWithVoice extends LatinIME {
- @Override
- protected void launchSettings() {
- launchSettings(LatinIMEWithVoiceSettings.class);
- }
-}
diff --git a/src/com/android/inputmethod/voice/LatinIMEWithVoiceSettings.java b/src/com/android/inputmethod/voice/LatinIMEWithVoiceSettings.java
deleted file mode 100644
index 13a58e14d..000000000
--- a/src/com/android/inputmethod/voice/LatinIMEWithVoiceSettings.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2009 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.voice;
-
-import com.android.inputmethod.latin.LatinIMESettings;
-
-public class LatinIMEWithVoiceSettings extends LatinIMESettings {}
diff --git a/src/com/android/inputmethod/voice/RecognitionView.java b/src/com/android/inputmethod/voice/RecognitionView.java
deleted file mode 100644
index 1e99c3cf7..000000000
--- a/src/com/android/inputmethod/voice/RecognitionView.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (C) 2009 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.voice;
-
-import java.io.ByteArrayOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.ShortBuffer;
-import java.util.ArrayList;
-import java.util.List;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.CornerPathEffect;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PathEffect;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.util.TypedValue;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup.MarginLayoutParams;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.android.inputmethod.latin.R;
-
-/**
- * The user interface for the "Speak now" and "working" states.
- * Displays a recognition dialog (with waveform, voice meter, etc.),
- * plays beeps, shows errors, etc.
- */
-public class RecognitionView {
- private static final String TAG = "RecognitionView";
-
- private Handler mUiHandler; // Reference to UI thread
- private View mView;
- private Context mContext;
-
- private ImageView mImage;
- private TextView mText;
- private View mButton;
- private TextView mButtonText;
- private View mProgress;
-
- private Drawable mInitializing;
- private Drawable mError;
- private List<Drawable> mSpeakNow;
-
- private float mVolume = 0.0f;
- private int mLevel = 0;
-
- private enum State {LISTENING, WORKING, READY}
- private State mState = State.READY;
-
- private float mMinMicrophoneLevel;
- private float mMaxMicrophoneLevel;
-
- /** Updates the microphone icon to show user their volume.*/
- private Runnable mUpdateVolumeRunnable = new Runnable() {
- public void run() {
- if (mState != State.LISTENING) {
- return;
- }
-
- final float min = mMinMicrophoneLevel;
- final float max = mMaxMicrophoneLevel;
- final int maxLevel = mSpeakNow.size() - 1;
-
- int index = (int) ((mVolume - min) / (max - min) * maxLevel);
- final int level = Math.min(Math.max(0, index), maxLevel);
-
- if (level != mLevel) {
- mImage.setImageDrawable(mSpeakNow.get(level));
- mLevel = level;
- }
- mUiHandler.postDelayed(mUpdateVolumeRunnable, 50);
- }
- };
-
- public RecognitionView(Context context, OnClickListener clickListener) {
- mUiHandler = new Handler();
-
- LayoutInflater inflater = (LayoutInflater) context.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- mView = inflater.inflate(R.layout.recognition_status, null);
- ContentResolver cr = context.getContentResolver();
- mMinMicrophoneLevel = SettingsUtil.getSettingsFloat(
- cr, SettingsUtil.LATIN_IME_MIN_MICROPHONE_LEVEL, 15.f);
- mMaxMicrophoneLevel = SettingsUtil.getSettingsFloat(
- cr, SettingsUtil.LATIN_IME_MAX_MICROPHONE_LEVEL, 30.f);
-
- // Pre-load volume level images
- Resources r = context.getResources();
-
- mSpeakNow = new ArrayList<Drawable>();
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level0));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level1));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level2));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level3));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level4));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level5));
- mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level6));
-
- mInitializing = r.getDrawable(R.drawable.mic_slash);
- mError = r.getDrawable(R.drawable.caution);
-
- mImage = (ImageView) mView.findViewById(R.id.image);
- mButton = mView.findViewById(R.id.button);
- mButton.setOnClickListener(clickListener);
- mText = (TextView) mView.findViewById(R.id.text);
- mButtonText = (TextView) mView.findViewById(R.id.button_text);
- mProgress = mView.findViewById(R.id.progress);
-
- mContext = context;
- }
-
- public View getView() {
- return mView;
- }
-
- public void restoreState() {
- mUiHandler.post(new Runnable() {
- public void run() {
- // Restart the spinner
- if (mState == State.WORKING) {
- ((ProgressBar)mProgress).setIndeterminate(false);
- ((ProgressBar)mProgress).setIndeterminate(true);
- }
- }
- });
- }
-
- public void showInitializing() {
- mUiHandler.post(new Runnable() {
- public void run() {
- prepareDialog(false, mContext.getText(R.string.voice_initializing), mInitializing,
- mContext.getText(R.string.cancel));
- }
- });
- }
-
- public void showListening() {
- mUiHandler.post(new Runnable() {
- public void run() {
- mState = State.LISTENING;
- prepareDialog(false, mContext.getText(R.string.voice_listening), mSpeakNow.get(0),
- mContext.getText(R.string.cancel));
- }
- });
- mUiHandler.postDelayed(mUpdateVolumeRunnable, 50);
- }
-
- public void updateVoiceMeter(final float rmsdB) {
- mVolume = rmsdB;
- }
-
- public void showError(final String message) {
- mUiHandler.post(new Runnable() {
- public void run() {
- mState = State.READY;
- prepareDialog(false, message, mError, mContext.getText(R.string.ok));
- }
- });
- }
-
- public void showWorking(
- final ByteArrayOutputStream waveBuffer,
- final int speechStartPosition,
- final int speechEndPosition) {
-
- mUiHandler.post(new Runnable() {
- public void run() {
- mState = State.WORKING;
- prepareDialog(true, mContext.getText(R.string.voice_working), null, mContext
- .getText(R.string.cancel));
- final ShortBuffer buf = ByteBuffer.wrap(waveBuffer.toByteArray()).order(
- ByteOrder.nativeOrder()).asShortBuffer();
- buf.position(0);
- waveBuffer.reset();
- showWave(buf, speechStartPosition / 2, speechEndPosition / 2);
- }
- });
- }
-
- private void prepareDialog(boolean spinVisible, CharSequence text, Drawable image,
- CharSequence btnTxt) {
- if (spinVisible) {
- mProgress.setVisibility(View.VISIBLE);
- mImage.setVisibility(View.GONE);
- } else {
- mProgress.setVisibility(View.GONE);
- mImage.setImageDrawable(image);
- mImage.setVisibility(View.VISIBLE);
- }
- mText.setText(text);
- mButtonText.setText(btnTxt);
- }
-
- /**
- * @return an average abs of the specified buffer.
- */
- private static int getAverageAbs(ShortBuffer buffer, int start, int i, int npw) {
- int from = start + i * npw;
- int end = from + npw;
- int total = 0;
- for (int x = from; x < end; x++) {
- total += Math.abs(buffer.get(x));
- }
- return total / npw;
- }
-
-
- /**
- * Shows waveform of input audio.
- *
- * Copied from version in VoiceSearch's RecognitionActivity.
- *
- * TODO: adjust stroke width based on the size of data.
- * TODO: use dip rather than pixels.
- */
- private void showWave(ShortBuffer waveBuffer, int startPosition, int endPosition) {
- final int w = ((View) mImage.getParent()).getWidth();
- final int h = mImage.getHeight();
- if (w <= 0 || h <= 0) {
- // view is not visible this time. Skip drawing.
- return;
- }
- final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- final Canvas c = new Canvas(b);
- final Paint paint = new Paint();
- paint.setColor(0xFFFFFFFF); // 0xAARRGGBB
- paint.setAntiAlias(true);
- paint.setStyle(Paint.Style.STROKE);
- paint.setAlpha(0x90);
-
- final PathEffect effect = new CornerPathEffect(3);
- paint.setPathEffect(effect);
-
- final int numSamples = waveBuffer.remaining();
- int endIndex;
- if (endPosition == 0) {
- endIndex = numSamples;
- } else {
- endIndex = Math.min(endPosition, numSamples);
- }
-
- int startIndex = startPosition - 2000; // include 250ms before speech
- if (startIndex < 0) {
- startIndex = 0;
- }
- final int numSamplePerWave = 200; // 8KHz 25ms = 200 samples
- final float scale = 10.0f / 65536.0f;
-
- final int count = (endIndex - startIndex) / numSamplePerWave;
- final float deltaX = 1.0f * w / count;
- int yMax = h / 2 - 10;
- Path path = new Path();
- c.translate(0, yMax);
- float x = 0;
- path.moveTo(x, 0);
- yMax -= 10;
- for (int i = 0; i < count; i++) {
- final int avabs = getAverageAbs(waveBuffer, startIndex, i , numSamplePerWave);
- int sign = ( (i & 01) == 0) ? -1 : 1;
- final float y = Math.min(yMax, avabs * h * scale) * sign;
- path.lineTo(x, y);
- x += deltaX;
- path.lineTo(x, y);
- }
- if (deltaX > 4) {
- paint.setStrokeWidth(3);
- } else {
- paint.setStrokeWidth(Math.max(1, (int) (deltaX -.05)));
- }
- c.drawPath(path, paint);
- mImage.setImageBitmap(b);
- mImage.setVisibility(View.VISIBLE);
- MarginLayoutParams mProgressParams = (MarginLayoutParams)mProgress.getLayoutParams();
- mProgressParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- -h / 2 - 18, mContext.getResources().getDisplayMetrics());
-
- // Tweak the padding manually to fill out the whole view horizontally.
- // TODO: Do this in the xml layout instead.
- ((View) mImage.getParent()).setPadding(4, ((View) mImage.getParent()).getPaddingTop(), 3,
- ((View) mImage.getParent()).getPaddingBottom());
- mProgress.setLayoutParams(mProgressParams);
- }
-
-
- public void finish() {
- mUiHandler.post(new Runnable() {
- public void run() {
- mState = State.READY;
- exitWorking();
- }
- });
- }
-
- private void exitWorking() {
- mProgress.setVisibility(View.GONE);
- mImage.setVisibility(View.VISIBLE);
- }
-}
diff --git a/src/com/android/inputmethod/voice/SettingsUtil.java b/src/com/android/inputmethod/voice/SettingsUtil.java
deleted file mode 100644
index abf52047f..000000000
--- a/src/com/android/inputmethod/voice/SettingsUtil.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2009 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.voice;
-
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.Settings;
-import android.util.Log;
-
-/**
- * Utility for retrieving settings from Settings.Secure.
- */
-public class SettingsUtil {
- /**
- * A whitespace-separated list of supported locales for voice input from the keyboard.
- */
- public static final String LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES =
- "latin_ime_voice_input_supported_locales";
-
- /**
- * A whitespace-separated list of recommended app packages for voice input from the
- * keyboard.
- */
- public static final String LATIN_IME_VOICE_INPUT_RECOMMENDED_PACKAGES =
- "latin_ime_voice_input_recommended_packages";
-
- /**
- * The maximum number of unique days to show the swipe hint for voice input.
- */
- public static final String LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS =
- "latin_ime_voice_input_swipe_hint_max_days";
-
- /**
- * The maximum number of times to show the punctuation hint for voice input.
- */
- public static final String LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS =
- "latin_ime_voice_input_punctuation_hint_max_displays";
-
- /**
- * Endpointer parameters for voice input from the keyboard.
- */
- public static final String LATIN_IME_SPEECH_MINIMUM_LENGTH_MILLIS =
- "latin_ime_speech_minimum_length_millis";
- public static final String LATIN_IME_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS =
- "latin_ime_speech_input_complete_silence_length_millis";
- public static final String LATIN_IME_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS =
- "latin_ime_speech_input_possibly_complete_silence_length_millis";
-
- /**
- * Min and max volume levels that can be displayed on the "speak now" screen.
- */
- public static final String LATIN_IME_MIN_MICROPHONE_LEVEL =
- "latin_ime_min_microphone_level";
- public static final String LATIN_IME_MAX_MICROPHONE_LEVEL =
- "latin_ime_max_microphone_level";
-
- /**
- * The number of sentence-level alternates to request of the server.
- */
- public static final String LATIN_IME_MAX_VOICE_RESULTS = "latin_ime_max_voice_results";
-
- /**
- * Get a string-valued setting.
- *
- * @param cr The content resolver to use
- * @param key The setting to look up
- * @param defaultValue The default value to use if none can be found
- * @return The value of the setting, or defaultValue if it couldn't be found
- */
- public static String getSettingsString(ContentResolver cr, String key, String defaultValue) {
- String result = Settings.Secure.getString(cr, key);
- return (result == null) ? defaultValue : result;
- }
-
- /**
- * Get an int-valued setting.
- *
- * @param cr The content resolver to use
- * @param key The setting to look up
- * @param defaultValue The default value to use if the setting couldn't be found or parsed
- * @return The value of the setting, or defaultValue if it couldn't be found or parsed
- */
- public static int getSettingsInt(ContentResolver cr, String key, int defaultValue) {
- return Settings.Secure.getInt(cr, key, defaultValue);
- }
-
- /**
- * Get a float-valued setting.
- *
- * @param cr The content resolver to use
- * @param key The setting to look up
- * @param defaultValue The default value to use if the setting couldn't be found or parsed
- * @return The value of the setting, or defaultValue if it couldn't be found or parsed
- */
- public static float getSettingsFloat(ContentResolver cr, String key, float defaultValue) {
- return Settings.Secure.getFloat(cr, key, defaultValue);
- }
-}
diff --git a/src/com/android/inputmethod/voice/VoiceInput.java b/src/com/android/inputmethod/voice/VoiceInput.java
deleted file mode 100644
index e881856dd..000000000
--- a/src/com/android/inputmethod/voice/VoiceInput.java
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Copyright (C) 2009 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.voice;
-
-import com.android.inputmethod.latin.R;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.speech.RecognitionListener;
-import android.speech.RecognitionManager;
-import android.speech.RecognizerIntent;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Speech recognition input, including both user interface and a background
- * process to stream audio to the network recognizer. This class supplies a
- * View (getView()), which it updates as recognition occurs. The user of this
- * class is responsible for making the view visible to the user, as well as
- * handling various events returned through UiListener.
- */
-public class VoiceInput implements OnClickListener {
- private static final String TAG = "VoiceInput";
- private static final String EXTRA_RECOGNITION_CONTEXT =
- "android.speech.extras.RECOGNITION_CONTEXT";
- private static final String EXTRA_CALLING_PACKAGE = "calling_package";
-
- private static final String DEFAULT_RECOMMENDED_PACKAGES =
- "com.android.mms " +
- "com.google.android.gm " +
- "com.google.android.talk " +
- "com.google.android.apps.googlevoice " +
- "com.android.email " +
- "com.android.browser ";
-
- // WARNING! Before enabling this, fix the problem with calling getExtractedText() in
- // landscape view. It causes Extracted text updates to be rejected due to a token mismatch
- public static boolean ENABLE_WORD_CORRECTIONS = false;
-
- // Dummy word suggestion which means "delete current word"
- public static final String DELETE_SYMBOL = " \u00D7 "; // times symbol
-
- private Whitelist mRecommendedList;
- private Whitelist mBlacklist;
-
- private VoiceInputLogger mLogger;
-
- // Names of a few intent extras defined in VoiceSearch's RecognitionService.
- // These let us tweak the endpointer parameters.
- private static final String EXTRA_SPEECH_MINIMUM_LENGTH_MILLIS =
- "android.speech.extras.SPEECH_INPUT_MINIMUM_LENGTH_MILLIS";
- private static final String EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS =
- "android.speech.extras.SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS";
- private static final String EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS =
- "android.speech.extras.SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS";
-
- // The usual endpointer default value for input complete silence length is 0.5 seconds,
- // but that's used for things like voice search. For dictation-like voice input like this,
- // we go with a more liberal value of 1 second. This value will only be used if a value
- // is not provided from Gservices.
- private static final String INPUT_COMPLETE_SILENCE_LENGTH_DEFAULT_VALUE_MILLIS = "1000";
-
- // Used to record part of that state for logging purposes.
- public static final int DEFAULT = 0;
- public static final int LISTENING = 1;
- public static final int WORKING = 2;
- public static final int ERROR = 3;
-
- private int mState = DEFAULT;
-
- private final static int MSG_CLOSE_ERROR_DIALOG = 1;
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_CLOSE_ERROR_DIALOG) {
- mState = DEFAULT;
- mRecognitionView.finish();
- mUiListener.onCancelVoice();
- }
- }
- };
-
- /**
- * Events relating to the recognition UI. You must implement these.
- */
- public interface UiListener {
-
- /**
- * @param recognitionResults a set of transcripts for what the user
- * spoke, sorted by likelihood.
- */
- public void onVoiceResults(
- List<String> recognitionResults,
- Map<String, List<CharSequence>> alternatives);
-
- /**
- * Called when the user cancels speech recognition.
- */
- public void onCancelVoice();
- }
-
- private RecognitionManager mRecognitionManager;
- private RecognitionListener mRecognitionListener;
- private RecognitionView mRecognitionView;
- private UiListener mUiListener;
- private Context mContext;
-
- /**
- * @param context the service or activity in which we're running.
- * @param uiHandler object to receive events from VoiceInput.
- */
- public VoiceInput(Context context, UiListener uiHandler) {
- mLogger = VoiceInputLogger.getLogger(context);
- mRecognitionListener = new ImeRecognitionListener();
- mRecognitionManager = RecognitionManager.createRecognitionManager(context);
- mRecognitionManager.setRecognitionListener(mRecognitionListener);
- mUiListener = uiHandler;
- mContext = context;
- newView();
-
- String recommendedPackages = SettingsUtil.getSettingsString(
- context.getContentResolver(),
- SettingsUtil.LATIN_IME_VOICE_INPUT_RECOMMENDED_PACKAGES,
- DEFAULT_RECOMMENDED_PACKAGES);
-
- mRecommendedList = new Whitelist();
- for (String recommendedPackage : recommendedPackages.split("\\s+")) {
- mRecommendedList.addApp(recommendedPackage);
- }
-
- mBlacklist = new Whitelist();
- mBlacklist.addApp("com.android.setupwizard");
- }
-
- /**
- * The configuration of the IME changed and may have caused the views to be layed out
- * again. Restore the state of the recognition view.
- */
- public void onConfigurationChanged() {
- mRecognitionView.restoreState();
- }
-
- /**
- * @return true if field is blacklisted for voice
- */
- public boolean isBlacklistedField(FieldContext context) {
- return mBlacklist.matches(context);
- }
-
- /**
- * Used to decide whether to show voice input hints for this field, etc.
- *
- * @return true if field is recommended for voice
- */
- public boolean isRecommendedField(FieldContext context) {
- return mRecommendedList.matches(context);
- }
-
- /**
- * Start listening for speech from the user. This will grab the microphone
- * and start updating the view provided by getView(). It is the caller's
- * responsibility to ensure that the view is visible to the user at this stage.
- *
- * @param context the same FieldContext supplied to voiceIsEnabled()
- * @param swipe whether this voice input was started by swipe, for logging purposes
- */
- public void startListening(FieldContext context, boolean swipe) {
- mState = DEFAULT;
-
- Locale locale = Locale.getDefault();
- String localeString = locale.getLanguage() + "-" + locale.getCountry();
-
- mLogger.start(localeString, swipe);
-
- mState = LISTENING;
-
- mRecognitionView.showInitializing();
- startListeningAfterInitialization(context);
- }
-
- /**
- * Called only when the recognition manager's initialization completed
- *
- * @param context context with which {@link #startListening(FieldContext, boolean)} was executed
- */
- private void startListeningAfterInitialization(FieldContext context) {
- Intent intent = makeIntent();
- intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "");
- intent.putExtra(EXTRA_RECOGNITION_CONTEXT, context.getBundle());
- intent.putExtra(EXTRA_CALLING_PACKAGE, "VoiceIME");
- intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS,
- SettingsUtil.getSettingsInt(
- mContext.getContentResolver(),
- SettingsUtil.LATIN_IME_MAX_VOICE_RESULTS,
- 1));
-
- // Get endpointer params from Gservices.
- // TODO: Consider caching these values for improved performance on slower devices.
- final ContentResolver cr = mContext.getContentResolver();
- putEndpointerExtra(
- cr,
- intent,
- SettingsUtil.LATIN_IME_SPEECH_MINIMUM_LENGTH_MILLIS,
- EXTRA_SPEECH_MINIMUM_LENGTH_MILLIS,
- null /* rely on endpointer default */);
- putEndpointerExtra(
- cr,
- intent,
- SettingsUtil.LATIN_IME_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,
- EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,
- INPUT_COMPLETE_SILENCE_LENGTH_DEFAULT_VALUE_MILLIS
- /* our default value is different from the endpointer's */);
- putEndpointerExtra(
- cr,
- intent,
- SettingsUtil.
- LATIN_IME_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS,
- EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS,
- null /* rely on endpointer default */);
-
- mRecognitionManager.startListening(intent);
- }
-
- /**
- * Gets the value of the provided Gservices key, attempts to parse it into a long,
- * and if successful, puts the long value as an extra in the provided intent.
- */
- private void putEndpointerExtra(ContentResolver cr, Intent i,
- String gservicesKey, String intentExtraKey, String defaultValue) {
- long l = -1;
- String s = SettingsUtil.getSettingsString(cr, gservicesKey, defaultValue);
- if (s != null) {
- try {
- l = Long.valueOf(s);
- } catch (NumberFormatException e) {
- Log.e(TAG, "could not parse value for " + gservicesKey + ": " + s);
- }
- }
-
- if (l != -1) i.putExtra(intentExtraKey, l);
- }
-
- public void destroy() {
- mRecognitionManager.destroy();
- }
-
- /**
- * Creates a new instance of the view that is returned by {@link #getView()}
- * Clients should use this when a previously returned view is stuck in a
- * layout that is being thrown away and a new one is need to show to the
- * user.
- */
- public void newView() {
- mRecognitionView = new RecognitionView(mContext, this);
- }
-
- /**
- * @return a view that shows the recognition flow--e.g., "Speak now" and
- * "working" dialogs.
- */
- public View getView() {
- return mRecognitionView.getView();
- }
-
- /**
- * Handle the cancel button.
- */
- public void onClick(View view) {
- switch(view.getId()) {
- case R.id.button:
- cancel();
- break;
- }
- }
-
- public void logTextModified() {
- mLogger.textModified();
- }
-
- public void logKeyboardWarningDialogShown() {
- mLogger.keyboardWarningDialogShown();
- }
-
- public void logKeyboardWarningDialogDismissed() {
- mLogger.keyboardWarningDialogDismissed();
- }
-
- public void logKeyboardWarningDialogOk() {
- mLogger.keyboardWarningDialogOk();
- }
-
- public void logKeyboardWarningDialogCancel() {
- mLogger.keyboardWarningDialogCancel();
- }
-
- public void logSwipeHintDisplayed() {
- mLogger.swipeHintDisplayed();
- }
-
- public void logPunctuationHintDisplayed() {
- mLogger.punctuationHintDisplayed();
- }
-
- public void logVoiceInputDelivered() {
- mLogger.voiceInputDelivered();
- }
-
- public void logNBestChoose(int index) {
- mLogger.nBestChoose(index);
- }
-
- public void logInputEnded() {
- mLogger.inputEnded();
- }
-
- public void flushLogs() {
- mLogger.flush();
- }
-
- private static Intent makeIntent() {
- Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
-
- // On Cupcake, use VoiceIMEHelper since VoiceSearch doesn't support.
- // On Donut, always use VoiceSearch, since VoiceIMEHelper and
- // VoiceSearch may conflict.
- if (Build.VERSION.RELEASE.equals("1.5")) {
- intent = intent.setClassName(
- "com.google.android.voiceservice",
- "com.google.android.voiceservice.IMERecognitionService");
- } else {
- intent = intent.setClassName(
- "com.google.android.voicesearch",
- "com.google.android.voicesearch.RecognitionService");
- }
-
- return intent;
- }
-
- /**
- * Cancel in-progress speech recognition.
- */
- public void cancel() {
- switch (mState) {
- case LISTENING:
- mLogger.cancelDuringListening();
- break;
- case WORKING:
- mLogger.cancelDuringWorking();
- break;
- case ERROR:
- mLogger.cancelDuringError();
- break;
- }
- mState = DEFAULT;
-
- // Remove all pending tasks (e.g., timers to cancel voice input)
- mHandler.removeMessages(MSG_CLOSE_ERROR_DIALOG);
-
- mRecognitionManager.cancel();
- mUiListener.onCancelVoice();
- mRecognitionView.finish();
- }
-
- private int getErrorStringId(int errorType, boolean endpointed) {
- switch (errorType) {
- // We use CLIENT_ERROR to signify that voice search is not available on the device.
- case RecognitionManager.ERROR_CLIENT:
- return R.string.voice_not_installed;
- case RecognitionManager.ERROR_NETWORK:
- return R.string.voice_network_error;
- case RecognitionManager.ERROR_NETWORK_TIMEOUT:
- return endpointed ?
- R.string.voice_network_error : R.string.voice_too_much_speech;
- case RecognitionManager.ERROR_AUDIO:
- return R.string.voice_audio_error;
- case RecognitionManager.ERROR_SERVER:
- return R.string.voice_server_error;
- case RecognitionManager.ERROR_SPEECH_TIMEOUT:
- return R.string.voice_speech_timeout;
- case RecognitionManager.ERROR_NO_MATCH:
- return R.string.voice_no_match;
- default: return R.string.voice_error;
- }
- }
-
- private void onError(int errorType, boolean endpointed) {
- Log.i(TAG, "error " + errorType);
- mLogger.error(errorType);
- onError(mContext.getString(getErrorStringId(errorType, endpointed)));
- }
-
- private void onError(String error) {
- mState = ERROR;
- mRecognitionView.showError(error);
- // Wait a couple seconds and then automatically dismiss message.
- mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_CLOSE_ERROR_DIALOG), 2000);
- }
-
- private class ImeRecognitionListener implements RecognitionListener {
- // Waveform data
- final ByteArrayOutputStream mWaveBuffer = new ByteArrayOutputStream();
- int mSpeechStart;
- private boolean mEndpointed = false;
-
- public void onReadyForSpeech(Bundle noiseParams) {
- mRecognitionView.showListening();
- }
-
- public void onBeginningOfSpeech() {
- mEndpointed = false;
- mSpeechStart = mWaveBuffer.size();
- }
-
- public void onRmsChanged(float rmsdB) {
- mRecognitionView.updateVoiceMeter(rmsdB);
- }
-
- public void onBufferReceived(byte[] buf) {
- try {
- mWaveBuffer.write(buf);
- } catch (IOException e) {}
- }
-
- public void onEndOfSpeech() {
- mEndpointed = true;
- mState = WORKING;
- mRecognitionView.showWorking(mWaveBuffer, mSpeechStart, mWaveBuffer.size());
- }
-
- public void onError(int errorType) {
- mState = ERROR;
- VoiceInput.this.onError(errorType, mEndpointed);
- }
-
- public void onResults(Bundle resultsBundle) {
- List<String> results = resultsBundle
- .getStringArrayList(RecognitionManager.RESULTS_RECOGNITION);
- mState = DEFAULT;
-
- final Map<String, List<CharSequence>> alternatives =
- new HashMap<String, List<CharSequence>>();
- if (results.size() >= 2 && ENABLE_WORD_CORRECTIONS) {
- final String[][] words = new String[results.size()][];
- for (int i = 0; i < words.length; i++) {
- words[i] = results.get(i).split(" ");
- }
-
- for (int key = 0; key < words[0].length; key++) {
- alternatives.put(words[0][key], new ArrayList<CharSequence>());
- for (int alt = 1; alt < words.length; alt++) {
- int keyBegin = key * words[alt].length / words[0].length;
- int keyEnd = (key + 1) * words[alt].length / words[0].length;
-
- for (int i = keyBegin; i < Math.min(words[alt].length, keyEnd); i++) {
- List<CharSequence> altList = alternatives.get(words[0][key]);
- if (!altList.contains(words[alt][i]) && altList.size() < 6) {
- altList.add(words[alt][i]);
- }
- }
- }
- }
- }
-
- if (results.size() > 5) {
- results = results.subList(0, 5);
- }
- mUiListener.onVoiceResults(results, alternatives);
- mRecognitionView.finish();
- }
-
- public void onPartialResults(final Bundle partialResults) {
- // currently - do nothing
- }
-
- public void onEvent(int eventType, Bundle params) {
- // do nothing - reserved for events that might be added in the future
- }
- }
-}
diff --git a/src/com/android/inputmethod/voice/VoiceInputLogger.java b/src/com/android/inputmethod/voice/VoiceInputLogger.java
deleted file mode 100644
index 659033340..000000000
--- a/src/com/android/inputmethod/voice/VoiceInputLogger.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2008 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.voice;
-
-import com.android.common.speech.LoggingEvents;
-
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Provides the logging facility for voice input events. This fires broadcasts back to
- * the voice search app which then logs on our behalf.
- *
- * Note that debug console logging does not occur in this class. If you want to
- * see console output of these logging events, there is a boolean switch to turn
- * on on the VoiceSearch side.
- */
-public class VoiceInputLogger {
- private static final String TAG = VoiceInputLogger.class.getSimpleName();
-
- private static VoiceInputLogger sVoiceInputLogger;
-
- private final Context mContext;
-
- // The base intent used to form all broadcast intents to the logger
- // in VoiceSearch.
- private final Intent mBaseIntent;
-
- /**
- * Returns the singleton of the logger.
- *
- * @param contextHint a hint context used when creating the logger instance.
- * Ignored if the singleton instance already exists.
- */
- public static synchronized VoiceInputLogger getLogger(Context contextHint) {
- if (sVoiceInputLogger == null) {
- sVoiceInputLogger = new VoiceInputLogger(contextHint);
- }
- return sVoiceInputLogger;
- }
-
- public VoiceInputLogger(Context context) {
- mContext = context;
-
- mBaseIntent = new Intent(LoggingEvents.ACTION_LOG_EVENT);
- mBaseIntent.putExtra(LoggingEvents.EXTRA_APP_NAME, LoggingEvents.VoiceIme.APP_NAME);
- }
-
- private Intent newLoggingBroadcast(int event) {
- Intent i = new Intent(mBaseIntent);
- i.putExtra(LoggingEvents.EXTRA_EVENT, event);
- return i;
- }
-
- public void flush() {
- Intent i = new Intent(mBaseIntent);
- i.putExtra(LoggingEvents.EXTRA_FLUSH, true);
- mContext.sendBroadcast(i);
- }
-
- public void keyboardWarningDialogShown() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_SHOWN));
- }
-
- public void keyboardWarningDialogDismissed() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_DISMISSED));
- }
-
- public void keyboardWarningDialogOk() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_OK));
- }
-
- public void keyboardWarningDialogCancel() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_CANCEL));
- }
-
- public void settingsWarningDialogShown() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_SHOWN));
- }
-
- public void settingsWarningDialogDismissed() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_DISMISSED));
- }
-
- public void settingsWarningDialogOk() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_OK));
- }
-
- public void settingsWarningDialogCancel() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_CANCEL));
- }
-
- public void swipeHintDisplayed() {
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.SWIPE_HINT_DISPLAYED));
- }
-
- public void cancelDuringListening() {
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_LISTENING));
- }
-
- public void cancelDuringWorking() {
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_WORKING));
- }
-
- public void cancelDuringError() {
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_ERROR));
- }
-
- public void punctuationHintDisplayed() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.PUNCTUATION_HINT_DISPLAYED));
- }
-
- public void error(int code) {
- Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.ERROR);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_ERROR_CODE, code);
- mContext.sendBroadcast(i);
- }
-
- public void start(String locale, boolean swipe) {
- Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.START);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_START_LOCALE, locale);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_START_SWIPE, swipe);
- i.putExtra(LoggingEvents.EXTRA_TIMESTAMP, System.currentTimeMillis());
- mContext.sendBroadcast(i);
- }
-
- public void voiceInputDelivered() {
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.VOICE_INPUT_DELIVERED));
- }
-
- public void textModified() {
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED));
- }
-
- public void nBestChoose(int index) {
- Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.N_BEST_CHOOSE);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_N_BEST_CHOOSE_INDEX, index);
- mContext.sendBroadcast(i);
- }
-
- public void inputEnded() {
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.INPUT_ENDED));
- }
-
- public void voiceInputSettingEnabled() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.VOICE_INPUT_SETTING_ENABLED));
- }
-
- public void voiceInputSettingDisabled() {
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.VOICE_INPUT_SETTING_DISABLED));
- }
-}
diff --git a/src/com/android/inputmethod/voice/WaveformImage.java b/src/com/android/inputmethod/voice/WaveformImage.java
deleted file mode 100644
index 08d87c8f3..000000000
--- a/src/com/android/inputmethod/voice/WaveformImage.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.voice;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-
-import java.io.ByteArrayOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.ShortBuffer;
-
-/**
- * Utility class to draw a waveform into a bitmap, given a byte array
- * that represents the waveform as a sequence of 16-bit integers.
- * Adapted from RecognitionActivity.java.
- */
-public class WaveformImage {
- private static final int SAMPLING_RATE = 8000;
-
- private WaveformImage() {}
-
- public static Bitmap drawWaveform(
- ByteArrayOutputStream waveBuffer, int w, int h, int start, int end) {
- final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- final Canvas c = new Canvas(b);
- final Paint paint = new Paint();
- paint.setColor(0xFFFFFFFF); // 0xRRGGBBAA
- paint.setAntiAlias(true);
- paint.setStrokeWidth(0);
-
- final ShortBuffer buf = ByteBuffer
- .wrap(waveBuffer.toByteArray())
- .order(ByteOrder.nativeOrder())
- .asShortBuffer();
- buf.position(0);
-
- final int numSamples = waveBuffer.size() / 2;
- final int delay = (SAMPLING_RATE * 100 / 1000);
- int endIndex = end / 2 + delay;
- if (end == 0 || endIndex >= numSamples) {
- endIndex = numSamples;
- }
- int index = start / 2 - delay;
- if (index < 0) {
- index = 0;
- }
- final int size = endIndex - index;
- int numSamplePerPixel = 32;
- int delta = size / (numSamplePerPixel * w);
- if (delta == 0) {
- numSamplePerPixel = size / w;
- delta = 1;
- }
-
- final float scale = 3.5f / 65536.0f;
- // do one less column to make sure we won't read past
- // the buffer.
- try {
- for (int i = 0; i < w - 1 ; i++) {
- final float x = i;
- for (int j = 0; j < numSamplePerPixel; j++) {
- final short s = buf.get(index);
- final float y = (h / 2) - (s * h * scale);
- c.drawPoint(x, y, paint);
- index += delta;
- }
- }
- } catch (IndexOutOfBoundsException e) {
- // this can happen, but we don't care
- }
-
- return b;
- }
-}
diff --git a/src/com/android/inputmethod/voice/Whitelist.java b/src/com/android/inputmethod/voice/Whitelist.java
deleted file mode 100644
index 167b688ca..000000000
--- a/src/com/android/inputmethod/voice/Whitelist.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2009 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.voice;
-
-import android.os.Bundle;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A set of text fields where speech has been explicitly enabled.
- */
-public class Whitelist {
- private List<Bundle> mConditions;
-
- public Whitelist() {
- mConditions = new ArrayList<Bundle>();
- }
-
- public Whitelist(List<Bundle> conditions) {
- this.mConditions = conditions;
- }
-
- public void addApp(String app) {
- Bundle bundle = new Bundle();
- bundle.putString("packageName", app);
- mConditions.add(bundle);
- }
-
- /**
- * @return true if the field is a member of the whitelist.
- */
- public boolean matches(FieldContext context) {
- for (Bundle condition : mConditions) {
- if (matches(condition, context.getBundle())) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * @return true of all values in condition are matched by a value
- * in target.
- */
- private boolean matches(Bundle condition, Bundle target) {
- for (String key : condition.keySet()) {
- if (!condition.getString(key).equals(target.getString(key))) {
- return false;
- }
- }
- return true;
- }
-}
diff --git a/src/com/google/android/voicesearch/LatinIMEWithVoice.java b/src/com/google/android/voicesearch/LatinIMEWithVoice.java
deleted file mode 100644
index 8a339d14a..000000000
--- a/src/com/google/android/voicesearch/LatinIMEWithVoice.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- *
- * Copyright (C) 2009 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.google.android.voicesearch;
-
-import android.content.Intent;
-
-import com.android.inputmethod.latin.LatinIME;
-
-public class LatinIMEWithVoice extends LatinIME {
- @Override
- protected void launchSettings() {
- launchSettings(LatinIMEWithVoiceSettings.class);
- }
-}
diff --git a/src/com/google/android/voicesearch/LatinIMEWithVoiceSettings.java b/src/com/google/android/voicesearch/LatinIMEWithVoiceSettings.java
deleted file mode 100644
index a53cebfd9..000000000
--- a/src/com/google/android/voicesearch/LatinIMEWithVoiceSettings.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.google.android.voicesearch;
-
-import com.android.inputmethod.latin.LatinIMESettings;
-
-public class LatinIMEWithVoiceSettings extends LatinIMESettings {}