Remove Tutorial class and unused debug feature

This change also cleanups compiler warnings.

Bug: 2897373
Change-Id: If972cf45c1eb40436adbddbf71969e5409f4c9c5
main
Tadashi G. Takaoka 2010-12-10 15:24:28 +09:00
parent 20cdb37bd0
commit e26ef1bccd
26 changed files with 358 additions and 771 deletions

View File

@ -47,6 +47,7 @@ public class KeyStyles {
public static class EmptyKeyStyle implements KeyStyle { public static class EmptyKeyStyle implements KeyStyle {
private EmptyKeyStyle() { private EmptyKeyStyle() {
// Nothing to do.
} }
@Override @Override

View File

@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import android.content.res.Resources; import android.content.res.Resources;
@ -142,8 +143,8 @@ public class KeyboardParser {
public void parseKeyboard(XmlResourceParser parser) public void parseKeyboard(XmlResourceParser parser)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
int event; int event;
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) { while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (event == XmlResourceParser.START_TAG) { if (event == XmlPullParser.START_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (DEBUG_TAG) debugStartTag("parseKeyboard", tag, false); if (DEBUG_TAG) debugStartTag("parseKeyboard", tag, false);
if (TAG_KEYBOARD.equals(tag)) { if (TAG_KEYBOARD.equals(tag)) {
@ -186,8 +187,8 @@ public class KeyboardParser {
private void parseKeyboardContent(XmlResourceParser parser, List<Key> keys) private void parseKeyboardContent(XmlResourceParser parser, List<Key> keys)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
int event; int event;
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) { while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (event == XmlResourceParser.START_TAG) { if (event == XmlPullParser.START_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (DEBUG_TAG) debugStartTag("parseKeyboardContent", tag, keys == null); if (DEBUG_TAG) debugStartTag("parseKeyboardContent", tag, keys == null);
if (TAG_ROW.equals(tag)) { if (TAG_ROW.equals(tag)) {
@ -204,7 +205,7 @@ public class KeyboardParser {
} else { } else {
throw new IllegalStartTag(parser, TAG_ROW); throw new IllegalStartTag(parser, TAG_ROW);
} }
} else if (event == XmlResourceParser.END_TAG) { } else if (event == XmlPullParser.END_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (DEBUG_TAG) debugEndTag("parseKeyboardContent", tag, keys == null); if (DEBUG_TAG) debugEndTag("parseKeyboardContent", tag, keys == null);
if (TAG_KEYBOARD.equals(tag)) { if (TAG_KEYBOARD.equals(tag)) {
@ -226,8 +227,8 @@ public class KeyboardParser {
private void parseRowContent(XmlResourceParser parser, Row row, List<Key> keys) private void parseRowContent(XmlResourceParser parser, Row row, List<Key> keys)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
int event; int event;
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) { while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (event == XmlResourceParser.START_TAG) { if (event == XmlPullParser.START_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (DEBUG_TAG) debugStartTag("parseRowContent", tag, keys == null); if (DEBUG_TAG) debugStartTag("parseRowContent", tag, keys == null);
if (TAG_KEY.equals(tag)) { if (TAG_KEY.equals(tag)) {
@ -243,7 +244,7 @@ public class KeyboardParser {
} else { } else {
throw new IllegalStartTag(parser, TAG_KEY); throw new IllegalStartTag(parser, TAG_KEY);
} }
} else if (event == XmlResourceParser.END_TAG) { } else if (event == XmlPullParser.END_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (DEBUG_TAG) debugEndTag("parseRowContent", tag, keys == null); if (DEBUG_TAG) debugEndTag("parseRowContent", tag, keys == null);
if (TAG_ROW.equals(tag)) { if (TAG_ROW.equals(tag)) {
@ -327,8 +328,8 @@ public class KeyboardParser {
private void parseMerge(XmlResourceParser parser, Row row, List<Key> keys) private void parseMerge(XmlResourceParser parser, Row row, List<Key> keys)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
int event; int event;
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) { while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (event == XmlResourceParser.START_TAG) { if (event == XmlPullParser.START_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (DEBUG_TAG) debugStartTag("parseMerge", tag, keys == null); if (DEBUG_TAG) debugStartTag("parseMerge", tag, keys == null);
if (TAG_MERGE.equals(tag)) { if (TAG_MERGE.equals(tag)) {
@ -361,8 +362,8 @@ public class KeyboardParser {
boolean selected = false; boolean selected = false;
int event; int event;
if (DEBUG_TAG) Log.d(TAG, "parseSwitchInternal: id=" + mKeyboard.mId); if (DEBUG_TAG) Log.d(TAG, "parseSwitchInternal: id=" + mKeyboard.mId);
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) { while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (event == XmlResourceParser.START_TAG) { if (event == XmlPullParser.START_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (DEBUG_TAG) debugStartTag("parseSwitchInternal", tag, keys == null); if (DEBUG_TAG) debugStartTag("parseSwitchInternal", tag, keys == null);
if (TAG_CASE.equals(tag)) { if (TAG_CASE.equals(tag)) {
@ -372,7 +373,7 @@ public class KeyboardParser {
} else { } else {
throw new IllegalStartTag(parser, TAG_KEY); throw new IllegalStartTag(parser, TAG_KEY);
} }
} else if (event == XmlResourceParser.END_TAG) { } else if (event == XmlPullParser.END_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (DEBUG_TAG) debugEndTag("parseRowContent", tag, keys == null); if (DEBUG_TAG) debugEndTag("parseRowContent", tag, keys == null);
if (TAG_SWITCH.equals(tag)) { if (TAG_SWITCH.equals(tag)) {
@ -469,8 +470,7 @@ public class KeyboardParser {
return true; return true;
} }
private void parseKeyStyle(XmlResourceParser parser, List<Key> keys) private void parseKeyStyle(XmlResourceParser parser, List<Key> keys) {
throws XmlPullParserException, IOException {
TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser), TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard_KeyStyle); R.styleable.Keyboard_KeyStyle);
TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser), TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
@ -489,7 +489,7 @@ public class KeyboardParser {
private static void checkEndTag(String tag, XmlResourceParser parser) private static void checkEndTag(String tag, XmlResourceParser parser)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
if (parser.next() == XmlResourceParser.END_TAG && tag.equals(parser.getName())) if (parser.next() == XmlPullParser.END_TAG && tag.equals(parser.getName()))
return; return;
throw new NonEmptyTag(tag, parser); throw new NonEmptyTag(tag, parser);
} }

View File

@ -100,6 +100,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
} }
private KeyboardSwitcher() { private KeyboardSwitcher() {
// Intentional empty constructor for singleton.
} }
public static void init(LatinIME ims, SharedPreferences prefs) { public static void init(LatinIME ims, SharedPreferences prefs) {
@ -554,12 +555,13 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
} }
private void createInputViewInternal(int newLayout, boolean forceReset) { private void createInputViewInternal(int newLayout, boolean forceReset) {
if (mLayoutId != newLayout || mInputView == null || forceReset) { int layoutId = newLayout;
if (mLayoutId != layoutId || mInputView == null || forceReset) {
if (mInputView != null) { if (mInputView != null) {
mInputView.closing(); mInputView.closing();
} }
if (THEMES.length <= newLayout) { if (THEMES.length <= layoutId) {
newLayout = Integer.valueOf(DEFAULT_LAYOUT_ID); layoutId = Integer.valueOf(DEFAULT_LAYOUT_ID);
} }
Utils.GCUtils.getInstance().reset(); Utils.GCUtils.getInstance().reset();
@ -567,20 +569,20 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
try { try {
mInputView = (LatinKeyboardView) mInputMethodService.getLayoutInflater( mInputView = (LatinKeyboardView) mInputMethodService.getLayoutInflater(
).inflate(THEMES[newLayout], null); ).inflate(THEMES[layoutId], null);
tryGC = false; tryGC = false;
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
Log.w(TAG, "load keyboard failed: " + e); Log.w(TAG, "load keyboard failed: " + e);
tryGC = Utils.GCUtils.getInstance().tryGCOrWait( tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
mLayoutId + "," + newLayout, e); mLayoutId + "," + layoutId, e);
} catch (InflateException e) { } catch (InflateException e) {
Log.w(TAG, "load keyboard failed: " + e); Log.w(TAG, "load keyboard failed: " + e);
tryGC = Utils.GCUtils.getInstance().tryGCOrWait( tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
mLayoutId + "," + newLayout, e); mLayoutId + "," + layoutId, e);
} }
} }
mInputView.setOnKeyboardActionListener(mInputMethodService); mInputView.setOnKeyboardActionListener(mInputMethodService);
mLayoutId = newLayout; mLayoutId = layoutId;
} }
} }

View File

@ -289,7 +289,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
cancelPopupPreview(); cancelPopupPreview();
cancelDismissPreview(); cancelDismissPreview();
} }
}; }
public KeyboardView(Context context, AttributeSet attrs) { public KeyboardView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.keyboardViewStyle); this(context, attrs, R.attr.keyboardViewStyle);
@ -587,7 +587,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
protected CharSequence adjustCase(CharSequence label) { protected CharSequence adjustCase(CharSequence label) {
if (mKeyboard.isShiftedOrShiftLocked() && label != null && label.length() < 3 if (mKeyboard.isShiftedOrShiftLocked() && label != null && label.length() < 3
&& Character.isLowerCase(label.charAt(0))) { && Character.isLowerCase(label.charAt(0))) {
label = label.toString().toUpperCase(); return label.toString().toUpperCase();
} }
return label; return label;
} }
@ -1089,7 +1089,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mKeyboardActionListener.onKey(Keyboard.CODE_CAPSLOCK, null, 0, 0); mKeyboardActionListener.onKey(Keyboard.CODE_CAPSLOCK, null, 0, 0);
} }
private void onDoubleTapShiftKey(PointerTracker tracker) { private void onDoubleTapShiftKey(@SuppressWarnings("unused") PointerTracker tracker) {
// When shift key is double tapped, the first tap is correctly processed as usual tap. And // When shift key is double tapped, the first tap is correctly processed as usual tap. And
// the second tap is treated as this double tap event, so that we need not mark tracker // the second tap is treated as this double tap event, so that we need not mark tracker
// calling setAlreadyProcessed() nor remove the tracker from mPointerQueueueue. // calling setAlreadyProcessed() nor remove the tracker from mPointerQueueueue.
@ -1126,15 +1126,19 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
@Override @Override
public void swipeLeft() { public void swipeLeft() {
// Nothing to do.
} }
@Override @Override
public void swipeRight() { public void swipeRight() {
// Nothing to do.
} }
@Override @Override
public void swipeUp() { public void swipeUp() {
// Nothing to do.
} }
@Override @Override
public void swipeDown() { public void swipeDown() {
// Nothing to do.
} }
@Override @Override
public void onPress(int primaryCode) { public void onPress(int primaryCode) {

View File

@ -280,7 +280,9 @@ public class LatinKeyboard extends Keyboard {
*/ */
@Override @Override
@SuppressWarnings("unused") // SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER is constant @SuppressWarnings("unused") // SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER is constant
public boolean isInside(Key key, int x, int y) { public boolean isInside(Key key, int pointX, int pointY) {
int x = pointX;
int y = pointY;
final int code = key.mCodes[0]; final int code = key.mCodes[0];
if (code == CODE_SHIFT || code == CODE_DELETE) { if (code == CODE_SHIFT || code == CODE_DELETE) {
y -= key.mHeight / 10; y -= key.mHeight / 10;

View File

@ -21,16 +21,10 @@ import com.android.inputmethod.voice.VoiceIMEConnector;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import java.util.List;
// TODO: We should remove this class // TODO: We should remove this class
public class LatinKeyboardView extends KeyboardView { public class LatinKeyboardView extends KeyboardView {
@ -45,6 +39,8 @@ public class LatinKeyboardView extends KeyboardView {
private int mJumpThresholdSquare = Integer.MAX_VALUE; private int mJumpThresholdSquare = Integer.MAX_VALUE;
/** The y coordinate of the last row */ /** The y coordinate of the last row */
private int mLastRowY; private int mLastRowY;
private int mLastX;
private int mLastY;
public LatinKeyboardView(Context context, AttributeSet attrs) { public LatinKeyboardView(Context context, AttributeSet attrs) {
this(context, attrs, 0); this(context, attrs, 0);
@ -73,7 +69,6 @@ public class LatinKeyboardView extends KeyboardView {
mJumpThresholdSquare *= mJumpThresholdSquare; mJumpThresholdSquare *= mJumpThresholdSquare;
// Assuming there are 4 rows, this is the coordinate of the last row // Assuming there are 4 rows, this is the coordinate of the last row
mLastRowY = (k.getHeight() * 3) / 4; mLastRowY = (k.getHeight() * 3) / 4;
setKeyboardLocal(k);
} }
public LatinKeyboard getLatinKeyboard() { public LatinKeyboard getLatinKeyboard() {
@ -112,7 +107,7 @@ public class LatinKeyboardView extends KeyboardView {
&& keyboard.isShiftedOrShiftLocked() && keyboard.isShiftedOrShiftLocked()
&& !TextUtils.isEmpty(label) && label.length() < 3 && !TextUtils.isEmpty(label) && label.length() < 3
&& Character.isLowerCase(label.charAt(0))) { && Character.isLowerCase(label.charAt(0))) {
label = label.toString().toUpperCase(); return label.toString().toUpperCase();
} }
return label; return label;
} }
@ -197,11 +192,6 @@ public class LatinKeyboardView extends KeyboardView {
@Override @Override
public boolean onTouchEvent(MotionEvent me) { public boolean onTouchEvent(MotionEvent me) {
LatinKeyboard keyboard = getLatinKeyboard(); LatinKeyboard keyboard = getLatinKeyboard();
if (DEBUG_LINE) {
mLastX = (int) me.getX();
mLastY = (int) me.getY();
invalidate();
}
// If there was a sudden jump, return without processing the actual motion event. // If there was a sudden jump, return without processing the actual motion event.
if (handleSuddenJump(me)) if (handleSuddenJump(me))
@ -228,106 +218,6 @@ public class LatinKeyboardView extends KeyboardView {
return super.onTouchEvent(me); return super.onTouchEvent(me);
} }
/**************************** INSTRUMENTATION *******************************/
public static final boolean DEBUG_AUTO_PLAY = false;
public 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;
private void setKeyboardLocal(LatinKeyboard 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[c] == null) {
mStringIndex++;
if (mStringIndex >= mStringToPlay.length()) {
mPlaying = false;
return;
}
c = mStringToPlay.charAt(mStringIndex);
}
int x = mAsciiKeys[c].mX + 10;
int y = mAsciiKeys[c].mY + 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].mX + 10;
int y2 = mAsciiKeys[cUp].mY + 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 = getLatinKeyboard().getKeys();
// Get the keys on this keyboard
for (int i = 0; i < keys.size(); i++) {
int code = keys.get(i).mCodes[0];
if (code >= 0 && code <= 255) {
mAsciiKeys[code] = keys.get(i);
}
}
}
public void startPlaying(String s) {
if (DEBUG_AUTO_PLAY) {
if (s == null) return;
mStringToPlay = s.toLowerCase();
mPlaying = true;
mDownDelivered = false;
mStringIndex = 0;
mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 10);
}
}
@Override @Override
public void draw(Canvas c) { public void draw(Canvas c) {
Utils.GCUtils.getInstance().reset(); Utils.GCUtils.getInstance().reset();
@ -340,26 +230,6 @@ public class LatinKeyboardView extends KeyboardView {
tryGC = Utils.GCUtils.getInstance().tryGCOrWait("LatinKeyboardView", e); tryGC = Utils.GCUtils.getInstance().tryGCOrWait("LatinKeyboardView", e);
} }
} }
if (DEBUG_AUTO_PLAY) {
if (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);
}
} }
@Override @Override

View File

@ -299,7 +299,7 @@ public class PointerTracker {
showKeyPreviewAndUpdateKeyGraphics(keyIndex); showKeyPreviewAndUpdateKeyGraphics(keyIndex);
} }
public void onMoveEvent(int x, int y, long eventTime) { public void onMoveEvent(int x, int y, @SuppressWarnings("unused") long eventTime) {
if (DEBUG_MOVE) if (DEBUG_MOVE)
debugLog("onMoveEvent:", x, y); debugLog("onMoveEvent:", x, y);
if (mKeyAlreadyProcessed) if (mKeyAlreadyProcessed)
@ -333,7 +333,9 @@ public class PointerTracker {
showKeyPreviewAndUpdateKeyGraphics(mKeyState.getKeyIndex()); showKeyPreviewAndUpdateKeyGraphics(mKeyState.getKeyIndex());
} }
public void onUpEvent(int x, int y, long eventTime) { public void onUpEvent(int pointX, int pointY, long eventTime) {
int x = pointX;
int y = pointY;
if (DEBUG) if (DEBUG)
debugLog("onUpEvent :", x, y); debugLog("onUpEvent :", x, y);
showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY); showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY);
@ -356,7 +358,7 @@ public class PointerTracker {
mProxy.invalidateKey(mKeys[keyIndex]); mProxy.invalidateKey(mKeys[keyIndex]);
} }
public void onCancelEvent(int x, int y, long eventTime) { public void onCancelEvent(int x, int y, @SuppressWarnings("unused") long eventTime) {
if (DEBUG) if (DEBUG)
debugLog("onCancelEvt:", x, y); debugLog("onCancelEvt:", x, y);
mHandler.cancelKeyTimers(); mHandler.cancelKeyTimers();

View File

@ -58,7 +58,7 @@ public class SlidingLocaleDrawable extends Drawable {
mContext = context; mContext = context;
mRes = context.getResources(); mRes = context.getResources();
mBackground = background; mBackground = background;
LatinKeyboard.setDefaultBounds(mBackground); Keyboard.setDefaultBounds(mBackground);
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
final TextPaint textPaint = new TextPaint(); final TextPaint textPaint = new TextPaint();
@ -123,7 +123,7 @@ public class SlidingLocaleDrawable extends Drawable {
canvas.drawText(mNextLanguage, diff - width / 2, baseline, paint); canvas.drawText(mNextLanguage, diff - width / 2, baseline, paint);
canvas.drawText(mPrevLanguage, diff + width + width / 2, baseline, paint); canvas.drawText(mPrevLanguage, diff + width + width / 2, baseline, paint);
LatinKeyboard.setDefaultBounds(lArrow); Keyboard.setDefaultBounds(lArrow);
rArrow.setBounds(width - rArrow.getIntrinsicWidth(), 0, width, rArrow.setBounds(width - rArrow.getIntrinsicWidth(), 0, width,
rArrow.getIntrinsicHeight()); rArrow.getIntrinsicHeight());
lArrow.draw(canvas); lArrow.draw(canvas);

View File

@ -98,7 +98,7 @@ public class AutoDictionary extends ExpandableDictionary {
} }
@Override @Override
public boolean isValidWord(CharSequence word) { public synchronized boolean isValidWord(CharSequence word) {
final int frequency = getWordFrequency(word); final int frequency = getWordFrequency(word);
return frequency >= VALIDITY_THRESHOLD; return frequency >= VALIDITY_THRESHOLD;
} }
@ -138,7 +138,8 @@ public class AutoDictionary extends ExpandableDictionary {
} }
@Override @Override
public void addWord(String word, int addFrequency) { public void addWord(String newWord, int addFrequency) {
String word = newWord;
final int length = word.length(); final int length = word.length();
// Don't add very short or very long words. // Don't add very short or very long words.
if (length < 2 || length > getMaxWordLength()) return; if (length < 2 || length > getMaxWordLength()) return;
@ -224,7 +225,7 @@ public class AutoDictionary extends ExpandableDictionary {
private final DatabaseHelper mDbHelper; private final DatabaseHelper mDbHelper;
private final String mLocale; private final String mLocale;
public UpdateDbTask(Context context, DatabaseHelper openHelper, public UpdateDbTask(@SuppressWarnings("unused") Context context, DatabaseHelper openHelper,
HashMap<String, Integer> pendingWrites, String locale) { HashMap<String, Integer> pendingWrites, String locale) {
mMap = pendingWrites; mMap = pendingWrites;
mLocale = locale; mLocale = locale;

View File

@ -23,6 +23,7 @@ import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.BackgroundColorSpan; import android.text.style.BackgroundColorSpan;
import android.text.style.CharacterStyle; import android.text.style.CharacterStyle;
@ -35,6 +36,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener; import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.PopupWindow; import android.widget.PopupWindow;
@ -129,7 +131,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
cancelHidePreview(); cancelHidePreview();
cancelUpdateSuggestions(); cancelUpdateSuggestions();
} }
}; }
/** /**
* Construct a CandidateView for showing suggested words for completion. * Construct a CandidateView for showing suggested words for completion.
@ -143,7 +145,8 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mPreviewPopup = new PopupWindow(context); mPreviewPopup = new PopupWindow(context);
LayoutInflater inflater = LayoutInflater.from(context); LayoutInflater inflater = LayoutInflater.from(context);
mPreviewText = (TextView) inflater.inflate(R.layout.candidate_preview, null); mPreviewText = (TextView) inflater.inflate(R.layout.candidate_preview, null);
mPreviewPopup.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); mPreviewPopup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
mPreviewPopup.setContentView(mPreviewText); mPreviewPopup.setContentView(mPreviewText);
mPreviewPopup.setBackgroundDrawable(null); mPreviewPopup.setBackgroundDrawable(null);
mPreviewPopup.setAnimationStyle(R.style.KeyPreviewAnimation); mPreviewPopup.setAnimationStyle(R.style.KeyPreviewAnimation);
@ -222,7 +225,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
style = UNDERLINE_SPAN; style = UNDERLINE_SPAN;
} }
final Spannable word = new SpannableString(suggestion); final Spannable word = new SpannableString(suggestion);
word.setSpan(style, 0, wordLength, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); word.setSpan(style, 0, wordLength, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
suggestion = word; suggestion = word;
existsAutoCompletion = true; existsAutoCompletion = true;
} else if (i != 0 || (wordLength == 1 && count > 1)) { } else if (i != 0 || (wordLength == 1 && count > 1)) {
@ -255,10 +258,8 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
final TextView tv = (TextView)mWords.get(1).findViewById(R.id.candidate_word); final TextView tv = (TextView)mWords.get(1).findViewById(R.id.candidate_word);
final Spannable word = new SpannableString(autoCorrectedWord); final Spannable word = new SpannableString(autoCorrectedWord);
final int wordLength = word.length(); final int wordLength = word.length();
word.setSpan(mInvertedBackgroundColorSpan, 0, wordLength, word.setSpan(mInvertedBackgroundColorSpan, 0, wordLength, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
Spannable.SPAN_INCLUSIVE_EXCLUSIVE); word.setSpan(mInvertedForegroundColorSpan, 0, wordLength, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
word.setSpan(mInvertedForegroundColorSpan, 0, wordLength,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
tv.setText(word); tv.setText(word);
mShowingAutoCorrectionInverted = true; mShowingAutoCorrectionInverted = true;
} }

View File

@ -21,6 +21,7 @@ import android.content.Context;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.Cursor; import android.database.Cursor;
import android.os.SystemClock; import android.os.SystemClock;
import android.provider.BaseColumns;
import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Contacts;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@ -28,7 +29,7 @@ import android.util.Log;
public class ContactsDictionary extends ExpandableDictionary { public class ContactsDictionary extends ExpandableDictionary {
private static final String[] PROJECTION = { private static final String[] PROJECTION = {
Contacts._ID, BaseColumns._ID,
Contacts.DISPLAY_NAME, Contacts.DISPLAY_NAME,
}; };

View File

@ -20,7 +20,7 @@ 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 * Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
* strokes. * strokes.
*/ */
abstract public class Dictionary { public abstract class Dictionary {
/** /**
* Whether or not to replicate the typed word in the suggested list, even if it's valid. * Whether or not to replicate the typed word in the suggested list, even if it's valid.
*/ */
@ -42,11 +42,11 @@ abstract public class Dictionary {
public interface WordCallback { public interface WordCallback {
/** /**
* Adds a word to a list of suggestions. The word is expected to be ordered based on * Adds a word to a list of suggestions. The word is expected to be ordered based on
* the provided frequency. * the provided frequency.
* @param word the character array containing the word * @param word the character array containing the word
* @param wordOffset starting offset of the word in the character array * @param wordOffset starting offset of the word in the character array
* @param wordLength length of valid characters 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 * @param frequency the frequency of occurrence. This is normalized between 1 and 255, but
* can exceed those limits * can exceed those limits
* @param dicTypeId of the dictionary where word was from * @param dicTypeId of the dictionary where word was from
* @param dataType tells type of this data * @param dataType tells type of this data
@ -74,6 +74,7 @@ abstract public class Dictionary {
* Searches for pairs in the bigram dictionary that matches the previous word and all the * Searches for pairs in the bigram dictionary that matches the previous word and all the
* possible words following are added through the callback object. * possible words following are added through the callback object.
* @param composer the key sequence to match * @param composer the key sequence to match
* @param previousWord the word before
* @param callback the callback object to send possible word following previous word * @param callback the callback object to send possible word following previous word
* @param nextLettersFrequencies array of frequencies of next letters that could follow the * @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 * word so far. For instance, "bracke" can be followed by "t", so array['t'] will have
@ -116,5 +117,6 @@ abstract public class Dictionary {
* Override to clean up any resources. * Override to clean up any resources.
*/ */
public void close() { public void close() {
// empty base implementation
} }
} }

View File

@ -28,7 +28,7 @@ import java.util.regex.Pattern;
/** /**
* Utility methods to deal with editing text through an InputConnection. * Utility methods to deal with editing text through an InputConnection.
*/ */
public class EditingUtil { public class EditingUtils {
/** /**
* Number of characters we want to look back in order to identify the previous word * Number of characters we want to look back in order to identify the previous word
*/ */
@ -39,7 +39,9 @@ public class EditingUtil {
private static Method sMethodGetSelectedText; private static Method sMethodGetSelectedText;
private static Method sMethodSetComposingRegion; private static Method sMethodSetComposingRegion;
private EditingUtil() {}; private EditingUtils() {
// Unintentional empty constructor for singleton.
}
/** /**
* Append newText to the text field represented by connection. * Append newText to the text field represented by connection.
@ -54,14 +56,15 @@ public class EditingUtil {
connection.finishComposingText(); connection.finishComposingText();
// Add a space if the field already has text. // Add a space if the field already has text.
String text = newText;
CharSequence charBeforeCursor = connection.getTextBeforeCursor(1, 0); CharSequence charBeforeCursor = connection.getTextBeforeCursor(1, 0);
if (charBeforeCursor != null if (charBeforeCursor != null
&& !charBeforeCursor.equals(" ") && !charBeforeCursor.equals(" ")
&& (charBeforeCursor.length() > 0)) { && (charBeforeCursor.length() > 0)) {
newText = " " + newText; text = " " + text;
} }
connection.setComposingText(newText, 1); connection.setComposingText(text, 1);
} }
private static int getCursorPosition(InputConnection connection) { private static int getCursorPosition(InputConnection connection) {
@ -76,33 +79,29 @@ public class EditingUtil {
/** /**
* @param connection connection to the current text field. * @param connection connection to the current text field.
* @param sep characters which may separate words * @param sep characters which may separate words
* @param range the range object to store the result into
* @return the word that surrounds the cursor, including up to one trailing * @return the word that surrounds the cursor, including up to one trailing
* separator. For example, if the field contains "he|llo world", where | * separator. For example, if the field contains "he|llo world", where |
* represents the cursor, then "hello " will be returned. * represents the cursor, then "hello " will be returned.
*/ */
public static String getWordAtCursor( public static String getWordAtCursor(InputConnection connection, String separators) {
InputConnection connection, String separators, Range range) { Range r = getWordRangeAtCursor(connection, separators);
Range r = getWordRangeAtCursor(connection, separators, range); return (r == null) ? null : r.mWord;
return (r == null) ? null : r.word;
} }
/** /**
* Removes the word surrounding the cursor. Parameters are identical to * Removes the word surrounding the cursor. Parameters are identical to
* getWordAtCursor. * getWordAtCursor.
*/ */
public static void deleteWordAtCursor( public static void deleteWordAtCursor(InputConnection connection, String separators) {
InputConnection connection, String separators) { Range range = getWordRangeAtCursor(connection, separators);
Range range = getWordRangeAtCursor(connection, separators, null);
if (range == null) return; if (range == null) return;
connection.finishComposingText(); connection.finishComposingText();
// Move cursor to beginning of word, to avoid crash when cursor is outside // Move cursor to beginning of word, to avoid crash when cursor is outside
// of valid range after deleting text. // of valid range after deleting text.
int newCursor = getCursorPosition(connection) - range.charsBefore; int newCursor = getCursorPosition(connection) - range.mCharsBefore;
connection.setSelection(newCursor, newCursor); connection.setSelection(newCursor, newCursor);
connection.deleteSurroundingText(0, range.charsBefore + range.charsAfter); connection.deleteSurroundingText(0, range.mCharsBefore + range.mCharsAfter);
} }
/** /**
@ -110,31 +109,28 @@ public class EditingUtil {
*/ */
public static class Range { public static class Range {
/** Characters before selection start */ /** Characters before selection start */
public int charsBefore; public final int mCharsBefore;
/** /**
* Characters after selection start, including one trailing word * Characters after selection start, including one trailing word
* separator. * separator.
*/ */
public int charsAfter; public final int mCharsAfter;
/** The actual characters that make up a word */ /** The actual characters that make up a word */
public String word; public final String mWord;
public Range() {}
public Range(int charsBefore, int charsAfter, String word) { public Range(int charsBefore, int charsAfter, String word) {
if (charsBefore < 0 || charsAfter < 0) { if (charsBefore < 0 || charsAfter < 0) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} }
this.charsBefore = charsBefore; this.mCharsBefore = charsBefore;
this.charsAfter = charsAfter; this.mCharsAfter = charsAfter;
this.word = word; this.mWord = word;
} }
} }
private static Range getWordRangeAtCursor( private static Range getWordRangeAtCursor(InputConnection connection, String sep) {
InputConnection connection, String sep, Range range) {
if (connection == null || sep == null) { if (connection == null || sep == null) {
return null; return null;
} }
@ -150,18 +146,15 @@ public class EditingUtil {
// Find last word separator after the cursor // Find last word separator after the cursor
int end = -1; int end = -1;
while (++end < after.length() && !isWhitespace(after.charAt(end), sep)); while (++end < after.length() && !isWhitespace(after.charAt(end), sep)) {
// Nothing to do here.
}
int cursor = getCursorPosition(connection); int cursor = getCursorPosition(connection);
if (start >= 0 && cursor + end <= after.length() + before.length()) { if (start >= 0 && cursor + end <= after.length() + before.length()) {
String word = before.toString().substring(start, before.length()) String word = before.toString().substring(start, before.length())
+ after.toString().substring(0, end); + after.toString().substring(0, end);
return new Range(before.length() - start, end, word);
Range returnRange = range != null? range : new Range();
returnRange.charsBefore = before.length() - start;
returnRange.charsAfter = end;
returnRange.word = word;
return returnRange;
} }
return null; return null;
@ -193,9 +186,15 @@ public class EditingUtil {
} }
public static class SelectedWord { public static class SelectedWord {
public int start; public final int mStart;
public int end; public final int mEnd;
public CharSequence word; public final CharSequence mWord;
public SelectedWord(int start, int end, CharSequence word) {
mStart = start;
mEnd = end;
mWord = word;
}
} }
/** /**
@ -223,14 +222,10 @@ public class EditingUtil {
int selStart, int selEnd, String wordSeparators) { int selStart, int selEnd, String wordSeparators) {
if (selStart == selEnd) { if (selStart == selEnd) {
// There is just a cursor, so get the word at the cursor // There is just a cursor, so get the word at the cursor
EditingUtil.Range range = new EditingUtil.Range(); EditingUtils.Range range = getWordRangeAtCursor(ic, wordSeparators);
CharSequence touching = getWordAtCursor(ic, wordSeparators, range); if (range != null && !TextUtils.isEmpty(range.mWord)) {
if (!TextUtils.isEmpty(touching)) { return new SelectedWord(selStart - range.mCharsBefore, selEnd + range.mCharsAfter,
SelectedWord selWord = new SelectedWord(); range.mWord);
selWord.word = touching;
selWord.start = selStart - range.charsBefore;
selWord.end = selEnd + range.charsAfter;
return selWord;
} }
} else { } else {
// Is the previous character empty or a word separator? If not, return null. // Is the previous character empty or a word separator? If not, return null.
@ -256,11 +251,7 @@ public class EditingUtil {
} }
} }
// Prepare the selected word // Prepare the selected word
SelectedWord selWord = new SelectedWord(); return new SelectedWord(selStart, selEnd, touching);
selWord.start = selStart;
selWord.end = selEnd;
selWord.word = touching;
return selWord;
} }
return null; return null;
} }
@ -324,7 +315,7 @@ public class EditingUtil {
} }
if (sMethodSetComposingRegion != null) { if (sMethodSetComposingRegion != null) {
try { try {
sMethodSetComposingRegion.invoke(ic, word.start, word.end); sMethodSetComposingRegion.invoke(ic, word.mStart, word.mEnd);
} catch (InvocationTargetException exc) { } catch (InvocationTargetException exc) {
// Ignore // Ignore
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {

View File

@ -49,53 +49,65 @@ public class ExpandableDictionary extends Dictionary {
// Use this lock before touching mUpdatingDictionary & mRequiresDownload // Use this lock before touching mUpdatingDictionary & mRequiresDownload
private Object mUpdatingLock = new Object(); private Object mUpdatingLock = new Object();
static class Node { private static class Node {
char code; char mCode;
int frequency; int mFrequency;
boolean terminal; boolean mTerminal;
Node parent; Node mParent;
NodeArray children; NodeArray mChildren;
LinkedList<NextWord> ngrams; // Supports ngram LinkedList<NextWord> mNGrams; // Supports ngram
} }
static class NodeArray { private static class NodeArray {
Node[] data; Node[] mData;
int length = 0; int mLength = 0;
private static final int INCREMENT = 2; private static final int INCREMENT = 2;
NodeArray() { NodeArray() {
data = new Node[INCREMENT]; mData = new Node[INCREMENT];
} }
void add(Node n) { void add(Node n) {
if (length + 1 > data.length) { if (mLength + 1 > mData.length) {
Node[] tempData = new Node[length + INCREMENT]; Node[] tempData = new Node[mLength + INCREMENT];
if (length > 0) { if (mLength > 0) {
System.arraycopy(data, 0, tempData, 0, length); System.arraycopy(mData, 0, tempData, 0, mLength);
} }
data = tempData; mData = tempData;
} }
data[length++] = n; mData[mLength++] = n;
} }
} }
static class NextWord { private static class NextWord {
Node word; public final Node mWord;
NextWord nextWord; private int mFrequency;
int frequency;
NextWord(Node word, int frequency) { public NextWord(Node word, int frequency) {
this.word = word; mWord = word;
this.frequency = frequency; mFrequency = frequency;
}
public int getFrequency() {
return mFrequency;
}
public int setFrequency(int freq) {
mFrequency = freq;
return mFrequency;
}
public int addFrequency(int add) {
mFrequency += add;
return mFrequency;
} }
} }
private NodeArray mRoots; private NodeArray mRoots;
private int[][] mCodes; private int[][] mCodes;
ExpandableDictionary(Context context, int dicTypeId) { public ExpandableDictionary(Context context, int dicTypeId) {
mContext = context; mContext = context;
clearDictionary(); clearDictionary();
mCodes = new int[MAX_WORD_LENGTH][]; mCodes = new int[MAX_WORD_LENGTH][];
@ -128,13 +140,14 @@ public class ExpandableDictionary extends Dictionary {
/** Override to load your dictionary here, on a background thread. */ /** Override to load your dictionary here, on a background thread. */
public void loadDictionaryAsync() { public void loadDictionaryAsync() {
// empty base implementation
} }
Context getContext() { public Context getContext() {
return mContext; return mContext;
} }
int getMaxWordLength() { public int getMaxWordLength() {
return MAX_WORD_LENGTH; return MAX_WORD_LENGTH;
} }
@ -147,33 +160,33 @@ public class ExpandableDictionary extends Dictionary {
final int wordLength = word.length(); final int wordLength = word.length();
final char c = word.charAt(depth); final char c = word.charAt(depth);
// Does children have the current character? // Does children have the current character?
final int childrenLength = children.length; final int childrenLength = children.mLength;
Node childNode = null; Node childNode = null;
boolean found = false; boolean found = false;
for (int i = 0; i < childrenLength; i++) { for (int i = 0; i < childrenLength; i++) {
childNode = children.data[i]; childNode = children.mData[i];
if (childNode.code == c) { if (childNode.mCode == c) {
found = true; found = true;
break; break;
} }
} }
if (!found) { if (!found) {
childNode = new Node(); childNode = new Node();
childNode.code = c; childNode.mCode = c;
childNode.parent = parentNode; childNode.mParent = parentNode;
children.add(childNode); children.add(childNode);
} }
if (wordLength == depth + 1) { if (wordLength == depth + 1) {
// Terminate this word // Terminate this word
childNode.terminal = true; childNode.mTerminal = true;
childNode.frequency = Math.max(frequency, childNode.frequency); childNode.mFrequency = Math.max(frequency, childNode.mFrequency);
if (childNode.frequency > 255) childNode.frequency = 255; if (childNode.mFrequency > 255) childNode.mFrequency = 255;
return; return;
} }
if (childNode.children == null) { if (childNode.mChildren == null) {
childNode.children = new NodeArray(); childNode.mChildren = new NodeArray();
} }
addWordRec(childNode.children, word, depth + 1, frequency, childNode); addWordRec(childNode.mChildren, word, depth + 1, frequency, childNode);
} }
@Override @Override
@ -216,7 +229,7 @@ public class ExpandableDictionary extends Dictionary {
*/ */
public int getWordFrequency(CharSequence word) { public int getWordFrequency(CharSequence word) {
Node node = searchNode(mRoots, word, 0, word.length()); Node node = searchNode(mRoots, word, 0, word.length());
return (node == null) ? -1 : node.frequency; return (node == null) ? -1 : node.mFrequency;
} }
/** /**
@ -241,7 +254,7 @@ public class ExpandableDictionary extends Dictionary {
protected void getWordsRec(NodeArray roots, final WordComposer codes, final char[] word, protected void getWordsRec(NodeArray roots, final WordComposer codes, final char[] word,
final int depth, boolean completion, int snr, int inputIndex, int skipPos, final int depth, boolean completion, int snr, int inputIndex, int skipPos,
WordCallback callback) { WordCallback callback) {
final int count = roots.length; final int count = roots.mLength;
final int codeSize = mInputLength; final int codeSize = mInputLength;
// Optimization: Prune out words that are too long compared to how much was typed. // Optimization: Prune out words that are too long compared to how much was typed.
if (depth > mMaxDepth) { if (depth > mMaxDepth) {
@ -255,12 +268,12 @@ public class ExpandableDictionary extends Dictionary {
} }
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
final Node node = roots.data[i]; final Node node = roots.mData[i];
final char c = node.code; final char c = node.mCode;
final char lowerC = toLowerCase(c); final char lowerC = toLowerCase(c);
final boolean terminal = node.terminal; final boolean terminal = node.mTerminal;
final NodeArray children = node.children; final NodeArray children = node.mChildren;
final int freq = node.frequency; final int freq = node.mFrequency;
if (completion) { if (completion) {
word[depth] = c; word[depth] = c;
if (terminal) { if (terminal) {
@ -340,24 +353,22 @@ public class ExpandableDictionary extends Dictionary {
private int addOrSetBigram(String word1, String word2, int frequency, boolean addFrequency) { private int addOrSetBigram(String word1, String word2, int frequency, boolean addFrequency) {
Node firstWord = searchWord(mRoots, word1, 0, null); Node firstWord = searchWord(mRoots, word1, 0, null);
Node secondWord = searchWord(mRoots, word2, 0, null); Node secondWord = searchWord(mRoots, word2, 0, null);
LinkedList<NextWord> bigram = firstWord.ngrams; LinkedList<NextWord> bigram = firstWord.mNGrams;
if (bigram == null || bigram.size() == 0) { if (bigram == null || bigram.size() == 0) {
firstWord.ngrams = new LinkedList<NextWord>(); firstWord.mNGrams = new LinkedList<NextWord>();
bigram = firstWord.ngrams; bigram = firstWord.mNGrams;
} else { } else {
for (NextWord nw : bigram) { for (NextWord nw : bigram) {
if (nw.word == secondWord) { if (nw.mWord == secondWord) {
if (addFrequency) { if (addFrequency) {
nw.frequency += frequency; return nw.addFrequency(frequency);
} else { } else {
nw.frequency = frequency; return nw.setFrequency(frequency);
} }
return nw.frequency;
} }
} }
} }
NextWord nw = new NextWord(secondWord, frequency); firstWord.mNGrams.add(new NextWord(secondWord, frequency));
firstWord.ngrams.add(nw);
return frequency; return frequency;
} }
@ -369,31 +380,31 @@ public class ExpandableDictionary extends Dictionary {
final int wordLength = word.length(); final int wordLength = word.length();
final char c = word.charAt(depth); final char c = word.charAt(depth);
// Does children have the current character? // Does children have the current character?
final int childrenLength = children.length; final int childrenLength = children.mLength;
Node childNode = null; Node childNode = null;
boolean found = false; boolean found = false;
for (int i = 0; i < childrenLength; i++) { for (int i = 0; i < childrenLength; i++) {
childNode = children.data[i]; childNode = children.mData[i];
if (childNode.code == c) { if (childNode.mCode == c) {
found = true; found = true;
break; break;
} }
} }
if (!found) { if (!found) {
childNode = new Node(); childNode = new Node();
childNode.code = c; childNode.mCode = c;
childNode.parent = parentNode; childNode.mParent = parentNode;
children.add(childNode); children.add(childNode);
} }
if (wordLength == depth + 1) { if (wordLength == depth + 1) {
// Terminate this word // Terminate this word
childNode.terminal = true; childNode.mTerminal = true;
return childNode; return childNode;
} }
if (childNode.children == null) { if (childNode.mChildren == null) {
childNode.children = new NodeArray(); childNode.mChildren = new NodeArray();
} }
return searchWord(childNode.children, word, depth + 1, childNode); return searchWord(childNode.mChildren, word, depth + 1, childNode);
} }
// @VisibleForTesting // @VisibleForTesting
@ -408,8 +419,8 @@ public class ExpandableDictionary extends Dictionary {
private void runReverseLookUp(final CharSequence previousWord, final WordCallback callback) { private void runReverseLookUp(final CharSequence previousWord, final WordCallback callback) {
Node prevWord = searchNode(mRoots, previousWord, 0, previousWord.length()); Node prevWord = searchNode(mRoots, previousWord, 0, previousWord.length());
if (prevWord != null && prevWord.ngrams != null) { if (prevWord != null && prevWord.mNGrams != null) {
reverseLookUp(prevWord.ngrams, callback); reverseLookUp(prevWord.mNGrams, callback);
} }
} }
@ -430,6 +441,7 @@ public class ExpandableDictionary extends Dictionary {
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
//
} }
} }
} }
@ -444,14 +456,14 @@ public class ExpandableDictionary extends Dictionary {
Node node; Node node;
int freq; int freq;
for (NextWord nextWord : terminalNodes) { for (NextWord nextWord : terminalNodes) {
node = nextWord.word; node = nextWord.mWord;
freq = nextWord.frequency; freq = nextWord.getFrequency();
// TODO Not the best way to limit suggestion threshold // TODO Not the best way to limit suggestion threshold
if (freq >= UserBigramDictionary.SUGGEST_THRESHOLD) { if (freq >= UserBigramDictionary.SUGGEST_THRESHOLD) {
sb.setLength(0); sb.setLength(0);
do { do {
sb.insert(0, node.code); sb.insert(0, node.mCode);
node = node.parent; node = node.mParent;
} while(node != null); } while(node != null);
// TODO better way to feed char array? // TODO better way to feed char array?
@ -468,18 +480,18 @@ public class ExpandableDictionary extends Dictionary {
private Node searchNode(final NodeArray children, final CharSequence word, final int offset, private Node searchNode(final NodeArray children, final CharSequence word, final int offset,
final int length) { final int length) {
// TODO Consider combining with addWordRec // TODO Consider combining with addWordRec
final int count = children.length; final int count = children.mLength;
char currentChar = word.charAt(offset); char currentChar = word.charAt(offset);
for (int j = 0; j < count; j++) { for (int j = 0; j < count; j++) {
final Node node = children.data[j]; final Node node = children.mData[j];
if (node.code == currentChar) { if (node.mCode == currentChar) {
if (offset == length - 1) { if (offset == length - 1) {
if (node.terminal) { if (node.mTerminal) {
return node; return node;
} }
} else { } else {
if (node.children != null) { if (node.mChildren != null) {
Node returnNode = searchNode(node.children, word, offset + 1, length); Node returnNode = searchNode(node.mChildren, word, offset + 1, length);
if (returnNode != null) return returnNode; if (returnNode != null) return returnNode;
} }
} }
@ -504,15 +516,16 @@ public class ExpandableDictionary extends Dictionary {
} }
static char toLowerCase(char c) { static char toLowerCase(char c) {
char baseChar = c;
if (c < BASE_CHARS.length) { if (c < BASE_CHARS.length) {
c = BASE_CHARS[c]; baseChar = BASE_CHARS[c];
} }
if (c >= 'A' && c <= 'Z') { if (baseChar >= 'A' && baseChar <= 'Z') {
c = (char) (c | 32); return (char)(baseChar | 32);
} else if (c > 127) { } else if (baseChar > 127) {
c = Character.toLowerCase(c); return Character.toLowerCase(baseChar);
} }
return c; return baseChar;
} }
/** /**

View File

@ -42,24 +42,28 @@ public class InputLanguageSelection extends PreferenceActivity {
}; };
private static class Loc implements Comparable<Object> { private static class Loc implements Comparable<Object> {
static Collator sCollator = Collator.getInstance(); private static Collator sCollator = Collator.getInstance();
String label; private String mLabel;
Locale locale; public final Locale mLocale;
public Loc(String label, Locale locale) { public Loc(String label, Locale locale) {
this.label = label; this.mLabel = label;
this.locale = locale; this.mLocale = locale;
}
public void setLabel(String label) {
this.mLabel = label;
} }
@Override @Override
public String toString() { public String toString() {
return this.label; return this.mLabel;
} }
@Override @Override
public int compareTo(Object o) { public int compareTo(Object o) {
return sCollator.compare(this.label, ((Loc) o).label); return sCollator.compare(this.mLabel, ((Loc) o).mLabel);
} }
} }
@ -75,7 +79,7 @@ public class InputLanguageSelection extends PreferenceActivity {
PreferenceGroup parent = getPreferenceScreen(); PreferenceGroup parent = getPreferenceScreen();
for (int i = 0; i < mAvailableLanguages.size(); i++) { for (int i = 0; i < mAvailableLanguages.size(); i++) {
CheckBoxPreference pref = new CheckBoxPreference(this); CheckBoxPreference pref = new CheckBoxPreference(this);
Locale locale = mAvailableLanguages.get(i).locale; Locale locale = mAvailableLanguages.get(i).mLocale;
pref.setTitle(SubtypeSwitcher.getFullDisplayName(locale, true)); pref.setTitle(SubtypeSwitcher.getFullDisplayName(locale, true));
boolean checked = isLocaleIn(locale, languageList); boolean checked = isLocaleIn(locale, languageList);
pref.setChecked(checked); pref.setChecked(checked);
@ -137,7 +141,7 @@ public class InputLanguageSelection extends PreferenceActivity {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
CheckBoxPreference pref = (CheckBoxPreference) parent.getPreference(i); CheckBoxPreference pref = (CheckBoxPreference) parent.getPreference(i);
if (pref.isChecked()) { if (pref.isChecked()) {
Locale locale = mAvailableLanguages.get(i).locale; Locale locale = mAvailableLanguages.get(i).mLocale;
checkedLanguages += get5Code(locale) + ","; checkedLanguages += get5Code(locale) + ",";
} }
} }
@ -147,7 +151,7 @@ public class InputLanguageSelection extends PreferenceActivity {
SharedPreferencesCompat.apply(editor); SharedPreferencesCompat.apply(editor);
} }
ArrayList<Loc> getUniqueLocales() { public ArrayList<Loc> getUniqueLocales() {
String[] locales = getAssets().getLocales(); String[] locales = getAssets().getLocales();
Arrays.sort(locales); Arrays.sort(locales);
ArrayList<Loc> uniqueLocales = new ArrayList<Loc>(); ArrayList<Loc> uniqueLocales = new ArrayList<Loc>();
@ -174,15 +178,16 @@ public class InputLanguageSelection extends PreferenceActivity {
// same lang and a country -> upgrade to full name and // same lang and a country -> upgrade to full name and
// insert ours with full name // insert ours with full name
// diff lang -> insert ours with lang-only name // diff lang -> insert ours with lang-only name
if (preprocess[finalSize-1].locale.getLanguage().equals( if (preprocess[finalSize-1].mLocale.getLanguage().equals(
language)) { language)) {
preprocess[finalSize-1].label = SubtypeSwitcher.getFullDisplayName( preprocess[finalSize-1].setLabel(SubtypeSwitcher.getFullDisplayName(
preprocess[finalSize-1].locale, false); preprocess[finalSize-1].mLocale, false));
preprocess[finalSize++] = preprocess[finalSize++] =
new Loc(SubtypeSwitcher.getFullDisplayName(l, false), l); new Loc(SubtypeSwitcher.getFullDisplayName(l, false), l);
} else { } else {
String displayName; String displayName;
if (s.equals("zz_ZZ")) { if (s.equals("zz_ZZ")) {
// ignore this locale
} else { } else {
displayName = SubtypeSwitcher.getFullDisplayName(l, true); displayName = SubtypeSwitcher.getFullDisplayName(l, true);
preprocess[finalSize++] = new Loc(displayName, l); preprocess[finalSize++] = new Loc(displayName, l);

View File

@ -25,6 +25,7 @@ import com.android.inputmethod.keyboard.LatinKeyboardView;
import com.android.inputmethod.latin.Utils.RingCharBuffer; import com.android.inputmethod.latin.Utils.RingCharBuffer;
import com.android.inputmethod.voice.VoiceIMEConnector; import com.android.inputmethod.voice.VoiceIMEConnector;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import android.app.AlertDialog; import android.app.AlertDialog;
@ -46,6 +47,7 @@ import android.os.SystemClock;
import android.os.Vibrator; import android.os.Vibrator;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.InputType;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
@ -82,7 +84,7 @@ import java.util.Locale;
* Input method implementation for Qwerty'ish keyboard. * Input method implementation for Qwerty'ish keyboard.
*/ */
public class LatinIME extends InputMethodService implements KeyboardActionListener, public class LatinIME extends InputMethodService implements KeyboardActionListener,
SharedPreferences.OnSharedPreferenceChangeListener, Tutorial.TutorialListener { SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "LatinIME"; private static final String TAG = "LatinIME";
private static final boolean PERF_DEBUG = false; private static final boolean PERF_DEBUG = false;
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
@ -91,7 +93,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private static final int DELAY_UPDATE_SUGGESTIONS = 180; private static final int DELAY_UPDATE_SUGGESTIONS = 180;
private static final int DELAY_UPDATE_OLD_SUGGESTIONS = 300; private static final int DELAY_UPDATE_OLD_SUGGESTIONS = 300;
private static final int DELAY_UPDATE_SHIFT_STATE = 300; private static final int DELAY_UPDATE_SHIFT_STATE = 300;
private static final int DELAY_START_TUTORIAL = 500;
// How many continuous deletes at which to start deleting at a higher speed. // How many continuous deletes at which to start deleting at a higher speed.
private static final int DELETE_ACCELERATE_AT = 20; private static final int DELETE_ACCELERATE_AT = 20;
@ -172,8 +173,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private int mDeleteCount; private int mDeleteCount;
private long mLastKeyTime; private long mLastKeyTime;
private Tutorial mTutorial;
private AudioManager mAudioManager; private AudioManager mAudioManager;
// Align sound effect volume on music volume // Align sound effect volume on music volume
private static final float FX_VOLUME = -1.0f; private static final float FX_VOLUME = -1.0f;
@ -246,7 +245,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1; private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1;
private static final int MSG_UPDATE_SHIFT_STATE = 2; private static final int MSG_UPDATE_SHIFT_STATE = 2;
private static final int MSG_VOICE_RESULTS = 3; private static final int MSG_VOICE_RESULTS = 3;
private static final int MSG_START_TUTORIAL = 4;
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
@ -261,21 +259,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mKeyboardSwitcher.updateShiftState(); mKeyboardSwitcher.updateShiftState();
break; break;
case MSG_VOICE_RESULTS: case MSG_VOICE_RESULTS:
mVoiceConnector.handleVoiceResults(mKeyboardSwitcher, preferCapitalization() mVoiceConnector.handleVoiceResults(preferCapitalization()
|| (mKeyboardSwitcher.isAlphabetMode() || (mKeyboardSwitcher.isAlphabetMode()
&& mKeyboardSwitcher.isShiftedOrShiftLocked())); && mKeyboardSwitcher.isShiftedOrShiftLocked()));
break; break;
case MSG_START_TUTORIAL:
if (mTutorial == null) {
if (mKeyboardSwitcher.isInputViewShown()) {
mTutorial = new Tutorial(LatinIME.this, mKeyboardSwitcher);
mTutorial.start();
} else {
// Try again soon if the view is not yet showing
sendMessageDelayed(obtainMessage(MSG_START_TUTORIAL), 100);
}
}
break;
} }
} }
@ -314,10 +301,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void updateVoiceResults() { public void updateVoiceResults() {
sendMessage(obtainMessage(MSG_VOICE_RESULTS)); sendMessage(obtainMessage(MSG_VOICE_RESULTS));
} }
public void startTutorial() {
sendMessageDelayed(obtainMessage(MSG_START_TUTORIAL), DELAY_START_TUTORIAL);
}
} }
@Override @Override
@ -369,8 +352,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
try { try {
int current = xrp.getEventType(); int current = xrp.getEventType();
while (current != XmlResourceParser.END_DOCUMENT) { while (current != XmlPullParser.END_DOCUMENT) {
if (current == XmlResourceParser.START_TAG) { if (current == XmlPullParser.START_TAG) {
String tag = xrp.getName(); String tag = xrp.getName();
if (tag != null) { if (tag != null) {
if (tag.equals("part")) { if (tag.equals("part")) {
@ -501,14 +484,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
private static boolean isPasswordVariation(int variation) { private static boolean isPasswordVariation(int variation) {
return variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD return variation == InputType.TYPE_TEXT_VARIATION_PASSWORD
|| variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD || variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|| variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD; || variation == InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD;
} }
private static boolean isEmailVariation(int variation) { private static boolean isEmailVariation(int variation) {
return variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS return variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|| variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS; || variation == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
} }
@Override @Override
@ -533,7 +516,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Most such things we decide below in the switch statement, but we need to know // 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 // 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. // the switch statement) whether we want to enable the voice button.
int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION; int variation = attribute.inputType & InputType.TYPE_MASK_VARIATION;
mVoiceConnector.resetVoiceStates(isPasswordVariation(variation)); mVoiceConnector.resetVoiceStates(isPasswordVariation(variation));
mInputTypeNoAutoCorrect = false; mInputTypeNoAutoCorrect = false;
mPredictionOn = false; mPredictionOn = false;
@ -542,15 +525,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mEnteredText = null; mEnteredText = null;
final int mode; final int mode;
switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) { switch (attribute.inputType & InputType.TYPE_MASK_CLASS) {
case EditorInfo.TYPE_CLASS_NUMBER: case InputType.TYPE_CLASS_NUMBER:
case EditorInfo.TYPE_CLASS_DATETIME: case InputType.TYPE_CLASS_DATETIME:
mode = KeyboardId.MODE_NUMBER; mode = KeyboardId.MODE_NUMBER;
break; break;
case EditorInfo.TYPE_CLASS_PHONE: case InputType.TYPE_CLASS_PHONE:
mode = KeyboardId.MODE_PHONE; mode = KeyboardId.MODE_PHONE;
break; break;
case EditorInfo.TYPE_CLASS_TEXT: case InputType.TYPE_CLASS_TEXT:
//startPrediction(); //startPrediction();
mPredictionOn = true; mPredictionOn = true;
// Make sure that passwords are not displayed in candidate view // Make sure that passwords are not displayed in candidate view
@ -558,7 +541,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mPredictionOn = false; mPredictionOn = false;
} }
if (isEmailVariation(variation) if (isEmailVariation(variation)
|| variation == EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME) { || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) {
mAutoSpace = false; mAutoSpace = false;
} else { } else {
mAutoSpace = true; mAutoSpace = true;
@ -566,19 +549,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (isEmailVariation(variation)) { if (isEmailVariation(variation)) {
mPredictionOn = false; mPredictionOn = false;
mode = KeyboardId.MODE_EMAIL; mode = KeyboardId.MODE_EMAIL;
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) { } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) {
mPredictionOn = false; mPredictionOn = false;
mode = KeyboardId.MODE_URL; mode = KeyboardId.MODE_URL;
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) { } else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
mode = KeyboardId.MODE_IM; mode = KeyboardId.MODE_IM;
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) { } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
mPredictionOn = false; mPredictionOn = false;
mode = KeyboardId.MODE_TEXT; mode = KeyboardId.MODE_TEXT;
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) {
mode = KeyboardId.MODE_WEB; mode = KeyboardId.MODE_WEB;
// If it's a browser edit field and auto correct is not ON explicitly, then // If it's a browser edit field and auto correct is not ON explicitly, then
// disable auto correction, but keep suggestions on. // disable auto correction, but keep suggestions on.
if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
mInputTypeNoAutoCorrect = true; mInputTypeNoAutoCorrect = true;
} }
} else { } else {
@ -586,16 +569,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
// If NO_SUGGESTIONS is set, don't do prediction. // If NO_SUGGESTIONS is set, don't do prediction.
if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) {
mPredictionOn = false; mPredictionOn = false;
mInputTypeNoAutoCorrect = true; mInputTypeNoAutoCorrect = true;
} }
// If it's not multiline and the autoCorrect flag is not set, then don't correct // 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 && if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 &&
(attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { (attribute.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) {
mInputTypeNoAutoCorrect = true; mInputTypeNoAutoCorrect = true;
} }
if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
mPredictionOn = false; mPredictionOn = false;
mCompletionOn = isFullscreenMode(); mCompletionOn = isFullscreenMode();
} }
@ -632,7 +615,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mPredictionOn = mPredictionOn && (mCorrectionMode > 0 || isSuggestionShown()); mPredictionOn = mPredictionOn && (mCorrectionMode > 0 || isSuggestionShown());
// If we just entered a text field, maybe it has some old text that requires correction // If we just entered a text field, maybe it has some old text that requires correction
checkReCorrectionOnStart(); checkReCorrectionOnStart();
checkTutorial(attribute.privateImeOptions);
inputView.setForeground(true); inputView.setForeground(true);
mVoiceConnector.onStartInputView(mKeyboardSwitcher.getInputView().getWindowToken()); mVoiceConnector.onStartInputView(mKeyboardSwitcher.getInputView().getWindowToken());
@ -733,12 +715,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mVoiceConnector.setVoiceInputHighlighted(false); mVoiceConnector.setVoiceInputHighlighted(false);
} else if (!mPredicting && !mJustAccepted) { } else if (!mPredicting && !mJustAccepted) {
switch (TextEntryState.getState()) { switch (TextEntryState.getState()) {
case ACCEPTED_DEFAULT: case ACCEPTED_DEFAULT:
TextEntryState.reset(); TextEntryState.reset();
// fall through // $FALL-THROUGH$
case SPACE_AFTER_PICKED: case SPACE_AFTER_PICKED:
mJustAddedAutoSpace = false; // The user moved the cursor. mJustAddedAutoSpace = false; // The user moved the cursor.
break; break;
default:
break;
} }
} }
mJustAccepted = false; mJustAccepted = false;
@ -835,7 +819,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
List<CharSequence> stringList = new ArrayList<CharSequence>(); List<CharSequence> stringList = new ArrayList<CharSequence>();
for (int i=0; i<(completions != null ? completions.length : 0); i++) { for (int i = 0; i < completions.length; i++) {
CompletionInfo ci = completions[i]; CompletionInfo ci = completions[i];
if (ci != null) stringList.add(ci.getText()); if (ci != null) stringList.add(ci.getText());
} }
@ -883,25 +867,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override @Override
public boolean onKeyDown(int keyCode, KeyEvent event) { public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) { switch (keyCode) {
case KeyEvent.KEYCODE_BACK: case KeyEvent.KEYCODE_BACK:
if (event.getRepeatCount() == 0 && mKeyboardSwitcher.getInputView() != null) { if (event.getRepeatCount() == 0 && mKeyboardSwitcher.getInputView() != null) {
if (mKeyboardSwitcher.getInputView().handleBack()) { if (mKeyboardSwitcher.getInputView().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; return true;
} }
break; }
break;
} }
return super.onKeyDown(keyCode, event); return super.onKeyDown(keyCode, event);
} }
@ -909,26 +881,23 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override @Override
public boolean onKeyUp(int keyCode, KeyEvent event) { public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) { switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_DOWN: case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_UP: case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_LEFT: case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT: case KeyEvent.KEYCODE_DPAD_RIGHT:
// If tutorial is visible, don't allow dpad to work // Enable shift key and DPAD to do selections
if (mTutorial != null) { if (mKeyboardSwitcher.isInputViewShown()
return true; && mKeyboardSwitcher.isShiftedOrShiftLocked()) {
} KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(),
// Enable shift key and DPAD to do selections event.getAction(), event.getKeyCode(), event.getRepeatCount(),
if (mKeyboardSwitcher.isInputViewShown() event.getDeviceId(), event.getScanCode(),
&& mKeyboardSwitcher.isShiftedOrShiftLocked()) { KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON);
event = new KeyEvent(event.getDownTime(), event.getEventTime(), InputConnection ic = getCurrentInputConnection();
event.getAction(), event.getKeyCode(), event.getRepeatCount(), if (ic != null)
event.getDeviceId(), event.getScanCode(), ic.sendKeyEvent(newEvent);
KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); return true;
InputConnection ic = getCurrentInputConnection(); }
if (ic != null) ic.sendKeyEvent(event); break;
return true;
}
break;
} }
return super.onKeyUp(keyCode, event); return super.onKeyUp(keyCode, event);
} }
@ -951,7 +920,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public boolean getCurrentAutoCapsState() { public boolean getCurrentAutoCapsState() {
InputConnection ic = getCurrentInputConnection(); InputConnection ic = getCurrentInputConnection();
EditorInfo ei = getCurrentInputEditorInfo(); EditorInfo ei = getCurrentInputEditorInfo();
if (mAutoCap && ic != null && ei != null && ei.inputType != EditorInfo.TYPE_NULL) { if (mAutoCap && ic != null && ei != null && ei.inputType != InputType.TYPE_NULL) {
return ic.getCursorCapsMode(ei.inputType) != 0; return ic.getCursorCapsMode(ei.inputType) != 0;
} }
return false; return false;
@ -1262,7 +1231,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
abortCorrection(false); abortCorrection(false);
} }
if (isAlphabet(primaryCode) && isPredictionOn() && !isCursorTouchingWord()) { int code = primaryCode;
if (isAlphabet(code) && isPredictionOn() && !isCursorTouchingWord()) {
if (!mPredicting) { if (!mPredicting) {
mPredicting = true; mPredicting = true;
mComposing.setLength(0); mComposing.setLength(0);
@ -1276,14 +1246,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|| keyCodes[0] > Character.MAX_CODE_POINT) { || keyCodes[0] > Character.MAX_CODE_POINT) {
return; return;
} }
primaryCode = keyCodes[0]; code = keyCodes[0];
if (switcher.isAlphabetMode() && Character.isLowerCase(primaryCode)) { if (switcher.isAlphabetMode() && Character.isLowerCase(code)) {
int upperCaseCode = Character.toUpperCase(primaryCode); int upperCaseCode = Character.toUpperCase(code);
if (upperCaseCode != primaryCode) { if (upperCaseCode != code) {
primaryCode = upperCaseCode; code = upperCaseCode;
} else { } else {
// Some keys, such as [eszett], have upper case as multi-characters. // Some keys, such as [eszett], have upper case as multi-characters.
String upperCase = new String(new int[] {primaryCode}, 0, 1).toUpperCase(); String upperCase = new String(new int[] {code}, 0, 1).toUpperCase();
onText(upperCase); onText(upperCase);
return; return;
} }
@ -1294,8 +1264,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
&& switcher.isShiftedOrShiftLocked()) { && switcher.isShiftedOrShiftLocked()) {
mWord.setFirstCharCapitalized(true); mWord.setFirstCharCapitalized(true);
} }
mComposing.append((char) primaryCode); mComposing.append((char) code);
mWord.add(primaryCode, keyCodes); mWord.add(code, keyCodes);
InputConnection ic = getCurrentInputConnection(); InputConnection ic = getCurrentInputConnection();
if (ic != null) { if (ic != null) {
// If it's the first letter, make note of auto-caps state // If it's the first letter, make note of auto-caps state
@ -1306,11 +1276,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
mHandler.postUpdateSuggestions(); mHandler.postUpdateSuggestions();
} else { } else {
sendKeyChar((char)primaryCode); sendKeyChar((char)code);
} }
switcher.updateShiftState(); switcher.updateShiftState();
if (LatinIME.PERF_DEBUG) measureCps(); if (LatinIME.PERF_DEBUG) measureCps();
TextEntryState.typedCharacter((char) primaryCode, isWordSeparator(primaryCode)); TextEntryState.typedCharacter((char) code, isWordSeparator(code));
} }
private void handleSeparator(int primaryCode) { private void handleSeparator(int primaryCode) {
@ -1502,7 +1472,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void showSuggestions(WordComposer word) { private void showSuggestions(WordComposer word) {
// long startTime = System.currentTimeMillis(); // TIME MEASUREMENT! // long startTime = System.currentTimeMillis(); // TIME MEASUREMENT!
// TODO Maybe need better way of retrieving previous word // TODO Maybe need better way of retrieving previous word
CharSequence prevWord = EditingUtil.getPreviousWord(getCurrentInputConnection(), CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(),
mWordSeparators); mWordSeparators);
List<CharSequence> stringList = mSuggest.getSuggestions( List<CharSequence> stringList = mSuggest.getSuggestions(
mKeyboardSwitcher.getInputView(), word, false, prevWord); mKeyboardSwitcher.getInputView(), word, false, prevWord);
@ -1672,12 +1642,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
* @param touching The word that the cursor is touching, with position information * @param touching The word that the cursor is touching, with position information
* @return true if an alternative was found, false otherwise. * @return true if an alternative was found, false otherwise.
*/ */
private boolean applyTypedAlternatives(EditingUtil.SelectedWord touching) { private boolean applyTypedAlternatives(EditingUtils.SelectedWord touching) {
// If we didn't find a match, search for result in typed word history // If we didn't find a match, search for result in typed word history
WordComposer foundWord = null; WordComposer foundWord = null;
WordAlternatives alternatives = null; WordAlternatives alternatives = null;
for (WordAlternatives entry : mWordHistory) { for (WordAlternatives entry : mWordHistory) {
if (TextUtils.equals(entry.getChosenWord(), touching.word)) { if (TextUtils.equals(entry.getChosenWord(), touching.mWord)) {
if (entry instanceof TypedWordAlternatives) { if (entry instanceof TypedWordAlternatives) {
foundWord = ((TypedWordAlternatives) entry).word; foundWord = ((TypedWordAlternatives) entry).word;
} }
@ -1687,20 +1657,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
// If we didn't find a match, at least suggest completions // If we didn't find a match, at least suggest completions
if (foundWord == null if (foundWord == null
&& (mSuggest.isValidWord(touching.word) && (mSuggest.isValidWord(touching.mWord)
|| mSuggest.isValidWord(touching.word.toString().toLowerCase()))) { || mSuggest.isValidWord(touching.mWord.toString().toLowerCase()))) {
foundWord = new WordComposer(); foundWord = new WordComposer();
for (int i = 0; i < touching.word.length(); i++) { for (int i = 0; i < touching.mWord.length(); i++) {
foundWord.add(touching.word.charAt(i), new int[] { foundWord.add(touching.mWord.charAt(i), new int[] {
touching.word.charAt(i) touching.mWord.charAt(i)
}); });
} }
foundWord.setFirstCharCapitalized(Character.isUpperCase(touching.word.charAt(0))); foundWord.setFirstCharCapitalized(Character.isUpperCase(touching.mWord.charAt(0)));
} }
// Found a match, show suggestions // Found a match, show suggestions
if (foundWord != null || alternatives != null) { if (foundWord != null || alternatives != null) {
if (alternatives == null) { if (alternatives == null) {
alternatives = new TypedWordAlternatives(touching.word, foundWord); alternatives = new TypedWordAlternatives(touching.mWord, foundWord);
} }
showCorrections(alternatives); showCorrections(alternatives);
if (foundWord != null) { if (foundWord != null) {
@ -1722,10 +1692,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (ic == null) return; if (ic == null) return;
if (!mPredicting) { if (!mPredicting) {
// Extract the selected or touching text // Extract the selected or touching text
EditingUtil.SelectedWord touching = EditingUtil.getWordAtCursorOrSelection(ic, EditingUtils.SelectedWord touching = EditingUtils.getWordAtCursorOrSelection(ic,
mLastSelectionStart, mLastSelectionEnd, mWordSeparators); mLastSelectionStart, mLastSelectionEnd, mWordSeparators);
if (touching != null && touching.word.length() > 1) { if (touching != null && touching.mWord.length() > 1) {
ic.beginBatchEdit(); ic.beginBatchEdit();
if (!mVoiceConnector.applyVoiceAlternatives(touching) if (!mVoiceConnector.applyVoiceAlternatives(touching)
@ -1733,7 +1703,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
abortCorrection(true); abortCorrection(true);
} else { } else {
TextEntryState.selectedForCorrection(); TextEntryState.selectedForCorrection();
EditingUtil.underlineWord(ic, touching); EditingUtils.underlineWord(ic, touching);
} }
ic.endBatchEdit(); ic.endBatchEdit();
@ -1773,19 +1743,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|| mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) {
return; return;
} }
if (suggestion != null) { if (!addToBigramDictionary && mAutoDictionary.isValidWord(suggestion)
if (!addToBigramDictionary && mAutoDictionary.isValidWord(suggestion) || (!mSuggest.isValidWord(suggestion.toString())
|| (!mSuggest.isValidWord(suggestion.toString()) && !mSuggest.isValidWord(suggestion.toString().toLowerCase()))) {
&& !mSuggest.isValidWord(suggestion.toString().toLowerCase()))) { mAutoDictionary.addWord(suggestion.toString(), frequencyDelta);
mAutoDictionary.addWord(suggestion.toString(), frequencyDelta); }
}
if (mUserBigramDictionary != null) { if (mUserBigramDictionary != null) {
CharSequence prevWord = EditingUtil.getPreviousWord(getCurrentInputConnection(), CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(),
mSentenceSeparators); mSentenceSeparators);
if (!TextUtils.isEmpty(prevWord)) { if (!TextUtils.isEmpty(prevWord)) {
mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString());
}
} }
} }
} }
@ -1896,17 +1864,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override @Override
public void swipeRight() { public void swipeRight() {
if (LatinKeyboardView.DEBUG_AUTO_PLAY) { // Nothing to do
CharSequence text = ((android.text.ClipboardManager)getSystemService(
CLIPBOARD_SERVICE)).getText();
if (!TextUtils.isEmpty(text)) {
mKeyboardSwitcher.getInputView().startPlaying(text.toString());
}
}
} }
@Override @Override
public void swipeLeft() { public void swipeLeft() {
// Nothing to do
} }
@Override @Override
@ -1916,6 +1879,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override @Override
public void swipeUp() { public void swipeUp() {
// Nothing to do
} }
@Override @Override
@ -2004,26 +1968,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
} }
private void checkTutorial(String privateImeOptions) {
if (privateImeOptions == null) return;
if (privateImeOptions.equals("com.android.setupwizard:ShowTutorial")) {
if (mTutorial == null) mHandler.startTutorial();
} else if (privateImeOptions.equals("com.android.setupwizard:HideTutorial")) {
if (mTutorial != null) {
if (mTutorial.close()) {
mTutorial = null;
}
}
}
}
// Tutorial.TutorialListener
@Override
public void onTutorialDone() {
sendDownUpKeyEvents(-1); // Inform the setupwizard that tutorial is in last bubble
mTutorial = null;
}
public void promoteToUserDictionary(String word, int frequency) { public void promoteToUserDictionary(String word, int frequency) {
if (mUserDictionary.isValidWord(word)) return; if (mUserDictionary.isValidWord(word)) return;
mUserDictionary.addWord(word, frequency); mUserDictionary.addWord(word, frequency);

View File

@ -92,6 +92,7 @@ public class SubtypeSwitcher {
} }
private SubtypeSwitcher() { private SubtypeSwitcher() {
// Intentional empty constructor for singleton.
} }
private void resetParams(LatinIME service) { private void resetParams(LatinIME service) {

View File

@ -113,7 +113,7 @@ public class TextEntryState {
sKeyLocationFile = null; sKeyLocationFile = null;
sUserActionFile = null; sUserActionFile = null;
} catch (IOException ioe) { } catch (IOException ioe) {
// ignore
} }
} }
@ -135,16 +135,18 @@ public class TextEntryState {
public static void backToAcceptedDefault(CharSequence typedWord) { public static void backToAcceptedDefault(CharSequence typedWord) {
if (typedWord == null) return; if (typedWord == null) return;
switch (sState) { switch (sState) {
case SPACE_AFTER_ACCEPTED: case SPACE_AFTER_ACCEPTED:
case PUNCTUATION_AFTER_ACCEPTED: case PUNCTUATION_AFTER_ACCEPTED:
case IN_WORD: case IN_WORD:
sState = State.ACCEPTED_DEFAULT; sState = State.ACCEPTED_DEFAULT;
break; break;
default:
break;
} }
displayState(); displayState();
} }
public static void acceptedTyped(CharSequence typedWord) { public static void acceptedTyped(@SuppressWarnings("unused") CharSequence typedWord) {
sWordNotInDictionaryCount++; sWordNotInDictionaryCount++;
sState = State.PICKED_SUGGESTION; sState = State.PICKED_SUGGESTION;
displayState(); displayState();

View File

@ -1,251 +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 com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.LatinKeyboardView;
import android.content.Context;
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;
public class Tutorial implements OnTouchListener {
public interface TutorialListener {
public void onTutorialDone();
}
private final ArrayList<Bubble> mBubbles = new ArrayList<Bubble>();
private final KeyboardSwitcher mKeyboardSwitcher;
private final View mInputView;
private final TutorialListener mListener;
private final int[] mLocation = new int[2];
private static final int MSG_SHOW_BUBBLE = 0;
private int mBubbleIndex;
private final 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;
}
}
};
private class Bubble {
private final Drawable bubbleBackground;
private final int x;
private final int y;
private final int width;
private final int gravity;
private final CharSequence text;
private final PopupWindow window;
private final TextView textView;
private final View inputView;
private 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.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();
}
private 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() {
@Override
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
}
}
}
private void hide() {
if (window.isShowing()) {
textView.setOnTouchListener(null);
window.dismiss();
}
}
private boolean isShowing() {
return window.isShowing();
}
}
public Tutorial(TutorialListener listener, KeyboardSwitcher keyboardSwitcher) {
mListener = listener;
mKeyboardSwitcher = keyboardSwitcher;
LatinKeyboardView inputView = keyboardSwitcher.getInputView();
mInputView = inputView;
Context context = inputView.getContext();
int inputWidth = inputView.getWidth();
final int x = inputWidth / 20; // Half of 1/10th
ArrayList<Bubble> bubbles = mBubbles;
Bubble bWelcome = new Bubble(context, inputView,
R.drawable.dialog_bubble_step02, x, 0,
R.string.tip_to_open_keyboard, R.string.touch_to_continue);
bubbles.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);
bubbles.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);
bubbles.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);
bubbles.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);
bubbles.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);
bubbles.add(bDone);
}
public void start() {
mInputView.getLocationInWindow(mLocation);
mBubbleIndex = -1;
mInputView.setOnTouchListener(this);
next();
}
private void next() {
if (mBubbleIndex >= 0) {
// If the bubble is not yet showing, don't move to the next.
if (!mBubbles.get(mBubbleIndex).isShowing()) {
return;
}
// 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);
mListener.onTutorialDone();
return;
}
if (mBubbleIndex == 3 || mBubbleIndex == 4) {
mKeyboardSwitcher.changeKeyboardMode();
}
mHandler.sendMessageDelayed(
mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(mBubbleIndex)), 500);
return;
}
private void hide() {
for (Bubble bubble : mBubbles) {
bubble.hide();
}
mInputView.setOnTouchListener(null);
}
public boolean close() {
mHandler.removeMessages(MSG_SHOW_BUBBLE);
hide();
return true;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
next();
}
return true;
}
}

View File

@ -108,25 +108,25 @@ public class UserBigramDictionary extends ExpandableDictionary {
private static DatabaseHelper sOpenHelper = null; private static DatabaseHelper sOpenHelper = null;
private static class Bigram { private static class Bigram {
String word1; public final String mWord1;
String word2; public final String mWord2;
int frequency; public final int frequency;
Bigram(String word1, String word2, int frequency) { Bigram(String word1, String word2, int frequency) {
this.word1 = word1; this.mWord1 = word1;
this.word2 = word2; this.mWord2 = word2;
this.frequency = frequency; this.frequency = frequency;
} }
@Override @Override
public boolean equals(Object bigram) { public boolean equals(Object bigram) {
Bigram bigram2 = (Bigram) bigram; Bigram bigram2 = (Bigram) bigram;
return (word1.equals(bigram2.word1) && word2.equals(bigram2.word2)); return (mWord1.equals(bigram2.mWord1) && mWord2.equals(bigram2.mWord2));
} }
@Override @Override
public int hashCode() { public int hashCode() {
return (word1 + " " + word2).hashCode(); return (mWord1 + " " + mWord2).hashCode();
} }
} }
@ -357,7 +357,7 @@ public class UserBigramDictionary extends ExpandableDictionary {
Cursor c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID }, Cursor c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID },
MAIN_COLUMN_WORD1 + "=? AND " + MAIN_COLUMN_WORD2 + "=? AND " MAIN_COLUMN_WORD1 + "=? AND " + MAIN_COLUMN_WORD2 + "=? AND "
+ MAIN_COLUMN_LOCALE + "=?", + MAIN_COLUMN_LOCALE + "=?",
new String[] { bi.word1, bi.word2, mLocale }, null, null, null); new String[] { bi.mWord1, bi.mWord2, mLocale }, null, null, null);
int pairId; int pairId;
if (c.moveToFirst()) { if (c.moveToFirst()) {
@ -368,7 +368,7 @@ public class UserBigramDictionary extends ExpandableDictionary {
} else { } else {
// new pair // new pair
Long pairIdLong = db.insert(MAIN_TABLE_NAME, null, Long pairIdLong = db.insert(MAIN_TABLE_NAME, null,
getContentValues(bi.word1, bi.word2, mLocale)); getContentValues(bi.mWord1, bi.mWord2, mLocale));
pairId = pairIdLong.intValue(); pairId = pairIdLong.intValue();
} }
c.close(); c.close();

View File

@ -66,7 +66,7 @@ public class UserDictionary extends ExpandableDictionary {
@Override @Override
public void loadDictionaryAsync() { public void loadDictionaryAsync() {
Cursor cursor = getContext().getContentResolver() Cursor cursor = getContext().getContentResolver()
.query(Words.CONTENT_URI, PROJECTION, "(locale IS NULL) or (locale=?)", .query(Words.CONTENT_URI, PROJECTION, "(locale IS NULL) or (locale=?)",
new String[] { mLocale }, null); new String[] { mLocale }, null);
addWords(cursor); addWords(cursor);
} }

View File

@ -110,6 +110,7 @@ public class Utils {
private int[] mYBuf = new int[BUFSIZE]; private int[] mYBuf = new int[BUFSIZE];
private RingCharBuffer() { private RingCharBuffer() {
// Intentional empty constructor for singleton.
} }
public static RingCharBuffer getInstance() { public static RingCharBuffer getInstance() {
return sRingCharBuffer; return sRingCharBuffer;
@ -349,6 +350,7 @@ public class Utils {
try { try {
br.close(); br.close();
} catch (IOException e) { } catch (IOException e) {
// ignore.
} }
} }
} }

View File

@ -16,8 +16,7 @@
package com.android.inputmethod.voice; package com.android.inputmethod.voice;
import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.latin.EditingUtils;
import com.android.inputmethod.latin.EditingUtil;
import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinIME.UIHandler; import com.android.inputmethod.latin.LatinIME.UIHandler;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
@ -133,6 +132,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
} }
private VoiceIMEConnector() { private VoiceIMEConnector() {
// Intentional empty constructor for singleton.
} }
public void resetVoiceStates(boolean isPasswordText) { public void resetVoiceStates(boolean isPasswordText) {
@ -228,7 +228,8 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
} }
private static class CustomLinkMovementMethod extends LinkMovementMethod { private static class CustomLinkMovementMethod extends LinkMovementMethod {
private static CustomLinkMovementMethod sInstance = new CustomLinkMovementMethod(); private static CustomLinkMovementMethod sLinkMovementMethodInstance =
new CustomLinkMovementMethod();
private AlertDialog mAlertDialog; private AlertDialog mAlertDialog;
public void setVoiceWarningDialog(AlertDialog alertDialog) { public void setVoiceWarningDialog(AlertDialog alertDialog) {
@ -236,7 +237,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
} }
public static CustomLinkMovementMethod getInstance() { public static CustomLinkMovementMethod getInstance() {
return sInstance; return sLinkMovementMethodInstance;
} }
// Almost the same as LinkMovementMethod.onTouchEvent(), but overrides it for // Almost the same as LinkMovementMethod.onTouchEvent(), but overrides it for
@ -391,9 +392,8 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
public void rememberReplacedWord(CharSequence suggestion,String wordSeparators) { public void rememberReplacedWord(CharSequence suggestion,String wordSeparators) {
if (mShowingVoiceSuggestions) { if (mShowingVoiceSuggestions) {
// Retain the replaced word in the alternatives array. // Retain the replaced word in the alternatives array.
EditingUtil.Range range = new EditingUtil.Range(); String wordToBeReplaced = EditingUtils.getWordAtCursor(
String wordToBeReplaced = EditingUtil.getWordAtCursor( mContext.getCurrentInputConnection(), wordSeparators);
mContext.getCurrentInputConnection(), wordSeparators, range);
if (!mWordToSuggestions.containsKey(wordToBeReplaced)) { if (!mWordToSuggestions.containsKey(wordToBeReplaced)) {
wordToBeReplaced = wordToBeReplaced.toLowerCase(); wordToBeReplaced = wordToBeReplaced.toLowerCase();
} }
@ -415,9 +415,9 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
* @param touching The word that the cursor is touching, with position information * @param touching The word that the cursor is touching, with position information
* @return true if an alternative was found, false otherwise. * @return true if an alternative was found, false otherwise.
*/ */
public boolean applyVoiceAlternatives(EditingUtil.SelectedWord touching) { public boolean applyVoiceAlternatives(EditingUtils.SelectedWord touching) {
// Search for result in spoken word alternatives // Search for result in spoken word alternatives
String selectedWord = touching.word.toString().trim(); String selectedWord = touching.mWord.toString().trim();
if (!mWordToSuggestions.containsKey(selectedWord)) { if (!mWordToSuggestions.containsKey(selectedWord)) {
selectedWord = selectedWord.toLowerCase(); selectedWord = selectedWord.toLowerCase();
} }
@ -426,7 +426,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord); List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord);
// If the first letter of touching is capitalized, make all the suggestions // If the first letter of touching is capitalized, make all the suggestions
// start with a capital letter. // start with a capital letter.
if (Character.isUpperCase(touching.word.charAt(0))) { if (Character.isUpperCase(touching.mWord.charAt(0))) {
for (int i = 0; i < suggestions.size(); i++) { for (int i = 0; i < suggestions.size(); i++) {
String origSugg = (String) suggestions.get(i); String origSugg = (String) suggestions.get(i);
String capsSugg = origSugg.toUpperCase().charAt(0) String capsSugg = origSugg.toUpperCase().charAt(0)
@ -478,7 +478,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
} }
public void handleVoiceResults(KeyboardSwitcher switcher, boolean capitalizeFirstWord) { public void handleVoiceResults(boolean capitalizeFirstWord) {
mAfterVoiceInput = true; mAfterVoiceInput = true;
mImmediatelyAfterVoiceInput = true; mImmediatelyAfterVoiceInput = true;
@ -508,7 +508,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text
mContext.commitTyped(ic); mContext.commitTyped(ic);
EditingUtil.appendText(ic, bestResult); EditingUtils.appendText(ic, bestResult);
if (ic != null) ic.endBatchEdit(); if (ic != null) ic.endBatchEdit();
mVoiceInputHighlighted = true; mVoiceInputHighlighted = true;

View File

@ -16,7 +16,7 @@
package com.android.inputmethod.voice; package com.android.inputmethod.voice;
import com.android.inputmethod.latin.EditingUtil; import com.android.inputmethod.latin.EditingUtils;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import android.content.ContentResolver; import android.content.ContentResolver;
@ -241,7 +241,7 @@ public class VoiceInput implements OnClickListener {
} }
public void incrementTextModificationInsertPunctuationCount(int count){ public void incrementTextModificationInsertPunctuationCount(int count){
mAfterVoiceInputInsertPunctuationCount += 1; mAfterVoiceInputInsertPunctuationCount += count;
if (mAfterVoiceInputSelectionSpan > 0) { if (mAfterVoiceInputSelectionSpan > 0) {
// If text was highlighted before inserting the char, count this as // If text was highlighted before inserting the char, count this as
// a delete. // a delete.
@ -429,8 +429,7 @@ public class VoiceInput implements OnClickListener {
public void logTextModifiedByChooseSuggestion(String suggestion, int index, public void logTextModifiedByChooseSuggestion(String suggestion, int index,
String wordSeparators, InputConnection ic) { String wordSeparators, InputConnection ic) {
EditingUtil.Range range = new EditingUtil.Range(); String wordToBeReplaced = EditingUtils.getWordAtCursor(ic, wordSeparators);
String wordToBeReplaced = EditingUtil.getWordAtCursor(ic, wordSeparators, range);
// If we enable phrase-based alternatives, only send up the first word // If we enable phrase-based alternatives, only send up the first word
// in suggestion and wordToBeReplaced. // in suggestion and wordToBeReplaced.
mLogger.textModifiedByChooseSuggestion(suggestion.length(), wordToBeReplaced.length(), mLogger.textModifiedByChooseSuggestion(suggestion.length(), wordToBeReplaced.length(),
@ -578,7 +577,9 @@ public class VoiceInput implements OnClickListener {
public void onBufferReceived(byte[] buf) { public void onBufferReceived(byte[] buf) {
try { try {
mWaveBuffer.write(buf); mWaveBuffer.write(buf);
} catch (IOException e) {} } catch (IOException e) {
// ignore.
}
} }
@Override @Override

View File

@ -33,7 +33,9 @@ import java.nio.ShortBuffer;
public class WaveformImage { public class WaveformImage {
private static final int SAMPLING_RATE = 8000; private static final int SAMPLING_RATE = 8000;
private WaveformImage() {} private WaveformImage() {
// Intentional empty constructor.
}
public static Bitmap drawWaveform( public static Bitmap drawWaveform(
ByteArrayOutputStream waveBuffer, int w, int h, int start, int end) { ByteArrayOutputStream waveBuffer, int w, int h, int start, int end) {

View File

@ -116,13 +116,6 @@ public class SuggestHelper {
return word; return word;
} }
private void showList(String title, List<CharSequence> suggestions) {
Log.i(TAG, title);
for (int i = 0; i < suggestions.size(); i++) {
Log.i(title, suggestions.get(i) + ", ");
}
}
private boolean isDefaultSuggestion(List<CharSequence> suggestions, CharSequence word) { private boolean isDefaultSuggestion(List<CharSequence> suggestions, CharSequence word) {
// Check if either the word is what you typed or the first alternative // Check if either the word is what you typed or the first alternative
return suggestions.size() > 0 && return suggestions.size() > 0 &&
@ -191,8 +184,6 @@ public class SuggestHelper {
boolean isUserBigramSuggestion(CharSequence previous, char typed, boolean isUserBigramSuggestion(CharSequence previous, char typed,
CharSequence expected) { CharSequence expected) {
WordComposer word = createWordComposer(Character.toString(typed));
if (mUserBigram == null) return false; if (mUserBigram == null) return false;
flushUserBigrams(); flushUserBigrams();