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;
36a2e365da0acf80c1bcd8413d72f697a0da374779Tadashi G. Takaokaimport android.view.accessibility.AccessibilityEvent;
37c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaokaimport android.widget.ImageButton;
38c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaokaimport android.widget.RelativeLayout;
39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.widget.TextView;
40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
41da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaokaimport com.android.inputmethod.accessibility.AccessibilityUtils;
427339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard;
43d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaokaimport com.android.inputmethod.keyboard.MainKeyboardView;
4429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaokaimport com.android.inputmethod.keyboard.MoreKeysPanel;
456f9105383a56c9ae15e35d3abf19c33d1efe5636Tadashi G. Takaokaimport com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
468c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.R;
478c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.SuggestedWords;
489310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalardimport com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
499342484e8d573a40f470b6a593df31c602fa4076Ken Wakasaimport com.android.inputmethod.latin.common.Constants;
502dae79b1966a7970c25c8b79beec1c95c13f6c87Tadashi G. Takaokaimport com.android.inputmethod.latin.define.DebugFlags;
51ce78a2d8ab7630cff509c2b21b4b11abd8db4795Tadashi G. Takaokaimport com.android.inputmethod.latin.settings.Settings;
52aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaokaimport com.android.inputmethod.latin.settings.SettingsValues;
5301748cde4e692c970617e4478368f83b710a86b6Tadashi G. Takaokaimport com.android.inputmethod.latin.suggestions.MoreSuggestionsView.MoreSuggestionsListener;
548dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaokaimport com.android.inputmethod.latin.utils.ImportantNoticeUtils;
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 {
618a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        public void showImportantNoticeContents();
6235c37dbef8a65cc1e199a60090d1b4e60da69fe6Jean Chalard        public void pickSuggestionManually(SuggestedWordInfo word);
63c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        public void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat);
64c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka    }
65c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka
662dae79b1966a7970c25c8b79beec1c95c13f6c87Tadashi G. Takaoka    static final boolean DBG = DebugFlags.DEBUG_ENABLED;
67c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka    private static final float DEBUG_INFO_TEXT_SIZE_IN_DIP = 6.0f;
686f7218627eda110a8454053f8ecb7b80edfdc8cesatok
69913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka    private final ViewGroup mSuggestionsStrip;
70c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka    private final ImageButton mVoiceKey;
718a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka    private final View mImportantNoticeStrip;
72d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka    MainKeyboardView mMainKeyboardView;
7374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
7429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final View mMoreSuggestionsContainer;
7529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final MoreSuggestionsView mMoreSuggestionsView;
7629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final MoreSuggestions.Builder mMoreSuggestionsBuilder;
7729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
78a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka    private final ArrayList<TextView> mWordViews = new ArrayList<>();
79a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka    private final ArrayList<TextView> mDebugInfoViews = new ArrayList<>();
80a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka    private final ArrayList<View> mDividerViews = new ArrayList<>();
8174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
823e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    Listener mListener;
8330f4a2a4d750dc8c3132d706d9148daf71fbd168Adrian Velicu    private SuggestedWords mSuggestedWords = SuggestedWords.getEmptyInstance();
842637be27c51be03e39b0db1c66312c4cc55bc7deTadashi G. Takaoka    private int mStartIndexOfMoreSuggestions;
856a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani
86653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka    private final SuggestionStripLayoutHelper mLayoutHelper;
87148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka    private final StripVisibilityGroup mStripVisibilityGroup;
88148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
89148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka    private static class StripVisibilityGroup {
90630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka        private final View mSuggestionStripView;
91148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        private final View mSuggestionsStrip;
928a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        private final View mImportantNoticeStrip;
93148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
94630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka        public StripVisibilityGroup(final View suggestionStripView,
9523574d1231296e090e6efb41a50c7885a116ddb4Dan Zivkovic                final ViewGroup suggestionsStrip, final View importantNoticeStrip) {
96630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka            mSuggestionStripView = suggestionStripView;
97148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            mSuggestionsStrip = suggestionsStrip;
988a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mImportantNoticeStrip = importantNoticeStrip;
99aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka            showSuggestionsStrip();
100148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        }
101148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
102630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka        public void setLayoutDirection(final boolean isRtlLanguage) {
103630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka            final int layoutDirection = isRtlLanguage ? ViewCompat.LAYOUT_DIRECTION_RTL
104630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka                    : ViewCompat.LAYOUT_DIRECTION_LTR;
105630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka            ViewCompat.setLayoutDirection(mSuggestionStripView, layoutDirection);
106bcd30bf3e74c7c10d5b69a54cdf90c6b682a0747Tadashi G. Takaoka            ViewCompat.setLayoutDirection(mSuggestionsStrip, layoutDirection);
1078a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            ViewCompat.setLayoutDirection(mImportantNoticeStrip, layoutDirection);
108bcd30bf3e74c7c10d5b69a54cdf90c6b682a0747Tadashi G. Takaoka        }
109bcd30bf3e74c7c10d5b69a54cdf90c6b682a0747Tadashi G. Takaoka
110aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka        public void showSuggestionsStrip() {
111148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            mSuggestionsStrip.setVisibility(VISIBLE);
1128a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mImportantNoticeStrip.setVisibility(INVISIBLE);
1138a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        }
1148a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka
115aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka        public void showImportantNoticeStrip() {
1168a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mSuggestionsStrip.setVisibility(INVISIBLE);
1178a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mImportantNoticeStrip.setVisibility(VISIBLE);
118148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        }
119148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
12021f038ee0aadfeb2036c238d543b107d97729449Tadashi G. Takaoka        public boolean isShowingImportantNoticeStrip() {
12121f038ee0aadfeb2036c238d543b107d97729449Tadashi G. Takaoka            return mImportantNoticeStrip.getVisibility() == VISIBLE;
12221f038ee0aadfeb2036c238d543b107d97729449Tadashi G. Takaoka        }
123148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka    }
12474b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
125923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    /**
1264702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka     * Construct a {@link SuggestionStripView} for showing suggestions to be picked by the user.
127923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     * @param context
128923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     * @param attrs
129923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     */
1303e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public SuggestionStripView(final Context context, final AttributeSet attrs) {
1314702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka        this(context, attrs, R.attr.suggestionStripViewStyle);
13208a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka    }
13308a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka
1343e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public SuggestionStripView(final Context context, final AttributeSet attrs,
1353e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka            final int defStyle) {
136c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka        super(context, attrs, defStyle);
137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
13816713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka        final LayoutInflater inflater = LayoutInflater.from(context);
139913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        inflater.inflate(R.layout.suggestions_strip, this);
14086e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka
141913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip);
142c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        mVoiceKey = (ImageButton)findViewById(R.id.suggestions_strip_voice_key);
1438a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        mImportantNoticeStrip = findViewById(R.id.important_notice_strip);
144aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka        mStripVisibilityGroup = new StripVisibilityGroup(this, mSuggestionsStrip,
14523574d1231296e090e6efb41a50c7885a116ddb4Dan Zivkovic                mImportantNoticeStrip);
146148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka
147a1ed211c4e80eb81ce399e0eaff88bbdf1e3199fJean Chalard        for (int pos = 0; pos < SuggestedWords.MAX_SUGGESTIONS; pos++) {
148c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka            final TextView word = new TextView(context, null, R.attr.suggestionWordStyle);
14924c275ccb9d12d6160b09c20afe17601b09957f1Dan Zivkovic            word.setContentDescription(getResources().getString(R.string.spoken_empty_suggestion));
1502442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka            word.setOnClickListener(this);
151ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka            word.setOnLongClickListener(this);
152500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka            mWordViews.add(word);
153913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka            final View divider = inflater.inflate(R.layout.suggestion_divider, null);
154500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka            mDividerViews.add(divider);
155c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka            final TextView info = new TextView(context, null, R.attr.suggestionWordStyle);
156c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka            info.setTextColor(Color.WHITE);
157c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka            info.setTextSize(TypedValue.COMPLEX_UNIT_DIP, DEBUG_INFO_TEXT_SIZE_IN_DIP);
158c2ea3f7dd95e7e9dccc61ac2ef9b56b1db8e5b48Tadashi G. Takaoka            mDebugInfoViews.add(info);
159c9716b28ce438e06b5cacc07fc002944bcbe24a0Tadashi G. Takaoka        }
160179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka
161653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka        mLayoutHelper = new SuggestionStripLayoutHelper(
162500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka                context, attrs, defStyle, mWordViews, mDividerViews, mDebugInfoViews);
16329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
16429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null);
16529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer
16629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka                .findViewById(R.id.more_suggestions_view);
16708ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka        mMoreSuggestionsBuilder = new MoreSuggestions.Builder(context, mMoreSuggestionsView);
168bfc1d732ac92fa1bd5b19ad9e7c71ce9a1f9dc00Tadashi G. Takaoka
16950e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        final Resources res = context.getResources();
17050e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset(
1712fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                R.dimen.config_more_suggestions_modal_tolerance);
1723fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        mMoreSuggestionsSlidingDetector = new GestureDetector(
1733fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka                context, mMoreSuggestionsSlidingListener);
174c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka
175c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        final TypedArray keyboardAttr = context.obtainStyledAttributes(attrs,
176c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka                R.styleable.Keyboard, defStyle, R.style.SuggestionStripView);
177c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        final Drawable iconVoice = keyboardAttr.getDrawable(R.styleable.Keyboard_iconShortcutKey);
178c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        keyboardAttr.recycle();
179c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        mVoiceKey.setImageDrawable(iconVoice);
180c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        mVoiceKey.setOnClickListener(this);
181923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
182c9716b28ce438e06b5cacc07fc002944bcbe24a0Tadashi G. Takaoka
183923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    /**
184c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka     * A connection back to the input method.
185923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     * @param listener
186923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     */
1873e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public void setListener(final Listener listener, final View inputView) {
188c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka        mListener = listener;
189d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka        mMainKeyboardView = (MainKeyboardView)inputView.findViewById(R.id.keyboard_view);
190923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
191923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
192aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka    public void updateVisibility(final boolean shouldBeVisible, final boolean isFullscreenMode) {
193aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka        final int visibility = shouldBeVisible ? VISIBLE : (isFullscreenMode ? GONE : INVISIBLE);
194aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka        setVisibility(visibility);
195aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka        final SettingsValues currentSettingsValues = Settings.getInstance().getCurrent();
196987bff9136ec101d06db7903ebb3f505e4ea78d6Tadashi G. Takaoka        mVoiceKey.setVisibility(currentSettingsValues.mShowsVoiceInputKey ? VISIBLE : INVISIBLE);
197c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka    }
198c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka
199bcd30bf3e74c7c10d5b69a54cdf90c6b682a0747Tadashi G. Takaoka    public void setSuggestions(final SuggestedWords suggestedWords, final boolean isRtlLanguage) {
200e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka        clear();
201630a24141eeb80063648bc1bc4678439117321d2Tadashi G. Takaoka        mStripVisibilityGroup.setLayoutDirection(isRtlLanguage);
202e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka        mSuggestedWords = suggestedWords;
2032637be27c51be03e39b0db1c66312c4cc55bc7deTadashi G. Takaoka        mStartIndexOfMoreSuggestions = mLayoutHelper.layoutAndReturnStartIndexOfMoreSuggestions(
20424c275ccb9d12d6160b09c20afe17601b09957f1Dan Zivkovic                getContext(), mSuggestedWords, mSuggestionsStrip, this);
205aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka        mStripVisibilityGroup.showSuggestionsStrip();
20616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka    }
20774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka
20816a43d2bd9c5d80f8e50f5a7682b657ee10621e1Yohei Yukawa    public void setMoreSuggestionsHeight(final int remainingHeight) {
20916a43d2bd9c5d80f8e50f5a7682b657ee10621e1Yohei Yukawa        mLayoutHelper.setMoreSuggestionsHeight(remainingHeight);
210c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka    }
211b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka
2128dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka    // This method checks if we should show the important notice (checks on permanent storage if
2138dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka    // it has been shown once already or not, and if in the setup wizard). If applicable, it shows
2148dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka    // the notice. In all cases, it returns true if it was shown, false otherwise.
215987bff9136ec101d06db7903ebb3f505e4ea78d6Tadashi G. Takaoka    public boolean maybeShowImportantNoticeTitle() {
2168ec36026c93d13c1118eda936ac12325e0085561Chieu Nguyen        final SettingsValues currentSettingsValues = Settings.getInstance().getCurrent();
2178ec36026c93d13c1118eda936ac12325e0085561Chieu Nguyen        if (!ImportantNoticeUtils.shouldShowImportantNotice(getContext(), currentSettingsValues)) {
2188dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka            return false;
2198dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka        }
22014e908c3486ae5996e66625e959ff45c5f3740efTadashi G. Takaoka        if (getWidth() <= 0) {
221affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka            return false;
222affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka        }
223604158669b407a40cd0f23538fad4dce5d738f24Mohammadinamul Sheik        final String importantNoticeTitle = ImportantNoticeUtils.getSuggestContactsNoticeTitle(
2246abc852255072e9c5741a7d8f264bec99b0ce14eTadashi G. Takaoka                getContext());
2256abc852255072e9c5741a7d8f264bec99b0ce14eTadashi G. Takaoka        if (TextUtils.isEmpty(importantNoticeTitle)) {
2266abc852255072e9c5741a7d8f264bec99b0ce14eTadashi G. Takaoka            return false;
2276abc852255072e9c5741a7d8f264bec99b0ce14eTadashi G. Takaoka        }
228c8abd13c77ed90b209301ea379e1142e0d60e3f5Tadashi G. Takaoka        if (isShowingMoreSuggestionPanel()) {
229c8abd13c77ed90b209301ea379e1142e0d60e3f5Tadashi G. Takaoka            dismissMoreSuggestionsPanel();
230c8abd13c77ed90b209301ea379e1142e0d60e3f5Tadashi G. Takaoka        }
23114e908c3486ae5996e66625e959ff45c5f3740efTadashi G. Takaoka        mLayoutHelper.layoutImportantNotice(mImportantNoticeStrip, importantNoticeTitle);
232aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka        mStripVisibilityGroup.showImportantNoticeStrip();
2338a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        mImportantNoticeStrip.setOnClickListener(this);
2348dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka        return true;
2358a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka    }
2368a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka
237923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void clear() {
238913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka        mSuggestionsStrip.removeAllViews();
2399ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka        removeAllDebugInfoViews();
240aa4b2c71270576f25e7c80a4b63a1956cec5f4e2Tadashi G. Takaoka        mStripVisibilityGroup.showSuggestionsStrip();
24119dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka        dismissMoreSuggestionsPanel();
242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
243923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
2449ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka    private void removeAllDebugInfoViews() {
2459ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka        // The debug info views may be placed as children views of this {@link SuggestionStripView}.
2469ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka        for (final View debugInfoView : mDebugInfoViews) {
2479ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka            final ViewParent parent = debugInfoView.getParent();
2489ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka            if (parent instanceof ViewGroup) {
2499ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka                ((ViewGroup)parent).removeView(debugInfoView);
2509ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka            }
2519ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka        }
2529ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka    }
2539ac6c9064d24a3a0e96db470bb76c997c51bb5c8Tadashi G. Takaoka
2546f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka    private final MoreSuggestionsListener mMoreSuggestionsListener = new MoreSuggestionsListener() {
25529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        @Override
25635c37dbef8a65cc1e199a60090d1b4e60da69fe6Jean Chalard        public void onSuggestionSelected(final SuggestedWordInfo wordInfo) {
25735c37dbef8a65cc1e199a60090d1b4e60da69fe6Jean Chalard            mListener.pickSuggestionManually(wordInfo);
25819dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka            dismissMoreSuggestionsPanel();
25929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
26029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
26129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        @Override
26229e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        public void onCancelInput() {
26319dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka            dismissMoreSuggestionsPanel();
26429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
26529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    };
26629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
26729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    private final MoreKeysPanel.Controller mMoreSuggestionsController =
26829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka            new MoreKeysPanel.Controller() {
26929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        @Override
2701f215a58c99f0eb2f536e9cccd51371f2883e201Tadashi G. Takaoka        public void onDismissMoreKeysPanel() {
2711f215a58c99f0eb2f536e9cccd51371f2883e201Tadashi G. Takaoka            mMainKeyboardView.onDismissMoreKeysPanel();
272fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        }
273fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang
274fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        @Override
275a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka        public void onShowMoreKeysPanel(final MoreKeysPanel panel) {
276d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka            mMainKeyboardView.onShowMoreKeysPanel(panel);
27729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
278ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang
279ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        @Override
2801f215a58c99f0eb2f536e9cccd51371f2883e201Tadashi G. Takaoka        public void onCancelMoreKeysPanel() {
28119dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka            dismissMoreSuggestionsPanel();
282ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        }
28329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    };
28429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
28519dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka    public boolean isShowingMoreSuggestionPanel() {
28619dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka        return mMoreSuggestionsView.isShowingInParent();
28719dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka    }
28819dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka
28919dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka    public void dismissMoreSuggestionsPanel() {
29019dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka        mMoreSuggestionsView.dismissMoreKeysPanel();
29119dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka    }
29219dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka
293e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka    @Override
2943e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public boolean onLongClick(final View view) {
295ab16237e69061bb0aa7f882e48e5d93459c22ef3Tadashi G. Takaoka        AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(
2966f9105383a56c9ae15e35d3abf19c33d1efe5636Tadashi G. Takaoka                Constants.NOT_A_CODE, this);
2973fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        return showMoreSuggestions();
2983fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    }
2993fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka
3003e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    boolean showMoreSuggestions() {
30156e0373b5c0c516cd57352cebf882e2b358f168cTadashi G. Takaoka        final Keyboard parentKeyboard = mMainKeyboardView.getKeyboard();
3027339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        if (parentKeyboard == null) {
3037339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka            return false;
304ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka        }
305653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka        final SuggestionStripLayoutHelper layoutHelper = mLayoutHelper;
3062637be27c51be03e39b0db1c66312c4cc55bc7deTadashi G. Takaoka        if (mSuggestedWords.size() <= mStartIndexOfMoreSuggestions) {
3077339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka            return false;
3087339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        }
3097339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final int stripWidth = getWidth();
3107339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final View container = mMoreSuggestionsContainer;
3117339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight();
3127339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder;
3132637be27c51be03e39b0db1c66312c4cc55bc7deTadashi G. Takaoka        builder.layout(mSuggestedWords, mStartIndexOfMoreSuggestions, maxWidth,
314653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka                (int)(maxWidth * layoutHelper.mMinMoreSuggestionsWidth),
315653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka                layoutHelper.getMaxMoreSuggestionsRow(), parentKeyboard);
3167339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        mMoreSuggestionsView.setKeyboard(builder.build());
3177339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
3187339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka
3197339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView;
3207339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        final int pointX = stripWidth / 2;
321653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka        final int pointY = -layoutHelper.mMoreSuggestionsBottomGap;
3227339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        moreKeysPanel.showMoreKeysPanel(this, mMoreSuggestionsController, pointX, pointY,
323fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang                mMoreSuggestionsListener);
3247339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        mOriginX = mLastX;
3257339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        mOriginY = mLastY;
3262637be27c51be03e39b0db1c66312c4cc55bc7deTadashi G. Takaoka        for (int i = 0; i < mStartIndexOfMoreSuggestions; i++) {
327500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka            mWordViews.get(i).setPressed(false);
3287339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        }
3297339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka        return true;
330ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka    }
331ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka
332da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka    // Working variables for {@link onInterceptTouchEvent(MotionEvent)} and
333da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka    // {@link onTouchEvent(MotionEvent)}.
33450e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mLastX;
33550e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mLastY;
33650e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mOriginX;
33750e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private int mOriginY;
33850e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka    private final int mMoreSuggestionsModalTolerance;
339da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka    private boolean mNeedsToTransformTouchEventToHoverEvent;
340da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka    private boolean mIsDispatchingHoverEventToMoreSuggestions;
3413fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    private final GestureDetector mMoreSuggestionsSlidingDetector;
3423fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    private final GestureDetector.OnGestureListener mMoreSuggestionsSlidingListener =
3433fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            new GestureDetector.SimpleOnGestureListener() {
3443fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        @Override
3453fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        public boolean onScroll(MotionEvent down, MotionEvent me, float deltaX, float deltaY) {
3463fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            final float dy = me.getY() - down.getY();
3473fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            if (deltaY > 0 && dy < 0) {
3483fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka                return showMoreSuggestions();
3493fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            }
3503fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka            return false;
3513fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka        }
3523fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka    };
35350e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka
354ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka    @Override
355e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka    public boolean onInterceptTouchEvent(final MotionEvent me) {
35621f038ee0aadfeb2036c238d543b107d97729449Tadashi G. Takaoka        if (mStripVisibilityGroup.isShowingImportantNoticeStrip()) {
357d144b7874efc843bccc3ec7cd9a48d32d8f2395dTadashi G. Takaoka            return false;
358d144b7874efc843bccc3ec7cd9a48d32d8f2395dTadashi G. Takaoka        }
3598ab46225b3e819fe31dd3bd487a7e9d1ff859dedTadashi G. Takaoka        // Detecting sliding up finger to show {@link MoreSuggestionsView}.
36051c38a441a09a4920703e765cb26179e7a80f029Tadashi G. Takaoka        if (!mMoreSuggestionsView.isShowingInParent()) {
36150e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            mLastX = (int)me.getX();
36250e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            mLastY = (int)me.getY();
363e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka            return mMoreSuggestionsSlidingDetector.onTouchEvent(me);
36429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        }
36521f038ee0aadfeb2036c238d543b107d97729449Tadashi G. Takaoka        if (mMoreSuggestionsView.isInModalMode()) {
36621f038ee0aadfeb2036c238d543b107d97729449Tadashi G. Takaoka            return false;
36721f038ee0aadfeb2036c238d543b107d97729449Tadashi G. Takaoka        }
3688ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka
36929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        final int action = me.getAction();
37029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        final int index = me.getActionIndex();
3718ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka        final int x = (int)me.getX(index);
3728ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka        final int y = (int)me.getY(index);
373e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        if (Math.abs(x - mOriginX) >= mMoreSuggestionsModalTolerance
374e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka                || mOriginY - y >= mMoreSuggestionsModalTolerance) {
375da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            // Decided to be in the sliding suggestion mode only when the touch point has been moved
376e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka            // upward. Further {@link MotionEvent}s will be delivered to
377e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka            // {@link #onTouchEvent(MotionEvent)}.
37804cd8794e04b14c2b7e7eed036b83075792134a1Tadashi G. Takaoka            mNeedsToTransformTouchEventToHoverEvent =
37904cd8794e04b14c2b7e7eed036b83075792134a1Tadashi G. Takaoka                    AccessibilityUtils.getInstance().isTouchExplorationEnabled();
380da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            mIsDispatchingHoverEventToMoreSuggestions = false;
38150e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka            return true;
38250e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        }
38350e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka
384e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {
385e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka            // Decided to be in the modal input mode.
386d144b7874efc843bccc3ec7cd9a48d32d8f2395dTadashi G. Takaoka            mMoreSuggestionsView.setModalMode();
387e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        }
388e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        return false;
389e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka    }
390e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka
391e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka    @Override
392a2e365da0acf80c1bcd8413d72f697a0da374779Tadashi G. Takaoka    public boolean dispatchPopulateAccessibilityEvent(final AccessibilityEvent event) {
393a2e365da0acf80c1bcd8413d72f697a0da374779Tadashi G. Takaoka        // Don't populate accessibility event with suggested words and voice key.
394a2e365da0acf80c1bcd8413d72f697a0da374779Tadashi G. Takaoka        return true;
395a2e365da0acf80c1bcd8413d72f697a0da374779Tadashi G. Takaoka    }
396a2e365da0acf80c1bcd8413d72f697a0da374779Tadashi G. Takaoka
397a2e365da0acf80c1bcd8413d72f697a0da374779Tadashi G. Takaoka    @Override
398e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka    public boolean onTouchEvent(final MotionEvent me) {
3998ab46225b3e819fe31dd3bd487a7e9d1ff859dedTadashi G. Takaoka        if (!mMoreSuggestionsView.isShowingInParent()) {
4008ab46225b3e819fe31dd3bd487a7e9d1ff859dedTadashi G. Takaoka            // Ignore any touch event while more suggestions panel hasn't been shown.
4018ab46225b3e819fe31dd3bd487a7e9d1ff859dedTadashi G. Takaoka            // Detecting sliding up is done at {@link #onInterceptTouchEvent}.
4028ab46225b3e819fe31dd3bd487a7e9d1ff859dedTadashi G. Takaoka            return true;
4038ab46225b3e819fe31dd3bd487a7e9d1ff859dedTadashi G. Takaoka        }
404e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        // In the sliding input mode. {@link MotionEvent} should be forwarded to
405e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        // {@link MoreSuggestionsView}.
406e32548f32d32bc2fbf07ccd373bc55ece80388ceTadashi G. Takaoka        final int index = me.getActionIndex();
407da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        final int x = mMoreSuggestionsView.translateX((int)me.getX(index));
408da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        final int y = mMoreSuggestionsView.translateY((int)me.getY(index));
409da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        me.setLocation(x, y);
410da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        if (!mNeedsToTransformTouchEventToHoverEvent) {
411da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            mMoreSuggestionsView.onTouchEvent(me);
412da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            return true;
413da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        }
414da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        // In sliding suggestion mode with accessibility mode on, a touch event should be
415da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        // transformed to a hover event.
416da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        final int width = mMoreSuggestionsView.getWidth();
417da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        final int height = mMoreSuggestionsView.getHeight();
418da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        final boolean onMoreSuggestions = (x >= 0 && x < width && y >= 0 && y < height);
419da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        if (!onMoreSuggestions && !mIsDispatchingHoverEventToMoreSuggestions) {
420da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            // Just drop this touch event because dispatching hover event isn't started yet and
421da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            // the touch event isn't on {@link MoreSuggestionsView}.
422da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            return true;
423da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        }
424da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        final int hoverAction;
425da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        if (onMoreSuggestions && !mIsDispatchingHoverEventToMoreSuggestions) {
426da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            // Transform this touch event to a hover enter event and start dispatching a hover
427da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            // event to {@link MoreSuggestionsView}.
428da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            mIsDispatchingHoverEventToMoreSuggestions = true;
429da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            hoverAction = MotionEvent.ACTION_HOVER_ENTER;
430da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        } else if (me.getActionMasked() == MotionEvent.ACTION_UP) {
431da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            // Transform this touch event to a hover exit event and stop dispatching a hover event
432da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            // after this.
433da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            mIsDispatchingHoverEventToMoreSuggestions = false;
434da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            mNeedsToTransformTouchEventToHoverEvent = false;
435da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            hoverAction = MotionEvent.ACTION_HOVER_EXIT;
436da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        } else {
437da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            // Transform this touch event to a hover move event.
438da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka            hoverAction = MotionEvent.ACTION_HOVER_MOVE;
439da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        }
440da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        me.setAction(hoverAction);
441da232a70a8c73f8d2a26a74e1937c12500244209Tadashi G. Takaoka        mMoreSuggestionsView.onHoverEvent(me);
44229e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka        return true;
44329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    }
44429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka
44529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka    @Override
4463e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka    public void onClick(final View view) {
447874a600dc805b6ab9fe92fccddfe4765b8d29a35Tadashi G. Takaoka        AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(
448874a600dc805b6ab9fe92fccddfe4765b8d29a35Tadashi G. Takaoka                Constants.CODE_UNSPECIFIED, this);
4498a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        if (view == mImportantNoticeStrip) {
4508a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            mListener.showImportantNoticeContents();
4518a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka            return;
4528a296e43c903a3377f28943ba4a59082ae7fe60aTadashi G. Takaoka        }
453c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        if (view == mVoiceKey) {
454c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka            mListener.onCodeInput(Constants.CODE_SHORTCUT,
455c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka                    Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE,
456c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka                    false /* isKeyRepeat */);
457c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka            return;
458c41d261b7e1e626aaa4e333c9c4cc73ec13cb68aTadashi G. Takaoka        }
459717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka
46023574d1231296e090e6efb41a50c7885a116ddb4Dan Zivkovic        final Object tag = view.getTag();
461148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        // {@link Integer} tag is set at
4629b570b5e62581f41c40c4558d95c77ad5896934cTadashi G. Takaoka        // {@link SuggestionStripLayoutHelper#setupWordViewsTextAndColor(SuggestedWords,int)} and
4639b570b5e62581f41c40c4558d95c77ad5896934cTadashi G. Takaoka        // {@link SuggestionStripLayoutHelper#layoutPunctuationSuggestions(SuggestedWords,ViewGroup}
464148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka        if (tag instanceof Integer) {
465148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            final int index = (Integer) tag;
466148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            if (index >= mSuggestedWords.size()) {
467148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka                return;
468148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            }
469148dedbc5dfa22d6db30b28ae9ede139206af429Tadashi G. Takaoka            final SuggestedWordInfo wordInfo = mSuggestedWords.getInfo(index);
47035c37dbef8a65cc1e199a60090d1b4e60da69fe6Jean Chalard            mListener.pickSuggestionManually(wordInfo);
471500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka        }
472923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
47382411d47ba7e8133ed2390c6920945e139a738cesatok
4746ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani    @Override
47573cd4c1428ac370e1c15c5f61b1ce499f0d4f4c7Tadashi G. Takaoka    protected void onDetachedFromWindow() {
4766ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani        super.onDetachedFromWindow();
47719dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka        dismissMoreSuggestionsPanel();
4786ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani    }
4798dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka
4808dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka    @Override
481affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka    protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
4828dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka        // Called by the framework when the size is known. Show the important notice if applicable.
4838dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka        // This may be overriden by showing suggestions later, if applicable.
484affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka        if (oldw <= 0 && w > 0) {
485987bff9136ec101d06db7903ebb3f505e4ea78d6Tadashi G. Takaoka            maybeShowImportantNoticeTitle();
486affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka        }
4878dda9e480b6519ca57565c8aa507e14bff739b60Tadashi G. Takaoka    }
488923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project}
489