SuggestionStripView.java revision 01748cde4e692c970617e4478368f83b710a86b6
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;
21c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaokaimport android.content.res.TypedArray;
22c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaokaimport android.graphics.Color;
23c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaokaimport android.graphics.drawable.Drawable;
24bcd30bf3e74c7c10d5b69a54cdf90c6b682a0747Tadashi G. Takaokaimport android.support.v4.view.ViewCompat;
256abc852255072e9c5741a7d8f264bec99b0ce14eTadashi G. Takaokaimport android.text.TextUtils;
26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.AttributeSet;
27c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaokaimport android.util.TypedValue;
283fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaokaimport android.view.GestureDetector;
29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.LayoutInflater;
3029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaokaimport android.view.MotionEvent;
31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View;
32e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.view.View.OnClickListener;
33ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaokaimport android.view.View.OnLongClickListener;
34e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.view.ViewGroup;
359ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaokaimport android.view.ViewParent;
36c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaokaimport android.widget.ImageButton;
37c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaokaimport android.widget.RelativeLayout;
38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.widget.TextView;
39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
407339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard;
41d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaokaimport com.android.inputmethod.keyboard.MainKeyboardView;
4229e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaokaimport com.android.inputmethod.keyboard.MoreKeysPanel;
436f9105383a56c9ae15e35d3abf19c33d1efe5636Tadashi G. Takaokaimport com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
445faf41951929301af80026bc3191812ef874fd5aTadashi G. Takaokaimport com.android.inputmethod.latin.Constants;
45ce78a2d8ab7630cff509c2b21b4b11abd8db4795Tadashi G. Takaokaimport com.android.inputmethod.latin.InputAttributes;
468c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinImeLogger;
478c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.R;
488c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.SuggestedWords;
499310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalardimport com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
50a9ca7867b5a7c0be115966211a05f5d460c8638cKurt Partridgeimport com.android.inputmethod.latin.define.ProductionFlag;
51ce78a2d8ab7630cff509c2b21b4b11abd8db4795Tadashi G. Takaokaimport com.android.inputmethod.latin.settings.Settings;
5201748cde4e692c970617e4478368f83b710a86b6Tadashi G. Takaokaimport com.android.inputmethod.latin.suggestions.MoreSuggestionsView.MoreSuggestionsListener;
538dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaokaimport com.android.inputmethod.latin.utils.ImportantNoticeUtils;
546b966160ac8570271547bf63217efa5e228d4accKurt Partridgeimport com.android.inputmethod.research.ResearchLogger;
55ddb61ea461b920d87be4ad78c8a36eec1013b965Tadashi G. Takaoka
56179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaokaimport java.util.ArrayList;
57179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka
58a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaokapublic final class SuggestionStripView extends RelativeLayout implements OnClickListener,
59c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka        OnLongClickListener {
60c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka    public interface Listener {
6118d688c94bb8e1e26de2d12445cb3096c6126f75Jean Chalard        public void addWordToUserDictionary(String word);
628a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        public void showImportantNoticeContents();
639310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard        public void pickSuggestionManually(int index, SuggestedWordInfo word);
64c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        public void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat);
65c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka    }
66c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka
678c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaoka    static final boolean DBG = LatinImeLogger.sDBG;
68c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka    private static final float DEBUG_INFO_TEXT_SIZE_IN_DIP = 6.0f;
696f7218627eda110a8454053f8ecb7b80edfdc8cesatok
70913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka    private final ViewGroup mSuggestionsStrip;
71c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka    private final ImageButton mVoiceKey;
72148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka    private final ViewGroup mAddToDictionaryStrip;
738a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka    private final View mImportantNoticeStrip;
74d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka    MainKeyboardView mMainKeyboardView;
7574b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
7629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final View mMoreSuggestionsContainer;
7729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final MoreSuggestionsView mMoreSuggestionsView;
7829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final MoreSuggestions.Builder mMoreSuggestionsBuilder;
7929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
80a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka    private final ArrayList<TextView> mWordViews = new ArrayList<>();
81a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka    private final ArrayList<TextView> mDebugInfoViews = new ArrayList<>();
82a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka    private final ArrayList<View> mDividerViews = new ArrayList<>();
8374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
843e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    Listener mListener;
856f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka    private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
864f8a8f125e329b55e49d31a98b5368113440c755Tadashi G. Takaoka    private int mSuggestionsCountInStrip;
876a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani
88653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka    private final SuggestionStripLayoutHelper mLayoutHelper;
89148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka    private final StripVisibilityGroup mStripVisibilityGroup;
90148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
91148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka    private static class StripVisibilityGroup {
92630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka        private final View mSuggestionStripView;
93148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        private final View mSuggestionsStrip;
94c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        private final View mVoiceKey;
95148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        private final View mAddToDictionaryStrip;
968a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        private final View mImportantNoticeStrip;
97148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
98630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka        public StripVisibilityGroup(final View suggestionStripView,
99630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka                final ViewGroup suggestionsStrip, final ImageButton voiceKey,
100630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka                final ViewGroup addToDictionaryStrip, final View importantNoticeStrip) {
101630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka            mSuggestionStripView = suggestionStripView;
102148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            mSuggestionsStrip = suggestionsStrip;
103c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka            mVoiceKey = voiceKey;
104148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            mAddToDictionaryStrip = addToDictionaryStrip;
1058a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mImportantNoticeStrip = importantNoticeStrip;
106c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka            showSuggestionsStrip(false /* voiceKeyEnabled */);
107148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        }
108148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
109630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka        public void setLayoutDirection(final boolean isRtlLanguage) {
110630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka            final int layoutDirection = isRtlLanguage ? ViewCompat.LAYOUT_DIRECTION_RTL
111630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka                    : ViewCompat.LAYOUT_DIRECTION_LTR;
112630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka            ViewCompat.setLayoutDirection(mSuggestionStripView, layoutDirection);
113bcd30bf3e74c7c10d5b69a54cdf90c6b682a0747Tadashi G. Takaoka            ViewCompat.setLayoutDirection(mSuggestionsStrip, layoutDirection);
114bcd30bf3e74c7c10d5b69a54cdf90c6b682a0747Tadashi G. Takaoka            ViewCompat.setLayoutDirection(mAddToDictionaryStrip, layoutDirection);
1158a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            ViewCompat.setLayoutDirection(mImportantNoticeStrip, layoutDirection);
116bcd30bf3e74c7c10d5b69a54cdf90c6b682a0747Tadashi G. Takaoka        }
117bcd30bf3e74c7c10d5b69a54cdf90c6b682a0747Tadashi G. Takaoka
118c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        public void showSuggestionsStrip(final boolean enableVoiceKey) {
119148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            mSuggestionsStrip.setVisibility(VISIBLE);
120c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka            mVoiceKey.setVisibility(enableVoiceKey ? VISIBLE : INVISIBLE);
121148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            mAddToDictionaryStrip.setVisibility(INVISIBLE);
1228a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mImportantNoticeStrip.setVisibility(INVISIBLE);
123148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        }
124148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
125148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        public void showAddToDictionaryStrip() {
126148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            mSuggestionsStrip.setVisibility(INVISIBLE);
127c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka            mVoiceKey.setVisibility(INVISIBLE);
128148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            mAddToDictionaryStrip.setVisibility(VISIBLE);
1298a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mImportantNoticeStrip.setVisibility(INVISIBLE);
1308a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        }
1318a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka
13208103a0e0784ef0396fd17cbd955309270f8d3a9Tadashi G. Takaoka        public void showImportantNoticeStrip(final boolean enableVoiceKey) {
1338a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mSuggestionsStrip.setVisibility(INVISIBLE);
13408103a0e0784ef0396fd17cbd955309270f8d3a9Tadashi G. Takaoka            mVoiceKey.setVisibility(enableVoiceKey ? VISIBLE : INVISIBLE);
1358a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mAddToDictionaryStrip.setVisibility(INVISIBLE);
1368a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mImportantNoticeStrip.setVisibility(VISIBLE);
137148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        }
138148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
139148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        public boolean isShowingAddToDictionaryStrip() {
140148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            return mAddToDictionaryStrip.getVisibility() == VISIBLE;
141148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        }
142148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka    }
14374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
144923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    /**
1454702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka     * Construct a {@link SuggestionStripView} for showing suggestions to be picked by the user.
146923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     * @param context
147923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     * @param attrs
148923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     */
1493e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public SuggestionStripView(final Context context, final AttributeSet attrs) {
1504702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka        this(context, attrs, R.attr.suggestionStripViewStyle);
15108a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka    }
15208a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka
1533e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public SuggestionStripView(final Context context, final AttributeSet attrs,
1543e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka            final int defStyle) {
155c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka        super(context, attrs, defStyle);
156923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
15716713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka        final LayoutInflater inflater = LayoutInflater.from(context);
158913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        inflater.inflate(R.layout.suggestions_strip, this);
15986e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka
160913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip);
161c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        mVoiceKey = (ImageButton)findViewById(R.id.suggestions_strip_voice_key);
162148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        mAddToDictionaryStrip = (ViewGroup)findViewById(R.id.add_to_dictionary_strip);
1638a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        mImportantNoticeStrip = findViewById(R.id.important_notice_strip);
164630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka        mStripVisibilityGroup = new StripVisibilityGroup(this, mSuggestionsStrip, mVoiceKey,
165c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka                mAddToDictionaryStrip, mImportantNoticeStrip);
166148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
167a1ed211c4e80eb81ce399e0eaff88bbdf1e3199fJean Chalard        for (int pos = 0; pos < SuggestedWords.MAX_SUGGESTIONS; pos++) {
168c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka            final TextView word = new TextView(context, null, R.attr.suggestionWordStyle);
1692442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka            word.setOnClickListener(this);
170ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka            word.setOnLongClickListener(this);
171500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka            mWordViews.add(word);
172913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            final View divider = inflater.inflate(R.layout.suggestion_divider, null);
173a1aab83a24e74cb0fad4b1c1e59b18d23ecbdad3Tadashi G. Takaoka            divider.setOnClickListener(this);
174500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka            mDividerViews.add(divider);
175c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka            final TextView info = new TextView(context, null, R.attr.suggestionWordStyle);
176c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka            info.setTextColor(Color.WHITE);
177c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka            info.setTextSize(TypedValue.COMPLEX_UNIT_DIP, DEBUG_INFO_TEXT_SIZE_IN_DIP);
178c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka            mDebugInfoViews.add(info);
179c9716b28ce438e06b5cacc07fc002944bcbe24a0Tadashi G. Takaoka        }
180179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka
181653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka        mLayoutHelper = new SuggestionStripLayoutHelper(
182500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka                context, attrs, defStyle, mWordViews, mDividerViews, mDebugInfoViews);
18329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
18429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null);
18529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer
18629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka                .findViewById(R.id.more_suggestions_view);
18708ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka        mMoreSuggestionsBuilder = new MoreSuggestions.Builder(context, mMoreSuggestionsView);
188bfc1d732ac92fa1bd5b19ad9e7c71ce9a1f9dc00Tadashi G. Takaoka
18950e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        final Resources res = context.getResources();
19050e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset(
1912fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                R.dimen.config_more_suggestions_modal_tolerance);
1923fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        mMoreSuggestionsSlidingDetector = new GestureDetector(
1933fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka                context, mMoreSuggestionsSlidingListener);
194c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka
195c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        final TypedArray keyboardAttr = context.obtainStyledAttributes(attrs,
196c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka                R.styleable.Keyboard, defStyle, R.style.SuggestionStripView);
197c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        final Drawable iconVoice = keyboardAttr.getDrawable(R.styleable.Keyboard_iconShortcutKey);
198c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        keyboardAttr.recycle();
199c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        mVoiceKey.setImageDrawable(iconVoice);
200c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        mVoiceKey.setOnClickListener(this);
201923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
202c9716b28ce438e06b5cacc07fc002944bcbe24a0Tadashi G. Takaoka
203923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    /**
204c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka     * A connection back to the input method.
205923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     * @param listener
206923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     */
2073e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public void setListener(final Listener listener, final View inputView) {
208c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka        mListener = listener;
209d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka        mMainKeyboardView = (MainKeyboardView)inputView.findViewById(R.id.keyboard_view);
210923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
211923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
212c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka    private boolean isVoiceKeyEnabled() {
213c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        if (mMainKeyboardView == null) {
214c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka            return false;
215c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        }
216c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        final Keyboard keyboard = mMainKeyboardView.getKeyboard();
217c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        if (keyboard == null) {
218c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka            return false;
219c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        }
220c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        return keyboard.mId.mHasShortcutKey;
221c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka    }
222c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka
223bcd30bf3e74c7c10d5b69a54cdf90c6b682a0747Tadashi G. Takaoka    public void setSuggestions(final SuggestedWords suggestedWords, final boolean isRtlLanguage) {
224e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka        clear();
225630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka        mStripVisibilityGroup.setLayoutDirection(isRtlLanguage);
226e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka        mSuggestedWords = suggestedWords;
2274f8a8f125e329b55e49d31a98b5368113440c755Tadashi G. Takaoka        mSuggestionsCountInStrip = mLayoutHelper.layoutAndReturnSuggestionCountInStrip(
2284f8a8f125e329b55e49d31a98b5368113440c755Tadashi G. Takaoka                mSuggestedWords, mSuggestionsStrip, this);
2299c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
2304702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka            ResearchLogger.suggestionStripView_setSuggestions(mSuggestedWords);
231a9ca7867b5a7c0be115966211a05f5d460c8638cKurt Partridge        }
232c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        mStripVisibilityGroup.showSuggestionsStrip(isVoiceKeyEnabled());
23316713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka    }
23474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
235c160a3932f74fea72c5347798c001d4ae961864cKen Wakasa    public int setMoreSuggestionsHeight(final int remainingHeight) {
236c160a3932f74fea72c5347798c001d4ae961864cKen Wakasa        return mLayoutHelper.setMoreSuggestionsHeight(remainingHeight);
237c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka    }
238b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka
239b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani    public boolean isShowingAddToDictionaryHint() {
240148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        return mStripVisibilityGroup.isShowingAddToDictionaryStrip();
241b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani    }
242b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani
2439b1a66843ddde552ea626a7b24c2c71ba23aa63aTadashi G. Takaoka    public void showAddToDictionaryHint(final String word) {
2442b479cccaeb0bb54121730cb5e47cca3f7517c67Tadashi G. Takaoka        mLayoutHelper.layoutAddToDictionaryHint(word, mAddToDictionaryStrip);
245148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        // {@link TextView#setTag()} is used to hold the word to be added to dictionary. The word
246148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        // will be extracted at {@link #onClick(View)}.
247148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        mAddToDictionaryStrip.setTag(word);
248148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        mAddToDictionaryStrip.setOnClickListener(this);
249148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        mStripVisibilityGroup.showAddToDictionaryStrip();
25066a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani    }
25166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani
2526558253160e2039c87f424bd814f402ecd31de3bKen Wakasa    public boolean dismissAddToDictionaryHint() {
253c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        if (isShowingAddToDictionaryHint()) {
254c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            clear();
255c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka            return true;
256c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        }
257c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka        return false;
2586558253160e2039c87f424bd814f402ecd31de3bKen Wakasa    }
2596558253160e2039c87f424bd814f402ecd31de3bKen Wakasa
2608dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka    // This method checks if we should show the important notice (checks on permanent storage if
2618dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka    // it has been shown once already or not, and if in the setup wizard). If applicable, it shows
2628dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka    // the notice. In all cases, it returns true if it was shown, false otherwise.
263ce78a2d8ab7630cff509c2b21b4b11abd8db4795Tadashi G. Takaoka    public boolean maybeShowImportantNoticeTitle(final InputAttributes inputAttributes) {
264ce78a2d8ab7630cff509c2b21b4b11abd8db4795Tadashi G. Takaoka        if (!ImportantNoticeUtils.shouldShowImportantNotice(getContext(), inputAttributes)) {
2658dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka            return false;
2668dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka        }
26714e908c3486ae5996e66625e959ff45c5f3740efTadashi G. Takaoka        if (getWidth() <= 0) {
268affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka            return false;
269affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka        }
2701672ccbbb6167f434842093feaadc2bcd5634eabTadashi G. Takaoka        final String importantNoticeTitle = ImportantNoticeUtils.getNextImportantNoticeTitle(
2716abc852255072e9c5741a7d8f264bec99b0ce14eTadashi G. Takaoka                getContext());
2726abc852255072e9c5741a7d8f264bec99b0ce14eTadashi G. Takaoka        if (TextUtils.isEmpty(importantNoticeTitle)) {
2736abc852255072e9c5741a7d8f264bec99b0ce14eTadashi G. Takaoka            return false;
2746abc852255072e9c5741a7d8f264bec99b0ce14eTadashi G. Takaoka        }
275c8abd13c77ed90b209301ea379e1142e0d60e3f5Tadashi G. Takaoka        if (isShowingMoreSuggestionPanel()) {
276c8abd13c77ed90b209301ea379e1142e0d60e3f5Tadashi G. Takaoka            dismissMoreSuggestionsPanel();
277c8abd13c77ed90b209301ea379e1142e0d60e3f5Tadashi G. Takaoka        }
27814e908c3486ae5996e66625e959ff45c5f3740efTadashi G. Takaoka        mLayoutHelper.layoutImportantNotice(mImportantNoticeStrip, importantNoticeTitle);
27908103a0e0784ef0396fd17cbd955309270f8d3a9Tadashi G. Takaoka        mStripVisibilityGroup.showImportantNoticeStrip(isVoiceKeyEnabled());
2808a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        mImportantNoticeStrip.setOnClickListener(this);
2818dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka        return true;
2828a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka    }
2838a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka
284923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void clear() {
285913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        mSuggestionsStrip.removeAllViews();
2869ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka        removeAllDebugInfoViews();
287c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        mStripVisibilityGroup.showSuggestionsStrip(false /* enableVoiceKey */);
28819dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka        dismissMoreSuggestionsPanel();
289923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
290923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
2919ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka    private void removeAllDebugInfoViews() {
2929ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka        // The debug info views may be placed as children views of this {@link SuggestionStripView}.
2939ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka        for (final View debugInfoView : mDebugInfoViews) {
2949ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka            final ViewParent parent = debugInfoView.getParent();
2959ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka            if (parent instanceof ViewGroup) {
2969ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka                ((ViewGroup)parent).removeView(debugInfoView);
2979ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka            }
2989ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka        }
2999ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka    }
3009ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka
3016f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka    private final MoreSuggestionsListener mMoreSuggestionsListener = new MoreSuggestionsListener() {
30229e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        @Override
3036f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka        public void onSuggestionSelected(final int index, final SuggestedWordInfo wordInfo) {
3049310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard            mListener.pickSuggestionManually(index, wordInfo);
30519dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka            dismissMoreSuggestionsPanel();
30629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
30729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
30829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        @Override
30929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        public void onCancelInput() {
31019dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka            dismissMoreSuggestionsPanel();
31129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
31229e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    };
31329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
31429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final MoreKeysPanel.Controller mMoreSuggestionsController =
31529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka            new MoreKeysPanel.Controller() {
31629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        @Override
3171f215a58c99f0eb2f536e9cccd51371f2883e201Tadashi G. Takaoka        public void onDismissMoreKeysPanel() {
3181f215a58c99f0eb2f536e9cccd51371f2883e201Tadashi G. Takaoka            mMainKeyboardView.onDismissMoreKeysPanel();
319fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        }
320fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang
321fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        @Override
322a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka        public void onShowMoreKeysPanel(final MoreKeysPanel panel) {
323d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka            mMainKeyboardView.onShowMoreKeysPanel(panel);
32429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
325ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang
326ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        @Override
3271f215a58c99f0eb2f536e9cccd51371f2883e201Tadashi G. Takaoka        public void onCancelMoreKeysPanel() {
32819dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka            dismissMoreSuggestionsPanel();
329ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        }
33029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    };
33129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
33219dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka    public boolean isShowingMoreSuggestionPanel() {
33319dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka        return mMoreSuggestionsView.isShowingInParent();
33419dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka    }
33519dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka
33619dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka    public void dismissMoreSuggestionsPanel() {
33719dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka        mMoreSuggestionsView.dismissMoreKeysPanel();
33819dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka    }
33919dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka
340e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka    @Override
3413e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public boolean onLongClick(final View view) {
342ab16237e69061bb0aa7f882e48e5d93459c22ef3Tadashi G. Takaoka        AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(
3436f9105383a56c9ae15e35d3abf19c33d1efe5636Tadashi G. Takaoka                Constants.NOT_A_CODE, this);
3443fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        return showMoreSuggestions();
3453fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    }
3463fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka
3473e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    boolean showMoreSuggestions() {
34856e0373b5c0c516cd57352cebf882e2b358f168cTadashi G. Takaoka        final Keyboard parentKeyboard = mMainKeyboardView.getKeyboard();
3497339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        if (parentKeyboard == null) {
3507339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka            return false;
351ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka        }
352653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka        final SuggestionStripLayoutHelper layoutHelper = mLayoutHelper;
353653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka        if (!layoutHelper.mMoreSuggestionsAvailable) {
3547339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka            return false;
3557339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        }
35656e0373b5c0c516cd57352cebf882e2b358f168cTadashi G. Takaoka        // Dismiss another {@link MoreKeysPanel} that may be being showed, for example
35756e0373b5c0c516cd57352cebf882e2b358f168cTadashi G. Takaoka        // {@link MoreKeysKeyboardView}.
3581f215a58c99f0eb2f536e9cccd51371f2883e201Tadashi G. Takaoka        mMainKeyboardView.onDismissMoreKeysPanel();
359ddc21f5bd1113c24840fd436d09de62c8e476335Tadashi G. Takaoka        // Dismiss all key previews and sliding key input preview that may be being showed.
360ddc21f5bd1113c24840fd436d09de62c8e476335Tadashi G. Takaoka        mMainKeyboardView.dismissAllKeyPreviews();
361ddc21f5bd1113c24840fd436d09de62c8e476335Tadashi G. Takaoka        mMainKeyboardView.dismissSlidingKeyInputPreview();
3627339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final int stripWidth = getWidth();
3637339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final View container = mMoreSuggestionsContainer;
3647339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight();
3657339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder;
3664f8a8f125e329b55e49d31a98b5368113440c755Tadashi G. Takaoka        builder.layout(mSuggestedWords, mSuggestionsCountInStrip, maxWidth,
367653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka                (int)(maxWidth * layoutHelper.mMinMoreSuggestionsWidth),
368653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka                layoutHelper.getMaxMoreSuggestionsRow(), parentKeyboard);
3697339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        mMoreSuggestionsView.setKeyboard(builder.build());
3707339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
3717339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka
3727339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView;
3737339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final int pointX = stripWidth / 2;
374653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka        final int pointY = -layoutHelper.mMoreSuggestionsBottomGap;
3757339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        moreKeysPanel.showMoreKeysPanel(this, mMoreSuggestionsController, pointX, pointY,
376fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang                mMoreSuggestionsListener);
3777339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        mOriginX = mLastX;
3787339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        mOriginY = mLastY;
3794f8a8f125e329b55e49d31a98b5368113440c755Tadashi G. Takaoka        for (int i = 0; i < mSuggestionsCountInStrip; i++) {
380500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka            mWordViews.get(i).setPressed(false);
3817339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        }
3827339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        return true;
383ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka    }
384ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka
385e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka    // Working variables for {@link #onLongClick(View)} and
386e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka    // {@link onInterceptTouchEvent(MotionEvent)}.
38750e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mLastX;
38850e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mLastY;
38950e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mOriginX;
39050e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mOriginY;
39150e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private final int mMoreSuggestionsModalTolerance;
3923fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    private final GestureDetector mMoreSuggestionsSlidingDetector;
3933fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    private final GestureDetector.OnGestureListener mMoreSuggestionsSlidingListener =
3943fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            new GestureDetector.SimpleOnGestureListener() {
3953fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        @Override
3963fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        public boolean onScroll(MotionEvent down, MotionEvent me, float deltaX, float deltaY) {
3973fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            final float dy = me.getY() - down.getY();
3983fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            if (deltaY > 0 && dy < 0) {
3993fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka                return showMoreSuggestions();
4003fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            }
4013fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            return false;
4023fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        }
4033fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    };
40450e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka
405ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka    @Override
406e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka    public boolean onInterceptTouchEvent(final MotionEvent me) {
40751c38a441a09a4920703e765cb26179e7a80f029Tadashi G. Takaoka        if (!mMoreSuggestionsView.isShowingInParent()) {
40850e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            mLastX = (int)me.getX();
40950e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            mLastY = (int)me.getY();
410e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka            return mMoreSuggestionsSlidingDetector.onTouchEvent(me);
41129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
4128ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka
41329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        final int action = me.getAction();
41429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        final int index = me.getActionIndex();
4158ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka        final int x = (int)me.getX(index);
4168ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka        final int y = (int)me.getY(index);
417e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        if (Math.abs(x - mOriginX) >= mMoreSuggestionsModalTolerance
418e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka                || mOriginY - y >= mMoreSuggestionsModalTolerance) {
419e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka            // Decided to be in the sliding input mode only when the touch point has been moved
420e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka            // upward. Further {@link MotionEvent}s will be delivered to
421e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka            // {@link #onTouchEvent(MotionEvent)}.
42250e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            return true;
42350e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        }
42450e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka
425e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {
426e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka            // Decided to be in the modal input mode.
427e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka            mMoreSuggestionsView.adjustVerticalCorrectionForModalMode();
428e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        }
429e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        return false;
430e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka    }
431e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka
432e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka    @Override
433e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka    public boolean onTouchEvent(final MotionEvent me) {
434e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        // In the sliding input mode. {@link MotionEvent} should be forwarded to
435e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        // {@link MoreSuggestionsView}.
436e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        final int index = me.getActionIndex();
437e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        final int x = (int)me.getX(index);
438e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        final int y = (int)me.getY(index);
43933482a9b9ccf605c63fab7c9b8273a240bbc2035Tadashi G. Takaoka        me.setLocation(mMoreSuggestionsView.translateX(x), mMoreSuggestionsView.translateY(y));
44033482a9b9ccf605c63fab7c9b8273a240bbc2035Tadashi G. Takaoka        mMoreSuggestionsView.onTouchEvent(me);
44129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        return true;
44229e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    }
44329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
44429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    @Override
4453e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public void onClick(final View view) {
4468a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        if (view == mImportantNoticeStrip) {
4478a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mListener.showImportantNoticeContents();
4488a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            return;
4498a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        }
450c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        if (view == mVoiceKey) {
451c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka            mListener.onCodeInput(Constants.CODE_SHORTCUT,
452c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka                    Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE,
453c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka                    false /* isKeyRepeat */);
454c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka            return;
455c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        }
456148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        final Object tag = view.getTag();
457148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        // {@link String} tag is set at {@link #showAddToDictionaryHint(String,CharSequence)}.
458148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        if (tag instanceof String) {
459148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            final String wordToSave = (String)tag;
460148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            mListener.addWordToUserDictionary(wordToSave);
461717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka            clear();
462717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka            return;
463717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka        }
464717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka
465148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        // {@link Integer} tag is set at
4669b570b5e62581f41c40c4558d95c77ad5896934cTadashi G. Takaoka        // {@link SuggestionStripLayoutHelper#setupWordViewsTextAndColor(SuggestedWords,int)} and
4679b570b5e62581f41c40c4558d95c77ad5896934cTadashi G. Takaoka        // {@link SuggestionStripLayoutHelper#layoutPunctuationSuggestions(SuggestedWords,ViewGroup}
468148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        if (tag instanceof Integer) {
469148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            final int index = (Integer) tag;
470148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            if (index >= mSuggestedWords.size()) {
471148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka                return;
472148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            }
473148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            final SuggestedWordInfo wordInfo = mSuggestedWords.getInfo(index);
474148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            mListener.pickSuggestionManually(index, wordInfo);
475500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka        }
476923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
47782411d47ba7e8133ed2390c6920945e139a738cesatok
4786ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani    @Override
47973cd4c1428ac370e1c15c5f61b1ce499f0d4f4c7Tadashi G. Takaoka    protected void onDetachedFromWindow() {
4806ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani        super.onDetachedFromWindow();
48119dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka        dismissMoreSuggestionsPanel();
4826ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani    }
4838dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka
4848dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka    @Override
485affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka    protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
4868dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka        // Called by the framework when the size is known. Show the important notice if applicable.
4878dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka        // This may be overriden by showing suggestions later, if applicable.
488affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka        if (oldw <= 0 && w > 0) {
489affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka            maybeShowImportantNoticeTitle(Settings.getInstance().getCurrent().mInputAttributes);
490affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka        }
4918dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka    }
492923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project}
493