aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
authorsatok <satok@google.com>2011-06-27 20:19:50 +0900
committersatok <satok@google.com>2011-06-27 20:19:50 +0900
commita12292f053470072cb4bfac2b2ff8fc5a2db0a5d (patch)
treedf8e195cbee4cb9a7beccc0eaacd203d12e7c646 /java/src
parent49043b841a5075038529971477d478947bb85a14 (diff)
parentd8850ae1abca823632014a01315ebc1f27f7ffd8 (diff)
downloadlatinime-a12292f053470072cb4bfac2b2ff8fc5a2db0a5d.tar.gz
latinime-a12292f053470072cb4bfac2b2ff8fc5a2db0a5d.tar.xz
latinime-a12292f053470072cb4bfac2b2ff8fc5a2db0a5d.zip
Merge remote-tracking branch 'goog/master' into merge
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java14
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java6
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java17
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java60
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java253
-rw-r--r--java/src/com/android/inputmethod/keyboard/PointerTracker.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java42
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java2
-rw-r--r--java/src/com/android/inputmethod/latin/CandidateView.java148
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java60
-rw-r--r--java/src/com/android/inputmethod/latin/StaticInnerHandlerWrapper.java42
12 files changed, 408 insertions, 240 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java
index 043266c70..7199550a9 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java
@@ -18,7 +18,6 @@ package com.android.inputmethod.accessibility;
import android.content.SharedPreferences;
import android.inputmethodservice.InputMethodService;
-import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
@@ -26,6 +25,7 @@ import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActionListener {
private static final AccessibleInputMethodServiceProxy sInstance =
@@ -42,18 +42,20 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi
private AccessibilityHandler mAccessibilityHandler;
- private class AccessibilityHandler extends Handler {
+ private static class AccessibilityHandler
+ extends StaticInnerHandlerWrapper<AccessibleInputMethodServiceProxy> {
private static final int MSG_NO_HOVER_SELECTION = 0;
- public AccessibilityHandler(Looper looper) {
- super(looper);
+ public AccessibilityHandler(AccessibleInputMethodServiceProxy outerInstance,
+ Looper looper) {
+ super(outerInstance, looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_NO_HOVER_SELECTION:
- notifyNoHoverSelection();
+ getOuterInstance().notifyNoHoverSelection();
break;
}
}
@@ -82,7 +84,7 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi
private void initInternal(InputMethodService inputMethod, SharedPreferences prefs) {
mInputMethod = inputMethod;
- mAccessibilityHandler = new AccessibilityHandler(inputMethod.getMainLooper());
+ mAccessibilityHandler = new AccessibilityHandler(this, inputMethod.getMainLooper());
}
/**
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index 154f4af91..a31911d60 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -134,7 +134,7 @@ public class KeyCodeDescriptionMapper {
return context.getString(mKeyLabelMap.get(label));
} else if (label.length() == 1
|| (keyboard.isManualTemporaryUpperCase() && !TextUtils
- .isEmpty(key.mHintLetter))) {
+ .isEmpty(key.mHintLabel))) {
return getDescriptionForKeyCode(context, keyboard, key);
} else {
return label;
@@ -181,8 +181,8 @@ public class KeyCodeDescriptionMapper {
* @return the key code for the specified key
*/
private int getCorrectKeyCode(Keyboard keyboard, Key key) {
- if (keyboard.isManualTemporaryUpperCase() && !TextUtils.isEmpty(key.mHintLetter)) {
- return key.mHintLetter.charAt(0);
+ if (keyboard.isManualTemporaryUpperCase() && !TextUtils.isEmpty(key.mHintLabel)) {
+ return key.mHintLabel.charAt(0);
} else {
return key.mCode;
}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java b/java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java
index b718ebbb7..8969a2168 100644
--- a/java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java
+++ b/java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java
@@ -19,6 +19,7 @@ package com.android.inputmethod.deprecated.voice;
import com.android.inputmethod.latin.EditingUtils;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
import android.content.ContentResolver;
import android.content.Context;
@@ -26,7 +27,6 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.speech.RecognitionListener;
@@ -132,13 +132,20 @@ public class VoiceInput implements OnClickListener {
private final static int MSG_RESET = 1;
- private final Handler mHandler = new Handler() {
+ private final UIHandler mHandler = new UIHandler(this);
+
+ private static class UIHandler extends StaticInnerHandlerWrapper<VoiceInput> {
+ public UIHandler(VoiceInput outerInstance) {
+ super(outerInstance);
+ }
+
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_RESET) {
- mState = DEFAULT;
- mRecognitionView.finish();
- mUiListener.onCancelVoice();
+ final VoiceInput voiceInput = getOuterInstance();
+ voiceInput.mState = DEFAULT;
+ voiceInput.mRecognitionView.finish();
+ voiceInput.mUiListener.onCancelVoice();
}
}
};
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 2850c95df..872fbf823 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -19,17 +19,18 @@ package com.android.inputmethod.keyboard;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
+import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.Xml;
import com.android.inputmethod.keyboard.internal.KeyStyles;
+import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.keyboard.internal.KeyboardParser;
+import com.android.inputmethod.keyboard.internal.KeyboardParser.ParseException;
import com.android.inputmethod.keyboard.internal.PopupCharactersParser;
import com.android.inputmethod.keyboard.internal.Row;
-import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle;
-import com.android.inputmethod.keyboard.internal.KeyboardParser.ParseException;
import com.android.inputmethod.latin.R;
import java.util.ArrayList;
@@ -45,18 +46,22 @@ public class Key {
/** Label to display */
public final CharSequence mLabel;
- /** Hint letter to display on the key in conjunction with the label */
- public final CharSequence mHintLetter;
+ /** Hint label to display on the key in conjunction with the label */
+ public final CharSequence mHintLabel;
/** Option of the label */
public final int mLabelOption;
public static final int LABEL_OPTION_ALIGN_LEFT = 0x01;
public static final int LABEL_OPTION_ALIGN_RIGHT = 0x02;
- public static final int LABEL_OPTION_ALIGN_BOTTOM = 0x08;
- public static final int LABEL_OPTION_FONT_NORMAL = 0x10;
- public static final int LABEL_OPTION_FONT_FIXED_WIDTH = 0x20;
- public static final int LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO = 0x40;
- private static final int LABEL_OPTION_POPUP_HINT = 0x80;
- private static final int LABEL_OPTION_HAS_UPPERCASE_LETTER = 0x100;
+ public static final int LABEL_OPTION_ALIGN_BOTTOM = 0x04;
+ public static final int LABEL_OPTION_ALIGN_LEFT_OF_CENTER = 0x08;
+ private static final int LABEL_OPTION_LARGE_LETTER = 0x10;
+ private static final int LABEL_OPTION_FONT_NORMAL = 0x20;
+ private static final int LABEL_OPTION_FONT_MONO_SPACE = 0x40;
+ private static final int LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO = 0x80;
+ private static final int LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO = 0x100;
+ private static final int LABEL_OPTION_HAS_POPUP_HINT = 0x200;
+ private static final int LABEL_OPTION_HAS_UPPERCASE_LETTER = 0x400;
+ private static final int LABEL_OPTION_HAS_HINT_LABEL = 0x800;
/** Icon to display instead of a label. Icon takes precedence over a label */
private Drawable mIcon;
@@ -160,7 +165,7 @@ public class Key {
mVisualInsetsLeft = mVisualInsetsRight = 0;
mWidth = width - mGap;
mEdgeFlags = edgeFlags;
- mHintLetter = null;
+ mHintLabel = null;
mLabelOption = 0;
mFunctional = false;
mSticky = false;
@@ -282,7 +287,7 @@ public class Key {
keyAttr, R.styleable.Keyboard_Key_keyIcon,
KeyboardIconsSet.ICON_UNDEFINED));
Keyboard.setDefaultBounds(mIcon);
- mHintLetter = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLetter);
+ mHintLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
mLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyLabel);
mLabelOption = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption, 0);
@@ -309,14 +314,43 @@ public class Key {
}
}
+ public Typeface selectTypeface(Typeface defaultTypeface) {
+ // TODO: Handle "bold" here too?
+ if ((mLabelOption & LABEL_OPTION_FONT_NORMAL) != 0) {
+ return Typeface.DEFAULT;
+ } else if ((mLabelOption & LABEL_OPTION_FONT_MONO_SPACE) != 0) {
+ return Typeface.MONOSPACE;
+ } else {
+ return defaultTypeface;
+ }
+ }
+
+ public int selectTextSize(int letter, int largeLetter, int label, int hintLabel) {
+ if (mLabel.length() > 1
+ && (mLabelOption & (LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO
+ | LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO)) == 0) {
+ return label;
+ } else if ((mLabelOption & LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO) != 0) {
+ return hintLabel;
+ } else if ((mLabelOption & LABEL_OPTION_LARGE_LETTER) != 0) {
+ return largeLetter;
+ } else {
+ return letter;
+ }
+ }
+
public boolean hasPopupHint() {
- return (mLabelOption & LABEL_OPTION_POPUP_HINT) != 0;
+ return (mLabelOption & LABEL_OPTION_HAS_POPUP_HINT) != 0;
}
public boolean hasUppercaseLetter() {
return (mLabelOption & LABEL_OPTION_HAS_UPPERCASE_LETTER) != 0;
}
+ public boolean hasHintLabel() {
+ return (mLabelOption & LABEL_OPTION_HAS_HINT_LABEL) != 0;
+ }
+
private static boolean isDigitPopupCharacter(CharSequence label) {
return label != null && label.length() == 1 && Character.isDigit(label.charAt(0));
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 9dc019c61..8ca6ade6c 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -30,7 +30,6 @@ import android.graphics.Rect;
import android.graphics.Region.Op;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
-import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
@@ -53,6 +52,7 @@ import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.keyboard.internal.SwipeTracker;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
import java.util.ArrayList;
import java.util.HashMap;
@@ -66,16 +66,20 @@ import java.util.WeakHashMap;
* @attr ref R.styleable#KeyboardView_keyBackground
* @attr ref R.styleable#KeyboardView_keyHysteresisDistance
* @attr ref R.styleable#KeyboardView_keyLetterRatio
+ * @attr ref R.styleable#KeyboardView_keyLargeLetterRatio
* @attr ref R.styleable#KeyboardView_keyLabelRatio
* @attr ref R.styleable#KeyboardView_keyHintLetterRatio
* @attr ref R.styleable#KeyboardView_keyUppercaseLetterRatio
+ * @attr ref R.styleable#KeyboardView_keyHintLabelRatio
* @attr ref R.styleable#KeyboardView_keyTextStyle
* @attr ref R.styleable#KeyboardView_keyPreviewLayout
+ * @attr ref R.styleable#KeyboardView_keyPreviewTextRatio
* @attr ref R.styleable#KeyboardView_keyPreviewOffset
* @attr ref R.styleable#KeyboardView_keyPreviewHeight
* @attr ref R.styleable#KeyboardView_keyTextColor
* @attr ref R.styleable#KeyboardView_keyTextColorDisabled
* @attr ref R.styleable#KeyboardView_keyHintLetterColor
+ * @attr ref R.styleable#KeyboardView_keyHintLabelColor
* @attr ref R.styleable#KeyboardView_keyUppercaseLetterInactivatedColor
* @attr ref R.styleable#KeyboardView_keyUppercaseLetterActivatedColor
* @attr ref R.styleable#KeyboardView_verticalCorrection
@@ -99,13 +103,15 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
private static final int HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL = -1;
// XML attribute
- private final float mKeyLetterRatio;
private final int mKeyTextColor;
private final int mKeyTextInactivatedColor;
private final Typeface mKeyTextStyle;
+ private final float mKeyLetterRatio;
+ private final float mKeyLargeLetterRatio;
private final float mKeyLabelRatio;
private final float mKeyHintLetterRatio;
private final float mKeyUppercaseLetterRatio;
+ private final float mKeyHintLabelRatio;
private final int mShadowColor;
private final float mShadowRadius;
private final Drawable mKeyBackground;
@@ -117,15 +123,18 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
private final int mPopupLayout;
private final Drawable mKeyPopupHintIcon;
private final int mKeyHintLetterColor;
+ private final int mKeyHintLabelColor;
private final int mKeyUppercaseLetterInactivatedColor;
private final int mKeyUppercaseLetterActivatedColor;
// Main keyboard
private Keyboard mKeyboard;
private int mKeyLetterSize;
+ private int mKeyLargeLetterSize;
private int mKeyLabelSize;
private int mKeyHintLetterSize;
private int mKeyUppercaseLetterSize;
+ private int mKeyHintLabelSize;
// Key preview
private boolean mInForeground;
@@ -182,7 +191,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
private Canvas mCanvas;
private final Paint mPaint = new Paint();
private final Rect mPadding = new Rect();
- private final Rect mTextBounds = new Rect();
// This map caches key label text height in pixel as value and key label text size as map key.
private final HashMap<Integer, Integer> mTextHeightCache = new HashMap<Integer, Integer>();
// This map caches key label text width in pixel as value and key label text size as map key.
@@ -193,9 +201,9 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
private static final String KEY_LABEL_REFERENCE_CHAR = "M";
private final int mKeyLabelHorizontalPadding;
- private final UIHandler mHandler = new UIHandler();
+ private final UIHandler mHandler = new UIHandler(this);
- class UIHandler extends Handler {
+ public static class UIHandler extends StaticInnerHandlerWrapper<KeyboardView> {
private static final int MSG_SHOW_KEY_PREVIEW = 1;
private static final int MSG_DISMISS_KEY_PREVIEW = 2;
private static final int MSG_REPEAT_KEY = 3;
@@ -205,34 +213,40 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
private boolean mInKeyRepeat;
+ public UIHandler(KeyboardView outerInstance) {
+ super(outerInstance);
+ }
+
@Override
public void handleMessage(Message msg) {
+ final KeyboardView keyboardView = getOuterInstance();
final PointerTracker tracker = (PointerTracker) msg.obj;
switch (msg.what) {
case MSG_SHOW_KEY_PREVIEW:
- showKey(msg.arg1, tracker);
+ keyboardView.showKey(msg.arg1, tracker);
break;
case MSG_DISMISS_KEY_PREVIEW:
- mPreviewText.setVisibility(View.INVISIBLE);
+ keyboardView.mPreviewText.setVisibility(View.INVISIBLE);
break;
case MSG_REPEAT_KEY:
tracker.onRepeatKey(msg.arg1);
- startKeyRepeatTimer(mKeyRepeatInterval, msg.arg1, tracker);
+ startKeyRepeatTimer(keyboardView.mKeyRepeatInterval, msg.arg1, tracker);
break;
case MSG_LONGPRESS_KEY:
- openMiniKeyboardIfRequired(msg.arg1, tracker);
+ keyboardView.openMiniKeyboardIfRequired(msg.arg1, tracker);
break;
case MSG_LONGPRESS_SHIFT_KEY:
- onLongPressShiftKey(tracker);
+ keyboardView.onLongPressShiftKey(tracker);
break;
}
}
public void showKeyPreview(long delay, int keyIndex, PointerTracker tracker) {
+ final KeyboardView keyboardView = getOuterInstance();
removeMessages(MSG_SHOW_KEY_PREVIEW);
- if (mPreviewText.getVisibility() == VISIBLE || delay == 0) {
+ if (keyboardView.mPreviewText.getVisibility() == VISIBLE || delay == 0) {
// Show right away, if it's already visible and finger is moving around
- showKey(keyIndex, tracker);
+ keyboardView.showKey(keyIndex, tracker);
} else {
sendMessageDelayed(
obtainMessage(MSG_SHOW_KEY_PREVIEW, keyIndex, 0, tracker), delay);
@@ -332,15 +346,19 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mPreviewOffset = a.getDimensionPixelOffset(R.styleable.KeyboardView_keyPreviewOffset, 0);
mPreviewHeight = a.getDimensionPixelSize(R.styleable.KeyboardView_keyPreviewHeight, 80);
mKeyLetterRatio = getRatio(a, R.styleable.KeyboardView_keyLetterRatio);
+ mKeyLargeLetterRatio = getRatio(a, R.styleable.KeyboardView_keyLargeLetterRatio);
mKeyLabelRatio = getRatio(a, R.styleable.KeyboardView_keyLabelRatio);
mKeyHintLetterRatio = getRatio(a, R.styleable.KeyboardView_keyHintLetterRatio);
mKeyUppercaseLetterRatio = getRatio(a,
R.styleable.KeyboardView_keyUppercaseLetterRatio);
+ mKeyHintLabelRatio = getRatio(a, R.styleable.KeyboardView_keyHintLabelRatio);
+ mPreviewTextRatio = getRatio(a, R.styleable.KeyboardView_keyPreviewTextRatio);
mKeyTextColor = a.getColor(R.styleable.KeyboardView_keyTextColor, 0xFF000000);
mKeyTextInactivatedColor = a.getColor(
R.styleable.KeyboardView_keyTextInactivatedColor, 0xFF000000);
mKeyPopupHintIcon = a.getDrawable(R.styleable.KeyboardView_keyPopupHintIcon);
mKeyHintLetterColor = a.getColor(R.styleable.KeyboardView_keyHintLetterColor, 0);
+ mKeyHintLabelColor = a.getColor(R.styleable.KeyboardView_keyHintLabelColor, 0);
mKeyUppercaseLetterInactivatedColor = a.getColor(
R.styleable.KeyboardView_keyUppercaseLetterInactivatedColor, 0);
mKeyUppercaseLetterActivatedColor = a.getColor(
@@ -359,7 +377,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
if (previewLayout != 0) {
mPreviewText = (TextView) LayoutInflater.from(context).inflate(previewLayout, null);
mPreviewBackground = mPreviewText.getBackground();
- mPreviewTextRatio = getRatio(res, R.fraction.key_preview_text_ratio);
} else {
mShowKeyPreviewPopup = false;
}
@@ -456,11 +473,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
return a.getFraction(index, 1000, 1000, 1) / 1000.0f;
}
- // Read fraction value in resource as float.
- private static float getRatio(Resources res, int id) {
- return res.getFraction(id, 1000, 1000) / 1000.0f;
- }
-
public void startIgnoringDoubleTap() {
if (ENABLE_CAPSLOCK_BY_DOUBLETAP)
mHandler.startIgnoringDoubleTap();
@@ -515,10 +527,12 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mPopupPanelCache.clear();
final int keyHeight = keyboard.getRowHeight() - keyboard.getVerticalGap();
mKeyLetterSize = (int)(keyHeight * mKeyLetterRatio);
+ mKeyLargeLetterSize = (int)(keyHeight * mKeyLargeLetterRatio);
mKeyLabelSize = (int)(keyHeight * mKeyLabelRatio);
mKeyHintLetterSize = (int)(keyHeight * mKeyHintLetterRatio);
mKeyUppercaseLetterSize = (int)(
keyHeight * mKeyUppercaseLetterRatio);
+ mKeyHintLabelSize = (int)(keyHeight * mKeyHintLabelRatio);
mPreviewTextSize = (int)(keyHeight * mPreviewTextRatio);
}
@@ -581,7 +595,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
protected CharSequence adjustCase(CharSequence label) {
if (mKeyboard.isShiftedOrShiftLocked() && label != null && label.length() < 3
&& Character.isLowerCase(label.charAt(0))) {
- return label.toString().toUpperCase();
+ return label.toString().toUpperCase(mKeyboard.mId.mLocale);
}
return label;
}
@@ -683,6 +697,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
final int kbdPaddingTop = getPaddingTop();
final int keyDrawX = key.mX + key.mVisualInsetsLeft;
final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
+ final int centerX = (keyDrawWidth + padding.left - padding.right) / 2;
+ final float centerY = (key.mHeight + padding.top - padding.bottom) / 2;
final int rowHeight = padding.top + key.mHeight;
final boolean isManualTemporaryUpperCase = mKeyboard.isManualTemporaryUpperCase();
@@ -698,47 +714,48 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
keyBackground.draw(canvas);
// Draw key label.
+ int positionX = centerX;
if (key.mLabel != null) {
// Switch the character to uppercase if shift is pressed
- final String label = key.mLabel == null ? null : adjustCase(key.mLabel).toString();
- // For characters, use large font. For labels like "Done", use small font.
- final int labelSize = getLabelSizeAndSetPaint(label, key.mLabelOption, paint);
- final int labelCharHeight = getLabelCharHeight(labelSize, paint);
+ final CharSequence label = key.mLabel == null ? null : adjustCase(key.mLabel);
+ // For characters, use large font. For labels like "Done", use smaller font.
+ paint.setTypeface(key.selectTypeface(mKeyTextStyle));
+ final int labelSize = key.selectTextSize(mKeyLetterSize, mKeyLargeLetterSize,
+ mKeyLabelSize, mKeyHintLabelSize);
+ paint.setTextSize(labelSize);
+ final int labelCharHeight = getLabelCharHeight(paint);
+ final int labelCharWidth = getLabelCharWidth(paint);
// Vertical label text alignment.
final float baseline;
+ // TODO: Generalize the following calculations.
if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_BOTTOM) != 0) {
baseline = key.mHeight - labelCharHeight * KEY_LABEL_VERTICAL_PADDING_FACTOR;
- if (DEBUG_SHOW_ALIGN)
- drawHorizontalLine(canvas, (int)baseline, keyDrawWidth, 0xc0008000,
- new Paint());
} else { // Align center
- final float centerY = (key.mHeight + padding.top - padding.bottom) / 2;
baseline = centerY + labelCharHeight * KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR_CENTER;
- if (DEBUG_SHOW_ALIGN)
- drawHorizontalLine(canvas, (int)baseline, keyDrawWidth, 0xc0008000,
- new Paint());
}
+
// Horizontal label text alignment
- final int positionX;
if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_LEFT) != 0) {
- positionX = mKeyLabelHorizontalPadding + padding.left;
+ positionX = padding.left + mKeyLabelHorizontalPadding;
paint.setTextAlign(Align.LEFT);
- if (DEBUG_SHOW_ALIGN)
- drawVerticalLine(canvas, positionX, rowHeight, 0xc0800080, new Paint());
} else if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_RIGHT) != 0) {
positionX = keyDrawWidth - mKeyLabelHorizontalPadding - padding.right;
paint.setTextAlign(Align.RIGHT);
- if (DEBUG_SHOW_ALIGN)
- drawVerticalLine(canvas, positionX, rowHeight, 0xc0808000, new Paint());
+ } else if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_LEFT_OF_CENTER) != 0) {
+ // TODO: Parameterise this?
+ positionX = centerX - labelCharWidth * 7 / 4;
+ paint.setTextAlign(Align.LEFT);
} else {
- positionX = (keyDrawWidth + padding.left - padding.right) / 2;
+ positionX = centerX;
paint.setTextAlign(Align.CENTER);
- if (DEBUG_SHOW_ALIGN) {
- if (label.length() > 1)
- drawVerticalLine(canvas, positionX, rowHeight, 0xc0008080, new Paint());
- }
}
+ if (DEBUG_SHOW_ALIGN) {
+ final Paint line = new Paint();
+ drawHorizontalLine(canvas, (int)baseline, keyDrawWidth, 0xc0008000, line);
+ drawVerticalLine(canvas, positionX, rowHeight, 0xc0800080, line);
+ }
+
if (key.hasUppercaseLetter() && isManualTemporaryUpperCase) {
paint.setColor(mKeyTextInactivatedColor);
} else {
@@ -751,59 +768,67 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
// Make label invisible
paint.setColor(Color.TRANSPARENT);
}
- canvas.drawText(label, positionX, baseline, paint);
+ canvas.drawText(label, 0, label.length(), positionX, baseline, paint);
// Turn off drop shadow
paint.setShadowLayer(0, 0, 0, 0);
+
}
- // Draw hint letter.
- if (key.mHintLetter != null) {
- final String label = key.mHintLetter.toString();
- final int textColor;
- final int textSize;
+ // Draw hint label.
+ if (key.mHintLabel != null) {
+ final CharSequence hint = key.mHintLabel;
+ final int hintColor;
+ final int hintSize;
if (key.hasUppercaseLetter()) {
- textColor = isManualTemporaryUpperCase ? mKeyUppercaseLetterActivatedColor
+ hintColor = isManualTemporaryUpperCase ? mKeyUppercaseLetterActivatedColor
: mKeyUppercaseLetterInactivatedColor;
- textSize = mKeyUppercaseLetterSize;
+ hintSize = mKeyUppercaseLetterSize;
+ } else if (key.hasHintLabel()) {
+ hintColor = mKeyHintLabelColor;
+ hintSize = mKeyHintLabelSize;
+ paint.setTypeface(Typeface.DEFAULT);
} else {
- textColor = mKeyHintLetterColor;
- textSize = mKeyHintLetterSize;
+ hintColor = mKeyHintLetterColor;
+ hintSize = mKeyHintLetterSize;
}
- paint.setColor(textColor);
- paint.setTextSize(textSize);
+ paint.setColor(hintColor);
+ paint.setTextSize(hintSize);
// Note: padding.right for drawX?
- final float drawX = keyDrawWidth - getLabelCharWidth(textSize, paint);
- final float drawY = -paint.ascent() + padding.top;
- canvas.drawText(label, drawX, drawY, paint);
+ final float hintX, hintY;
+ if (key.hasHintLabel()) {
+ // TODO: Generalize the following calculations.
+ hintX = positionX + getLabelCharWidth(paint) * 2;
+ hintY = centerY + getLabelCharHeight(paint) / 2;
+ } else {
+ hintX = keyDrawWidth - getLabelCharWidth(paint);
+ hintY = -paint.ascent() + padding.top;
+ }
+ canvas.drawText(hint, 0, hint.length(), hintX, hintY, paint);
}
// Draw key icon.
final Drawable icon = key.getIcon();
if (key.mLabel == null && icon != null) {
- final int drawableWidth = icon.getIntrinsicWidth();
- final int drawableHeight = icon.getIntrinsicHeight();
- final int drawableX;
- final int drawableY = (key.mHeight + padding.top - padding.bottom - drawableHeight) / 2;
+ final int iconWidth = icon.getIntrinsicWidth();
+ final int iconHeight = icon.getIntrinsicHeight();
+ final int iconX, alignX;
+ final int iconY = (key.mHeight + padding.top - padding.bottom - iconHeight) / 2;
if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_LEFT) != 0) {
- drawableX = padding.left + mKeyLabelHorizontalPadding;
- if (DEBUG_SHOW_ALIGN)
- drawVerticalLine(canvas, drawableX, rowHeight, 0xc0800080, new Paint());
+ iconX = padding.left + mKeyLabelHorizontalPadding;
+ alignX = iconX;
} else if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_RIGHT) != 0) {
- drawableX = keyDrawWidth - padding.right - mKeyLabelHorizontalPadding
- - drawableWidth;
- if (DEBUG_SHOW_ALIGN)
- drawVerticalLine(canvas, drawableX + drawableWidth, rowHeight,
- 0xc0808000, new Paint());
+ iconX = keyDrawWidth - padding.right - mKeyLabelHorizontalPadding - iconWidth;
+ alignX = iconX + iconWidth;
} else { // Align center
- drawableX = (keyDrawWidth + padding.left - padding.right - drawableWidth) / 2;
- if (DEBUG_SHOW_ALIGN)
- drawVerticalLine(canvas, drawableX + drawableWidth / 2, rowHeight,
- 0xc0008080, new Paint());
+ iconX = (keyDrawWidth + padding.left - padding.right - iconWidth) / 2;
+ alignX = iconX + iconWidth / 2;
+ }
+ drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
+ if (DEBUG_SHOW_ALIGN) {
+ final Paint line = new Paint();
+ drawVerticalLine(canvas, alignX, rowHeight, 0xc0800080, line);
+ drawRectangle(canvas, iconX, iconY, iconWidth, iconHeight, 0x80c00000, line);
}
- drawIcon(canvas, icon, drawableX, drawableY, drawableWidth, drawableHeight);
- if (DEBUG_SHOW_ALIGN)
- drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight,
- 0x80c00000, new Paint());
}
// Draw popup hint icon "...".
@@ -815,60 +840,60 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
final int drawableY = HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL;
final Drawable hintIcon = mKeyPopupHintIcon;
drawIcon(canvas, hintIcon, drawableX, drawableY, drawableWidth, drawableHeight);
- if (DEBUG_SHOW_ALIGN)
+ if (DEBUG_SHOW_ALIGN) {
drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight,
0x80c0c000, new Paint());
+ }
}
canvas.translate(-keyDrawX - kbdPaddingLeft, -key.mY - kbdPaddingTop);
}
- public int getLabelSizeAndSetPaint(CharSequence label, int keyLabelOption, Paint paint) {
+ // This method is currently being used only by MiniKeyboardBuilder
+ public int getDefaultLabelSizeAndSetPaint(Paint paint) {
// For characters, use large font. For labels like "Done", use small font.
- final int labelSize;
- final Typeface labelStyle;
- if ((keyLabelOption & Key.LABEL_OPTION_FONT_NORMAL) != 0) {
- labelStyle = Typeface.DEFAULT;
- } else if ((keyLabelOption & Key.LABEL_OPTION_FONT_FIXED_WIDTH) != 0) {
- labelStyle = Typeface.MONOSPACE;
- } else {
- labelStyle = mKeyTextStyle;
- }
- if (label.length() > 1) {
- labelSize = (keyLabelOption & Key.LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO) != 0
- ? mKeyLetterSize : mKeyLabelSize;
- } else {
- labelSize = mKeyLetterSize;
- }
+ final int labelSize = mKeyLabelSize;
paint.setTextSize(labelSize);
- paint.setTypeface(labelStyle);
+ paint.setTypeface(mKeyTextStyle);
return labelSize;
}
- private int getLabelCharHeight(int labelSize, Paint paint) {
- Integer labelHeightValue = mTextHeightCache.get(labelSize);
- final int labelCharHeight;
- if (labelHeightValue != null) {
- labelCharHeight = labelHeightValue;
- } else {
- paint.getTextBounds(KEY_LABEL_REFERENCE_CHAR, 0, 1, mTextBounds);
- labelCharHeight = mTextBounds.height();
- mTextHeightCache.put(labelSize, labelCharHeight);
- }
- return labelCharHeight;
+ private final Rect mTextBounds = new Rect();
+
+ private int getLabelCharHeight(Paint paint) {
+ final int labelSize = (int)paint.getTextSize();
+ final Integer cachedValue = mTextHeightCache.get(labelSize);
+ if (cachedValue != null)
+ return cachedValue;
+
+ paint.getTextBounds(KEY_LABEL_REFERENCE_CHAR, 0, 1, mTextBounds);
+ final int height = mTextBounds.height();
+ mTextHeightCache.put(labelSize, height);
+ return height;
}
- private int getLabelCharWidth(int labelSize, Paint paint) {
- Integer labelWidthValue = mTextWidthCache.get(labelSize);
- final int labelCharWidth;
- if (labelWidthValue != null) {
- labelCharWidth = labelWidthValue;
+ private int getLabelCharWidth(Paint paint) {
+ final int labelSize = (int)paint.getTextSize();
+ final Typeface face = paint.getTypeface();
+ final Integer key;
+ if (face == Typeface.DEFAULT) {
+ key = labelSize;
+ } else if (face == Typeface.DEFAULT_BOLD) {
+ key = labelSize + 1000;
+ } else if (face == Typeface.MONOSPACE) {
+ key = labelSize + 2000;
} else {
- paint.getTextBounds(KEY_LABEL_REFERENCE_CHAR, 0, 1, mTextBounds);
- labelCharWidth = mTextBounds.width();
- mTextWidthCache.put(labelSize, labelCharWidth);
+ key = labelSize;
}
- return labelCharWidth;
+
+ final Integer cached = mTextWidthCache.get(key);
+ if (cached != null)
+ return cached;
+
+ paint.getTextBounds(KEY_LABEL_REFERENCE_CHAR, 0, 1, mTextBounds);
+ final int width = mTextBounds.width();
+ mTextWidthCache.put(key, width);
+ return width;
}
private static void drawIcon(Canvas canvas, Drawable icon, int x, int y, int width,
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index c7620f946..8b03360bf 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -670,7 +670,7 @@ public class PointerTracker {
// If keyboard is in manual temporary upper case state and key has manual temporary
// uppercase letter as key hint letter, alternate character code should be sent.
if (mKeyboard.isManualTemporaryUpperCase() && key.hasUppercaseLetter()) {
- code = key.mHintLetter.charAt(0);
+ code = key.mHintLabel.charAt(0);
codes[0] = code;
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index 983f0649d..30d9692a8 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -165,7 +165,7 @@ public class KeyStyles {
readInt(keyAttr, R.styleable.Keyboard_Key_code);
readText(keyAttr, R.styleable.Keyboard_Key_keyLabel);
readText(keyAttr, R.styleable.Keyboard_Key_keyOutputText);
- readText(keyAttr, R.styleable.Keyboard_Key_keyHintLetter);
+ readText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
readTextArray(keyAttr, R.styleable.Keyboard_Key_popupCharacters);
readFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption);
readInt(keyAttr, R.styleable.Keyboard_Key_keyIcon);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 37b36825a..1530fed6f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -40,25 +40,15 @@ public class KeyboardIconsSet {
private static final int ICON_RETURN_KEY = 8;
private static final int ICON_SEARCH_KEY = 9;
private static final int ICON_TAB_KEY = 10;
- private static final int ICON_NUM1_KEY = 11;
- private static final int ICON_NUM2_KEY = 12;
- private static final int ICON_NUM3_KEY = 13;
- private static final int ICON_NUM4_KEY = 14;
- private static final int ICON_NUM5_KEY = 15;
- private static final int ICON_NUM6_KEY = 16;
- private static final int ICON_NUM7_KEY = 17;
- private static final int ICON_NUM8_KEY = 18;
- private static final int ICON_NUM9_KEY = 19;
- private static final int ICON_NUM0_KEY = 20;
// This should be aligned with Keyboard.keyIconShifted enum.
- private static final int ICON_SHIFTED_SHIFT_KEY = 21;
+ private static final int ICON_SHIFTED_SHIFT_KEY = 11;
// This should be aligned with Keyboard.keyIconPreview enum.
- private static final int ICON_PREVIEW_SPACE_KEY = 22;
- private static final int ICON_PREVIEW_TAB_KEY = 23;
- private static final int ICON_PREVIEW_SETTINGS_KEY = 24;
- private static final int ICON_PREVIEW_SHORTCUT_KEY = 25;
+ private static final int ICON_PREVIEW_SPACE_KEY = 12;
+ private static final int ICON_PREVIEW_TAB_KEY = 13;
+ private static final int ICON_PREVIEW_SETTINGS_KEY = 14;
+ private static final int ICON_PREVIEW_SHORTCUT_KEY = 15;
- private static final int ICON_LAST = 25;
+ private static final int ICON_LAST = 15;
private final Drawable mIcons[] = new Drawable[ICON_LAST + 1];
@@ -84,26 +74,6 @@ public class KeyboardIconsSet {
return ICON_SEARCH_KEY;
case R.styleable.Keyboard_iconTabKey:
return ICON_TAB_KEY;
- case R.styleable.Keyboard_iconNum1Key:
- return ICON_NUM1_KEY;
- case R.styleable.Keyboard_iconNum2Key:
- return ICON_NUM2_KEY;
- case R.styleable.Keyboard_iconNum3Key:
- return ICON_NUM3_KEY;
- case R.styleable.Keyboard_iconNum4Key:
- return ICON_NUM4_KEY;
- case R.styleable.Keyboard_iconNum5Key:
- return ICON_NUM5_KEY;
- case R.styleable.Keyboard_iconNum6Key:
- return ICON_NUM6_KEY;
- case R.styleable.Keyboard_iconNum7Key:
- return ICON_NUM7_KEY;
- case R.styleable.Keyboard_iconNum8Key:
- return ICON_NUM8_KEY;
- case R.styleable.Keyboard_iconNum9Key:
- return ICON_NUM9_KEY;
- case R.styleable.Keyboard_iconNum0Key:
- return ICON_NUM0_KEY;
case R.styleable.Keyboard_iconShiftedShiftKey:
return ICON_SHIFTED_SHIFT_KEY;
case R.styleable.Keyboard_iconPreviewSpaceKey:
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java
index 040c16ded..1e67eec70 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java
@@ -221,7 +221,7 @@ public class MiniKeyboardBuilder {
paint = new Paint();
paint.setAntiAlias(true);
}
- final int labelSize = view.getLabelSizeAndSetPaint(label, 0, paint);
+ final int labelSize = view.getDefaultLabelSizeAndSetPaint(paint);
paint.setTextSize(labelSize);
if (bounds == null) bounds = new Rect();
paint.getTextBounds(label.toString(), 0, label.length(), bounds);
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index 09fd3b473..a5bfea0f8 100644
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -21,16 +21,15 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Typeface;
-import android.os.Handler;
import android.os.Message;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
+import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.BackgroundColorSpan;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
-import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;
import android.util.AttributeSet;
import android.view.Gravity;
@@ -58,15 +57,15 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
public void pickSuggestionManually(int index, CharSequence word);
}
- private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
// The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}.
private static final int MAX_SUGGESTIONS = 18;
- private static final int UNSPECIFIED_MEASURESPEC = MeasureSpec.makeMeasureSpec(
- 0, MeasureSpec.UNSPECIFIED);
+ private static final int MATCH_PARENT = MeasureSpec.makeMeasureSpec(
+ -1, MeasureSpec.UNSPECIFIED);
private static final boolean DBG = LatinImeLogger.sDBG;
+ private final View mCandidatesStrip;
private static final int NUM_CANDIDATES_IN_STRIP = 3;
private final ImageView mExpandCandidatesPane;
private final ImageView mCloseCandidatesPane;
@@ -76,7 +75,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
private final ArrayList<TextView> mWords = new ArrayList<TextView>();
private final ArrayList<TextView> mInfos = new ArrayList<TextView>();
private final ArrayList<View> mDividers = new ArrayList<View>();
- private final int mCandidatePadding;
private final int mCandidateStripHeight;
private final CharacterStyle mInvertedForegroundColorSpan;
private final CharacterStyle mInvertedBackgroundColorSpan;
@@ -90,28 +88,39 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
private final PopupWindow mPreviewPopup;
private final TextView mPreviewText;
+ private final View mTouchToSave;
+ private final TextView mWordToSave;
+
private Listener mListener;
private SuggestedWords mSuggestions = SuggestedWords.EMPTY;
private boolean mShowingAutoCorrectionInverted;
private boolean mShowingAddToDictionary;
- private final UiHandler mHandler = new UiHandler();
+ private static final float MIN_TEXT_XSCALE = 0.4f;
+ private static final String ELLIPSIS = "\u2026";
+
+ private final UiHandler mHandler = new UiHandler(this);
- private class UiHandler extends Handler {
+ private static class UiHandler extends StaticInnerHandlerWrapper<CandidateView> {
private static final int MSG_HIDE_PREVIEW = 0;
private static final int MSG_UPDATE_SUGGESTION = 1;
private static final long DELAY_HIDE_PREVIEW = 1000;
private static final long DELAY_UPDATE_SUGGESTION = 300;
+ public UiHandler(CandidateView outerInstance) {
+ super(outerInstance);
+ }
+
@Override
public void dispatchMessage(Message msg) {
+ final CandidateView candidateView = getOuterInstance();
switch (msg.what) {
case MSG_HIDE_PREVIEW:
- hidePreview();
+ candidateView.hidePreview();
break;
case MSG_UPDATE_SUGGESTION:
- updateSuggestions();
+ candidateView.updateSuggestions();
break;
}
}
@@ -175,14 +184,13 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mPreviewPopup.setContentView(mPreviewText);
mPreviewPopup.setBackgroundDrawable(null);
- mCandidatePadding = res.getDimensionPixelOffset(R.dimen.candidate_padding);
+ mCandidatesStrip = findViewById(R.id.candidates_strip);
mCandidateStripHeight = res.getDimensionPixelOffset(R.dimen.candidate_strip_height);
for (int i = 0; i < MAX_SUGGESTIONS; i++) {
final TextView word, info;
switch (i) {
case 0:
word = (TextView)findViewById(R.id.word_left);
- word.setPadding(mCandidatePadding, 0, 0, 0);
info = (TextView)findViewById(R.id.info_left);
break;
case 1:
@@ -206,11 +214,15 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mInfos.add(info);
if (i > 0) {
final View divider = inflater.inflate(R.layout.candidate_divider, null);
- divider.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC);
+ divider.measure(MATCH_PARENT, MATCH_PARENT);
mDividers.add(divider);
}
}
+ mTouchToSave = findViewById(R.id.touch_to_save);
+ mWordToSave = (TextView)findViewById(R.id.word_to_save);
+ mWordToSave.setOnClickListener(this);
+
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.CandidateView, defStyle, R.style.CandidateViewStyle);
mAutoCorrectHighlight = a.getInt(R.styleable.CandidateView_autoCorrectHighlight, 0);
@@ -267,12 +279,14 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
}
}
- private CharSequence getStyledCandidateWord(CharSequence word, boolean isAutoCorrect) {
+ private CharSequence getStyledCandidateWord(CharSequence word, TextView v,
+ boolean isAutoCorrect) {
+ v.setTypeface(Typeface.DEFAULT);
if (!isAutoCorrect)
return word;
final Spannable spannedWord = new SpannableString(word);
if ((mAutoCorrectHighlight & AUTO_CORRECT_BOLD) != 0)
- spannedWord.setSpan(BOLD_SPAN, 0, word.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ v.setTypeface(Typeface.DEFAULT_BOLD);
if ((mAutoCorrectHighlight & AUTO_CORRECT_UNDERLINE) != 0)
spannedWord.setSpan(UNDERLINE_SPAN, 0, word.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
return spannedWord;
@@ -309,7 +323,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
int fromIndex = NUM_CANDIDATES_IN_STRIP;
final int count = Math.min(mWords.size(), suggestions.size());
closeCandidatesPane();
- mExpandCandidatesPane.setEnabled(count >= NUM_CANDIDATES_IN_STRIP);
+ mExpandCandidatesPane.setVisibility(count > NUM_CANDIDATES_IN_STRIP ? VISIBLE : GONE);
for (int i = 0; i < count; i++) {
final CharSequence suggestion = suggestions.getWord(i);
if (suggestion == null) continue;
@@ -330,11 +344,15 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
// the word when space is typed (valid typed word or auto corrected word).
word.setTextColor(getCandidateTextColor(isAutoCorrect,
isSuggestedCandidate || isPunctuationSuggestions, suggestionInfo));
- word.setText(getStyledCandidateWord(suggestion, isAutoCorrect));
- // TODO: call TextView.setTextScaleX() to fit the candidate in single line.
- word.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC);
- final int width = word.getMeasuredWidth();
- final int height = word.getMeasuredHeight();
+ final CharSequence text = getStyledCandidateWord(suggestion, word, isAutoCorrect);
+ if (i < NUM_CANDIDATES_IN_STRIP) {
+ final View parent = (View)word.getParent();
+ final int width = parent.getWidth() - word.getPaddingLeft()
+ - word.getPaddingRight();
+ setTextWithAutoScaleAndEllipsis(text, width, word);
+ } else {
+ setTextWithAutoScaleAndEllipsis(text, paneWidth, word);
+ }
final TextView info;
if (DBG && suggestionInfo != null
@@ -342,18 +360,23 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
info = mInfos.get(i);
info.setText(suggestionInfo.getDebugString());
info.setVisibility(View.VISIBLE);
- info.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC);
} else {
info = null;
}
if (i < NUM_CANDIDATES_IN_STRIP) {
if (info != null) {
+ word.measure(MATCH_PARENT, MATCH_PARENT);
+ info.measure(MATCH_PARENT, MATCH_PARENT);
+ final int width = word.getMeasuredWidth();
final int infoWidth = info.getMeasuredWidth();
FrameLayoutCompatUtils.placeViewAt(
- info, x + width - infoWidth, y, infoWidth, info.getMeasuredHeight());
+ info, width - infoWidth, 0, infoWidth, info.getMeasuredHeight());
}
} else {
+ word.measure(MATCH_PARENT, MATCH_PARENT);
+ final int width = word.getMeasuredWidth();
+ final int height = word.getMeasuredHeight();
// TODO: Handle overflow case.
if (dividerWidth + x + width >= paneWidth) {
centeringCandidates(fromIndex, i - 1, x, paneWidth);
@@ -374,6 +397,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
word, x, y + (mCandidateStripHeight - height) / 2, width, height);
if (info != null) {
mCandidatesPane.addView(info);
+ info.measure(MATCH_PARENT, MATCH_PARENT);
final int infoWidth = info.getMeasuredWidth();
FrameLayoutCompatUtils.placeViewAt(
info, x + width - infoWidth, y, infoWidth, info.getMeasuredHeight());
@@ -412,6 +436,60 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
}
}
+ private static void setTextWithAutoScaleAndEllipsis(CharSequence text, int w, TextView v) {
+ // To prevent partially rendered character at the end of text, subtract few extra pixels
+ // from the width.
+ final int width = w - 4;
+
+ final TextPaint paint = v.getPaint();
+ final int textWidth = getTextWidth(text, paint, 1.0f);
+ if (textWidth < width || textWidth == 0 || width <= 0) {
+ v.setTextScaleX(1.0f);
+ v.setText(text);
+ return;
+ }
+
+ final float scaleX = Math.min((float)width / textWidth, 1.0f);
+ if (scaleX >= MIN_TEXT_XSCALE) {
+ v.setTextScaleX(scaleX);
+ v.setText(text);
+ return;
+ }
+
+ final int truncatedWidth = width - getTextWidth(ELLIPSIS, paint, MIN_TEXT_XSCALE);
+ final CharSequence ellipsized = getTextEllipsizedAtStart(text, paint, truncatedWidth);
+ v.setTextScaleX(MIN_TEXT_XSCALE);
+ v.setText(ELLIPSIS);
+ v.append(ellipsized);
+ }
+
+ private static int getTextWidth(CharSequence text, TextPaint paint, float scaleX) {
+ if (TextUtils.isEmpty(text)) return 0;
+ final int len = text.length();
+ final float[] widths = new float[len];
+ paint.setTextScaleX(scaleX);
+ final int count = paint.getTextWidths(text, 0, len, widths);
+ float width = 0;
+ for (int i = 0; i < count; i++) {
+ width += widths[i];
+ }
+ return (int)Math.round(width + 0.5);
+ }
+
+ private static CharSequence getTextEllipsizedAtStart(CharSequence text, TextPaint paint,
+ int maxWidth) {
+ final int len = text.length();
+ final float[] widths = new float[len];
+ final int count = paint.getTextWidths(text, 0, len, widths);
+ float width = 0;
+ for (int i = count - 1; i >= 0; i--) {
+ width += widths[i];
+ if (width > maxWidth)
+ return text.subSequence(i + 1, len);
+ }
+ return text;
+ }
+
private void expandCandidatesPane() {
mExpandCandidatesPane.setVisibility(View.GONE);
mCloseCandidatesPane.setVisibility(View.VISIBLE);
@@ -446,14 +524,10 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
}
public void showAddToDictionaryHint(CharSequence word) {
- SuggestedWords.Builder builder = new SuggestedWords.Builder()
- .addWord(word)
- .addWord(getContext().getText(R.string.hint_add_to_dictionary));
- setSuggestions(builder.build());
+ mWordToSave.setText(word);
mShowingAddToDictionary = true;
- // Disable R.string.hint_add_to_dictionary button
- TextView tv = mWords.get(1);
- tv.setClickable(false);
+ mCandidatesStrip.setVisibility(View.GONE);
+ mTouchToSave.setVisibility(View.VISIBLE);
}
public boolean dismissAddToDictionaryHint() {
@@ -473,6 +547,8 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mWords.get(i).setText(null);
mInfos.get(i).setVisibility(View.GONE);
}
+ mTouchToSave.setVisibility(View.GONE);
+ mCandidatesStrip.setVisibility(View.VISIBLE);
mCandidatesPane.removeAllViews();
}
@@ -528,6 +604,12 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
@Override
public void onClick(View view) {
+ if (view == mWordToSave) {
+ addToDictionary(((TextView)view).getText());
+ clear();
+ return;
+ }
+
final Object tag = view.getTag();
if (!(tag instanceof Integer))
return;
@@ -536,11 +618,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
return;
final CharSequence word = mSuggestions.getWord(index);
- if (mShowingAddToDictionary && index == 0) {
- addToDictionary(word);
- } else {
- mListener.pickSuggestionManually(index, word);
- }
+ mListener.pickSuggestionManually(index, word);
// Because some punctuation letters are not treated as word separator depending on locale,
// {@link #setSuggestions} might not be called and candidates pane left opened.
closeCandidatesPane();
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 9c6465dd2..52935ef7d 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -29,7 +29,6 @@ import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.os.Debug;
-import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.SystemClock;
@@ -206,9 +205,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private CharSequence mEnteredText;
- public final UIHandler mHandler = new UIHandler();
+ public final UIHandler mHandler = new UIHandler(this);
- public class UIHandler extends Handler {
+ public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> {
private static final int MSG_UPDATE_SUGGESTIONS = 0;
private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1;
private static final int MSG_UPDATE_SHIFT_STATE = 2;
@@ -218,42 +217,50 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private static final int MSG_SPACE_TYPED = 6;
private static final int MSG_SET_BIGRAM_PREDICTIONS = 7;
+ public UIHandler(LatinIME outerInstance) {
+ super(outerInstance);
+ }
+
@Override
public void handleMessage(Message msg) {
- final KeyboardSwitcher switcher = mKeyboardSwitcher;
+ final LatinIME latinIme = getOuterInstance();
+ final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher;
final LatinKeyboardView inputView = switcher.getKeyboardView();
switch (msg.what) {
case MSG_UPDATE_SUGGESTIONS:
- updateSuggestions();
+ latinIme.updateSuggestions();
break;
case MSG_UPDATE_OLD_SUGGESTIONS:
- mRecorrection.fetchAndDisplayRecorrectionSuggestions(mVoiceProxy, mCandidateView,
- mSuggest, mKeyboardSwitcher, mWord, mHasUncommittedTypedChars,
- mLastSelectionStart, mLastSelectionEnd, mSettingsValues.mWordSeparators);
+ latinIme.mRecorrection.fetchAndDisplayRecorrectionSuggestions(
+ latinIme.mVoiceProxy, latinIme.mCandidateView,
+ latinIme.mSuggest, latinIme.mKeyboardSwitcher, latinIme.mWord,
+ latinIme.mHasUncommittedTypedChars, latinIme.mLastSelectionStart,
+ latinIme.mLastSelectionEnd, latinIme.mSettingsValues.mWordSeparators);
break;
case MSG_UPDATE_SHIFT_STATE:
switcher.updateShiftState();
break;
case MSG_SET_BIGRAM_PREDICTIONS:
- updateBigramPredictions();
+ latinIme.updateBigramPredictions();
break;
case MSG_VOICE_RESULTS:
- mVoiceProxy.handleVoiceResults(preferCapitalization()
+ latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization()
|| (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked()));
break;
case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR:
if (inputView != null) {
inputView.setSpacebarTextFadeFactor(
- (1.0f + mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar) / 2,
+ (1.0f + latinIme.mSettingsValues.
+ mFinalFadeoutFactorOfLanguageOnSpacebar) / 2,
(LatinKeyboard)msg.obj);
}
sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj),
- mSettingsValues.mDurationOfFadeoutLanguageOnSpacebar);
+ latinIme.mSettingsValues.mDurationOfFadeoutLanguageOnSpacebar);
break;
case MSG_DISMISS_LANGUAGE_ON_SPACEBAR:
if (inputView != null) {
inputView.setSpacebarTextFadeFactor(
- mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar,
+ latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar,
(LatinKeyboard)msg.obj);
}
break;
@@ -263,7 +270,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public void postUpdateSuggestions() {
removeMessages(MSG_UPDATE_SUGGESTIONS);
sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS),
- mSettingsValues.mDelayUpdateSuggestions);
+ getOuterInstance().mSettingsValues.mDelayUpdateSuggestions);
}
public void cancelUpdateSuggestions() {
@@ -277,7 +284,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public void postUpdateOldSuggestions() {
removeMessages(MSG_UPDATE_OLD_SUGGESTIONS);
sendMessageDelayed(obtainMessage(MSG_UPDATE_OLD_SUGGESTIONS),
- mSettingsValues.mDelayUpdateOldSuggestions);
+ getOuterInstance().mSettingsValues.mDelayUpdateOldSuggestions);
}
public void cancelUpdateOldSuggestions() {
@@ -287,7 +294,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public void postUpdateShiftKeyState() {
removeMessages(MSG_UPDATE_SHIFT_STATE);
sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE),
- mSettingsValues.mDelayUpdateShiftState);
+ getOuterInstance().mSettingsValues.mDelayUpdateShiftState);
}
public void cancelUpdateShiftState() {
@@ -297,7 +304,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public void postUpdateBigramPredictions() {
removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS),
- mSettingsValues.mDelayUpdateSuggestions);
+ getOuterInstance().mSettingsValues.mDelayUpdateSuggestions);
}
public void cancelUpdateBigramPredictions() {
@@ -309,23 +316,26 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
public void startDisplayLanguageOnSpacebar(boolean localeChanged) {
+ final LatinIME latinIme = getOuterInstance();
removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR);
removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR);
- final LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
+ final LatinKeyboardView inputView = latinIme.mKeyboardSwitcher.getKeyboardView();
if (inputView != null) {
- final LatinKeyboard keyboard = mKeyboardSwitcher.getLatinKeyboard();
+ final LatinKeyboard keyboard = latinIme.mKeyboardSwitcher.getLatinKeyboard();
// The language is always displayed when the delay is negative.
final boolean needsToDisplayLanguage = localeChanged
- || mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar < 0;
+ || latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar < 0;
// The language is never displayed when the delay is zero.
- if (mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar != 0) {
+ if (latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar != 0) {
inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f
- : mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar, keyboard);
+ : latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar,
+ keyboard);
}
// The fadeout animation will start when the delay is positive.
- if (localeChanged && mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar > 0) {
+ if (localeChanged
+ && latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar > 0) {
sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard),
- mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar);
+ latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar);
}
}
}
@@ -333,7 +343,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public void startDoubleSpacesTimer() {
removeMessages(MSG_SPACE_TYPED);
sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED),
- mSettingsValues.mDoubleSpacesTurnIntoPeriodTimeout);
+ getOuterInstance().mSettingsValues.mDoubleSpacesTurnIntoPeriodTimeout);
}
public void cancelDoubleSpacesTimer() {
diff --git a/java/src/com/android/inputmethod/latin/StaticInnerHandlerWrapper.java b/java/src/com/android/inputmethod/latin/StaticInnerHandlerWrapper.java
new file mode 100644
index 000000000..89d9ea844
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/StaticInnerHandlerWrapper.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import java.lang.ref.WeakReference;
+
+public class StaticInnerHandlerWrapper<T> extends Handler {
+ final private WeakReference<T> mOuterInstanceRef;
+
+ public StaticInnerHandlerWrapper(T outerInstance) {
+ super();
+ if (outerInstance == null) throw new NullPointerException("outerInstance is null");
+ mOuterInstanceRef = new WeakReference<T>(outerInstance);
+ }
+
+ public StaticInnerHandlerWrapper(T outerInstance, Looper looper) {
+ super(looper);
+ if (outerInstance == null) throw new NullPointerException("outerInstance is null");
+ mOuterInstanceRef = new WeakReference<T>(outerInstance);
+ }
+
+ public T getOuterInstance() {
+ return mOuterInstanceRef.get();
+ }
+}