SuggestionStripView.java revision 19dd753c0ccaea8dee71eeae7edc724c58c6f024
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; 21923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.AttributeSet; 223fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaokaimport android.view.GestureDetector; 23923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.LayoutInflater; 2429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaokaimport android.view.MotionEvent; 25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View; 26e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaokaimport android.view.View.OnClickListener; 27ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaokaimport android.view.View.OnLongClickListener; 28e26ef1bccddc942fdaeada3409c8e8ff18a35008Tadashi G. Takaokaimport android.view.ViewGroup; 29c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaokaimport android.widget.RelativeLayout; 30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.widget.TextView; 31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 327339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 337339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardSwitcher; 34d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaokaimport com.android.inputmethod.keyboard.MainKeyboardView; 3529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaokaimport com.android.inputmethod.keyboard.MoreKeysPanel; 366f9105383a56c9ae15e35d3abf19c33d1efe5636Tadashi G. Takaokaimport com.android.inputmethod.latin.AudioAndHapticFeedbackManager; 375faf41951929301af80026bc3191812ef874fd5aTadashi G. Takaokaimport com.android.inputmethod.latin.Constants; 388c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.LatinImeLogger; 398c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.R; 408c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaokaimport com.android.inputmethod.latin.SuggestedWords; 419310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalardimport com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; 42a9ca7867b5a7c0be115966211a05f5d460c8638cKurt Partridgeimport com.android.inputmethod.latin.define.ProductionFlag; 436f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaokaimport com.android.inputmethod.latin.suggestions.MoreSuggestions.MoreSuggestionsListener; 44e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasaimport com.android.inputmethod.latin.utils.CollectionUtils; 456b966160ac8570271547bf63217efa5e228d4accKurt Partridgeimport com.android.inputmethod.research.ResearchLogger; 46ddb61ea461b920d87be4ad78c8a36eec1013b965Tadashi G. Takaoka 47179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaokaimport java.util.ArrayList; 48179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka 49a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaokapublic final class SuggestionStripView extends RelativeLayout implements OnClickListener, 50c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka OnLongClickListener { 51c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka public interface Listener { 5218d688c94bb8e1e26de2d12445cb3096c6126f75Jean Chalard public void addWordToUserDictionary(String word); 539310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard public void pickSuggestionManually(int index, SuggestedWordInfo word); 54c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka } 55c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka 5686e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}. 5729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka public static final int MAX_SUGGESTIONS = 18; 58923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 598c3d5b6961a9b9d40c4bf21ad495f852971c24f4Tadashi G. Takaoka static final boolean DBG = LatinImeLogger.sDBG; 606f7218627eda110a8454053f8ecb7b80edfdc8cesatok 61913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka private final ViewGroup mSuggestionsStrip; 62d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka MainKeyboardView mMainKeyboardView; 6374b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 6429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka private final View mMoreSuggestionsContainer; 6529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka private final MoreSuggestionsView mMoreSuggestionsView; 6629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka private final MoreSuggestions.Builder mMoreSuggestionsBuilder; 6729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka 68500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka private final ArrayList<TextView> mWordViews = CollectionUtils.newArrayList(); 69500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka private final ArrayList<TextView> mDebugInfoViews = CollectionUtils.newArrayList(); 70500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka private final ArrayList<View> mDividerViews = CollectionUtils.newArrayList(); 7174b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 723e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka Listener mListener; 736f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY; 746a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani 75653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka private final SuggestionStripLayoutHelper mLayoutHelper; 7674b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 77923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 784702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka * Construct a {@link SuggestionStripView} for showing suggestions to be picked by the user. 79923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param context 80923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param attrs 81923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 823e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka public SuggestionStripView(final Context context, final AttributeSet attrs) { 834702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka this(context, attrs, R.attr.suggestionStripViewStyle); 8408a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka } 8508a6f2aea71d998206c47c16dcda4eaa90f8c9eaTadashi G. Takaoka 863e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka public SuggestionStripView(final Context context, final AttributeSet attrs, 873e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka final int defStyle) { 88c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka super(context, attrs, defStyle); 89923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 9016713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka final LayoutInflater inflater = LayoutInflater.from(context); 91913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka inflater.inflate(R.layout.suggestions_strip, this); 9286e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka 93913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip); 9460a004f78e73b5208c2a0a79454dabfbc0e1aa33Tadashi G. Takaoka for (int pos = 0; pos < MAX_SUGGESTIONS; pos++) { 95913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka final TextView word = (TextView)inflater.inflate(R.layout.suggestion_word, null); 962442e779857e7eda253aadcb1c4dff5ccb3e53f4Tadashi G. Takaoka word.setOnClickListener(this); 97ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka word.setOnLongClickListener(this); 98500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka mWordViews.add(word); 99913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka final View divider = inflater.inflate(R.layout.suggestion_divider, null); 100a1aab83a24e74cb0fad4b1c1e59b18d23ecbdad3Tadashi G. Takaoka divider.setOnClickListener(this); 101500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka mDividerViews.add(divider); 102500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka mDebugInfoViews.add((TextView)inflater.inflate(R.layout.suggestion_info, null)); 103c9716b28ce438e06b5cacc07fc002944bcbe24a0Tadashi G. Takaoka } 104179ada958b0bb46c6b9c8eb8b220d84dd3db855aTadashi G. Takaoka 105653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka mLayoutHelper = new SuggestionStripLayoutHelper( 106500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka context, attrs, defStyle, mWordViews, mDividerViews, mDebugInfoViews); 10729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka 10829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null); 10929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer 11029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka .findViewById(R.id.more_suggestions_view); 11108ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka mMoreSuggestionsBuilder = new MoreSuggestions.Builder(context, mMoreSuggestionsView); 112bfc1d732ac92fa1bd5b19ad9e7c71ce9a1f9dc00Tadashi G. Takaoka 11350e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka final Resources res = context.getResources(); 11450e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset( 1152fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa R.dimen.config_more_suggestions_modal_tolerance); 1163fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka mMoreSuggestionsSlidingDetector = new GestureDetector( 1173fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka context, mMoreSuggestionsSlidingListener); 118923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 119c9716b28ce438e06b5cacc07fc002944bcbe24a0Tadashi G. Takaoka 120923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 121c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka * A connection back to the input method. 122923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param listener 123923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 1243e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka public void setListener(final Listener listener, final View inputView) { 125c97810693dfe83bf37c09f73c8d4b40f2ba8dddbTadashi G. Takaoka mListener = listener; 126d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka mMainKeyboardView = (MainKeyboardView)inputView.findViewById(R.id.keyboard_view); 127923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 128923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1293e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka public void setSuggestions(final SuggestedWords suggestedWords) { 130e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka clear(); 131e79b1a83126b41e09a8ec0a8dbb751ae0e02c7f6Tadashi G. Takaoka mSuggestedWords = suggestedWords; 132500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka mLayoutHelper.layout(mSuggestedWords, mSuggestionsStrip, this); 1339c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { 1344702671ea4feb0c79a879e2e3013afdd6ed800b1Tadashi G. Takaoka ResearchLogger.suggestionStripView_setSuggestions(mSuggestedWords); 135a9ca7867b5a7c0be115966211a05f5d460c8638cKurt Partridge } 13616713e5630b93fb5625df26745eb73271f189457Tadashi G. Takaoka } 13774b6897a12ec603ef835aaa77a01f0c32f49aa1cTadashi G. Takaoka 138c160a3932f74fea72c5347798c001d4ae961864cKen Wakasa public int setMoreSuggestionsHeight(final int remainingHeight) { 139c160a3932f74fea72c5347798c001d4ae961864cKen Wakasa return mLayoutHelper.setMoreSuggestionsHeight(remainingHeight); 140c8b0e5797e20d3fa25d319a9709aabc9149f8ff9Tadashi G. Takaoka } 141b47319867ef3834a222865b8cb6abe62962e70f7Tadashi G. Takaoka 142b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani public boolean isShowingAddToDictionaryHint() { 143913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka return mSuggestionsStrip.getChildCount() > 0 144653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka && mLayoutHelper.isAddToDictionaryShowing(mSuggestionsStrip.getChildAt(0)); 145b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani } 146b00a1d0c0adbdfc507676772201e979e539a2801Amith Yamasani 147bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka public void showAddToDictionaryHint(final String word, final CharSequence hintText) { 148c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka clear(); 149653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka mLayoutHelper.layoutAddToDictionaryHint( 150653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka word, mSuggestionsStrip, getWidth(), hintText, this); 15166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani } 15266a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani 1536558253160e2039c87f424bd814f402ecd31de3bKen Wakasa public boolean dismissAddToDictionaryHint() { 154c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka if (isShowingAddToDictionaryHint()) { 155c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka clear(); 156c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka return true; 157c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka } 158c04bbc1ae9be81d25a356407c27a8e7fa22028bfTadashi G. Takaoka return false; 1596558253160e2039c87f424bd814f402ecd31de3bKen Wakasa } 1606558253160e2039c87f424bd814f402ecd31de3bKen Wakasa 161923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void clear() { 162913e2aeef26f172d500a4ebfc644b5f47778841aTadashi G. Takaoka mSuggestionsStrip.removeAllViews(); 163c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka removeAllViews(); 164c412309b7a32308b1b0a175dafc13f90254353c5Tadashi G. Takaoka addView(mSuggestionsStrip); 16519dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka dismissMoreSuggestionsPanel(); 166923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 167923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1686f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka private final MoreSuggestionsListener mMoreSuggestionsListener = new MoreSuggestionsListener() { 16929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka @Override 1706f7905ae757c30ac0f8080f025b88afc61a6f6b1Tadashi G. Takaoka public void onSuggestionSelected(final int index, final SuggestedWordInfo wordInfo) { 1719310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard mListener.pickSuggestionManually(index, wordInfo); 17219dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka dismissMoreSuggestionsPanel(); 17329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka } 17429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka 17529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka @Override 17629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka public void onCancelInput() { 17719dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka dismissMoreSuggestionsPanel(); 17829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka } 17929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka }; 18029e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka 18129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka private final MoreKeysPanel.Controller mMoreSuggestionsController = 18229e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka new MoreKeysPanel.Controller() { 18329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka @Override 1840e08d70fe52737582b6c83dbf48aaf4d83063566Tadashi G. Takaoka public void onDismissMoreKeysPanel(final MoreKeysPanel panel) { 1850e08d70fe52737582b6c83dbf48aaf4d83063566Tadashi G. Takaoka mMainKeyboardView.onDismissMoreKeysPanel(panel); 186fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang } 187fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang 188fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang @Override 189a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka public void onShowMoreKeysPanel(final MoreKeysPanel panel) { 190d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka mMainKeyboardView.onShowMoreKeysPanel(panel); 19129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka } 192ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang 193ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang @Override 1940e08d70fe52737582b6c83dbf48aaf4d83063566Tadashi G. Takaoka public void onCancelMoreKeysPanel(final MoreKeysPanel panel) { 19519dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka dismissMoreSuggestionsPanel(); 196ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang } 19729e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka }; 19829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka 19919dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka public boolean isShowingMoreSuggestionPanel() { 20019dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka return mMoreSuggestionsView.isShowingInParent(); 20119dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka } 20219dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka 20319dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka public void dismissMoreSuggestionsPanel() { 20419dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka mMoreSuggestionsView.dismissMoreKeysPanel(); 20519dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka } 20619dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka 207e49bd1c43acad08f103b38430a8bbcba23f325b3Tadashi G. Takaoka @Override 2083e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka public boolean onLongClick(final View view) { 209ab16237e69061bb0aa7f882e48e5d93459c22ef3Tadashi G. Takaoka AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback( 2106f9105383a56c9ae15e35d3abf19c33d1efe5636Tadashi G. Takaoka Constants.NOT_A_CODE, this); 2113fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka return showMoreSuggestions(); 2123fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka } 2133fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka 2143e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka boolean showMoreSuggestions() { 2157339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka final Keyboard parentKeyboard = KeyboardSwitcher.getInstance().getKeyboard(); 2167339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka if (parentKeyboard == null) { 2177339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka return false; 218ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka } 219653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka final SuggestionStripLayoutHelper layoutHelper = mLayoutHelper; 220653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka if (!layoutHelper.mMoreSuggestionsAvailable) { 2217339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka return false; 2227339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka } 2237339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka final int stripWidth = getWidth(); 2247339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka final View container = mMoreSuggestionsContainer; 2257339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight(); 2267339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder; 227653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka builder.layout(mSuggestedWords, layoutHelper.mSuggestionsCountInStrip, maxWidth, 228653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka (int)(maxWidth * layoutHelper.mMinMoreSuggestionsWidth), 229653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka layoutHelper.getMaxMoreSuggestionsRow(), parentKeyboard); 2307339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka mMoreSuggestionsView.setKeyboard(builder.build()); 2317339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 2327339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka 2337339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView; 2347339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka final int pointX = stripWidth / 2; 235653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka final int pointY = -layoutHelper.mMoreSuggestionsBottomGap; 2367339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka moreKeysPanel.showMoreKeysPanel(this, mMoreSuggestionsController, pointX, pointY, 237fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang mMoreSuggestionsListener); 2387339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING; 2397339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka mOriginX = mLastX; 2407339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka mOriginY = mLastY; 241653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka for (int i = 0; i < layoutHelper.mSuggestionsCountInStrip; i++) { 242500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka mWordViews.get(i).setPressed(false); 2437339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka } 2447339a62a1368b632c0cedaf1d876a0e8590a47edTadashi G. Takaoka return true; 245ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka } 246ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka 24750e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka // Working variables for onLongClick and dispatchTouchEvent. 248d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka private int mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_MODAL_MODE; 249d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka private static final int MORE_SUGGESTIONS_IN_MODAL_MODE = 0; 250d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka private static final int MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING = 1; 251d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka private static final int MORE_SUGGESTIONS_IN_SLIDING_MODE = 2; 25250e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka private int mLastX; 25350e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka private int mLastY; 25450e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka private int mOriginX; 25550e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka private int mOriginY; 25650e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka private final int mMoreSuggestionsModalTolerance; 2573fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka private final GestureDetector mMoreSuggestionsSlidingDetector; 2583fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka private final GestureDetector.OnGestureListener mMoreSuggestionsSlidingListener = 2593fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka new GestureDetector.SimpleOnGestureListener() { 2603fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka @Override 2613fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka public boolean onScroll(MotionEvent down, MotionEvent me, float deltaX, float deltaY) { 2623fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka final float dy = me.getY() - down.getY(); 2633fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka if (deltaY > 0 && dy < 0) { 2643fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka return showMoreSuggestions(); 2653fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka } 2663fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka return false; 2673fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka } 2683fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka }; 26950e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka 270ae5c736e37973e26b201d45ff6c139862a6e05cfTadashi G. Takaoka @Override 2713e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka public boolean dispatchTouchEvent(final MotionEvent me) { 27251c38a441a09a4920703e765cb26179e7a80f029Tadashi G. Takaoka if (!mMoreSuggestionsView.isShowingInParent()) { 27350e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka mLastX = (int)me.getX(); 27450e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka mLastY = (int)me.getY(); 2753fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka if (mMoreSuggestionsSlidingDetector.onTouchEvent(me)) { 2763fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka return true; 2773fc4ddec68b4f56f53ed6da80b5e44f38c085740Tadashi G. Takaoka } 27829e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka return super.dispatchTouchEvent(me); 27929e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka } 2808ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka 28129e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka final int action = me.getAction(); 28229e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka final int index = me.getActionIndex(); 2838ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka final int x = (int)me.getX(index); 2848ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka final int y = (int)me.getY(index); 2858ac6d505b7ceab020a4085b3dfbea5b47362b030Tadashi G. Takaoka 286d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka if (mMoreSuggestionsMode == MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING) { 28787104bace9cb9ed1a700f05a37743a21c2722fffTadashi G. Takaoka if (Math.abs(x - mOriginX) >= mMoreSuggestionsModalTolerance 28887104bace9cb9ed1a700f05a37743a21c2722fffTadashi G. Takaoka || mOriginY - y >= mMoreSuggestionsModalTolerance) { 28987104bace9cb9ed1a700f05a37743a21c2722fffTadashi G. Takaoka // Decided to be in the sliding input mode only when the touch point has been moved 29087104bace9cb9ed1a700f05a37743a21c2722fffTadashi G. Takaoka // upward. 291d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_SLIDING_MODE; 29250e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) { 29350e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka // Decided to be in the modal input mode 294d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_MODAL_MODE; 29551c38a441a09a4920703e765cb26179e7a80f029Tadashi G. Takaoka mMoreSuggestionsView.adjustVerticalCorrectionForModalMode(); 29650e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka } 29750e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka return true; 29850e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka } 29950e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka 300d7b00f34904c61f955e439160e2dbaa3a4b6983cTadashi G. Takaoka // MORE_SUGGESTIONS_IN_SLIDING_MODE 30133482a9b9ccf605c63fab7c9b8273a240bbc2035Tadashi G. Takaoka me.setLocation(mMoreSuggestionsView.translateX(x), mMoreSuggestionsView.translateY(y)); 30233482a9b9ccf605c63fab7c9b8273a240bbc2035Tadashi G. Takaoka mMoreSuggestionsView.onTouchEvent(me); 30329e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka return true; 30429e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka } 30529e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka 30629e7b7ed6ef88c3e10cc6469801fef87241c9cb5Tadashi G. Takaoka @Override 3073e5a3c18bebbfb56012383411b24ee81ffde09cbTadashi G. Takaoka public void onClick(final View view) { 308653603b7253d96c7fad674ed301de5bc8050b68cTadashi G. Takaoka if (mLayoutHelper.isAddToDictionaryShowing(view)) { 3099b570b5e62581f41c40c4558d95c77ad5896934cTadashi G. Takaoka mListener.addWordToUserDictionary(mLayoutHelper.getAddToDictionaryWord()); 310717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka clear(); 311717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka return; 312717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka } 313717a8f50aec421f74e4d43432059c2fb41cb32c7Tadashi G. Takaoka 31486e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka final Object tag = view.getTag(); 3159b570b5e62581f41c40c4558d95c77ad5896934cTadashi G. Takaoka // Integer tag is set at 3169b570b5e62581f41c40c4558d95c77ad5896934cTadashi G. Takaoka // {@link SuggestionStripLayoutHelper#setupWordViewsTextAndColor(SuggestedWords,int)} and 3179b570b5e62581f41c40c4558d95c77ad5896934cTadashi G. Takaoka // {@link SuggestionStripLayoutHelper#layoutPunctuationSuggestions(SuggestedWords,ViewGroup} 318500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka if (!(tag instanceof Integer)) { 31986e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka return; 320500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka } 32186e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka final int index = (Integer) tag; 322500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka if (index >= mSuggestedWords.size()) { 32337deb112c727dfed5e94d054cf5f00f5d60c8120Tadashi G. Takaoka return; 324500a9752b1e61885f37b0fb26f09dfdd65da4e5eTadashi G. Takaoka } 32586e815a142c8aa13213151e381a8a24ef23073d3Tadashi G. Takaoka 3269310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard final SuggestedWordInfo wordInfo = mSuggestedWords.getInfo(index); 3279310f42a36eabe99ed7dcd3b835d6cdaa3c6fdcaJean Chalard mListener.pickSuggestionManually(index, wordInfo); 328923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 32982411d47ba7e8133ed2390c6920945e139a738cesatok 3306ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani @Override 33173cd4c1428ac370e1c15c5f61b1ce499f0d4f4c7Tadashi G. Takaoka protected void onDetachedFromWindow() { 3326ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani super.onDetachedFromWindow(); 33319dd753c0ccaea8dee71eeae7edc724c58c6f024Tadashi G. Takaoka dismissMoreSuggestionsPanel(); 3346ec55a1599c74150e82ea7e4371ec815f0d2df27Amith Yamasani } 335923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 336