aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java3
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java20
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java3
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java10
-rw-r--r--java/src/com/android/inputmethod/keyboard/PointerTracker.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java2
-rw-r--r--java/src/com/android/inputmethod/latin/CandidateView.java361
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java59
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java2
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java35
11 files changed, 246 insertions, 257 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 518bc8e9e..f8e08b06a 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -79,8 +79,7 @@ public class Keyboard {
public static final int CODE_CANCEL = -4;
public static final int CODE_DELETE = -5;
public static final int CODE_SETTINGS = -6;
- public static final int CODE_SETTINGS_LONGPRESS = -7;
- public static final int CODE_SHORTCUT = -8;
+ public static final int CODE_SHORTCUT = -7;
// Code value representing the code is not specified.
public static final int CODE_UNSPECIFIED = -99;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
index 905f779c0..864091289 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
@@ -70,4 +70,10 @@ public interface KeyboardActionListener {
* Called when user released a finger outside any key.
*/
public void onCancelInput();
+
+ /**
+ * Send a non-"code input" custom request to the listener.
+ * @return true if the request has been consumed, false otherwise.
+ */
+ public boolean onCustomRequest(int requestCode);
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index aab58b52c..da3aa50c5 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -35,6 +35,7 @@ import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.inputmethod.compat.FrameLayoutCompatUtils;
@@ -349,8 +350,11 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
* @param keyboard the keyboard to display in this view
*/
public void setKeyboard(Keyboard keyboard) {
- // Remove any pending messages, except dismissing preview
+ // Remove any pending dismissing preview
mDrawingHandler.cancelAllShowKeyPreviews();
+ if (mKeyboard != null) {
+ PointerTracker.dismissAllKeyPreviews();
+ }
mKeyboard = keyboard;
LatinImeLogger.onSetKeyboard(keyboard);
requestLayout();
@@ -788,14 +792,15 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
private void addKeyPreview(TextView keyPreview) {
if (mPreviewPlacer == null) {
- mPreviewPlacer = FrameLayoutCompatUtils.getPlacer(
- (ViewGroup)getRootView().findViewById(android.R.id.content));
+ mPreviewPlacer = new RelativeLayout(getContext());
+ final ViewGroup windowContentView =
+ (ViewGroup)getRootView().findViewById(android.R.id.content);
+ windowContentView.addView(mPreviewPlacer);
}
- final ViewGroup placer = mPreviewPlacer;
- placer.addView(keyPreview, FrameLayoutCompatUtils.newLayoutParam(placer, 0, 0));
+ mPreviewPlacer.addView(
+ keyPreview, FrameLayoutCompatUtils.newLayoutParam(mPreviewPlacer, 0, 0));
}
- // TODO: Introduce minimum duration for displaying key previews
private void showKey(final int keyIndex, PointerTracker tracker) {
final TextView previewText = tracker.getKeyPreviewText();
// If the key preview has no parent view yet, add it to the ViewGroup which can place
@@ -914,5 +919,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
closing();
+ if (mPreviewPlacer != null) {
+ mPreviewPlacer.removeAllViews();
+ }
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
index abf28c73c..12aadcb5c 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
@@ -281,9 +281,6 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke
*/
@Override
public void setKeyboard(Keyboard keyboard) {
- if (getKeyboard() != null) {
- PointerTracker.dismissAllKeyPreviews();
- }
// Remove any pending messages, except dismissing preview
mKeyTimerHandler.cancelKeyTimers();
super.setKeyboard(keyboard);
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 04096778b..dad37e728 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -23,6 +23,7 @@ import android.util.Log;
import android.view.MotionEvent;
import com.android.inputmethod.deprecated.VoiceProxy;
+import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.Utils;
@@ -99,9 +100,14 @@ public class LatinKeyboardView extends LatinKeyboardBaseView {
}
}
if (primaryCode == Keyboard.CODE_SETTINGS || primaryCode == Keyboard.CODE_SPACE) {
- tracker.onLongPressed();
// Both long pressing settings key and space key invoke IME switcher dialog.
- return invokeOnKey(Keyboard.CODE_SETTINGS_LONGPRESS);
+ if (getKeyboardActionListener().onCustomRequest(
+ LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) {
+ tracker.onLongPressed();
+ return true;
+ } else {
+ return super.onLongPress(key, tracker);
+ }
} else {
return super.onLongPress(key, tracker);
}
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index dc2d6e4b0..1f8119a0f 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -151,6 +151,8 @@ public class PointerTracker {
public void onTextInput(CharSequence text) {}
@Override
public void onCancelInput() {}
+ @Override
+ public boolean onCustomRequest(int requestCode) { return false; }
};
public static void init(boolean hasDistinctMultitouch, Context context) {
diff --git a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
index dfaaa707c..fb932e3e8 100644
--- a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
@@ -79,6 +79,8 @@ public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel {
public void onRelease(int primaryCode, boolean withSliding) {
mParentKeyboardView.getKeyboardActionListener().onRelease(primaryCode, withSliding);
}
+ @Override
+ public boolean onCustomRequest(int requestCode) { return false; }
};
public PopupMiniKeyboardView(Context context, AttributeSet attrs) {
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index 915e73ccb..d779c8565 100644
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -38,6 +38,7 @@ import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
@@ -50,8 +51,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.util.ArrayList;
import java.util.List;
-public class CandidateView extends LinearLayout implements OnClickListener {
-
+public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener {
public interface Listener {
public boolean addWordToDictionary(String word);
public void pickSuggestionManually(int index, CharSequence word);
@@ -65,9 +65,6 @@ public class CandidateView extends LinearLayout implements OnClickListener {
private static final boolean DBG = LatinImeLogger.sDBG;
private final ViewGroup mCandidatesStrip;
- private final ViewGroup mCandidatesPaneControl;
- private final TextView mExpandCandidatesPane;
- private final TextView mCloseCandidatesPane;
private ViewGroup mCandidatesPane;
private ViewGroup mCandidatesPaneContainer;
private View mKeyboardView;
@@ -89,7 +86,7 @@ public class CandidateView extends LinearLayout implements OnClickListener {
private final SuggestionsStripParams mStripParams;
private final SuggestionsPaneParams mPaneParams;
- private static final float MIN_TEXT_XSCALE = 0.75f;
+ private static final float MIN_TEXT_XSCALE = 0.70f;
private final UiHandler mHandler = new UiHandler(this);
@@ -146,7 +143,6 @@ public class CandidateView extends LinearLayout implements OnClickListener {
public final int mPadding;
public final int mDividerWidth;
public final int mDividerHeight;
- public final int mControlWidth;
public final int mCandidateStripHeight;
protected final List<TextView> mWords;
@@ -154,7 +150,7 @@ public class CandidateView extends LinearLayout implements OnClickListener {
protected final List<TextView> mInfos;
protected CandidateViewParams(List<TextView> words, List<View> dividers,
- List<TextView> infos, View control) {
+ List<TextView> infos) {
mWords = words;
mDividers = dividers;
mInfos = infos;
@@ -165,7 +161,6 @@ public class CandidateView extends LinearLayout implements OnClickListener {
divider.measure(WRAP_CONTENT, MATCH_PARENT);
mDividerWidth = divider.getMeasuredWidth();
mDividerHeight = divider.getMeasuredHeight();
- mControlWidth = control.getMeasuredWidth();
final Resources res = word.getResources();
mCandidateStripHeight = res.getDimensionPixelOffset(R.dimen.candidate_strip_height);
@@ -174,8 +169,8 @@ public class CandidateView extends LinearLayout implements OnClickListener {
private static class SuggestionsPaneParams extends CandidateViewParams {
public SuggestionsPaneParams(List<TextView> words, List<View> dividers,
- List<TextView> infos, View control) {
- super(words, dividers, infos, control);
+ List<TextView> infos) {
+ super(words, dividers, infos);
}
public int layout(SuggestedWords suggestions, ViewGroup paneView, int from, int textColor,
@@ -259,12 +254,16 @@ public class CandidateView extends LinearLayout implements OnClickListener {
private static class SuggestionsStripParams extends CandidateViewParams {
private static final int DEFAULT_CANDIDATE_COUNT_IN_STRIP = 3;
+ private static final int DEFAULT_CENTER_CANDIDATE_PERCENTILE = 40;
private static final int PUNCTUATIONS_IN_STRIP = 6;
private final int mColorTypedWord;
private final int mColorAutoCorrect;
private final int mColorSuggestedCandidate;
private final int mCandidateCountInStrip;
+ private final float mCenterCandidateWeight;
+ private final int mCenterCandidateIndex;
+ private final Drawable mMoreCandidateHint;
private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
@@ -278,21 +277,12 @@ public class CandidateView extends LinearLayout implements OnClickListener {
private final int mAutoCorrectHighlight;
private final ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>();
- private SuggestedWords mSuggestedWords;
-
- private int mCountInStrip;
- // True if the mCountInStrip suggestions can fit in suggestion strip in equally divided
- // width without squeezing the text.
- private boolean mCanUseFixedWidthColumns;
- private int mMaxWidth;
- private int mAvailableWidthForWords;
- private int mConstantWidthForPaddings;
- private int mVariableWidthForWords;
- private float mScaleX;
+
+ public boolean mMoreSuggestionsAvailable;
public SuggestionsStripParams(Context context, AttributeSet attrs, int defStyle,
- List<TextView> words, List<View> dividers, List<TextView> infos, View control) {
- super(words, dividers, infos, control);
+ List<TextView> words, List<View> dividers, List<TextView> infos) {
+ super(words, dividers, infos);
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.CandidateView, defStyle, R.style.CandidateViewStyle);
mAutoCorrectHighlight = a.getInt(R.styleable.CandidateView_autoCorrectHighlight, 0);
@@ -302,13 +292,20 @@ public class CandidateView extends LinearLayout implements OnClickListener {
mCandidateCountInStrip = a.getInt(
R.styleable.CandidateView_candidateCountInStrip,
DEFAULT_CANDIDATE_COUNT_IN_STRIP);
+ mCenterCandidateWeight = a.getInt(
+ R.styleable.CandidateView_centerCandidatePercentile,
+ DEFAULT_CENTER_CANDIDATE_PERCENTILE) / 100.0f;
a.recycle();
+ mCenterCandidateIndex = mCandidateCountInStrip / 2;
+ final Resources res = context.getResources();
+ mMoreCandidateHint = res.getDrawable(R.drawable.more_suggestions_hint);
+
mInvertedForegroundColorSpan = new ForegroundColorSpan(mColorTypedWord ^ 0x00ffffff);
mInvertedBackgroundColorSpan = new BackgroundColorSpan(mColorTypedWord);
mPaint = new TextPaint();
- final float textSize = context.getResources().getDimension(R.dimen.candidate_text_size);
+ final float textSize = res.getDimension(R.dimen.candidate_text_size);
mPaint.setTextSize(textSize);
}
@@ -328,35 +325,38 @@ public class CandidateView extends LinearLayout implements OnClickListener {
return spannedWord;
}
- private int getWordPosition(int index) {
- if (index >= 2) {
+ private static boolean willAutoCorrect(SuggestedWords suggestions) {
+ return !suggestions.mTypedWordValid && suggestions.mHasMinimalSuggestion;
+ }
+
+ private int getWordPosition(int index, SuggestedWords suggestions) {
+ // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more
+ // suggestions.
+ final int centerPos = willAutoCorrect(suggestions) ? 1 : 0;
+ if (index == mCenterCandidateIndex) {
+ return centerPos;
+ } else if (index == centerPos) {
+ return mCenterCandidateIndex;
+ } else {
return index;
}
- final boolean willAutoCorrect = !mSuggestedWords.mTypedWordValid
- && mSuggestedWords.mHasMinimalSuggestion;
- return willAutoCorrect ? 1 - index : index;
}
- private int getCandidateTextColor(int pos) {
- final SuggestedWords suggestions = mSuggestedWords;
- final boolean isAutoCorrect = suggestions.mHasMinimalSuggestion
- && ((pos == 1 && !suggestions.mTypedWordValid)
- || (pos == 0 && suggestions.mTypedWordValid));
+ private int getCandidateTextColor(int index, SuggestedWords suggestions, int pos) {
// TODO: Need to revisit this logic with bigram suggestions
final boolean isSuggestedCandidate = (pos != 0);
- final boolean isPunctuationSuggestions = suggestions.isPunctuationSuggestions();
final int color;
- if (isPunctuationSuggestions) {
- color = mColorTypedWord;
- } else if (isAutoCorrect) {
+ if (index == mCenterCandidateIndex && willAutoCorrect(suggestions)) {
color = mColorAutoCorrect;
} else if (isSuggestedCandidate) {
color = mColorSuggestedCandidate;
} else {
color = mColorTypedWord;
}
- final SuggestedWordInfo info = suggestions.getInfo(pos);
+
+ final SuggestedWordInfo info = (pos < suggestions.size())
+ ? suggestions.getInfo(pos) : null;
if (info != null && info.isPreviousSuggestedWord()) {
return applyAlpha(color, 0.5f);
} else {
@@ -381,136 +381,113 @@ public class CandidateView extends LinearLayout implements OnClickListener {
public int layout(SuggestedWords suggestions, ViewGroup stripView, ViewGroup paneView,
int stripWidth) {
- mSuggestedWords = suggestions;
- final int maxCount = suggestions.isPunctuationSuggestions()
- ? PUNCTUATIONS_IN_STRIP : mCandidateCountInStrip;
- final int size = suggestions.size();
- setupTexts(suggestions, size);
- mCountInStrip = Math.min(maxCount, size);
- mScaleX = 1.0f;
- calculateParameters(size, stripWidth);
-
- int infoX = 0;
- for (int index = 0; index < mCountInStrip; index++) {
- final int pos = getWordPosition(index);
- final TextView word = mWords.get(pos);
- final View divider = mDividers.get(pos);
- final TextPaint paint = word.getPaint();
- // TODO: Reorder candidates in strip as appropriate. The center candidate should
- // hold the word when space is typed (valid typed word or auto corrected word).
- word.setTextColor(getCandidateTextColor(pos));
+ if (suggestions.isPunctuationSuggestions()) {
+ return layoutPunctuationSuggestions(suggestions, stripView);
+ }
+
+ final int countInStrip = mCandidateCountInStrip;
+ setupTexts(suggestions, countInStrip);
+ mMoreSuggestionsAvailable = (suggestions.size() > countInStrip);
+ int x = 0;
+ for (int index = 0; index < countInStrip; index++) {
+ final int pos = getWordPosition(index, suggestions);
+
+ if (index != 0) {
+ final View divider = mDividers.get(pos);
+ // Add divider if this isn't the left most suggestion in candidate strip.
+ stripView.addView(divider);
+ }
+
final CharSequence styled = mTexts.get(pos);
+ final TextView word = mWords.get(pos);
+ if (index == mCenterCandidateIndex && mMoreSuggestionsAvailable) {
+ // TODO: This "more suggestions hint" should have nicely designed icon.
+ word.setCompoundDrawablesWithIntrinsicBounds(
+ null, null, null, mMoreCandidateHint);
+ } else {
+ word.setCompoundDrawables(null, null, null, null);
+ }
+
+ // Disable this candidate if the suggestion is null or empty.
+ word.setEnabled(!TextUtils.isEmpty(styled));
+ word.setTextColor(getCandidateTextColor(index, suggestions, pos));
+ final int width = getCandidateWidth(index, stripWidth);
+ final CharSequence text = getEllipsizedText(styled, width, word.getPaint());
+ final float scaleX = word.getTextScaleX();
+ word.setText(text); // TextView.setText() resets text scale x to 1.0.
+ word.setTextScaleX(scaleX);
+ stripView.addView(word);
+ setLayoutWeight(word, getCandidateWeight(index), mCandidateStripHeight);
- final TextView info;
if (DBG) {
- final CharSequence debugInfo = getDebugInfo(mSuggestedWords, index);
+ final CharSequence debugInfo = getDebugInfo(suggestions, pos);
if (debugInfo != null) {
- info = mInfos.get(index);
+ final TextView info = mInfos.get(pos);
info.setText(debugInfo);
- } else {
- info = null;
- }
- } else {
- info = null;
- }
-
- final CharSequence text;
- final float scaleX;
- if (index == 0 && mCountInStrip == 1) {
- text = getEllipsizedText(styled, mMaxWidth, paint);
- scaleX = paint.getTextScaleX();
- } else {
- text = styled;
- scaleX = mScaleX;
- }
- word.setText(text);
- word.setTextScaleX(scaleX);
- if (index != 0) {
- // Add divider if this isn't the left most suggestion in candidate strip.
- stripView.addView(divider);
- }
- stripView.addView(word);
- if (mCanUseFixedWidthColumns) {
- setLayoutWeight(word, 1.0f, mCandidateStripHeight);
- } else {
- final int width = getTextWidth(text, paint) + mPadding;
- setLayoutWeight(word, width, mCandidateStripHeight);
- }
- if (info != null) {
paneView.addView(info);
info.measure(WRAP_CONTENT, WRAP_CONTENT);
- final int width = info.getMeasuredWidth();
+ final int infoWidth = info.getMeasuredWidth();
final int y = info.getMeasuredHeight();
- FrameLayoutCompatUtils.placeViewAt(info, infoX, 0, width, y);
- infoX += width * 2;
+ FrameLayoutCompatUtils.placeViewAt(info, x, 0, infoWidth, y);
+ x += infoWidth * 2;
}
+ }
}
- return mCountInStrip;
+ return countInStrip;
}
- private void calculateParameters(int size, int maxWidth) {
- do {
- mMaxWidth = maxWidth;
- if (size > mCountInStrip) {
- mMaxWidth -= mControlWidth;
- }
-
- tryLayout();
-
- if (mCanUseFixedWidthColumns) {
- return;
- }
- if (mVariableWidthForWords <= mAvailableWidthForWords) {
- return;
- }
-
- final float scaleX = mAvailableWidthForWords / (float)mVariableWidthForWords;
- if (scaleX >= MIN_TEXT_XSCALE) {
- mScaleX = scaleX;
- return;
- }
+ private int getCandidateWidth(int index, int maxWidth) {
+ final int paddings = mPadding * mCandidateCountInStrip;
+ final int dividers = mDividerWidth * (mCandidateCountInStrip - 1);
+ final int availableWidth = maxWidth - paddings - dividers;
+ return (int)(availableWidth * getCandidateWeight(index));
+ }
- mCountInStrip--;
- } while (mCountInStrip > 1);
- }
-
- private void tryLayout() {
- final int maxCount = mCountInStrip;
- final int dividers = mDividerWidth * (maxCount - 1);
- mConstantWidthForPaddings = dividers + mPadding * maxCount;
- mAvailableWidthForWords = mMaxWidth - mConstantWidthForPaddings;
-
- mPaint.setTextScaleX(mScaleX);
- final int maxFixedWidthForWord = (mMaxWidth - dividers) / maxCount - mPadding;
- mCanUseFixedWidthColumns = true;
- mVariableWidthForWords = 0;
- for (int i = 0; i < maxCount; i++) {
- final int width = getTextWidth(mTexts.get(i), mPaint);
- if (width > maxFixedWidthForWord)
- mCanUseFixedWidthColumns = false;
- mVariableWidthForWords += width;
+ private float getCandidateWeight(int index) {
+ if (index == mCenterCandidateIndex) {
+ return mCenterCandidateWeight;
+ } else {
+ // TODO: Revisit this for cases of 5 or more suggestions
+ return (1.0f - mCenterCandidateWeight) / (mCandidateCountInStrip - 1);
}
}
- private void setupTexts(SuggestedWords suggestions, int count) {
+ private void setupTexts(SuggestedWords suggestions, int countInStrip) {
mTexts.clear();
- for (int i = 0; i < count; i++) {
- final CharSequence word = suggestions.getWord(i);
- final boolean isAutoCorrect = suggestions.mHasMinimalSuggestion
- && ((i == 1 && !suggestions.mTypedWordValid)
- || (i == 0 && suggestions.mTypedWordValid));
+ final int count = Math.min(suggestions.size(), countInStrip);
+ for (int pos = 0; pos < count; pos++) {
+ final CharSequence word = suggestions.getWord(pos);
+ final boolean isAutoCorrect = pos == 1 && willAutoCorrect(suggestions);
final CharSequence styled = getStyledCandidateWord(word, isAutoCorrect);
mTexts.add(styled);
}
+ for (int pos = count; pos < countInStrip; pos++) {
+ // Make this inactive for touches in layout().
+ mTexts.add(null);
+ }
}
- @Override
- public String toString() {
- return String.format(
- "count=%d width=%d avail=%d fixcol=%s scaleX=%4.2f const=%d var=%d",
- mCountInStrip, mMaxWidth, mAvailableWidthForWords, mCanUseFixedWidthColumns,
- mScaleX, mConstantWidthForPaddings, mVariableWidthForWords);
+ private int layoutPunctuationSuggestions(SuggestedWords suggestions, ViewGroup stripView) {
+ final int countInStrip = Math.min(suggestions.size(), PUNCTUATIONS_IN_STRIP);
+ for (int index = 0; index < countInStrip; index++) {
+ if (index != 0) {
+ // Add divider if this isn't the left most suggestion in candidate strip.
+ stripView.addView(mDividers.get(index));
+ }
+
+ final TextView word = mWords.get(index);
+ word.setEnabled(true);
+ word.setTextColor(mColorTypedWord);
+ final CharSequence text = suggestions.getWord(index);
+ word.setText(text);
+ word.setTextScaleX(1.0f);
+ word.setCompoundDrawables(null, null, null, null);
+ stripView.addView(word);
+ setLayoutWeight(word, 1.0f, mCandidateStripHeight);
+ }
+ mMoreSuggestionsAvailable = false;
+ return countInStrip;
}
}
@@ -548,13 +525,14 @@ public class CandidateView extends LinearLayout implements OnClickListener {
mPreviewPopup.setBackgroundDrawable(null);
mCandidatesStrip = (ViewGroup)findViewById(R.id.candidates_strip);
- for (int i = 0; i < MAX_SUGGESTIONS; i++) {
+ for (int pos = 0; pos < MAX_SUGGESTIONS; pos++) {
final TextView word = (TextView)inflater.inflate(R.layout.candidate_word, null);
- word.setTag(i);
+ word.setTag(pos);
word.setOnClickListener(this);
+ word.setOnLongClickListener(this);
mWords.add(word);
final View divider = inflater.inflate(R.layout.candidate_divider, null);
- divider.setTag(i);
+ divider.setTag(pos);
divider.setOnClickListener(this);
mDividers.add(divider);
mInfos.add((TextView)inflater.inflate(R.layout.candidate_info, null));
@@ -564,41 +542,9 @@ public class CandidateView extends LinearLayout implements OnClickListener {
mWordToSave = (TextView)findViewById(R.id.word_to_save);
mWordToSave.setOnClickListener(this);
- final TypedArray keyboardViewAttr = context.obtainStyledAttributes(
- attrs, R.styleable.KeyboardView, R.attr.keyboardViewStyle, R.style.KeyboardView);
- final Drawable expandBackground = keyboardViewAttr.getDrawable(
- R.styleable.KeyboardView_keyBackground);
- final Drawable closeBackground = keyboardViewAttr.getDrawable(
- R.styleable.KeyboardView_keyBackground);
- final int keyTextColor = keyboardViewAttr.getColor(
- R.styleable.KeyboardView_keyTextColor, 0xFF000000);
- keyboardViewAttr.recycle();
-
- mCandidatesPaneControl = (ViewGroup)findViewById(R.id.candidates_pane_control);
- mExpandCandidatesPane = (TextView)findViewById(R.id.expand_candidates_pane);
- mExpandCandidatesPane.setBackgroundDrawable(expandBackground);
- mExpandCandidatesPane.setTextColor(keyTextColor);
- mExpandCandidatesPane.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- expandCandidatesPane();
- }
- });
- mCloseCandidatesPane = (TextView)findViewById(R.id.close_candidates_pane);
- mCloseCandidatesPane.setBackgroundDrawable(closeBackground);
- mCloseCandidatesPane.setTextColor(keyTextColor);
- mCloseCandidatesPane.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- closeCandidatesPane();
- }
- });
- mCandidatesPaneControl.measure(WRAP_CONTENT, WRAP_CONTENT);
-
- mStripParams = new SuggestionsStripParams(context, attrs, defStyle,
- mWords, mDividers, mInfos, mCandidatesPaneControl);
- mPaneParams = new SuggestionsPaneParams(
- mWords, mDividers, mInfos, mCandidatesPaneControl);
+ mStripParams = new SuggestionsStripParams(context, attrs, defStyle, mWords, mDividers,
+ mInfos);
+ mPaneParams = new SuggestionsPaneParams(mWords, mDividers, mInfos);
}
/**
@@ -619,7 +565,6 @@ public class CandidateView extends LinearLayout implements OnClickListener {
if (suggestions == null)
return;
mSuggestions = suggestions;
- mExpandCandidatesPane.setEnabled(false);
if (mShowingAutoCorrectionInverted) {
mHandler.postUpdateSuggestions();
} else {
@@ -638,18 +583,10 @@ public class CandidateView extends LinearLayout implements OnClickListener {
mSuggestions, mCandidatesStrip, mCandidatesPane, width);
final int countInPane = mPaneParams.layout(
mSuggestions, mCandidatesPane, countInStrip, mStripParams.getTextColor(), width);
-
- if (countInPane <= 0 && !DBG) {
- mCandidatesPaneControl.setVisibility(GONE);
- } else {
- mCandidatesPaneControl.setVisibility(VISIBLE);
- mExpandCandidatesPane.setVisibility(VISIBLE);
- mExpandCandidatesPane.setEnabled(true);
- }
}
private static CharSequence getDebugInfo(SuggestedWords suggestions, int pos) {
- if (DBG) {
+ if (DBG && pos < suggestions.size()) {
final SuggestedWordInfo wordInfo = suggestions.getInfo(pos);
if (wordInfo != null) {
final CharSequence debugInfo = wordInfo.getDebugString();
@@ -695,14 +632,17 @@ public class CandidateView extends LinearLayout implements OnClickListener {
TextPaint paint) {
paint.setTextScaleX(1.0f);
final int width = getTextWidth(text, paint);
- final float scaleX = Math.min(maxWidth / (float)width, 1.0f);
+ if (width <= maxWidth) {
+ return text;
+ }
+ final float scaleX = maxWidth / (float)width;
if (scaleX >= MIN_TEXT_XSCALE) {
paint.setTextScaleX(scaleX);
return text;
}
// Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To get
- // squeezed and ellipsezed text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE).
+ // squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE).
final CharSequence ellipsized = TextUtils.ellipsize(
text, paint, maxWidth / MIN_TEXT_XSCALE, TextUtils.TruncateAt.MIDDLE);
paint.setTextScaleX(MIN_TEXT_XSCALE);
@@ -741,20 +681,24 @@ public class CandidateView extends LinearLayout implements OnClickListener {
}
private void expandCandidatesPane() {
- mExpandCandidatesPane.setVisibility(GONE);
- mCloseCandidatesPane.setVisibility(VISIBLE);
mCandidatesPaneContainer.setMinimumHeight(mKeyboardView.getMeasuredHeight());
mCandidatesPaneContainer.setVisibility(VISIBLE);
mKeyboardView.setVisibility(GONE);
}
private void closeCandidatesPane() {
- mExpandCandidatesPane.setVisibility(VISIBLE);
- mCloseCandidatesPane.setVisibility(GONE);
mCandidatesPaneContainer.setVisibility(GONE);
mKeyboardView.setVisibility(VISIBLE);
}
+ private void toggleCandidatesPane() {
+ if (mCandidatesPaneContainer.getVisibility() == VISIBLE) {
+ closeCandidatesPane();
+ } else {
+ expandCandidatesPane();
+ }
+ }
+
public void onAutoCorrectionInverted(CharSequence autoCorrectedWord) {
final CharSequence inverted = mStripParams.getInvertedText(autoCorrectedWord);
if (inverted == null)
@@ -772,7 +716,6 @@ public class CandidateView extends LinearLayout implements OnClickListener {
mWordToSave.setText(word);
mShowingAddToDictionary = true;
mCandidatesStrip.setVisibility(GONE);
- mCandidatesPaneControl.setVisibility(GONE);
mTouchToSave.setVisibility(VISIBLE);
}
@@ -831,6 +774,15 @@ public class CandidateView extends LinearLayout implements OnClickListener {
}
@Override
+ public boolean onLongClick(View view) {
+ if (mStripParams.mMoreSuggestionsAvailable) {
+ toggleCandidatesPane();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
public void onClick(View view) {
if (view == mWordToSave) {
addToDictionary(((TextView)view).getText());
@@ -838,6 +790,11 @@ public class CandidateView extends LinearLayout implements OnClickListener {
return;
}
+ if (view == mCandidatesPane) {
+ closeCandidatesPane();
+ return;
+ }
+
final Object tag = view.getTag();
if (!(tag instanceof Integer))
return;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 6c91c454c..a58815892 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -170,7 +170,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private WordComposer mWordComposer = new WordComposer();
private CharSequence mBestWord;
private boolean mHasUncommittedTypedChars;
- private boolean mHasDictionary;
// Magic space: a space that should disappear on space/apostrophe insertion, move after the
// punctuation on punctuation insertion, and become a real space on alpha char insertion.
private boolean mJustAddedMagicSpace; // This indicates whether the last char is a magic space.
@@ -430,8 +429,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public boolean postStartInputView(EditorInfo attribute) {
if (hasMessages(MSG_CONFIRM_ORIENTATION_CHANGE) || hasMessages(MSG_START_INPUT_VIEW)) {
removeMessages(MSG_START_INPUT_VIEW);
- // Postpone onStartInputView 20ms afterward and see if orientation change has
- // finished.
+ // Postpone onStartInputView by ACCUMULATE_START_INPUT_VIEW_DELAY and see if
+ // orientation change has finished.
sendMessageDelayed(obtainMessage(MSG_START_INPUT_VIEW, attribute),
ACCUMULATE_START_INPUT_VIEW_DELAY);
return true;
@@ -684,8 +683,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Delay updating suggestions because keyboard input view may not be shown at this point.
mHandler.postUpdateSuggestions();
- updateCorrectionMode();
-
inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn,
mSettingsValues.mKeyPreviewPopupDismissDelay);
inputView.setProximityCorrectionEnabled(true);
@@ -1152,25 +1149,33 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
private void onSettingsKeyPressed() {
- if (isShowingOptionDialog())
- return;
+ if (isShowingOptionDialog()) return;
if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
showSubtypeSelectorAndSettings();
- } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) {
+ } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm,
+ false /* should exclude auxiliary subtypes */)) {
showOptionsMenu();
} else {
launchSettings();
}
}
- private void onSettingsKeyLongPressed() {
- if (!isShowingOptionDialog()) {
- if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) {
+ // Virtual codes representing custom requests. These are used in onCustomRequest() below.
+ public static final int CODE_SHOW_INPUT_METHOD_PICKER = 1;
+
+ @Override
+ public boolean onCustomRequest(int requestCode) {
+ if (isShowingOptionDialog()) return false;
+ switch (requestCode) {
+ case CODE_SHOW_INPUT_METHOD_PICKER:
+ if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm,
+ true /* should include auxiliary subtypes */)) {
mImm.showInputMethodPicker();
- } else {
- launchSettings();
+ return true;
}
+ return false;
}
+ return false;
}
private boolean isShowingOptionDialog() {
@@ -1214,9 +1219,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
case Keyboard.CODE_SETTINGS:
onSettingsKeyPressed();
break;
- case Keyboard.CODE_SETTINGS_LONGPRESS:
- onSettingsKeyLongPressed();
- break;
case Keyboard.CODE_CAPSLOCK:
switcher.toggleCapsLock();
break;
@@ -1457,7 +1459,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// in Italian dov' should not be expanded to dove' because the elision
// requires the last vowel to be removed.
final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled
- && !mInputTypeNoAutoCorrect && mHasDictionary;
+ && !mInputTypeNoAutoCorrect;
if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) {
pickedDefault = pickDefaultSuggestion(primaryCode);
} else {
@@ -1752,9 +1754,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
sendMagicSpace();
}
- // We should show the hint if the user pressed the first entry AND either:
+ // We should show the "Touch again to save" hint if the user pressed the first entry
+ // AND either:
// - There is no dictionary (we know that because we tried to load it => null != mSuggest
- // AND mHasDictionary is false)
+ // AND mSuggest.hasMainDictionary() is false)
// - There is a dictionary and the word is not in it
// Please note that if mSuggest is null, it means that everything is off: suggestion
// and correction, so we shouldn't try to show the hint
@@ -1762,7 +1765,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// to do with the autocorrection setting.
final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null
// If there is no dictionary the hint should be shown.
- && (!mHasDictionary
+ && (!mSuggest.hasMainDictionary()
// If "suggestion" is not in the dictionary, the hint should be shown.
|| !AutoCorrection.isValidWord(
mSuggest.getUnigramDictionaries(), suggestion, true));
@@ -1925,15 +1928,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
final CharSequence separator = ic.getTextBeforeCursor(1, 0);
- ic.deleteSurroundingText(mCommittedLength + 1 /* separator */, 0);
+ ic.deleteSurroundingText(1, 0);
+ final CharSequence textToTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0);
+ ic.deleteSurroundingText(mCommittedLength, 0);
// Re-insert "separator" only when the deleted character was word separator and the
// composing text wasn't equal to the auto-corrected text which can be found before
// the cursor.
if (!TextUtils.isEmpty(separator)
&& mSettingsValues.isWordSeparator(separator.charAt(0))
- && !TextUtils.equals(mComposingStringBuilder,
- ic.getTextBeforeCursor(mCommittedLength, 0))) {
+ && !TextUtils.equals(mComposingStringBuilder, textToTheLeft)) {
ic.commitText(mComposingStringBuilder, 1);
TextEntryState.acceptedTyped(mComposingStringBuilder);
ic.commitText(separator, 1);
@@ -2096,9 +2100,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private void updateCorrectionMode() {
// TODO: cleanup messy flags
- mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false;
final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled
- && !mInputTypeNoAutoCorrect && mHasDictionary;
+ && !mInputTypeNoAutoCorrect;
mCorrectionMode = (shouldAutoCorrect && mSettingsValues.mAutoCorrectEnabled)
? Suggest.CORRECTION_FULL
: (shouldAutoCorrect ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE);
@@ -2135,14 +2138,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
protected void launchSettings() {
- launchSettings(Settings.class);
+ launchSettingsClass(Settings.class);
}
public void launchDebugSettings() {
- launchSettings(DebugSettings.class);
+ launchSettingsClass(DebugSettings.class);
}
- protected void launchSettings(Class<? extends PreferenceActivity> settingsClass) {
+ protected void launchSettingsClass(Class<? extends PreferenceActivity> settingsClass) {
handleClose();
Intent intent = new Intent();
intent.setClass(LatinIME.this, settingsClass);
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 933a94176..36a29e896 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -191,6 +191,8 @@ public class Suggest implements Dictionary.WordCallback {
mCorrectionMode = mode;
}
+ // The main dictionary could have been loaded asynchronously. Don't cache the return value
+ // of this method.
public boolean hasMainDictionary() {
return mMainDict != null;
}
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 16a2b0e5f..c07793c33 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -111,35 +111,42 @@ public class Utils {
}
}
- public static boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManagerCompatWrapper imm) {
+ public static boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManagerCompatWrapper imm,
+ boolean shouldIncludeAuxiliarySubtypes) {
final List<InputMethodInfoCompatWrapper> enabledImis = imm.getEnabledInputMethodList();
- // Filters out IMEs that have auxiliary subtypes only (including either implicitly or
- // explicitly enabled ones).
- final ArrayList<InputMethodInfoCompatWrapper> filteredImis =
- new ArrayList<InputMethodInfoCompatWrapper>();
+ // Number of the filtered IMEs
+ int filteredImisCount = 0;
- outerloop:
for (InputMethodInfoCompatWrapper imi : enabledImis) {
// We can return true immediately after we find two or more filtered IMEs.
- if (filteredImis.size() > 1) return true;
+ if (filteredImisCount > 1) return true;
final List<InputMethodSubtypeCompatWrapper> subtypes =
imm.getEnabledInputMethodSubtypeList(imi, true);
- // IMEs that have no subtypes should be included.
+ // IMEs that have no subtypes should be counted.
if (subtypes.isEmpty()) {
- filteredImis.add(imi);
+ ++filteredImisCount;
continue;
}
- // IMEs that have one or more non-auxiliary subtypes should be included.
+
+ int auxCount = 0;
for (InputMethodSubtypeCompatWrapper subtype : subtypes) {
- if (!subtype.isAuxiliary()) {
- filteredImis.add(imi);
- continue outerloop;
+ if (subtype.isAuxiliary()) {
+ ++auxCount;
}
}
+ final int nonAuxCount = subtypes.size() - auxCount;
+
+ // IMEs that have one or more non-auxiliary subtypes should be counted.
+ // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
+ // subtypes should be counted as well.
+ if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
+ ++filteredImisCount;
+ continue;
+ }
}
- return filteredImis.size() > 1
+ return filteredImisCount > 1
// imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
// input method subtype (The current IME should be LatinIME.)
|| imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;