SearchActivity.java revision fde948e69f59589cf0d217ea414af7947de600bb
13e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert/* 23e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Copyright (C) 2009 The Android Open Source Project 33e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 43e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 53e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * you may not use this file except in compliance with the License. 63e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * You may obtain a copy of the License at 73e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 83e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 93e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * See the License for the specific language governing permissions and 143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * limitations under the License. 153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertpackage com.android.quicksearchbox; 183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 193f71a11f8858b9164ca83e8d2f558dd8a8a5e2deBjorn Bringertimport com.android.common.Search; 20fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport com.android.quicksearchbox.ui.CorpusIndicator; 21185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionClickListener; 227b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionSelectionListener; 23185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionViewFactory; 24185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionsAdapter; 25185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionsView; 26185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.app.Activity; 282617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringertimport android.app.Dialog; 293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.app.SearchManager; 303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.content.Intent; 313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.database.DataSetObserver; 323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.graphics.drawable.Animatable; 33d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinneyimport android.graphics.drawable.Drawable; 34fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.net.Uri; 353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.os.Bundle; 36ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringertimport android.os.SystemClock; 373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.text.Editable; 383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.text.TextUtils; 393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.text.TextWatcher; 403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.util.Log; 413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.KeyEvent; 423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.Menu; 433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.View; 443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.View.OnFocusChangeListener; 453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.inputmethod.InputMethodManager; 463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.widget.EditText; 473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.widget.ImageButton; 483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 49ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringertimport java.util.ArrayList; 50ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert/** 523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * The main activity for Quick Search Box. Shows the search UI. 533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertpublic class SearchActivity extends Activity { 563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private static final boolean DBG = true; 580484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert private static final String TAG = "QSB.SearchActivity"; 593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 60fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private static final String SCHEME_CORPUS = "qsb.corpus"; 61fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 62fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public static final String INTENT_ACTION_QSB_AND_SELECT_CORPUS 63fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert = "com.android.quicksearchbox.action.QSB_AND_SELECT_CORPUS"; 643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 659ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Keys for the saved instance state. 66fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private static final String INSTANCE_KEY_CORPUS = "corpus"; 679ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert private static final String INSTANCE_KEY_USER_QUERY = "query"; 68713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 692617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert // Dialog IDs 70fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private static final int CORPUS_SELECTION_DIALOG = 0; 712617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 72ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // Timestamp for last onCreate()/onNewIntent() call, as returned by SystemClock.uptimeMillis(). 73ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private long mStartTime; 74ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // Whether QSB is starting. True between the calls to onCreate()/onNewIntent() and onResume(). 75ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private boolean mStarting; 76ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // True if the user has taken some action, e.g. launching a search, voice search, 77ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // or suggestions, since QSB was last started. 78ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private boolean mTookAction; 79ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 80185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert protected SuggestionsAdapter mSuggestionsAdapter; 81185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 823e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected EditText mQueryTextView; 833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected SuggestionsView mSuggestionsView; 853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected ImageButton mSearchGoButton; 873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected ImageButton mVoiceSearchButton; 88fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected CorpusIndicator mCorpusIndicator; 893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private Launcher mLauncher; 913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 92fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpus mCorpus; 932617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert private Bundle mAppSearchData; 94713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private boolean mUpdateSuggestions; 95713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private String mUserQuery; 96713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private boolean mSelectAll; 973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** Called when the activity is first created. */ 993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 1003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onCreate(Bundle savedInstanceState) { 101ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert recordStartTime(); 1023e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "onCreate()"); 1033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onCreate(savedInstanceState); 104713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 1053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert setContentView(R.layout.search_bar); 1063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 107816804b67619af133860a1e28e92f58bc642260dBjorn Bringert mSuggestionsAdapter = getQsbApplication().createSuggestionsAdapter(); 108185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 1093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mQueryTextView = (EditText) findViewById(R.id.search_src_text); 1103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSuggestionsView = (SuggestionsView) findViewById(R.id.suggestions); 111782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mSuggestionsView.setSuggestionClickListener(new ClickHandler()); 1127b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mSuggestionsView.setSuggestionSelectionListener(new SelectionHandler()); 113782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mSuggestionsView.setInteractionListener(new InputMethodCloser()); 114713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert mSuggestionsView.setOnKeyListener(new SuggestionsViewKeyListener()); 1157b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mSuggestionsView.setOnFocusChangeListener(new SuggestListFocusListener()); 1163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSearchGoButton = (ImageButton) findViewById(R.id.search_go_btn); 1183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mVoiceSearchButton = (ImageButton) findViewById(R.id.search_voice_btn); 119fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpusIndicator = new CorpusIndicator(findViewById(R.id.corpus_indicator)); 1203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1219ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mLauncher = new Launcher(this); 1223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 123782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mQueryTextView.addTextChangedListener(new SearchTextWatcher()); 124782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mQueryTextView.setOnKeyListener(new QueryTextViewKeyListener()); 1257b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mQueryTextView.setOnFocusChangeListener(new QueryTextViewFocusListener()); 126782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 127fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpusIndicator.setOnClickListener(new CorpusIndicatorClickListener()); 1282617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 129782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mSearchGoButton.setOnClickListener(new SearchGoButtonClickListener()); 130782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 131782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mVoiceSearchButton.setOnClickListener(new VoiceSearchButtonClickListener()); 1327be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert 1337be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert ButtonsKeyListener buttonsKeyListener = new ButtonsKeyListener(); 1347be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert mSearchGoButton.setOnKeyListener(buttonsKeyListener); 1357be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert mVoiceSearchButton.setOnKeyListener(buttonsKeyListener); 136fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpusIndicator.setOnKeyListener(buttonsKeyListener); 137713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 1389ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mUpdateSuggestions = true; 1399ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 1409ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // First get setup from intent 1419ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert Intent intent = getIntent(); 1429ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setupFromIntent(intent); 1439ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Then restore any saved instance state 1449ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert restoreInstanceState(savedInstanceState); 1459ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 146713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert // Do this at the end, to avoid updating the list view when setSource() 147713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert // is called. 148713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert mSuggestionsView.setAdapter(mSuggestionsAdapter); 1499ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 150713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 1519ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert @Override 1529ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void onNewIntent(Intent intent) { 153ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert recordStartTime(); 1549ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setIntent(intent); 1559ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setupFromIntent(intent); 1569ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 1579ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 158ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private void recordStartTime() { 159ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mStartTime = SystemClock.uptimeMillis(); 160ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mStarting = true; 161ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = false; 162ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 163ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 1649ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void restoreInstanceState(Bundle savedInstanceState) { 1659ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (savedInstanceState == null) return; 166fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String corpusName = savedInstanceState.getString(INSTANCE_KEY_CORPUS); 1679ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert String query = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY); 168fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert setCorpus(getCorpus(corpusName)); 1699ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setUserQuery(query); 170713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 171713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 172713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert @Override 1739ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void onSaveInstanceState(Bundle outState) { 1749ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert super.onSaveInstanceState(outState); 1759ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // We don't save appSearchData, since we always get the value 1769ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // from the intent and the user can't change it. 177fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 178fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String corpusName = mCorpus == null ? null : mCorpus.getName(); 179fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert outState.putString(INSTANCE_KEY_CORPUS, corpusName); 1809ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert outState.putString(INSTANCE_KEY_USER_QUERY, mUserQuery); 181713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 182713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 183713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private void setupFromIntent(Intent intent) { 184713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert if (DBG) Log.d(TAG, "setupFromIntent(" + intent.toUri(0) + ")"); 185fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Corpus corpus = getCorpusFromUri(intent.getData()); 1862617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert String query = intent.getStringExtra(SearchManager.QUERY); 1872617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert Bundle appSearchData = intent.getBundleExtra(SearchManager.APP_DATA); 1882617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 189fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert setCorpus(corpus); 1902617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert setUserQuery(query); 191154017089860da89ec020ed37e502d194253cc67Bjorn Bringert mSelectAll = intent.getBooleanExtra(SearchManager.EXTRA_SELECT_QUERY, false); 1922617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert setAppSearchData(appSearchData); 1932617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 194fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (INTENT_ACTION_QSB_AND_SELECT_CORPUS.equals(intent.getAction())) { 1952617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert showSourceSelectorDialog(); 1962617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 1979ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 1989ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 199fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public static Uri getCorpusUri(Corpus corpus) { 200fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (corpus == null) return null; 201fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return new Uri.Builder() 202fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert .scheme(SCHEME_CORPUS) 203fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert .authority(corpus.getName()) 204fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert .build(); 205fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 206fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 207fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpus getCorpusFromUri(Uri uri) { 208fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (uri == null) return null; 209fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (!SCHEME_CORPUS.equals(uri.getScheme())) return null; 210fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String name = uri.getAuthority(); 211fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getCorpus(name); 212fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 213fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 214fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpus getCorpus(String sourceName) { 2150ccab5903ba2c64ec4cdd33dbcea91b1e279d556Bjorn Bringert if (sourceName == null) return null; 216fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Corpus corpus = getCorpora().getCorpus(sourceName); 217fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (corpus == null) { 218fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Log.w(TAG, "Unknown corpus " + sourceName); 2199ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert return null; 220713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 221fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return corpus; 222713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 223713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 224fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private void setCorpus(Corpus corpus) { 225fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (DBG) Log.d(TAG, "setCorpus(" + corpus + ")"); 226fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpus = corpus; 2279ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert Drawable sourceIcon; 228fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (corpus == null) { 2299ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert sourceIcon = getSuggestionViewFactory().getGlobalSearchIcon(); 230713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } else { 231fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert sourceIcon = corpus.getCorpusIcon(); 232713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 233fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mSuggestionsAdapter.setCorpus(corpus); 234fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpusIndicator.setSourceIcon(sourceIcon); 2353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 236fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert boolean enableVoiceSearch = Launcher.shouldShowVoiceSearch(this, mCorpus); 237fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mVoiceSearchButton.setVisibility(enableVoiceSearch ? View.VISIBLE : View.GONE); 2380484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert } 2390484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert 2403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private QsbApplication getQsbApplication() { 2413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return (QsbApplication) getApplication(); 2423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 244fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpora getCorpora() { 245fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getQsbApplication().getCorpora(); 246fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 247fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 248fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private CorpusRanker getCorpusRanker() { 249fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getQsbApplication().getCorpusRanker(); 250713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 251713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 2523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private ShortcutRepository getShortcutRepository() { 2533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return getQsbApplication().getShortcutRepository(); 2543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 256ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private SuggestionsProvider getSuggestionsProvider() { 257fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getQsbApplication().getSuggestionsProvider(mCorpus); 2583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 260185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert private SuggestionViewFactory getSuggestionViewFactory() { 261185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert return getQsbApplication().getSuggestionViewFactory(); 262185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert } 263185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 264ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private Logger getLogger() { 265ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert return getQsbApplication().getLogger(); 266ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 267ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 2683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 2693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onDestroy() { 2703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "onDestroy()"); 2713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onDestroy(); 272185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert mSuggestionsView.setAdapter(null); // closes mSuggestionsAdapter 2733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 2753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 2763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onStop() { 2779ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (DBG) Log.d(TAG, "onStop()"); 2789ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Close all open suggestion cursors. The query will be redone in onResume() 2793e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // if we come back to this activity. 280185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert mSuggestionsAdapter.setSuggestions(null); 28194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney getQsbApplication().getShortcutRefresher().reset(); 2823e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onStop(); 2833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 2853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 286b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert protected void onResume() { 2879ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (DBG) Log.d(TAG, "onResume()"); 288b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert super.onResume(); 2899ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setQuery(mUserQuery, mSelectAll); 2909ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Only select everything the first time after creating the activity. 2919ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mSelectAll = false; 2929ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert updateSuggestions(mUserQuery); 293b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert mQueryTextView.requestFocus(); 294ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert if (mStarting) { 295ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mStarting = false; 296ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // Start up latency should not exceed 2^31 ms (~ 25 days). Note that 297ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // SystemClock.uptimeMillis() does not advance during deep sleep. 298ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert int latency = (int) (SystemClock.uptimeMillis() - mStartTime); 2993f71a11f8858b9164ca83e8d2f558dd8a8a5e2deBjorn Bringert String source = getIntent().getStringExtra(Search.SOURCE); 300fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getLogger().logStart(latency, source, mCorpus, 301fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getSuggestionsProvider().getOrderedCorpora()); 302ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 303b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert } 304b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert 305b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert @Override 3063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean onCreateOptionsMenu(Menu menu) { 3073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onCreateOptionsMenu(menu); 3083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3092617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert Intent settings = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS); 3103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert settings.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 3113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Don't show activity chooser if there are multiple search settings activities, 3123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // e.g. from different QSB implementations. 3133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert settings.setPackage(this.getPackageName()); 3143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert menu.add(Menu.NONE, Menu.NONE, 0, R.string.menu_settings) 3153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert .setIcon(android.R.drawable.ic_menu_preferences).setAlphabeticShortcut('P') 3163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert .setIntent(settings); 3173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return true; 3193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3219ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert /** 3229ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert * Sets the query as typed by the user. Does not update the suggestions 3239ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert * or the text in the query box. 3249ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert */ 3259ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void setUserQuery(String userQuery) { 3269ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (userQuery == null) userQuery = ""; 3279ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mUserQuery = userQuery; 3289ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 3299ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 3309ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void setAppSearchData(Bundle appSearchData) { 3312617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert mAppSearchData = appSearchData; 3329ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mLauncher.setAppSearchData(appSearchData); 3339ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 3349ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 335713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert protected String getQuery() { 3363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert CharSequence q = mQueryTextView.getText(); 3373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return q == null ? "" : q.toString(); 3383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 3413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Restores the query entered by the user. 3423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 3433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void restoreUserQuery() { 3443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "Restoring query to '" + mUserQuery + "'"); 3453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert setQuery(mUserQuery, false); 3463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 3493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Sets the text in the query box. Does not update the suggestions, 3503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * and does not change the saved user-entered query. 3513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * {@link #restoreUserQuery()} will restore the query to the last 3523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * user-entered query. 3533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 3543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void setQuery(String query, boolean selectAll) { 3553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mUpdateSuggestions = false; 3563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mQueryTextView.setText(query); 3573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert setTextSelection(selectAll); 3583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mUpdateSuggestions = true; 3593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 3623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Sets the text selection in the query text view. 3633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 3643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * @param selectAll If {@code true}, selects the entire query. 3653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * If {@false}, no characters are selected, and the cursor is placed 3663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * at the end of the query. 3673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 3683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void setTextSelection(boolean selectAll) { 3693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (selectAll) { 3703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mQueryTextView.setSelection(0, mQueryTextView.length()); 3713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } else { 3723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mQueryTextView.setSelection(mQueryTextView.length()); 3733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3762617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert protected void showSourceSelectorDialog() { 377fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert showDialog(CORPUS_SELECTION_DIALOG); 3782617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 3792617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 3802617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 3812617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert @Override 3822617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert protected Dialog onCreateDialog(int id, Bundle args) { 3832617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert switch (id) { 384fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert case CORPUS_SELECTION_DIALOG: 385fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return createCorpusSelectionDialog(); 3862617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert default: 3872617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert throw new IllegalArgumentException("Unknown dialog: " + id); 3882617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 3892617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 3902617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 3912617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert @Override 3922617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert protected void onPrepareDialog(int id, Dialog dialog, Bundle args) { 3932617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert switch (id) { 394fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert case CORPUS_SELECTION_DIALOG: 395fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert prepareCorpusSelectionDialog((CorpusSelectionDialog) dialog); 3962617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert break; 3972617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert default: 3982617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert throw new IllegalArgumentException("Unknown dialog: " + id); 3992617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4002617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4012617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 402fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected CorpusSelectionDialog createCorpusSelectionDialog() { 403fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert CorpusSelectionDialog dialog = new CorpusSelectionDialog(this); 4042617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert dialog.setOwnerActivity(this); 4052617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert return dialog; 4062617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4072617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 408fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected void prepareCorpusSelectionDialog(CorpusSelectionDialog dialog) { 409fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert dialog.setCorpus(mCorpus); 4102617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert dialog.setQuery(getQuery()); 4112617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert dialog.setAppData(mAppSearchData); 4122617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4132617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 414ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert protected void onSearchClicked(int method) { 4153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String query = getQuery(); 4163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "Search clicked, query=" + query); 417ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = true; 418fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getLogger().logSearch(mCorpus, method, query.length()); 419fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mLauncher.startSearch(mCorpus, query); 4203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onVoiceSearchClicked() { 4233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "Voice Search clicked"); 424ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = true; 425fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getLogger().logVoiceSearch(mCorpus); 426ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 42784b72b7b9dacd54de9eff630dbbb37de372560f6Bjorn Bringert // TODO: should this start voice search in the current source? 428fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mLauncher.startVoiceSearch(mCorpus); 4293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 431fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected SuggestionCursor getSuggestions() { 432fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mSuggestionsAdapter.getCurrentSuggestions(); 433782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 434782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 435fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected boolean launchSuggestion(int position) { 436fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (DBG) Log.d(TAG, "Launching suggestion " + position); 437ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = true; 438fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert SuggestionCursor suggestions = getSuggestions(); 439ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // TODO: This should be just the queried sources, but currently 440ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // all sources are queried 441fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert ArrayList<Corpus> corpora = getCorpusRanker().rankCorpora(getCorpora().getEnabledCorpora()); 442fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getLogger().logSuggestionClick(position, suggestions, corpora); 443ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 444fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mLauncher.launchSuggestion(suggestions, position); 445fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getShortcutRepository().reportClick(suggestions, position); 4463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return true; 4473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 449fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected boolean onSuggestionLongClicked(int position) { 450fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (DBG) Log.d(TAG, "Long clicked on suggestion " + position); 4513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return false; 4523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 454fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected boolean onSuggestionKeyDown(int position, int keyCode, KeyEvent event) { 455782dd228e78e9294692d639597f96c26283968bbBjorn Bringert // Treat enter or search as a click 456782dd228e78e9294692d639597f96c26283968bbBjorn Bringert if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH) { 457fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return launchSuggestion(position); 458782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 459782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 4607b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (keyCode == KeyEvent.KEYCODE_DPAD_UP 4617b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert && mSuggestionsView.getSelectedItemPosition() == 0) { 4627b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // Moved up from the top suggestion, restore the user query and focus query box 4637b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Up and out"); 4647b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert restoreUserQuery(); 4657b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert return false; // let the framework handle the move 4667b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 4677b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 4687b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT 4697b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { 4707b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // Moved left / right from a suggestion, keep current query, move 4717b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // focus to query box, and move cursor to far left / right 4727b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Left/right on a suggestion"); 4737b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert int cursorPos = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mQueryTextView.length(); 4747b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mQueryTextView.setSelection(cursorPos); 4757b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mQueryTextView.requestFocus(); 4767b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // TODO: should we modify the list selection? 4777b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert return true; 4787b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 4797b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 480782dd228e78e9294692d639597f96c26283968bbBjorn Bringert return false; 481782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 482782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 4833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onSourceSelected() { 4843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "No suggestion selected"); 4853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert restoreUserQuery(); 4863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 488782dd228e78e9294692d639597f96c26283968bbBjorn Bringert protected int getSelectedPosition() { 489782dd228e78e9294692d639597f96c26283968bbBjorn Bringert return mSuggestionsView.getSelectedPosition(); 490782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 491782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 4923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 4933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Hides the input method. 4943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 4953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void hideInputMethod() { 4963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 4973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (imm != null) { 4983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert imm.hideSoftInputFromWindow(mQueryTextView.getWindowToken(), 0); 4993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5013e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 5027b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert protected void showInputMethodForQuery() { 5037b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 5047b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (imm != null) { 5057b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert imm.showSoftInput(mQueryTextView, 0); 5067b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5077b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5087b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 5093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 5103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Hides the input method when the suggestions get focus. 5113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 5123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class SuggestListFocusListener implements OnFocusChangeListener { 5133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onFocusChange(View v, boolean focused) { 5147b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Suggestions focus change, now: " + focused); 5157b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (focused) { 5167b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // The suggestions list got focus, hide the input method 5177b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert hideInputMethod(); 5187b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5197b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5207b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5217b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 5227b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert private class QueryTextViewFocusListener implements OnFocusChangeListener { 5237b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert public void onFocusChange(View v, boolean focused) { 5247b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Query focus change, now: " + focused); 5257b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (focused) { 5267b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // The query box got focus, show the input method if the 5277b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // query box got focus? 5287b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert showInputMethodForQuery(); 5293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 5333e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void startSearchProgress() { 5343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // TODO: Cache animation between calls? 5353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSearchGoButton.setImageResource(R.drawable.searching); 5363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Animatable animation = (Animatable) mSearchGoButton.getDrawable(); 5373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert animation.start(); 5383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 5403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void stopSearchProgress() { 541d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney Drawable animation = mSearchGoButton.getDrawable(); 542d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney if (animation instanceof Animatable) { 543d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney // TODO: Is this needed, or is it done automatically when the 544d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney // animation is removed? 545d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney ((Animatable) animation).stop(); 546d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney } 5473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSearchGoButton.setImageResource(R.drawable.ic_btn_search); 5483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 5503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void updateSuggestions(String query) { 5513d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney query = ltrim(query); 5523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert LatencyTracker latency = new LatencyTracker(TAG); 553ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert Suggestions suggestions = getSuggestionsProvider().getSuggestions(query); 5543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert latency.addEvent("getSuggestions_done"); 5553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (!suggestions.isDone()) { 5563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert suggestions.registerDataSetObserver(new ProgressUpdater(suggestions)); 5573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert startSearchProgress(); 558d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney } else { 559d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney stopSearchProgress(); 5603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 561185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert mSuggestionsAdapter.setSuggestions(suggestions); 5623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert latency.addEvent("shortcuts_shown"); 5633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert long userVisibleLatency = latency.getUserVisibleLatency(); 5643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) { 5653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Log.d(TAG, "User visible latency (shortcuts): " + userVisibleLatency + " ms."); 5663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 5697be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert private boolean forwardKeyToQueryTextView(int keyCode, KeyEvent event) { 5707be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert if (!event.isSystem() && !isDpadKey(keyCode)) { 5717be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert if (DBG) Log.d(TAG, "Forwarding key to query box: " + event); 5727be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert if (mQueryTextView.requestFocus()) { 5737be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return mQueryTextView.dispatchKeyEvent(event); 5747be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 5757be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 5767be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return false; 5777be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 5787be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert 5797be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert private boolean isDpadKey(int keyCode) { 5807be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert switch (keyCode) { 5817be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_UP: 5827be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_DOWN: 5837be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_LEFT: 5847be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_RIGHT: 5857be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_CENTER: 5867be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return true; 5877be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert default: 5887be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return false; 5897be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 5907be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 5917be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert 5923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 5933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Filters the suggestions list when the search text changes. 5943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 5953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class SearchTextWatcher implements TextWatcher { 5963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void afterTextChanged(Editable s) { 5973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (mUpdateSuggestions) { 5983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String query = s == null ? "" : s.toString(); 5999ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setUserQuery(query); 6003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert updateSuggestions(query); 6013e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6023e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void beforeTextChanged(CharSequence s, int start, int count, int after) { 6053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onTextChanged(CharSequence s, int start, int before, int count) { 6083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 6123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Handles non-text keys in the query text view. 6133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 6143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class QueryTextViewKeyListener implements View.OnKeyListener { 6153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean onKey(View view, int keyCode, KeyEvent event) { 6163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Handle IME search action key 6173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) { 618ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert onSearchClicked(Logger.SEARCH_METHOD_KEYBOARD); 6193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return false; 6213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 624782dd228e78e9294692d639597f96c26283968bbBjorn Bringert /** 625782dd228e78e9294692d639597f96c26283968bbBjorn Bringert * Handles key events on the search and voice search buttons, 626782dd228e78e9294692d639597f96c26283968bbBjorn Bringert * by refocusing to EditText. 627782dd228e78e9294692d639597f96c26283968bbBjorn Bringert */ 628782dd228e78e9294692d639597f96c26283968bbBjorn Bringert private class ButtonsKeyListener implements View.OnKeyListener { 629782dd228e78e9294692d639597f96c26283968bbBjorn Bringert public boolean onKey(View v, int keyCode, KeyEvent event) { 6307be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return forwardKeyToQueryTextView(keyCode, event); 631782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 632782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 633782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 634782dd228e78e9294692d639597f96c26283968bbBjorn Bringert /** 635782dd228e78e9294692d639597f96c26283968bbBjorn Bringert * Handles key events on the suggestions list view. 636782dd228e78e9294692d639597f96c26283968bbBjorn Bringert */ 637713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private class SuggestionsViewKeyListener implements View.OnKeyListener { 638782dd228e78e9294692d639597f96c26283968bbBjorn Bringert public boolean onKey(View v, int keyCode, KeyEvent event) { 639782dd228e78e9294692d639597f96c26283968bbBjorn Bringert if (event.getAction() == KeyEvent.ACTION_DOWN) { 640fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert int position = getSelectedPosition(); 641fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (onSuggestionKeyDown(position, keyCode, event)) { 6427be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return true; 643782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 644782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 6457be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return forwardKeyToQueryTextView(keyCode, event); 646782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 647782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 648782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 649185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert private class InputMethodCloser implements SuggestionsView.InteractionListener { 650185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert public void onInteraction() { 651185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert hideInputMethod(); 652185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert } 653185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert } 654185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 655185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert private class ClickHandler implements SuggestionClickListener { 656fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void onSuggestionClicked(int position) { 657fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert launchSuggestion(position); 6583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 660fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public boolean onSuggestionLongClicked(int position) { 661fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return SearchActivity.this.onSuggestionLongClicked(position); 662713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 6633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6657b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert private class SelectionHandler implements SuggestionSelectionListener { 666fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void onSuggestionSelected(int position) { 667fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert SuggestionCursor suggestions = getSuggestions(); 668fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert suggestions.moveTo(position); 669fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String displayQuery = suggestions.getSuggestionDisplayQuery(); 670fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (TextUtils.isEmpty(displayQuery)) { 671fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert restoreUserQuery(); 672fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } else { 673fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert setQuery(displayQuery, false); 674fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 675fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 676fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 677fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void onNothingSelected() { 678fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // This happens when a suggestion has been selected with the 679fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // dpad / trackball and then a different UI element is touched. 680fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Do nothing, since we want to keep the query of the selection 681fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // in the search box. 6827b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 6837b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 6847b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 6853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 6862617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert * Listens for clicks on the source selector. 6873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 6883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class SearchGoButtonClickListener implements View.OnClickListener { 6893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onClick(View view) { 690ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert onSearchClicked(Logger.SEARCH_METHOD_BUTTON); 6913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 6952617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert * Listens for clicks on the search button. 6962617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert */ 697fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private class CorpusIndicatorClickListener implements View.OnClickListener { 6982617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert public void onClick(View view) { 6992617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert showSourceSelectorDialog(); 7002617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 7012617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 7022617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 7032617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert /** 7043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Listens for clicks on the voice search button. 7053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 7063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class VoiceSearchButtonClickListener implements View.OnClickListener { 7073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onClick(View view) { 7083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert onVoiceSearchClicked(); 7093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 7123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 7133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Updates the progress bar when the suggestions adapter changes its progress. 7143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 7153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class ProgressUpdater extends DataSetObserver { 7163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private final Suggestions mSuggestions; 7173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 7183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public ProgressUpdater(Suggestions suggestions) { 7193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSuggestions = suggestions; 7203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 7223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 7233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onChanged() { 7243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (mSuggestions.isDone()) { 7253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert stopSearchProgress(); 7263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 729713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 7303d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney private static String ltrim(String text) { 7313d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney int start = 0; 7323d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney int length = text.length(); 7333d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney while (start < length && Character.isWhitespace(text.charAt(start))) { 7343d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney start++; 7353d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney } 7363d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney return start > 0 ? text.substring(start, length) : text; 7373d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney } 7383d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney 7393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert} 740