1c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert/* 2c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * Copyright (C) 2010 The Android Open Source Project 3c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * 4c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 5c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * you may not use this file except in compliance with the License. 6c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * You may obtain a copy of the License at 7c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * 8c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 9c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * 10c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 11c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 12c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * See the License for the specific language governing permissions and 14c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * limitations under the License. 15c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert */ 16c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert 17c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringertpackage com.android.quicksearchbox.ui; 18c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert 197010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport com.android.quicksearchbox.Corpora; 207010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport com.android.quicksearchbox.Corpus; 217010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport com.android.quicksearchbox.CorpusResult; 227010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport com.android.quicksearchbox.Logger; 238b2936607176720172aee068abc5631bdf77e843Bjorn Bringertimport com.android.quicksearchbox.Promoter; 247010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport com.android.quicksearchbox.QsbApplication; 257010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport com.android.quicksearchbox.R; 260a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwoodimport com.android.quicksearchbox.SearchActivity; 277010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport com.android.quicksearchbox.SuggestionCursor; 287010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport com.android.quicksearchbox.Suggestions; 297010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport com.android.quicksearchbox.VoiceSearch; 307010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 31c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringertimport android.content.Context; 327010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport android.database.DataSetObserver; 337010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport android.graphics.drawable.Drawable; 347010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport android.text.Editable; 359e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwoodimport android.text.TextUtils; 367010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport android.text.TextWatcher; 37c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringertimport android.util.AttributeSet; 387010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport android.util.Log; 39c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringertimport android.view.KeyEvent; 407010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport android.view.View; 417010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport android.view.inputmethod.CompletionInfo; 42c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringertimport android.view.inputmethod.InputMethodManager; 437010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport android.widget.AbsListView; 447010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport android.widget.ImageButton; 45fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwoodimport android.widget.ListAdapter; 4611234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringertimport android.widget.RelativeLayout; 47748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwoodimport android.widget.TextView; 48748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwoodimport android.widget.TextView.OnEditorActionListener; 49c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert 507010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport java.util.ArrayList; 517010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringertimport java.util.Arrays; 527010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5377909685887bd6db7454b73cf274afc3aca2f58dBjorn Bringertpublic abstract class SearchActivityView extends RelativeLayout { 540a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected static final boolean DBG = false; 550a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected static final String TAG = "QSB.SearchActivityView"; 567010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 577010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // The string used for privateImeOptions to identify to the IME that it should not show 587010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // a microphone button since one already exists in the search dialog. 597010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // TODO: This should move to android-common or something. 607010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private static final String IME_OPTION_NO_MICROPHONE = "nm"; 617010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 628b2936607176720172aee068abc5631bdf77e843Bjorn Bringert private Corpus mCorpus; 638b2936607176720172aee068abc5631bdf77e843Bjorn Bringert 640a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected QueryTextView mQueryTextView; 657010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // True if the query was empty on the previous call to updateQuery() 660a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected boolean mQueryWasEmpty = true; 670a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected Drawable mQueryTextEmptyBg; 680a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected Drawable mQueryTextNotEmptyBg; 690a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood 70fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood protected SuggestionsListView<ListAdapter> mSuggestionsView; 71fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood protected SuggestionsAdapter<ListAdapter> mSuggestionsAdapter; 727010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 732cbf1d099dbd04c612e3cba34a70293705730fa0Amith Yamasani protected ImageButton mSearchCloseButton; 740a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected ImageButton mSearchGoButton; 750a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected ImageButton mVoiceSearchButton; 767010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 770a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected ButtonsKeyListener mButtonsKeyListener; 787010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 797010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private boolean mUpdateSuggestions; 807010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 817010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private QueryListener mQueryListener; 827010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private SearchClickListener mSearchClickListener; 83b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert protected View.OnClickListener mExitClickListener; 847010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 8511234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringert public SearchActivityView(Context context) { 86c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert super(context); 87c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert } 88c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert 8911234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringert public SearchActivityView(Context context, AttributeSet attrs) { 90c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert super(context, attrs); 91c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert } 92c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert 9311234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringert public SearchActivityView(Context context, AttributeSet attrs, int defStyle) { 94c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert super(context, attrs, defStyle); 95c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert } 96c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert 977010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert @Override 987010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert protected void onFinishInflate() { 997010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView = (QueryTextView) findViewById(R.id.search_src_text); 1007010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1017010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsView = (SuggestionsView) findViewById(R.id.suggestions); 1027010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsView.setOnScrollListener(new InputMethodCloser()); 1037010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsView.setOnKeyListener(new SuggestionsViewKeyListener()); 1047010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsView.setOnFocusChangeListener(new SuggestListFocusListener()); 1057010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1067010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsAdapter = createSuggestionsAdapter(); 1077010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // TODO: why do we need focus listeners both on the SuggestionsView and the individual 1087010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // suggestions? 1097010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsAdapter.setOnFocusChangeListener(new SuggestListFocusListener()); 1107010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1112cbf1d099dbd04c612e3cba34a70293705730fa0Amith Yamasani mSearchCloseButton = (ImageButton) findViewById(R.id.search_close_btn); 1127010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchGoButton = (ImageButton) findViewById(R.id.search_go_btn); 1137010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mVoiceSearchButton = (ImageButton) findViewById(R.id.search_voice_btn); 1147a427f9830f7f9201299fae34a93016c77b0a569Mathew Inwood mVoiceSearchButton.setImageDrawable(getVoiceSearchIcon()); 1157010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1167010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.addTextChangedListener(new SearchTextWatcher()); 117748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood mQueryTextView.setOnEditorActionListener(new QueryTextEditorActionListener()); 1187010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.setOnFocusChangeListener(new QueryTextViewFocusListener()); 1197010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextEmptyBg = mQueryTextView.getBackground(); 1207010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1217010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchGoButton.setOnClickListener(new SearchGoButtonClickListener()); 1227010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1230a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood mButtonsKeyListener = new ButtonsKeyListener(); 1240a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood mSearchGoButton.setOnKeyListener(mButtonsKeyListener); 1250a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood mVoiceSearchButton.setOnKeyListener(mButtonsKeyListener); 1262cbf1d099dbd04c612e3cba34a70293705730fa0Amith Yamasani if (mSearchCloseButton != null) { 1272cbf1d099dbd04c612e3cba34a70293705730fa0Amith Yamasani mSearchCloseButton.setOnKeyListener(mButtonsKeyListener); 1282cbf1d099dbd04c612e3cba34a70293705730fa0Amith Yamasani mSearchCloseButton.setOnClickListener(new CloseClickListener()); 1292cbf1d099dbd04c612e3cba34a70293705730fa0Amith Yamasani } 1307010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1317010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mUpdateSuggestions = true; 1327010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1337010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1340a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood public abstract void onResume(); 1350a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood 1360a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood public abstract void onStop(); 1370a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood 1382e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani public void onPause() { 1392e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani // Override if necessary 1402e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani } 1412e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani 1427010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void start() { 143fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood mSuggestionsAdapter.getListAdapter().registerDataSetObserver(new SuggestionsObserver()); 144fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood mSuggestionsView.setSuggestionsAdapter(mSuggestionsAdapter); 1457010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1467010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1477010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void destroy() { 148fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood mSuggestionsView.setSuggestionsAdapter(null); // closes mSuggestionsAdapter 1497010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1505880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert 1517010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // TODO: Get rid of this. To make it more easily testable, 1527010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // the SearchActivityView should not depend on QsbApplication. 1537010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert protected QsbApplication getQsbApplication() { 1547010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return QsbApplication.get(getContext()); 1557010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1567010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1577a427f9830f7f9201299fae34a93016c77b0a569Mathew Inwood protected Drawable getVoiceSearchIcon() { 1587a427f9830f7f9201299fae34a93016c77b0a569Mathew Inwood return getResources().getDrawable(R.drawable.ic_btn_speak_now); 1597a427f9830f7f9201299fae34a93016c77b0a569Mathew Inwood } 1607a427f9830f7f9201299fae34a93016c77b0a569Mathew Inwood 1617a427f9830f7f9201299fae34a93016c77b0a569Mathew Inwood protected VoiceSearch getVoiceSearch() { 1627010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return getQsbApplication().getVoiceSearch(); 1637010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1647010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 165fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood protected SuggestionsAdapter<ListAdapter> createSuggestionsAdapter() { 166fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood return new DelayingSuggestionsAdapter<ListAdapter>(new SuggestionsListAdapter( 16777909685887bd6db7454b73cf274afc3aca2f58dBjorn Bringert getQsbApplication().getSuggestionViewFactory())); 1687010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1697010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1700a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected Corpora getCorpora() { 1717010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return getQsbApplication().getCorpora(); 1727010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1737010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1748b2936607176720172aee068abc5631bdf77e843Bjorn Bringert public Corpus getCorpus() { 1758b2936607176720172aee068abc5631bdf77e843Bjorn Bringert return mCorpus; 1768b2936607176720172aee068abc5631bdf77e843Bjorn Bringert } 1777010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1788b2936607176720172aee068abc5631bdf77e843Bjorn Bringert protected abstract Promoter createSuggestionsPromoter(); 1797010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1800a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected Corpus getCorpus(String sourceName) { 1810a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood if (sourceName == null) return null; 1820a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood Corpus corpus = getCorpora().getCorpus(sourceName); 1837010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (corpus == null) { 1840a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood Log.w(TAG, "Unknown corpus " + sourceName); 1850a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood return null; 1867010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1870a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood return corpus; 1887010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1897010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 1908b2936607176720172aee068abc5631bdf77e843Bjorn Bringert public void onCorpusSelected(String corpusName) { 1918b2936607176720172aee068abc5631bdf77e843Bjorn Bringert setCorpus(corpusName); 1928b2936607176720172aee068abc5631bdf77e843Bjorn Bringert focusQueryTextView(); 1938b2936607176720172aee068abc5631bdf77e843Bjorn Bringert showInputMethodForQuery(); 1948b2936607176720172aee068abc5631bdf77e843Bjorn Bringert } 1958b2936607176720172aee068abc5631bdf77e843Bjorn Bringert 1960a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood public void setCorpus(String corpusName) { 1970a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood if (DBG) Log.d(TAG, "setCorpus(" + corpusName + ")"); 1980a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood Corpus corpus = getCorpus(corpusName); 1990a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood setCorpus(corpus); 2008b2936607176720172aee068abc5631bdf77e843Bjorn Bringert updateUi(); 2018b2936607176720172aee068abc5631bdf77e843Bjorn Bringert } 2028b2936607176720172aee068abc5631bdf77e843Bjorn Bringert 2038b2936607176720172aee068abc5631bdf77e843Bjorn Bringert protected void setCorpus(Corpus corpus) { 2048b2936607176720172aee068abc5631bdf77e843Bjorn Bringert mCorpus = corpus; 2058b2936607176720172aee068abc5631bdf77e843Bjorn Bringert mSuggestionsAdapter.setPromoter(createSuggestionsPromoter()); 206dfc1772caf35942837d83331d787eb10734c37cbBjorn Bringert Suggestions suggestions = getSuggestions(); 207dfc1772caf35942837d83331d787eb10734c37cbBjorn Bringert if (corpus == null || suggestions == null || !suggestions.expectsCorpus(corpus)) { 208dfc1772caf35942837d83331d787eb10734c37cbBjorn Bringert getActivity().updateSuggestions(); 209dfc1772caf35942837d83331d787eb10734c37cbBjorn Bringert } 2107010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2117010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 2120a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood public String getCorpusName() { 2138b2936607176720172aee068abc5631bdf77e843Bjorn Bringert Corpus corpus = getCorpus(); 2148b2936607176720172aee068abc5631bdf77e843Bjorn Bringert return corpus == null ? null : corpus.getName(); 2150a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood } 2160a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood 2170a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood public abstract Corpus getSearchCorpus(); 2180a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood 2197010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public Corpus getWebCorpus() { 2207010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert Corpus webCorpus = getCorpora().getWebCorpus(); 2217010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (webCorpus == null) { 2227010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert Log.e(TAG, "No web corpus"); 2237010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2247010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return webCorpus; 2257010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2267010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 227f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood public void setMaxPromotedSuggestions(int maxPromoted) { 228fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood mSuggestionsView.setLimitSuggestionsToViewHeight(false); 2297010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsAdapter.setMaxPromoted(maxPromoted); 2307010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2317010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 232fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood public void limitSuggestionsToViewHeight() { 233fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood mSuggestionsView.setLimitSuggestionsToViewHeight(true); 234fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood } 235fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood 236f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood public void setMaxPromotedResults(int maxPromoted) { 237f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood } 238f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood 239f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood public void limitResultsToViewHeight() { 240f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood } 241f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood 2427010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void setQueryListener(QueryListener listener) { 2437010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryListener = listener; 2447010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2457010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 2467010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void setSearchClickListener(SearchClickListener listener) { 2477010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchClickListener = listener; 2487010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2497010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 2500a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood public abstract void showCorpusSelectionDialog(); 2517010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 2527010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void setVoiceSearchButtonClickListener(View.OnClickListener listener) { 2537010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (mVoiceSearchButton != null) { 2547010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mVoiceSearchButton.setOnClickListener(listener); 2557010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2567010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2577010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 2587010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void setSuggestionClickListener(final SuggestionClickListener listener) { 2597010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsAdapter.setSuggestionClickListener(listener); 2607010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.setCommitCompletionListener(new QueryTextView.CommitCompletionListener() { 2617010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert @Override 2627010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void onCommitCompletion(int position) { 2637010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsAdapter.onSuggestionClicked(position); 2647010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2657010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert }); 2667010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2677010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 2689e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood public void setExitClickListener(final View.OnClickListener listener) { 2699e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood mExitClickListener = listener; 2709e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood } 2719e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood 2727010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public Suggestions getSuggestions() { 2737010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return mSuggestionsAdapter.getSuggestions(); 2747010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2757010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 276fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood public SuggestionCursor getCurrentPromotedSuggestions() { 277fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood return mSuggestionsAdapter.getCurrentPromotedSuggestions(); 2787010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2797010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 2807010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void setSuggestions(Suggestions suggestions) { 2817010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert suggestions.acquire(); 2827010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsAdapter.setSuggestions(suggestions); 2837010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2847010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 2857010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void clearSuggestions() { 2867010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSuggestionsAdapter.setSuggestions(null); 2877010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2887010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 2897010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public String getQuery() { 2907010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert CharSequence q = mQueryTextView.getText(); 2917010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return q == null ? "" : q.toString(); 2927010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 2937010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 294b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert public boolean isQueryEmpty() { 295b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert return TextUtils.isEmpty(getQuery()); 296b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert } 297b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert 2987010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert /** 2997010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert * Sets the text in the query box. Does not update the suggestions. 3007010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert */ 3017010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void setQuery(String query, boolean selectAll) { 3027010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mUpdateSuggestions = false; 3037010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.setText(query); 3047010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.setTextSelection(selectAll); 3057010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mUpdateSuggestions = true; 3067010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3077010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 3080a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood protected SearchActivity getActivity() { 309c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert Context context = getContext(); 3100a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood if (context instanceof SearchActivity) { 3110a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood return (SearchActivity) context; 312c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert } else { 313c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert return null; 314c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert } 315c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert } 316c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert 3178749e424d7645e708f238530621248abb567e3beBjorn Bringert public void hideSuggestions() { 3188749e424d7645e708f238530621248abb567e3beBjorn Bringert mSuggestionsView.setVisibility(GONE); 3198749e424d7645e708f238530621248abb567e3beBjorn Bringert } 3208749e424d7645e708f238530621248abb567e3beBjorn Bringert 3218749e424d7645e708f238530621248abb567e3beBjorn Bringert public void showSuggestions() { 3228749e424d7645e708f238530621248abb567e3beBjorn Bringert mSuggestionsView.setVisibility(VISIBLE); 3238749e424d7645e708f238530621248abb567e3beBjorn Bringert } 3248749e424d7645e708f238530621248abb567e3beBjorn Bringert 3257010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void focusQueryTextView() { 3267010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.requestFocus(); 3277010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3287010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 3298b2936607176720172aee068abc5631bdf77e843Bjorn Bringert protected void updateUi() { 330b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert updateUi(isQueryEmpty()); 3318b2936607176720172aee068abc5631bdf77e843Bjorn Bringert } 3328b2936607176720172aee068abc5631bdf77e843Bjorn Bringert 3337010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert protected void updateUi(boolean queryEmpty) { 3347010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert updateQueryTextView(queryEmpty); 3357010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert updateSearchGoButton(queryEmpty); 3367010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert updateVoiceSearchButton(queryEmpty); 3377010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3387010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 33955938341e72f1581d6caae51a31d8d72a1cd8138Amith Yamasani protected void updateQueryTextView(boolean queryEmpty) { 3407010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (queryEmpty) { 3417010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (isSearchCorpusWeb()) { 3427010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.setBackgroundDrawable(mQueryTextEmptyBg); 3437010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.setHint(null); 3447010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } else { 3457010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (mQueryTextNotEmptyBg == null) { 3467010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextNotEmptyBg = 3477010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert getResources().getDrawable(R.drawable.textfield_search_empty); 3487010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3497010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.setBackgroundDrawable(mQueryTextNotEmptyBg); 3500a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood Corpus corpus = getCorpus(); 3510a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood mQueryTextView.setHint(corpus == null ? "" : corpus.getHint()); 3527010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3537010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } else { 3547010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.setBackgroundResource(R.drawable.textfield_search); 3557010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3567010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3577010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 3587010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private void updateSearchGoButton(boolean queryEmpty) { 3597010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (queryEmpty) { 3607010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchGoButton.setVisibility(View.GONE); 3617010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } else { 3627010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchGoButton.setVisibility(View.VISIBLE); 3637010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3647010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3657010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 3667010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert protected void updateVoiceSearchButton(boolean queryEmpty) { 3673be3f12c41baa6c91ebb4fef366bd3d9bfcbc093Bjorn Bringert if (shouldShowVoiceSearch(queryEmpty) 3683be3f12c41baa6c91ebb4fef366bd3d9bfcbc093Bjorn Bringert && getVoiceSearch().shouldShowVoiceSearch(getCorpus())) { 3697010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mVoiceSearchButton.setVisibility(View.VISIBLE); 3707010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE); 3717010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } else { 3727010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mVoiceSearchButton.setVisibility(View.GONE); 3737010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.setPrivateImeOptions(null); 3747010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3757010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3767010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 3773be3f12c41baa6c91ebb4fef366bd3d9bfcbc093Bjorn Bringert protected boolean shouldShowVoiceSearch(boolean queryEmpty) { 3783be3f12c41baa6c91ebb4fef366bd3d9bfcbc093Bjorn Bringert return queryEmpty; 3793be3f12c41baa6c91ebb4fef366bd3d9bfcbc093Bjorn Bringert } 3803be3f12c41baa6c91ebb4fef366bd3d9bfcbc093Bjorn Bringert 381c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert /** 382c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert * Hides the input method. 383c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert */ 384c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert protected void hideInputMethod() { 385c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert InputMethodManager imm = (InputMethodManager) 386c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 387c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert if (imm != null) { 388c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert imm.hideSoftInputFromWindow(getWindowToken(), 0); 389c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert } 390c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert } 391c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert 3928749e424d7645e708f238530621248abb567e3beBjorn Bringert public abstract void considerHidingInputMethod(); 3937010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 3947010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void showInputMethodForQuery() { 3957010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryTextView.showInputMethod(); 3967010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 3977010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 398c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert /** 399b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert * Dismiss the activity if BACK is pressed when the search box is empty. 400b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert */ 401b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert @Override 402b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert public boolean dispatchKeyEventPreIme(KeyEvent event) { 403b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert SearchActivity activity = getActivity(); 404b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert if (activity != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK 405b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert && isQueryEmpty()) { 406b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert KeyEvent.DispatcherState state = getKeyDispatcherState(); 407b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert if (state != null) { 408b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert if (event.getAction() == KeyEvent.ACTION_DOWN 409b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert && event.getRepeatCount() == 0) { 410b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert state.startTracking(event, this); 411b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert return true; 412b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert } else if (event.getAction() == KeyEvent.ACTION_UP 413b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert && !event.isCanceled() && state.isTracking(event)) { 414b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert hideInputMethod(); 415b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert activity.onBackPressed(); 416b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert return true; 417b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert } 418b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert } 419b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert } 420b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert return super.dispatchKeyEventPreIme(event); 421b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert } 422b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert 423b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert /** 4247010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert * If the input method is in fullscreen mode, and the selector corpus 4257010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert * is All or Web, use the web search suggestions as completions. 4267010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert */ 4277010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert protected void updateInputMethodSuggestions() { 4287010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert InputMethodManager imm = (InputMethodManager) 4297010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 4307010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (imm == null || !imm.isFullscreenMode()) return; 4317010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert Suggestions suggestions = mSuggestionsAdapter.getSuggestions(); 4327010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (suggestions == null) return; 4337010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert CompletionInfo[] completions = webSuggestionsToCompletions(suggestions); 4347010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (DBG) Log.d(TAG, "displayCompletions(" + Arrays.toString(completions) + ")"); 4357010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert imm.displayCompletions(mQueryTextView, completions); 4367010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 4377010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 4387010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private CompletionInfo[] webSuggestionsToCompletions(Suggestions suggestions) { 4397010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // TODO: This should also include include web search shortcuts 4407010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert CorpusResult cursor = suggestions.getWebResult(); 4417010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (cursor == null) return null; 4427010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert int count = cursor.getCount(); 4437010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert ArrayList<CompletionInfo> completions = new ArrayList<CompletionInfo>(count); 4447010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert boolean usingWebCorpus = isSearchCorpusWeb(); 4457010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert for (int i = 0; i < count; i++) { 4467010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert cursor.moveTo(i); 4477010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (!usingWebCorpus || cursor.isWebSearchSuggestion()) { 4487010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert String text1 = cursor.getSuggestionText1(); 4497010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert completions.add(new CompletionInfo(i, i, text1)); 4507010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 4517010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 4527010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return completions.toArray(new CompletionInfo[completions.size()]); 4537010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 4547010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 4558b2936607176720172aee068abc5631bdf77e843Bjorn Bringert protected void onSuggestionsChanged() { 4568b2936607176720172aee068abc5631bdf77e843Bjorn Bringert updateInputMethodSuggestions(); 4578b2936607176720172aee068abc5631bdf77e843Bjorn Bringert } 4588b2936607176720172aee068abc5631bdf77e843Bjorn Bringert 4597010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert /** 4607010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert * Checks if the corpus used for typed searches is the web corpus. 4617010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert */ 4627010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert protected boolean isSearchCorpusWeb() { 4637010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert Corpus corpus = getSearchCorpus(); 4647010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return corpus != null && corpus.isWebCorpus(); 4657010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 4667010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 467fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood protected boolean onSuggestionKeyDown(SuggestionsAdapter<?> adapter, 46845f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood long suggestionId, int keyCode, KeyEvent event) { 4697010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // Treat enter or search as a click 4707010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if ( keyCode == KeyEvent.KEYCODE_ENTER 4717010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert || keyCode == KeyEvent.KEYCODE_SEARCH 4727010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert || keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 4730a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood if (adapter != null) { 47445f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood adapter.onSuggestionClicked(suggestionId); 4757010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return true; 4767010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } else { 4777010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return false; 4787010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 4797010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 4807010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 4817010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return false; 4827010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 4837010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 4847010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert protected boolean onSearchClicked(int method) { 4857010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (mSearchClickListener != null) { 4867010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return mSearchClickListener.onSearchClicked(method); 4877010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 4887010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return false; 4897010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 4907010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 4917010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert /** 4927010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert * Filters the suggestions list when the search text changes. 4937010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert */ 4947010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private class SearchTextWatcher implements TextWatcher { 4957010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void afterTextChanged(Editable s) { 4967010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert boolean empty = s.length() == 0; 4977010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (empty != mQueryWasEmpty) { 4987010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryWasEmpty = empty; 4997010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert updateUi(empty); 5007010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5017010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (mUpdateSuggestions) { 5027010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (mQueryListener != null) { 5037010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mQueryListener.onQueryChanged(); 5047010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5057010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5067010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5077010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5087010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void beforeTextChanged(CharSequence s, int start, int count, int after) { 5097010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5107010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5117010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void onTextChanged(CharSequence s, int start, int before, int count) { 5127010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5137010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5147010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5157010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert /** 5167010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert * Handles key events on the suggestions list view. 5177010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert */ 5187010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert protected class SuggestionsViewKeyListener implements View.OnKeyListener { 5197010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public boolean onKey(View v, int keyCode, KeyEvent event) { 5207010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (event.getAction() == KeyEvent.ACTION_DOWN 52145f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood && v instanceof SuggestionsListView<?>) { 52245f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood SuggestionsListView<?> listView = (SuggestionsListView<?>) v; 52345f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood if (onSuggestionKeyDown(listView.getSuggestionsAdapter(), 52445f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood listView.getSelectedItemId(), keyCode, event)) { 5257010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return true; 5267010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5277010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5287010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return forwardKeyToQueryTextView(keyCode, event); 5297010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5307010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5317010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5327010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private class InputMethodCloser implements SuggestionsView.OnScrollListener { 5337010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5347010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 5357010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert int totalItemCount) { 5367010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5377010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5387010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void onScrollStateChanged(AbsListView view, int scrollState) { 5397010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert considerHidingInputMethod(); 5407010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5417010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5427010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5437010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert /** 5447010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert * Listens for clicks on the source selector. 5457010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert */ 5467010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private class SearchGoButtonClickListener implements View.OnClickListener { 5477010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void onClick(View view) { 5487010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert onSearchClicked(Logger.SEARCH_METHOD_BUTTON); 5497010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5507010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5517010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5527010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert /** 553748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood * This class handles enter key presses in the query text view. 5547010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert */ 555748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood private class QueryTextEditorActionListener implements OnEditorActionListener { 556748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 557748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood boolean consumed = false; 558748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood if (event != null) { 559748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood if (event.getAction() == KeyEvent.ACTION_UP) { 560748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood consumed = onSearchClicked(Logger.SEARCH_METHOD_KEYBOARD); 561748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood } else if (event.getAction() == KeyEvent.ACTION_DOWN) { 562748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood // we have to consume the down event so that we receive the up event too 563748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood consumed = true; 564748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood } 5657010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 566748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood if (DBG) Log.d(TAG, "onEditorAction consumed=" + consumed); 567748a3cd7cb44de0aedb05e3c5d19989e2e52164fMathew Inwood return consumed; 5687010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5697010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5707010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5717010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert /** 5727010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert * Handles key events on the search and voice search buttons, 5737010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert * by refocusing to EditText. 5747010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert */ 5757010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private class ButtonsKeyListener implements View.OnKeyListener { 5767010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public boolean onKey(View v, int keyCode, KeyEvent event) { 5777010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return forwardKeyToQueryTextView(keyCode, event); 5787010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5797010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5807010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 5817010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private boolean forwardKeyToQueryTextView(int keyCode, KeyEvent event) { 58245f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood if (!event.isSystem() && shouldForwardToQueryTextView(keyCode)) { 5837010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (DBG) Log.d(TAG, "Forwarding key to query box: " + event); 5847010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (mQueryTextView.requestFocus()) { 5857010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return mQueryTextView.dispatchKeyEvent(event); 5867010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5877010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5887010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return false; 5897010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 5907010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 59145f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood private boolean shouldForwardToQueryTextView(int keyCode) { 5927010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert switch (keyCode) { 5937010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert case KeyEvent.KEYCODE_DPAD_UP: 5947010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert case KeyEvent.KEYCODE_DPAD_DOWN: 5957010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert case KeyEvent.KEYCODE_DPAD_LEFT: 5967010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert case KeyEvent.KEYCODE_DPAD_RIGHT: 5977010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert case KeyEvent.KEYCODE_DPAD_CENTER: 59845f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood case KeyEvent.KEYCODE_ENTER: 59945f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood case KeyEvent.KEYCODE_SEARCH: 6007010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return false; 60145f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood default: 60245f42cab0664a8a23975e8913dbe77c1fd8ad86cMathew Inwood return true; 6037010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6047010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6057010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 6067010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert /** 6077010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert * Hides the input method when the suggestions get focus. 6087010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert */ 6097010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private class SuggestListFocusListener implements OnFocusChangeListener { 6107010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void onFocusChange(View v, boolean focused) { 6117010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (DBG) Log.d(TAG, "Suggestions focus change, now: " + focused); 6127010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (focused) { 6137010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert considerHidingInputMethod(); 6147010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6157010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6167010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6177010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 6187010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private class QueryTextViewFocusListener implements OnFocusChangeListener { 6197010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void onFocusChange(View v, boolean focused) { 6207010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (DBG) Log.d(TAG, "Query focus change, now: " + focused); 6217010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert if (focused) { 6227010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert // The query box got focus, show the input method 6237010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert showInputMethodForQuery(); 6247010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6257010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6267010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6277010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 6287a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood protected class SuggestionsObserver extends DataSetObserver { 6297010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert @Override 6307010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void onChanged() { 6318b2936607176720172aee068abc5631bdf77e843Bjorn Bringert onSuggestionsChanged(); 6327010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6337010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6347010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 6357010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public interface QueryListener { 6367010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert void onQueryChanged(); 6377010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6387010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 6397010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public interface SearchClickListener { 6407010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert boolean onSearchClicked(int method); 6417010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 6427010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert 6432cbf1d099dbd04c612e3cba34a70293705730fa0Amith Yamasani private class CloseClickListener implements OnClickListener { 6442cbf1d099dbd04c612e3cba34a70293705730fa0Amith Yamasani public void onClick(View v) { 645b28dcd61d3aec036c6a2b51571d11453ff6eb671Bjorn Bringert if (!isQueryEmpty()) { 6469e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood mQueryTextView.setText(""); 6479e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood } else { 6489e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood mExitClickListener.onClick(v); 6499e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood } 6502cbf1d099dbd04c612e3cba34a70293705730fa0Amith Yamasani } 6512cbf1d099dbd04c612e3cba34a70293705730fa0Amith Yamasani } 652c36735de23beadc017c484596b551d7c4eaff289Bjorn Bringert} 653