SuggestionStripView.java revision 6f7905ae757c30ac0f8080f025b88afc61a6f6b1
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/*
2913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka * Copyright (C) 2011 The Android Open Source Project
3e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka *
48aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License");
58aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * you may not use this file except in compliance with the License.
68aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * You may obtain a copy of the License at
7e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka *
88aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka *      http://www.apache.org/licenses/LICENSE-2.0
9e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka *
10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
118aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS,
128aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * See the License for the specific language governing permissions and
148aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * limitations under the License.
15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */
16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
178c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokapackage com.android.inputmethod.latin.suggestions;
18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
19923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context;
2066a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.content.res.Resources;
2108a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaokaimport android.content.res.TypedArray;
220967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport android.graphics.Bitmap;
230967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport android.graphics.Canvas;
246f7218627eda110a8454053f8ecb7b80edfdc8cesatokimport android.graphics.Color;
250967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport android.graphics.Paint;
260967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport android.graphics.Paint.Align;
270967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport android.graphics.Rect;
28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.graphics.Typeface;
290967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaokaimport android.graphics.drawable.BitmapDrawable;
30e583371b13ebd9aa336d0883e8c174ae4918c758Tadashi G. Takaokaimport android.graphics.drawable.Drawable;
31522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaokaimport android.text.Spannable;
32522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaokaimport android.text.SpannableString;
33e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.text.Spanned;
34b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaokaimport android.text.TextPaint;
35e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.text.TextUtils;
36522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaokaimport android.text.style.CharacterStyle;
3774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaokaimport android.text.style.StyleSpan;
38522d5c16d20657e7d26009fe9c067404e16a6c2aTadashi G. Takaokaimport android.text.style.UnderlineSpan;
39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.AttributeSet;
403fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaokaimport android.view.GestureDetector;
41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.Gravity;
42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.LayoutInflater;
4329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaokaimport android.view.MotionEvent;
44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View;
45e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.view.View.OnClickListener;
46ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaokaimport android.view.View.OnLongClickListener;
47e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.view.ViewGroup;
48e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.widget.LinearLayout;
49c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaokaimport android.widget.RelativeLayout;
50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.widget.TextView;
51923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
527339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard;
537339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher;
54d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaokaimport com.android.inputmethod.keyboard.MainKeyboardView;
5529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaokaimport com.android.inputmethod.keyboard.MoreKeysPanel;
56c8461d1ae26d43a09c0f835d833f3d49fbe8d2f3Tadashi G. Takaokaimport com.android.inputmethod.keyboard.ViewLayoutUtils;
57f72b8f5662afb42b08eb88e92731d52f99df13e3Jean Chalardimport com.android.inputmethod.latin.AutoCorrection;
585f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaokaimport com.android.inputmethod.latin.CollectionUtils;
595faf41951929301af80026bc3191812ef874fd5aTadashi G. Takaokaimport com.android.inputmethod.latin.Constants;
608c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinImeLogger;
618c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.R;
6292821614fd80112527e133f069e31ee48250314fTadashi G. Takaokaimport com.android.inputmethod.latin.ResourceUtils;
638c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.SuggestedWords;
649310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalardimport com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
65042557b45bf2554608cd22874633011157cd1752Jean Chalardimport com.android.inputmethod.latin.Utils;
66a9ca7867b5a7c0be115966211a05f5d460c8638cKurt Partridgeimport com.android.inputmethod.latin.define.ProductionFlag;
676f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaokaimport com.android.inputmethod.latin.suggestions.MoreSuggestions.MoreSuggestionsListener;
686b966160ac8570271547bf63217efa5e228d4accKurt Partridgeimport com.android.inputmethod.research.ResearchLogger;
69ddb61ea461b920d87be4ad78c8a36eec1013b965Tadashi G. Takaoka
70179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaokaimport java.util.ArrayList;
71179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka
72a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaokapublic final class SuggestionStripView extends RelativeLayout implements OnClickListener,
73c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka        OnLongClickListener {
74c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka    public interface Listener {
7518d688c94bb8e1e26de2d12445cb3096c6126f75Jean Chalard        public void addWordToUserDictionary(String word);
769310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard        public void pickSuggestionManually(int index, SuggestedWordInfo word);
77c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka    }
78c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka
7986e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka    // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}.
8029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    public static final int MAX_SUGGESTIONS = 18;
81923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
828c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaoka    static final boolean DBG = LatinImeLogger.sDBG;
836f7218627eda110a8454053f8ecb7b80edfdc8cesatok
84913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka    private final ViewGroup mSuggestionsStrip;
85d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka    MainKeyboardView mMainKeyboardView;
8674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
8729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final View mMoreSuggestionsContainer;
8829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final MoreSuggestionsView mMoreSuggestionsView;
8929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final MoreSuggestions.Builder mMoreSuggestionsBuilder;
9029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
915f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka    private final ArrayList<TextView> mWords = CollectionUtils.newArrayList();
925f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka    private final ArrayList<TextView> mInfos = CollectionUtils.newArrayList();
935f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka    private final ArrayList<View> mDividers = CollectionUtils.newArrayList();
9474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
953e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    Listener mListener;
966f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka    private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
976a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani
984702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka    private final SuggestionStripViewParams mParams;
99ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka    private static final float MIN_TEXT_XSCALE = 0.70f;
100b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka
101a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaoka    private static final class SuggestionStripViewParams {
102d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka        private static final int DEFAULT_SUGGESTIONS_COUNT_IN_STRIP = 3;
103ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka        private static final float DEFAULT_CENTER_SUGGESTION_PERCENTILE = 0.40f;
1049676038b6e9fb66760588d7f9c9c642cc493dd71Tadashi G. Takaoka        private static final int DEFAULT_MAX_MORE_SUGGESTIONS_ROW = 2;
105293db0873fd89b5c2bd077ffa5091321b3ab8149Ken Wakasa        private static final int PUNCTUATIONS_IN_STRIP = 5;
106d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka
10774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka        public final int mPadding;
10874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka        public final int mDividerWidth;
109913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        public final int mSuggestionsStripHeight;
110d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka        public final int mSuggestionsCountInStrip;
111c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        public final int mMoreSuggestionsRowHeight;
112c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        private int mMaxMoreSuggestionsRow;
1139676038b6e9fb66760588d7f9c9c642cc493dd71Tadashi G. Takaoka        public final float mMinMoreSuggestionsWidth;
1144269a7cebdfe5c76372d0f0dd187432f0594ffe5Tadashi G. Takaoka        public final int mMoreSuggestionsBottomGap;
11516713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka
116660776e09b9a3b321074a94721d901a035ca1b9fKen Wakasa        private final ArrayList<TextView> mWords;
117660776e09b9a3b321074a94721d901a035ca1b9fKen Wakasa        private final ArrayList<View> mDividers;
118660776e09b9a3b321074a94721d901a035ca1b9fKen Wakasa        private final ArrayList<TextView> mInfos;
119d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
120a44685ab326809185a0e4c44afabe8fd93441b4cTadashi G. Takaoka        private final int mColorValidTypedWord;
121d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        private final int mColorTypedWord;
122d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        private final int mColorAutoCorrect;
123913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        private final int mColorSuggested;
124697bf585f8dac6ffc4d008c02b63407cfdd83104Tadashi G. Takaoka        private final float mAlphaObsoleted;
125913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        private final float mCenterSuggestionWeight;
126913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        private final int mCenterSuggestionIndex;
127913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        private final Drawable mMoreSuggestionsHint;
1289bdce3a59e9bf00095bc92fae88b830b0a8455beFabrice Di Meglio        private static final String MORE_SUGGESTIONS_HINT = "\u2026";
1292eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka        private static final String LEFTWARDS_ARROW = "\u2190";
130d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
131d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
132d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
133d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        private static final int AUTO_CORRECT_BOLD = 0x01;
134d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        private static final int AUTO_CORRECT_UNDERLINE = 0x02;
13577a87e3cb5886b1319230906c77c0bc98b905248Tadashi G. Takaoka        private static final int VALID_TYPED_WORD_BOLD = 0x04;
136d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
137d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka        private final int mSuggestionStripOption;
13874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
1395f282ea9e4a4590fcbab6e27d5fca7dacbb40a6aTadashi G. Takaoka        private final ArrayList<CharSequence> mTexts = CollectionUtils.newArrayList();
14074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
141ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka        public boolean mMoreSuggestionsAvailable;
142ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka
1439f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka        private final TextView mWordToSaveView;
1442eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka        private final TextView mLeftwardsArrowView;
145c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        private final TextView mHintToSaveView;
146c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka
1473e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        public SuggestionStripViewParams(final Context context, final AttributeSet attrs,
1483e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                final int defStyle, final ArrayList<TextView> words, final ArrayList<View> dividers,
1493e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                final ArrayList<TextView> infos) {
150d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            mWords = words;
151d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            mDividers = dividers;
152d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            mInfos = infos;
153d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka
154d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            final TextView word = words.get(0);
155d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            final View divider = dividers.get(0);
156d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            mPadding = word.getCompoundPaddingLeft() + word.getCompoundPaddingRight();
157d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            divider.measure(
158d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
159d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            mDividerWidth = divider.getMeasuredWidth();
160d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka
161d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            final Resources res = word.getResources();
162d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka            mSuggestionsStripHeight = res.getDimensionPixelSize(R.dimen.suggestions_strip_height);
163d3e50a2acf04638f09786c487326f2c09e738f32Tadashi G. Takaoka
1644702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            final TypedArray a = context.obtainStyledAttributes(attrs,
1654702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    R.styleable.SuggestionStripView, defStyle, R.style.SuggestionStripViewStyle);
1664702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            mSuggestionStripOption = a.getInt(
1674702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    R.styleable.SuggestionStripView_suggestionStripOption, 0);
16892821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka            final float alphaValidTypedWord = ResourceUtils.getFraction(a,
169ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka                    R.styleable.SuggestionStripView_alphaValidTypedWord, 1.0f);
17092821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka            final float alphaTypedWord = ResourceUtils.getFraction(a,
171ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka                    R.styleable.SuggestionStripView_alphaTypedWord, 1.0f);
17292821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka            final float alphaAutoCorrect = ResourceUtils.getFraction(a,
173ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka                    R.styleable.SuggestionStripView_alphaAutoCorrect, 1.0f);
17492821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka            final float alphaSuggested = ResourceUtils.getFraction(a,
175ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka                    R.styleable.SuggestionStripView_alphaSuggested, 1.0f);
17692821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka            mAlphaObsoleted = ResourceUtils.getFraction(a,
177ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka                    R.styleable.SuggestionStripView_alphaSuggested, 1.0f);
1784702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            mColorValidTypedWord = applyAlpha(a.getColor(
1794702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    R.styleable.SuggestionStripView_colorValidTypedWord, 0), alphaValidTypedWord);
1804702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            mColorTypedWord = applyAlpha(a.getColor(
1814702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    R.styleable.SuggestionStripView_colorTypedWord, 0), alphaTypedWord);
1824702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            mColorAutoCorrect = applyAlpha(a.getColor(
1834702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    R.styleable.SuggestionStripView_colorAutoCorrect, 0), alphaAutoCorrect);
1844702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            mColorSuggested = applyAlpha(a.getColor(
1854702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    R.styleable.SuggestionStripView_colorSuggested, 0), alphaSuggested);
186913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            mSuggestionsCountInStrip = a.getInt(
1874702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    R.styleable.SuggestionStripView_suggestionsCountInStrip,
188913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                    DEFAULT_SUGGESTIONS_COUNT_IN_STRIP);
18992821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka            mCenterSuggestionWeight = ResourceUtils.getFraction(a,
1904702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    R.styleable.SuggestionStripView_centerSuggestionPercentile,
191697bf585f8dac6ffc4d008c02b63407cfdd83104Tadashi G. Takaoka                    DEFAULT_CENTER_SUGGESTION_PERCENTILE);
1929676038b6e9fb66760588d7f9c9c642cc493dd71Tadashi G. Takaoka            mMaxMoreSuggestionsRow = a.getInt(
1934702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                    R.styleable.SuggestionStripView_maxMoreSuggestionsRow,
1949676038b6e9fb66760588d7f9c9c642cc493dd71Tadashi G. Takaoka                    DEFAULT_MAX_MORE_SUGGESTIONS_ROW);
19592821614fd80112527e133f069e31ee48250314fTadashi G. Takaoka            mMinMoreSuggestionsWidth = ResourceUtils.getFraction(a,
196ef2bfad5903fb55adca61dbea51984fbc7e4375fTadashi G. Takaoka                    R.styleable.SuggestionStripView_minMoreSuggestionsWidth, 1.0f);
197d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            a.recycle();
198d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
1990967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            mMoreSuggestionsHint = getMoreSuggestionsHint(res,
2000967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka                    res.getDimension(R.dimen.more_suggestions_hint_text_size), mColorAutoCorrect);
201913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            mCenterSuggestionIndex = mSuggestionsCountInStrip / 2;
2024269a7cebdfe5c76372d0f0dd187432f0594ffe5Tadashi G. Takaoka            mMoreSuggestionsBottomGap = res.getDimensionPixelOffset(
2034269a7cebdfe5c76372d0f0dd187432f0594ffe5Tadashi G. Takaoka                    R.dimen.more_suggestions_bottom_gap);
204c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            mMoreSuggestionsRowHeight = res.getDimensionPixelSize(
205c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka                    R.dimen.more_suggestions_row_height);
20660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka
207c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            final LayoutInflater inflater = LayoutInflater.from(context);
208913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            mWordToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null);
2092eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            mLeftwardsArrowView = (TextView)inflater.inflate(R.layout.hint_add_to_dictionary, null);
2102eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            mHintToSaveView = (TextView)inflater.inflate(R.layout.hint_add_to_dictionary, null);
21174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka        }
21274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
213c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        public int getMaxMoreSuggestionsRow() {
214c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            return mMaxMoreSuggestionsRow;
215c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        }
216c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka
217c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        private int getMoreSuggestionsHeight() {
218c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            return mMaxMoreSuggestionsRow * mMoreSuggestionsRowHeight + mMoreSuggestionsBottomGap;
219c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        }
220c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka
2213e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        public int setMoreSuggestionsHeight(final int remainingHeight) {
222c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            final int currentHeight = getMoreSuggestionsHeight();
223c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            if (currentHeight <= remainingHeight) {
224c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka                return currentHeight;
225c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            }
226c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka
227c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            mMaxMoreSuggestionsRow = (remainingHeight - mMoreSuggestionsBottomGap)
228c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka                    / mMoreSuggestionsRowHeight;
229c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            final int newHeight = getMoreSuggestionsHeight();
230c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka            return newHeight;
231c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        }
232c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka
2333e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private static Drawable getMoreSuggestionsHint(final Resources res, final float textSize,
2343e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                final int color) {
2350967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            final Paint paint = new Paint();
2360967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            paint.setAntiAlias(true);
2370967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            paint.setTextAlign(Align.CENTER);
2380967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            paint.setTextSize(textSize);
2390967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            paint.setColor(color);
2400967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            final Rect bounds = new Rect();
241c9f562a9a4c2b634eb43d1ddaef69068c0d93f6fKen Wakasa            paint.getTextBounds(MORE_SUGGESTIONS_HINT, 0, MORE_SUGGESTIONS_HINT.length(), bounds);
2420967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            final int width = Math.round(bounds.width() + 0.5f);
2430967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            final int height = Math.round(bounds.height() + 0.5f);
2440967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            final Bitmap buffer = Bitmap.createBitmap(
2450967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka                    width, (height * 3 / 2), Bitmap.Config.ARGB_8888);
2460967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            final Canvas canvas = new Canvas(buffer);
2470967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            canvas.drawText(MORE_SUGGESTIONS_HINT, width / 2, height, paint);
2480967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka            return new BitmapDrawable(res, buffer);
2490967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka        }
2500967ef40368c4bc7a0576ecc3dc222a8fe9b94c3Tadashi G. Takaoka
2513e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private CharSequence getStyledSuggestionWord(final SuggestedWords suggestedWords,
2523e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                final int pos) {
253bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka            final String word = suggestedWords.getWord(pos);
254e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            final boolean isAutoCorrect = pos == 1 && suggestedWords.willAutoCorrect();
255e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            final boolean isTypedWordValid = pos == 0 && suggestedWords.mTypedWordValid;
256d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka            if (!isAutoCorrect && !isTypedWordValid)
257d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                return word;
258d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka
259d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            final int len = word.length();
260d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            final Spannable spannedWord = new SpannableString(word);
261d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka            final int option = mSuggestionStripOption;
262d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka            if ((isAutoCorrect && (option & AUTO_CORRECT_BOLD) != 0)
263d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka                    || (isTypedWordValid && (option & VALID_TYPED_WORD_BOLD) != 0)) {
264d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                spannedWord.setSpan(BOLD_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
265d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka            }
266d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka            if (isAutoCorrect && (option & AUTO_CORRECT_UNDERLINE) != 0) {
267d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                spannedWord.setSpan(UNDERLINE_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
268d47a955610987c8abdab4d275c044aefc8a7f1dbTadashi G. Takaoka            }
269d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            return spannedWord;
270d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        }
271d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
2723e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private int getWordPosition(final int index, final SuggestedWords suggestedWords) {
27360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more
27460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            // suggestions.
275e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            final int centerPos = suggestedWords.willAutoCorrect() ? 1 : 0;
276913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            if (index == mCenterSuggestionIndex) {
27760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                return centerPos;
27860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            } else if (index == centerPos) {
279913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                return mCenterSuggestionIndex;
28060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            } else {
281d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                return index;
282d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            }
283d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        }
284d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
2853e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private int getSuggestionTextColor(final int index, final SuggestedWords suggestedWords,
2863e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                final int pos) {
287d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            // TODO: Need to revisit this logic with bigram suggestions
288913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            final boolean isSuggested = (pos != 0);
289d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
290d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            final int color;
291e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            if (index == mCenterSuggestionIndex && suggestedWords.willAutoCorrect()) {
292d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                color = mColorAutoCorrect;
293e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            } else if (index == mCenterSuggestionIndex && suggestedWords.mTypedWordValid) {
294a44685ab326809185a0e4c44afabe8fd93441b4cTadashi G. Takaoka                color = mColorValidTypedWord;
295913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            } else if (isSuggested) {
296913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                color = mColorSuggested;
297d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            } else {
298d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                color = mColorTypedWord;
299d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            }
300c0c20b386fb06b688f56dd7f807e2bcbb70b3a59Jean Chalard            if (LatinImeLogger.sDBG && suggestedWords.size() > 1) {
301ebbb7e9665b2f9bce46ddc2daa82b9ef73f6c712Jean Chalard                // If we auto-correct, then the autocorrection is in slot 0 and the typed word
302ebbb7e9665b2f9bce46ddc2daa82b9ef73f6c712Jean Chalard                // is in slot 1.
303f72b8f5662afb42b08eb88e92731d52f99df13e3Jean Chalard                if (index == mCenterSuggestionIndex
304f72b8f5662afb42b08eb88e92731d52f99df13e3Jean Chalard                        && AutoCorrection.shouldBlockAutoCorrectionBySafetyNet(
305bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka                                suggestedWords.getWord(1), suggestedWords.getWord(0))) {
3062aa1dd45c44295e2f7e8ece1b520032d86b9f908satok                    return 0xFFFF0000;
3072aa1dd45c44295e2f7e8ece1b520032d86b9f908satok                }
3082aa1dd45c44295e2f7e8ece1b520032d86b9f908satok            }
30960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka
3104f6cf258fe208329247ade7a6701ac9709820717Jean Chalard            if (suggestedWords.mIsObsoleteSuggestions && isSuggested) {
311697bf585f8dac6ffc4d008c02b63407cfdd83104Tadashi G. Takaoka                return applyAlpha(color, mAlphaObsoleted);
312d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            } else {
313d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka                return color;
314d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            }
315d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        }
316d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
317d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        private static int applyAlpha(final int color, final float alpha) {
318d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            final int newAlpha = (int)(Color.alpha(color) * alpha);
319d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka            return Color.argb(newAlpha, Color.red(color), Color.green(color), Color.blue(color));
320d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka        }
321d95a6365be213c1a1d2ab948fc5b80ee1ce0e3ceTadashi G. Takaoka
3222c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka        private static void addDivider(final ViewGroup stripView, final View divider) {
3232c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka            stripView.addView(divider);
3242c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka            final LinearLayout.LayoutParams params =
3252c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka                    (LinearLayout.LayoutParams)divider.getLayoutParams();
3262c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka            params.gravity = Gravity.CENTER;
3272c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka        }
3282c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka
3293e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        public void layout(final SuggestedWords suggestedWords, final ViewGroup stripView,
3303e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                final ViewGroup placer, final int stripWidth) {
331e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            if (suggestedWords.mIsPunctuationSuggestions) {
332e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka                layoutPunctuationSuggestions(suggestedWords, stripView);
3333a566c48b0eb3625788e1cce3fb2f58d8f4b380dTadashi G. Takaoka                return;
33460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            }
33560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka
336913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            final int countInStrip = mSuggestionsCountInStrip;
337e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            setupTexts(suggestedWords, countInStrip);
338e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
33960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            int x = 0;
34060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            for (int index = 0; index < countInStrip; index++) {
341e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka                final int pos = getWordPosition(index, suggestedWords);
34260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka
34360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                if (index != 0) {
34460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                    final View divider = mDividers.get(pos);
345913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                    // Add divider if this isn't the left most suggestion in suggestions strip.
3462c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka                    addDivider(stripView, divider);
347013ba3e3e785980b74db83ac5ab1e11b438485daTadashi G. Takaoka                    x += divider.getMeasuredWidth();
34860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                }
34960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka
35016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka                final CharSequence styled = mTexts.get(pos);
35160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                final TextView word = mWords.get(pos);
352913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                if (index == mCenterSuggestionIndex && mMoreSuggestionsAvailable) {
353ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka                    // TODO: This "more suggestions hint" should have nicely designed icon.
354ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka                    word.setCompoundDrawablesWithIntrinsicBounds(
355913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                            null, null, null, mMoreSuggestionsHint);
356580e1d7ac0cb90a464a3b3aed88047f85a4ab41fTadashi G. Takaoka                    // HACK: To align with other TextView that has no compound drawables.
357913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                    word.setCompoundDrawablePadding(-mMoreSuggestionsHint.getIntrinsicHeight());
358ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka                } else {
359580e1d7ac0cb90a464a3b3aed88047f85a4ab41fTadashi G. Takaoka                    word.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
360ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka                }
361ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka
362913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                // Disable this suggestion if the suggestion is null or empty.
36360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                word.setEnabled(!TextUtils.isEmpty(styled));
364e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka                word.setTextColor(getSuggestionTextColor(index, suggestedWords, pos));
365913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                final int width = getSuggestionWidth(index, stripWidth);
36660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                final CharSequence text = getEllipsizedText(styled, width, word.getPaint());
36760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                final float scaleX = word.getTextScaleX();
36860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                word.setText(text); // TextView.setText() resets text scale x to 1.0.
36960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                word.setTextScaleX(scaleX);
37060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                stripView.addView(word);
371b8dc67466339dc14653ad634c86851025373326bTadashi G. Takaoka                setLayoutWeight(
372913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                        word, getSuggestionWeight(index), ViewGroup.LayoutParams.MATCH_PARENT);
373013ba3e3e785980b74db83ac5ab1e11b438485daTadashi G. Takaoka                x += word.getMeasuredWidth();
37416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka
375042557b45bf2554608cd22874633011157cd1752Jean Chalard                if (DBG && pos < suggestedWords.size()) {
376bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka                    final String debugInfo = Utils.getDebugInfo(suggestedWords, pos);
37716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka                    if (debugInfo != null) {
37860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                        final TextView info = mInfos.get(pos);
37916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka                        info.setText(debugInfo);
380013ba3e3e785980b74db83ac5ab1e11b438485daTadashi G. Takaoka                        placer.addView(info);
381b8dc67466339dc14653ad634c86851025373326bTadashi G. Takaoka                        info.measure(ViewGroup.LayoutParams.WRAP_CONTENT,
382b8dc67466339dc14653ad634c86851025373326bTadashi G. Takaoka                                ViewGroup.LayoutParams.WRAP_CONTENT);
38360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                        final int infoWidth = info.getMeasuredWidth();
38416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka                        final int y = info.getMeasuredHeight();
385c8461d1ae26d43a09c0f835d833f3d49fbe8d2f3Tadashi G. Takaoka                        ViewLayoutUtils.placeViewAt(
386013ba3e3e785980b74db83ac5ab1e11b438485daTadashi G. Takaoka                                info, x - infoWidth, y, infoWidth, info.getMeasuredHeight());
38716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka                    }
38860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                }
38916713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka            }
39016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka        }
39116713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka
3923e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private int getSuggestionWidth(final int index, final int maxWidth) {
393913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            final int paddings = mPadding * mSuggestionsCountInStrip;
394913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            final int dividers = mDividerWidth * (mSuggestionsCountInStrip - 1);
39560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            final int availableWidth = maxWidth - paddings - dividers;
396913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            return (int)(availableWidth * getSuggestionWeight(index));
39760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        }
39874b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
3993e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private float getSuggestionWeight(final int index) {
400913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            if (index == mCenterSuggestionIndex) {
401913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                return mCenterSuggestionWeight;
40260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            } else {
40360a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                // TODO: Revisit this for cases of 5 or more suggestions
404913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                return (1.0f - mCenterSuggestionWeight) / (mSuggestionsCountInStrip - 1);
40574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka            }
40674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka        }
40774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
4083e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private void setupTexts(final SuggestedWords suggestedWords, final int countInStrip) {
40974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka            mTexts.clear();
410e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            final int count = Math.min(suggestedWords.size(), countInStrip);
41160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            for (int pos = 0; pos < count; pos++) {
412e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka                final CharSequence styled = getStyledSuggestionWord(suggestedWords, pos);
41374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka                mTexts.add(styled);
41474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka            }
41560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            for (int pos = count; pos < countInStrip; pos++) {
41660a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                // Make this inactive for touches in layout().
41760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                mTexts.add(null);
41860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            }
41974b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka        }
42074b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
4213e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private void layoutPunctuationSuggestions(final SuggestedWords suggestedWords,
4223e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                final ViewGroup stripView) {
423e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka            final int countInStrip = Math.min(suggestedWords.size(), PUNCTUATIONS_IN_STRIP);
42460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            for (int index = 0; index < countInStrip; index++) {
42560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                if (index != 0) {
426913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                    // Add divider if this isn't the left most suggestion in suggestions strip.
4272c47080e7b4b9b2a6c2dbf1444e041c1b7943316Tadashi G. Takaoka                    addDivider(stripView, mDividers.get(index));
42860a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                }
42960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka
43060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                final TextView word = mWords.get(index);
43160a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                word.setEnabled(true);
432a44685ab326809185a0e4c44afabe8fd93441b4cTadashi G. Takaoka                word.setTextColor(mColorAutoCorrect);
433bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka                final String text = suggestedWords.getWord(index);
43460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                word.setText(text);
43560a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                word.setTextScaleX(1.0f);
436ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka                word.setCompoundDrawables(null, null, null, null);
43760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka                stripView.addView(word);
438913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                setLayoutWeight(word, 1.0f, mSuggestionsStripHeight);
43960a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            }
440ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka            mMoreSuggestionsAvailable = false;
44174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka        }
442c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka
443bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka        public void layoutAddToDictionaryHint(final String word, final ViewGroup stripView,
4443e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                final int stripWidth, final CharSequence hintText, final OnClickListener listener) {
445c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            final int width = stripWidth - mDividerWidth - mPadding * 2;
446c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka
447c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            final TextView wordView = mWordToSaveView;
448c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            wordView.setTextColor(mColorTypedWord);
449913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            final int wordWidth = (int)(width * mCenterSuggestionWeight);
450c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            final CharSequence text = getEllipsizedText(word, wordWidth, wordView.getPaint());
451c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            final float wordScaleX = wordView.getTextScaleX();
452c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            wordView.setTag(word);
453c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            wordView.setText(text);
454c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            wordView.setTextScaleX(wordScaleX);
455c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            stripView.addView(wordView);
456913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            setLayoutWeight(wordView, mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
457c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka
458c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            stripView.addView(mDividers.get(0));
459c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka
4602eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            final TextView leftArrowView = mLeftwardsArrowView;
4612eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            leftArrowView.setTextColor(mColorAutoCorrect);
4622eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            leftArrowView.setText(LEFTWARDS_ARROW);
4632eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            stripView.addView(leftArrowView);
4642eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka
465c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            final TextView hintView = mHintToSaveView;
4662eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            hintView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
467c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            hintView.setTextColor(mColorAutoCorrect);
4682eb8781dc2e42d55474fb6e5c461c56c066b8363Tadashi G. Takaoka            final int hintWidth = width - wordWidth - leftArrowView.getWidth();
469644d33d60ea5a87501274488013d65f55238895eKen Wakasa            final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint());
470644d33d60ea5a87501274488013d65f55238895eKen Wakasa            hintView.setText(hintText);
471c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            hintView.setTextScaleX(hintScaleX);
472c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            stripView.addView(hintView);
473b8dc67466339dc14653ad634c86851025373326bTadashi G. Takaoka            setLayoutWeight(
474913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka                    hintView, 1.0f - mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
4759f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka
4769f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka            wordView.setOnClickListener(listener);
4779f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka            leftArrowView.setOnClickListener(listener);
4789f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka            hintView.setOnClickListener(listener);
4799f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka        }
4809f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka
4819f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka        public CharSequence getAddToDictionaryWord() {
4829f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka            return (CharSequence)mWordToSaveView.getTag();
4839f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka        }
4849f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka
4853e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        public boolean isAddToDictionaryShowing(final View v) {
4869f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka            return v == mWordToSaveView || v == mHintToSaveView || v == mLeftwardsArrowView;
487c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        }
4882d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka
4893e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private static void setLayoutWeight(final View v, final float weight, final int height) {
4902d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final ViewGroup.LayoutParams lp = v.getLayoutParams();
4912d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            if (lp instanceof LinearLayout.LayoutParams) {
4922d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp;
4932d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                llp.weight = weight;
4942d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                llp.width = 0;
4952d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                llp.height = height;
4962d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            }
4972d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka        }
4982d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka
4993e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private static float getTextScaleX(final CharSequence text, final int maxWidth,
5003e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                final TextPaint paint) {
5012d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            paint.setTextScaleX(1.0f);
5022d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final int width = getTextWidth(text, paint);
5032d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            if (width <= maxWidth) {
5042d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                return 1.0f;
5052d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            }
5062d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            return maxWidth / (float)width;
5072d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka        }
5082d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka
5093e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private static CharSequence getEllipsizedText(final CharSequence text, final int maxWidth,
5103e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka                final TextPaint paint) {
5112d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            if (text == null) return null;
5122d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            paint.setTextScaleX(1.0f);
5132d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final int width = getTextWidth(text, paint);
5142d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            if (width <= maxWidth) {
5152d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                return text;
5162d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            }
5172d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final float scaleX = maxWidth / (float)width;
5182d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            if (scaleX >= MIN_TEXT_XSCALE) {
5192d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                paint.setTextScaleX(scaleX);
5202d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                return text;
5212d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            }
5222d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka
5232d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To
5242d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            // get squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE).
5252d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final CharSequence ellipsized = TextUtils.ellipsize(
5262d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                    text, paint, maxWidth / MIN_TEXT_XSCALE, TextUtils.TruncateAt.MIDDLE);
5272d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            paint.setTextScaleX(MIN_TEXT_XSCALE);
5282d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            return ellipsized;
5292d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka        }
5302d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka
5313e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private static int getTextWidth(final CharSequence text, final TextPaint paint) {
5322d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            if (TextUtils.isEmpty(text)) return 0;
5332d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final Typeface savedTypeface = paint.getTypeface();
5342d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            paint.setTypeface(getTextTypeface(text));
5352d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final int len = text.length();
5362d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final float[] widths = new float[len];
5372d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final int count = paint.getTextWidths(text, 0, len, widths);
5382d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            int width = 0;
5392d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            for (int i = 0; i < count; i++) {
5402d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                width += Math.round(widths[i] + 0.5f);
5412d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            }
5422d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            paint.setTypeface(savedTypeface);
5432d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            return width;
5442d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka        }
5452d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka
5463e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka        private static Typeface getTextTypeface(final CharSequence text) {
5472d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            if (!(text instanceof SpannableString))
5482d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                return Typeface.DEFAULT;
5492d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka
5502d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final SpannableString ss = (SpannableString)text;
5512d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class);
5522d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            if (styles.length == 0)
5532d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka                return Typeface.DEFAULT;
5542d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka
5552d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            switch (styles[0].getStyle()) {
5562d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            case Typeface.BOLD: return Typeface.DEFAULT_BOLD;
5572d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            // TODO: BOLD_ITALIC, ITALIC case?
5582d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            default: return Typeface.DEFAULT;
5592d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka            }
5602d74806262431ce25b159e1ec5c6ac4a26007c3eTadashi G. Takaoka        }
56174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka    }
56274b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
563923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    /**
5644702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka     * Construct a {@link SuggestionStripView} for showing suggestions to be picked by the user.
565923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     * @param context
566923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     * @param attrs
567923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     */
5683e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public SuggestionStripView(final Context context, final AttributeSet attrs) {
5694702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka        this(context, attrs, R.attr.suggestionStripViewStyle);
57008a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka    }
57108a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka
5723e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public SuggestionStripView(final Context context, final AttributeSet attrs,
5733e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka            final int defStyle) {
574c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka        super(context, attrs, defStyle);
575923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
57616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka        final LayoutInflater inflater = LayoutInflater.from(context);
577913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        inflater.inflate(R.layout.suggestions_strip, this);
57886e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka
579913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip);
58060a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka        for (int pos = 0; pos < MAX_SUGGESTIONS; pos++) {
581913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            final TextView word = (TextView)inflater.inflate(R.layout.suggestion_word, null);
58260a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            word.setTag(pos);
5832442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka            word.setOnClickListener(this);
584ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka            word.setOnLongClickListener(this);
5852442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka            mWords.add(word);
586913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            final View divider = inflater.inflate(R.layout.suggestion_divider, null);
58760a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka            divider.setTag(pos);
588a1aab83a24e74cb0fad4b1c1e59b18d23ecbdad3Tadashi G. Takaoka            divider.setOnClickListener(this);
589a1aab83a24e74cb0fad4b1c1e59b18d23ecbdad3Tadashi G. Takaoka            mDividers.add(divider);
590913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            mInfos.add((TextView)inflater.inflate(R.layout.suggestion_info, null));
591c9716b28ce438e06b5cacc07fc002944bcbe24a0Tadashi G. Takaoka        }
592179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka
5934702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka        mParams = new SuggestionStripViewParams(
5944702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka                context, attrs, defStyle, mWords, mDividers, mInfos);
59529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
59629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null);
59729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer
59829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka                .findViewById(R.id.more_suggestions_view);
59908ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka        mMoreSuggestionsBuilder = new MoreSuggestions.Builder(context, mMoreSuggestionsView);
600bfc1d732ac92fa1bd5b19ad9e7c71ce9a1f9dc00Tadashi G. Takaoka
60150e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        final Resources res = context.getResources();
60250e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset(
60350e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka                R.dimen.more_suggestions_modal_tolerance);
6043fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        mMoreSuggestionsSlidingDetector = new GestureDetector(
6053fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka                context, mMoreSuggestionsSlidingListener);
606923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
607c9716b28ce438e06b5cacc07fc002944bcbe24a0Tadashi G. Takaoka
608923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    /**
609c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka     * A connection back to the input method.
610923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     * @param listener
611923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     */
6123e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public void setListener(final Listener listener, final View inputView) {
613c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka        mListener = listener;
614d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka        mMainKeyboardView = (MainKeyboardView)inputView.findViewById(R.id.keyboard_view);
615923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
616923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
6173e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public void setSuggestions(final SuggestedWords suggestedWords) {
618e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka        clear();
619e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka        mSuggestedWords = suggestedWords;
620e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka        mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth());
6219c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
6224702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            ResearchLogger.suggestionStripView_setSuggestions(mSuggestedWords);
623a9ca7867b5a7c0be115966211a05f5d460c8638cKurt Partridge        }
62416713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka    }
62574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
6263e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public int setMoreSuggestionsHeight(final int remainingHeight) {
627c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka        return mParams.setMoreSuggestionsHeight(remainingHeight);
628c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka    }
629b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka
630b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani    public boolean isShowingAddToDictionaryHint() {
631913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        return mSuggestionsStrip.getChildCount() > 0
6329f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka                && mParams.isAddToDictionaryShowing(mSuggestionsStrip.getChildAt(0));
633b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani    }
634b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani
635bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public void showAddToDictionaryHint(final String word, final CharSequence hintText) {
636c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        clear();
6379f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka        mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth(), hintText, this);
63866a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani    }
63966a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani
6406558253160e2039c87f424bd814f402ecd31de3bKen Wakasa    public boolean dismissAddToDictionaryHint() {
641c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        if (isShowingAddToDictionaryHint()) {
642c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            clear();
643c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            return true;
644c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        }
645c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        return false;
6466558253160e2039c87f424bd814f402ecd31de3bKen Wakasa    }
6476558253160e2039c87f424bd814f402ecd31de3bKen Wakasa
648923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void clear() {
649913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        mSuggestionsStrip.removeAllViews();
650c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka        removeAllViews();
651c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka        addView(mSuggestionsStrip);
6521b087064c07975c5e2b9c17d4ca80c56e01c35c0Tadashi G. Takaoka        dismissMoreSuggestions();
653923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
654923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
6556f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka    private final MoreSuggestionsListener mMoreSuggestionsListener = new MoreSuggestionsListener() {
65629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        @Override
6576f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka        public void onSuggestionSelected(final int index, final SuggestedWordInfo wordInfo) {
6589310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard            mListener.pickSuggestionManually(index, wordInfo);
6591b087064c07975c5e2b9c17d4ca80c56e01c35c0Tadashi G. Takaoka            dismissMoreSuggestions();
66029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
66129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
66229e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        @Override
66329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        public void onCancelInput() {
6641b087064c07975c5e2b9c17d4ca80c56e01c35c0Tadashi G. Takaoka            dismissMoreSuggestions();
66529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
66629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    };
66729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
66829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final MoreKeysPanel.Controller mMoreSuggestionsController =
66929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka            new MoreKeysPanel.Controller() {
67029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        @Override
671fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        public boolean onDismissMoreKeysPanel() {
672d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka            return mMainKeyboardView.onDismissMoreKeysPanel();
673fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        }
674fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang
675fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        @Override
676a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka        public void onShowMoreKeysPanel(final MoreKeysPanel panel) {
677d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka            mMainKeyboardView.onShowMoreKeysPanel(panel);
67829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
679ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang
680ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        @Override
681ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        public void onCancelMoreKeysPanel() {
682ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang            dismissMoreSuggestions();
683ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        }
68429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    };
68529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
6863e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    boolean dismissMoreSuggestions() {
687fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        return mMoreSuggestionsView.dismissMoreKeysPanel();
6881b087064c07975c5e2b9c17d4ca80c56e01c35c0Tadashi G. Takaoka    }
6891b087064c07975c5e2b9c17d4ca80c56e01c35c0Tadashi G. Takaoka
690e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka    @Override
6913e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public boolean onLongClick(final View view) {
6925faf41951929301af80026bc3191812ef874fd5aTadashi G. Takaoka        KeyboardSwitcher.getInstance().hapticAndAudioFeedback(Constants.NOT_A_CODE);
6933fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        return showMoreSuggestions();
6943fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    }
6953fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka
6963e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    boolean showMoreSuggestions() {
6977339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final Keyboard parentKeyboard = KeyboardSwitcher.getInstance().getKeyboard();
6987339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        if (parentKeyboard == null) {
6997339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka            return false;
700ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka        }
7017339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final SuggestionStripViewParams params = mParams;
7027339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        if (!params.mMoreSuggestionsAvailable) {
7037339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka            return false;
7047339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        }
7057339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final int stripWidth = getWidth();
7067339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final View container = mMoreSuggestionsContainer;
7077339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight();
7087339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder;
7097339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        builder.layout(mSuggestedWords, params.mSuggestionsCountInStrip, maxWidth,
7107339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka                (int)(maxWidth * params.mMinMoreSuggestionsWidth),
7117339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka                params.getMaxMoreSuggestionsRow(), parentKeyboard);
7127339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        mMoreSuggestionsView.setKeyboard(builder.build());
7137339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
7147339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka
7157339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView;
7167339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final int pointX = stripWidth / 2;
7177339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final int pointY = -params.mMoreSuggestionsBottomGap;
7187339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        moreKeysPanel.showMoreKeysPanel(this, mMoreSuggestionsController, pointX, pointY,
719fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang                mMoreSuggestionsListener);
7207339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING;
7217339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        mOriginX = mLastX;
7227339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        mOriginY = mLastY;
7237339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        for (int i = 0; i < params.mSuggestionsCountInStrip; i++) {
7247339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka            mWords.get(i).setPressed(false);
7257339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        }
7267339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        return true;
727ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka    }
728ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka
72950e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    // Working variables for onLongClick and dispatchTouchEvent.
730d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka    private int mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_MODAL_MODE;
731d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka    private static final int MORE_SUGGESTIONS_IN_MODAL_MODE = 0;
732d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka    private static final int MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING = 1;
733d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka    private static final int MORE_SUGGESTIONS_IN_SLIDING_MODE = 2;
73450e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mLastX;
73550e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mLastY;
73650e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mOriginX;
73750e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mOriginY;
73850e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private final int mMoreSuggestionsModalTolerance;
7393fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    private final GestureDetector mMoreSuggestionsSlidingDetector;
7403fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    private final GestureDetector.OnGestureListener mMoreSuggestionsSlidingListener =
7413fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            new GestureDetector.SimpleOnGestureListener() {
7423fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        @Override
7433fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        public boolean onScroll(MotionEvent down, MotionEvent me, float deltaX, float deltaY) {
7443fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            final float dy = me.getY() - down.getY();
7453fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            if (deltaY > 0 && dy < 0) {
7463fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka                return showMoreSuggestions();
7473fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            }
7483fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            return false;
7493fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        }
7503fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    };
75150e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka
752ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka    @Override
7533e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public boolean dispatchTouchEvent(final MotionEvent me) {
75451c38a441a09a4920703e765cb26179e7a80f029Tadashi G. Takaoka        if (!mMoreSuggestionsView.isShowingInParent()) {
75550e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            mLastX = (int)me.getX();
75650e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            mLastY = (int)me.getY();
7573fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            if (mMoreSuggestionsSlidingDetector.onTouchEvent(me)) {
7583fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka                return true;
7593fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            }
76029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka            return super.dispatchTouchEvent(me);
76129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
7628ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka
7638ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka        final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView;
76429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        final int action = me.getAction();
76529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        final long eventTime = me.getEventTime();
76629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        final int index = me.getActionIndex();
76729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        final int id = me.getPointerId(index);
7688ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka        final int x = (int)me.getX(index);
7698ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka        final int y = (int)me.getY(index);
7708ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka        final int translatedX = moreKeysPanel.translateX(x);
7718ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka        final int translatedY = moreKeysPanel.translateY(y);
7728ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka
773d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka        if (mMoreSuggestionsMode == MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING) {
77487104bace9cb9ed1a700f05a37743a21c2722fffTadashi G. Takaoka            if (Math.abs(x - mOriginX) >= mMoreSuggestionsModalTolerance
77587104bace9cb9ed1a700f05a37743a21c2722fffTadashi G. Takaoka                    || mOriginY - y >= mMoreSuggestionsModalTolerance) {
77687104bace9cb9ed1a700f05a37743a21c2722fffTadashi G. Takaoka                // Decided to be in the sliding input mode only when the touch point has been moved
77787104bace9cb9ed1a700f05a37743a21c2722fffTadashi G. Takaoka                // upward.
778d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka                mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_SLIDING_MODE;
77950e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {
78050e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka                // Decided to be in the modal input mode
781d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka                mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_MODAL_MODE;
78251c38a441a09a4920703e765cb26179e7a80f029Tadashi G. Takaoka                mMoreSuggestionsView.adjustVerticalCorrectionForModalMode();
78350e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            }
78450e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            return true;
78550e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        }
78650e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka
787d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka        // MORE_SUGGESTIONS_IN_SLIDING_MODE
78835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        mMoreSuggestionsView.processMotionEvent(action, translatedX, translatedY, id, eventTime);
78929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        return true;
79029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    }
79129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
79229e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    @Override
7933e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public void onClick(final View view) {
7949f763d14451685965039990891eb0bc8e8db0735Tadashi G. Takaoka        if (mParams.isAddToDictionaryShowing(view)) {
7953d8e7a62fc6182c12ca28c29ceeee52ed4b9eea7Jean Chalard            mListener.addWordToUserDictionary(mParams.getAddToDictionaryWord().toString());
796717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka            clear();
797717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka            return;
798717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka        }
799717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka
80086e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka        final Object tag = view.getTag();
80186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka        if (!(tag instanceof Integer))
80286e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka            return;
80386e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka        final int index = (Integer) tag;
804e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka        if (index >= mSuggestedWords.size())
80537deb112c727dfed5e94d054cf5f00f5d60c8120Tadashi G. Takaoka            return;
80686e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka
8079310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard        final SuggestedWordInfo wordInfo = mSuggestedWords.getInfo(index);
8089310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard        mListener.pickSuggestionManually(index, wordInfo);
809923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
81082411d47ba7e8133ed2390c6920945e139a738cesatok
8116ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani    @Override
81273cd4c1428ac370e1c15c5f61b1ce499f0d4f4c7Tadashi G. Takaoka    protected void onDetachedFromWindow() {
8136ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani        super.onDetachedFromWindow();
81432f4ceb2434b6f204cf8152b406d0f9a642feb73Tadashi G. Takaoka        dismissMoreSuggestions();
8156ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani    }
816923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project}
817