aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java60
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java316
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboard.java71
-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/keyboard/internal/SlidingLocaleDrawable.java31
-rw-r--r--java/src/com/android/inputmethod/latin/CandidateView.java130
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java13
11 files changed, 377 insertions, 298 deletions
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/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 6a60a9ddf..da738b24c 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -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
@@ -96,42 +100,51 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
// Miscellaneous constants
private static final int[] LONG_PRESSABLE_STATE_SET = { android.R.attr.state_long_pressable };
- 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;
private final float mBackgroundDimAmount;
private final float mKeyHysteresisDistance;
private final float mVerticalCorrection;
+ private final Drawable mPreviewBackground;
+ private final Drawable mPreviewLeftBackground;
+ private final Drawable mPreviewRightBackground;
+ private final Drawable mPreviewSpacebarBackground;
+ private final int mPreviewTextColor;
+ private final float mPreviewTextRatio;
private final int mPreviewOffset;
private final int mPreviewHeight;
private final int mPopupLayout;
- private final Drawable mKeyPopupHintIcon;
private final int mKeyHintLetterColor;
+ private final int mKeyHintLabelColor;
private final int mKeyUppercaseLetterInactivatedColor;
private final int mKeyUppercaseLetterActivatedColor;
+ // HORIZONTAL ELLIPSIS "...", character for popup hint.
+ private static final String POPUP_HINT_CHAR = "\u2026";
+
// 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;
- private TextView mPreviewText;
- private Drawable mPreviewBackground;
- private float mPreviewTextRatio;
+ private final TextView mPreviewText;
private int mPreviewTextSize;
private boolean mShowKeyPreviewPopup = true;
private final int mDelayBeforePreview;
@@ -182,7 +195,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,6 +205,9 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
private static final String KEY_LABEL_REFERENCE_CHAR = "M";
private final int mKeyLabelHorizontalPadding;
+ private static final int MEASURESPEC_UNSPECIFIED = MeasureSpec.makeMeasureSpec(
+ 0, MeasureSpec.UNSPECIFIED);
+
private final UIHandler mHandler = new UIHandler(this);
public static class UIHandler extends StaticInnerHandlerWrapper<KeyboardView> {
@@ -334,19 +349,35 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
R.styleable.KeyboardView_keyHysteresisDistance, 0);
mVerticalCorrection = a.getDimensionPixelOffset(
R.styleable.KeyboardView_verticalCorrection, 0);
+ mPreviewTextColor = a.getColor(R.styleable.KeyboardView_keyPreviewTextColor, 0);
final int previewLayout = a.getResourceId(R.styleable.KeyboardView_keyPreviewLayout, 0);
+ if (previewLayout != 0) {
+ mPreviewText = (TextView) LayoutInflater.from(context).inflate(previewLayout, null);
+ mPreviewText.setTextColor(mPreviewTextColor);
+ } else {
+ mPreviewText = null;
+ mShowKeyPreviewPopup = false;
+ }
+ mPreviewBackground = a.getDrawable(R.styleable.KeyboardView_keyPreviewBackground);
+ mPreviewLeftBackground = a.getDrawable(R.styleable.KeyboardView_keyPreviewLeftBackground);
+ mPreviewRightBackground = a.getDrawable(R.styleable.KeyboardView_keyPreviewRightBackground);
+ mPreviewSpacebarBackground = a.getDrawable(
+ R.styleable.KeyboardView_keyPreviewSpacebarBackground);
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(
@@ -362,13 +393,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
final Resources res = getResources();
- 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;
- }
mDelayBeforePreview = res.getInteger(R.integer.config_delay_before_preview);
mDelayAfterPreview = res.getInteger(R.integer.config_delay_after_preview);
mKeyLabelHorizontalPadding = (int)res.getDimension(
@@ -462,11 +486,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();
@@ -521,10 +540,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);
}
@@ -587,7 +608,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;
}
@@ -689,6 +710,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();
@@ -704,47 +727,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 {
@@ -757,124 +781,128 @@ 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 "...".
- // TODO: Draw "..." by text.
+ // Draw popup hint "..." at the bottom right corner of the key.
if (key.hasPopupHint()) {
- final int drawableWidth = keyDrawWidth;
- final int drawableHeight = key.mHeight;
- final int drawableX = 0;
- final int drawableY = HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL;
- final Drawable hintIcon = mKeyPopupHintIcon;
- drawIcon(canvas, hintIcon, drawableX, drawableY, drawableWidth, drawableHeight);
- if (DEBUG_SHOW_ALIGN)
- drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight,
- 0x80c0c000, new Paint());
+ paint.setTextSize(mKeyHintLetterSize);
+ paint.setColor(mKeyHintLabelColor);
+ final int hintX = keyDrawWidth - getLabelCharWidth(paint);
+ // Using y-coordinate "key.mHeight - paint.descent()" draws "..." just on the bottom
+ // edge of the key. So we use slightly higher position by multiply descent length by 2.
+ final int hintY = key.mHeight - (int)paint.descent() * 2;
+ canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, 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,
@@ -909,10 +937,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
canvas.translate(-x, -y);
}
- public void setForeground(boolean foreground) {
- mInForeground = foreground;
- }
-
// TODO: clean up this method.
private void dismissAllKeyPreviews() {
for (PointerTracker tracker : mPointerTrackers) {
@@ -921,6 +945,10 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
}
}
+ public void cancelAllMessage() {
+ mHandler.cancelAllMessages();
+ }
+
@Override
public void showKeyPreview(int keyIndex, PointerTracker tracker) {
if (mShowKeyPreviewPopup) {
@@ -965,7 +993,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
// If keyIndex is invalid or IME is already closed, we must not show key preview.
// Trying to show key preview while root window is closed causes
// WindowManager.BadTokenException.
- if (key == null || !mInForeground)
+ if (key == null)
return;
mHandler.cancelAllDismissKeyPreviews();
@@ -991,25 +1019,29 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
previewText.setText(null);
}
if (key.mCode == Keyboard.CODE_SPACE) {
- previewText.setBackgroundColor(Color.TRANSPARENT);
+ previewText.setBackgroundDrawable(mPreviewSpacebarBackground);
} else {
previewText.setBackgroundDrawable(mPreviewBackground);
}
- // Set the preview background state
- previewText.getBackground().setState(
- key.mPopupCharacters != null ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
- previewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ previewText.measure(MEASURESPEC_UNSPECIFIED, MEASURESPEC_UNSPECIFIED);
final int previewWidth = Math.max(previewText.getMeasuredWidth(), keyDrawWidth
+ previewText.getPaddingLeft() + previewText.getPaddingRight());
final int previewHeight = mPreviewHeight;
getLocationInWindow(mCoordinates);
- final int previewX = keyDrawX - (previewWidth - keyDrawWidth) / 2 + mCoordinates[0];
+ int previewX = keyDrawX - (previewWidth - keyDrawWidth) / 2 + mCoordinates[0];
final int previewY = key.mY - previewHeight + mCoordinates[1] + mPreviewOffset;
+ if (previewX < 0 && mPreviewLeftBackground != null) {
+ previewText.setBackgroundDrawable(mPreviewLeftBackground);
+ previewX = 0;
+ } else if (previewX + previewWidth > getWidth() && mPreviewRightBackground != null) {
+ previewText.setBackgroundDrawable(mPreviewRightBackground);
+ previewX = getWidth() - previewWidth;
+ }
- // Place the key preview.
- // TODO: Adjust position of key previews which touch screen edges
+ // Set the preview background state
+ previewText.getBackground().setState(
+ key.mPopupCharacters != null ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
FrameLayoutCompatUtils.placeViewAt(
previewText, previewX, previewY, previewWidth, previewHeight);
previewText.setVisibility(VISIBLE);
@@ -1126,7 +1158,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
miniKeyboardView.setKeyboard(keyboard);
container.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ MEASURESPEC_UNSPECIFIED);
return miniKeyboardView;
}
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
index 00bf348f2..9d58f69ff 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
@@ -23,9 +23,6 @@ import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.PorterDuff;
@@ -61,8 +58,6 @@ public class LatinKeyboard extends Keyboard {
private final int mSpaceKeyIndex;
private final boolean mAutoCorrectionSpacebarLedEnabled;
private final Drawable mAutoCorrectionSpacebarLedIcon;
- private final Drawable mSpacebarArrowLeftIcon;
- private final Drawable mSpacebarArrowRightIcon;
private final int mSpacebarTextColor;
private final int mSpacebarTextShadowColor;
private float mSpacebarTextFadeFactor = 0.0f;
@@ -77,6 +72,11 @@ public class LatinKeyboard extends Keyboard {
private final Drawable mEnabledShortcutIcon;
private final Drawable mDisabledShortcutIcon;
+ // BLACK LEFT-POINTING TRIANGLE and two spaces.
+ public static final String ARROW_LEFT = "\u25C0 ";
+ // Two spaces and BLACK RIGHT-POINTING TRIANGLE.
+ public static final String ARROW_RIGHT = " \u25B6";
+
// Minimum width of spacebar dragging to trigger the language switch (represented by the number
// of the most common key width of this keyboard).
private static final int SPACEBAR_DRAG_WIDTH = 3;
@@ -131,10 +131,6 @@ public class LatinKeyboard extends Keyboard {
mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboard_spacebarTextColor, 0);
mSpacebarTextShadowColor = a.getColor(
R.styleable.LatinKeyboard_spacebarTextShadowColor, 0);
- mSpacebarArrowLeftIcon = a.getDrawable(
- R.styleable.LatinKeyboard_spacebarArrowLeftIcon);
- mSpacebarArrowRightIcon = a.getDrawable(
- R.styleable.LatinKeyboard_spacebarArrowRightIcon);
a.recycle();
// The threshold is "key width" x 1.25
@@ -165,12 +161,6 @@ public class LatinKeyboard extends Keyboard {
return newColor;
}
- private static ColorFilter getSpacebarDrawableFilter(float fadeFactor) {
- final ColorMatrix colorMatrix = new ColorMatrix();
- colorMatrix.setScale(1, 1, 1, fadeFactor);
- return new ColorMatrixColorFilter(colorMatrix);
- }
-
public void updateShortcutKey(boolean available, LatinKeyboardView view) {
if (mShortcutKey == null)
return;
@@ -214,52 +204,40 @@ public class LatinKeyboard extends Keyboard {
}
// Layout local language name and left and right arrow on spacebar.
- private static String layoutSpacebar(Paint paint, Locale locale, Drawable icon, Drawable lArrow,
- Drawable rArrow, int width, int height, float origTextSize) {
- final float arrowWidth = lArrow.getIntrinsicWidth();
- final float arrowHeight = lArrow.getIntrinsicHeight();
- final float maxTextWidth = width - (arrowWidth + arrowWidth);
+ private static String layoutSpacebar(Paint paint, Locale locale, int width,
+ float origTextSize) {
final Rect bounds = new Rect();
// Estimate appropriate language name text size to fit in maxTextWidth.
- String language = SubtypeSwitcher.getFullDisplayName(locale, true);
+ String language = ARROW_LEFT + SubtypeSwitcher.getFullDisplayName(locale, true)
+ + ARROW_RIGHT;
int textWidth = getTextWidth(paint, language, origTextSize, bounds);
// Assuming text width and text size are proportional to each other.
- float textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f);
+ float textSize = origTextSize * Math.min(width / textWidth, 1.0f);
// allow variable text size
textWidth = getTextWidth(paint, language, textSize, bounds);
// If text size goes too small or text does not fit, use middle or short name
final boolean useMiddleName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
- || (textWidth > maxTextWidth);
+ || (textWidth > width);
final boolean useShortName;
if (useMiddleName) {
- language = SubtypeSwitcher.getMiddleDisplayLanguage(locale);
+ language = ARROW_LEFT + SubtypeSwitcher.getMiddleDisplayLanguage(locale) + ARROW_RIGHT;
textWidth = getTextWidth(paint, language, origTextSize, bounds);
- textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f);
+ textSize = origTextSize * Math.min(width / textWidth, 1.0f);
useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
- || (textWidth > maxTextWidth);
+ || (textWidth > width);
} else {
useShortName = false;
}
if (useShortName) {
- language = SubtypeSwitcher.getShortDisplayLanguage(locale);
+ language = ARROW_LEFT + SubtypeSwitcher.getShortDisplayLanguage(locale) + ARROW_RIGHT;
textWidth = getTextWidth(paint, language, origTextSize, bounds);
- textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f);
+ textSize = origTextSize * Math.min(width / textWidth, 1.0f);
}
paint.setTextSize(textSize);
- // Place left and right arrow just before and after language text.
- final float textHeight = -paint.ascent() + paint.descent();
- final float baseline = (icon != null) ? height * SPACEBAR_LANGUAGE_BASELINE
- : height / 2 + textHeight / 2;
- final int top = (int)(baseline - arrowHeight);
- final float remains = (width - textWidth) / 2;
- lArrow.setBounds((int)(remains - arrowWidth), top, (int)remains, (int)baseline);
- rArrow.setBounds((int)(remains + textWidth), top, (int)(remains + textWidth + arrowWidth),
- (int)baseline);
-
return language;
}
@@ -304,9 +282,8 @@ public class LatinKeyboard extends Keyboard {
defaultTextSize = 14;
}
- final String language = layoutSpacebar(paint, inputLocale, mSpaceIcon,
- mSpacebarArrowLeftIcon, mSpacebarArrowRightIcon, width, height,
- getTextSizeFromTheme(mTheme, textStyle, defaultTextSize));
+ final String language = layoutSpacebar(paint, inputLocale, width, getTextSizeFromTheme(
+ mTheme, textStyle, defaultTextSize));
// Draw language text with shadow
// In case there is no space icon, we will place the language text at the center of
@@ -319,18 +296,6 @@ public class LatinKeyboard extends Keyboard {
canvas.drawText(language, width / 2, baseline - descent - 1, paint);
paint.setColor(getSpacebarTextColor(mSpacebarTextColor, textFadeFactor));
canvas.drawText(language, width / 2, baseline - descent, paint);
-
- // Put arrows that are already laid out on either side of the text
- // Because language switch is disabled on phone and number layouts, hide arrows.
- // TODO: Sort out how to enable language switch on these layouts.
- if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()
- && mSubtypeSwitcher.getEnabledKeyboardLocaleCount() > 1
- && !(isPhoneKeyboard() || isNumberKeyboard())) {
- mSpacebarArrowLeftIcon.setColorFilter(getSpacebarDrawableFilter(textFadeFactor));
- mSpacebarArrowRightIcon.setColorFilter(getSpacebarDrawableFilter(textFadeFactor));
- mSpacebarArrowLeftIcon.draw(canvas);
- mSpacebarArrowRightIcon.draw(canvas);
- }
}
// Draw the spacebar icon at the bottom
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/keyboard/internal/SlidingLocaleDrawable.java b/java/src/com/android/inputmethod/keyboard/internal/SlidingLocaleDrawable.java
index f8c81adfb..ef3ea4c12 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/SlidingLocaleDrawable.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/SlidingLocaleDrawable.java
@@ -46,8 +46,7 @@ public class SlidingLocaleDrawable extends Drawable {
private final int mSpacebarTextColor;
private final TextPaint mTextPaint;
private final int mMiddleX;
- private final Drawable mLeftDrawable;
- private final Drawable mRightDrawable;
+ private final boolean mDrawArrows;
private final int mThreshold;
private int mDiff;
@@ -65,16 +64,17 @@ public class SlidingLocaleDrawable extends Drawable {
textPaint.setTextSize(LatinKeyboard.getTextSizeFromTheme(
context.getTheme(), android.R.style.TextAppearance_Medium, 18));
textPaint.setColor(Color.TRANSPARENT);
- textPaint.setTextAlign(Align.CENTER);
textPaint.setAntiAlias(true);
mTextPaint = textPaint;
mMiddleX = (background != null) ? (mWidth - mBackground.getIntrinsicWidth()) / 2 : 0;
final TypedArray a = context.obtainStyledAttributes(
- null, R.styleable.LatinKeyboard, R.attr.latinKeyboardStyle, R.style.LatinKeyboard);
- mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboard_spacebarTextColor, 0);
- mLeftDrawable = a.getDrawable(R.styleable.LatinKeyboard_spacebarArrowPreviewLeftIcon);
- mRightDrawable = a.getDrawable(R.styleable.LatinKeyboard_spacebarArrowPreviewRightIcon);
+ null, R.styleable.KeyboardView, R.attr.keyboardViewStyle, R.style.KeyboardView);
+ mSpacebarTextColor = a.getColor(R.styleable.KeyboardView_keyPreviewTextColor, 0);
+ final int spacebarPreviewBackrgound = a.getResourceId(
+ R.styleable.KeyboardView_keyPreviewSpacebarBackground, 0);
+ // If spacebar preview background is transparent, we need not draw arrows.
+ mDrawArrows = (spacebarPreviewBackrgound != R.drawable.transparent);
a.recycle();
mThreshold = ViewConfiguration.get(context).getScaledTouchSlop();
@@ -102,8 +102,6 @@ public class SlidingLocaleDrawable extends Drawable {
final int width = mWidth;
final int height = mHeight;
final int diff = mDiff;
- final Drawable lArrow = mLeftDrawable;
- final Drawable rArrow = mRightDrawable;
canvas.clipRect(0, 0, width, height);
if (mCurrentLanguage == null) {
SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
@@ -111,20 +109,19 @@ public class SlidingLocaleDrawable extends Drawable {
mNextLanguage = subtypeSwitcher.getNextInputLanguageName();
mPrevLanguage = subtypeSwitcher.getPreviousInputLanguageName();
}
- // Draw language text with shadow
+ // Draw language text.
final float baseline = mHeight * LatinKeyboard.SPACEBAR_LANGUAGE_BASELINE
- paint.descent();
paint.setColor(mSpacebarTextColor);
+ paint.setTextAlign(Align.CENTER);
canvas.drawText(mCurrentLanguage, width / 2 + diff, baseline, paint);
canvas.drawText(mNextLanguage, diff - width / 2, baseline, paint);
canvas.drawText(mPrevLanguage, diff + width + width / 2, baseline, paint);
-
- if (lArrow != null && rArrow != null) {
- Keyboard.setDefaultBounds(lArrow);
- rArrow.setBounds(width - rArrow.getIntrinsicWidth(), 0, width,
- rArrow.getIntrinsicHeight());
- lArrow.draw(canvas);
- rArrow.draw(canvas);
+ if (mDrawArrows) {
+ paint.setTextAlign(Align.LEFT);
+ canvas.drawText(LatinKeyboard.ARROW_LEFT, 0, baseline, paint);
+ paint.setTextAlign(Align.RIGHT);
+ canvas.drawText(LatinKeyboard.ARROW_RIGHT, width, baseline, paint);
}
}
if (mBackground != null) {
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index 313555daa..a5bfea0f8 100644
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -25,11 +25,11 @@ 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;
@@ -57,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;
@@ -88,11 +88,17 @@ 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 static final float MIN_TEXT_XSCALE = 0.4f;
+ private static final String ELLIPSIS = "\u2026";
+
private final UiHandler mHandler = new UiHandler(this);
private static class UiHandler extends StaticInnerHandlerWrapper<CandidateView> {
@@ -178,13 +184,13 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mPreviewPopup.setContentView(mPreviewText);
mPreviewPopup.setBackgroundDrawable(null);
+ 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(res.getDimensionPixelOffset(R.dimen.candidate_padding), 0, 0, 0);
info = (TextView)findViewById(R.id.info_left);
break;
case 1:
@@ -208,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);
@@ -269,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;
@@ -311,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;
@@ -332,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
@@ -344,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, 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);
@@ -376,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());
@@ -414,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);
@@ -448,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() {
@@ -475,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();
}
@@ -530,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;
@@ -538,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 52935ef7d..874d77f19 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -514,7 +514,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
super.setInputView(view);
mCandidateViewContainer = view.findViewById(R.id.candidates_container);
mCandidateView = (CandidateView) view.findViewById(R.id.candidates);
- mCandidateView.setListener(this, view);
+ if (mCandidateView != null)
+ mCandidateView.setListener(this, view);
mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height);
}
@@ -590,7 +591,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
inputView.setProximityCorrectionEnabled(true);
// If we just entered a text field, maybe it has some old text that requires correction
mRecorrection.checkRecorrectionOnStart();
- inputView.setForeground(true);
voiceIme.onStartInputView(inputView.getWindowToken());
@@ -678,7 +678,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public void onFinishInputView(boolean finishingInput) {
super.onFinishInputView(finishingInput);
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
- if (inputView != null) inputView.setForeground(false);
+ if (inputView != null) inputView.cancelAllMessage();
// Remove pending messages related to update suggestions
mHandler.cancelUpdateSuggestions();
mHandler.cancelUpdateOldSuggestions();
@@ -842,7 +842,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) {
// TODO: Modify this if we support candidates with hard keyboard
- if (onEvaluateInputViewShown()) {
+ if (onEvaluateInputViewShown() && mCandidateViewContainer != null) {
final boolean shouldShowCandidates = shown
&& (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true);
if (isExtractViewShown()) {
@@ -1869,6 +1869,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Notify that language or mode have been changed and toggleLanguage will update KeyboardID
// according to new language or mode.
public void onRefreshKeyboard() {
+ if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
+ // Before Honeycomb, Voice IME is in LatinIME and it changes the current input view,
+ // so that we need to re-create the keyboard input view here.
+ setInputView(mKeyboardSwitcher.onCreateInputView());
+ }
// Reload keyboard because the current language has been changed.
mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(),
mSubtypeSwitcher.isShortcutImeEnabled() && mVoiceProxy.isVoiceButtonEnabled(),