SearchActivity.java revision c29c9f854db8fa0c85f17cc32bae33dc17c6b127
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; 20c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringertimport com.android.quicksearchbox.ui.CorpusViewFactory; 21185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionClickListener; 227b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionSelectionListener; 23185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionsAdapter; 24883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringertimport com.android.quicksearchbox.ui.SuggestionsFooter; 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; 44883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringertimport android.view.ViewGroup; 453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.View.OnFocusChangeListener; 463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.inputmethod.InputMethodManager; 473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.widget.EditText; 483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.widget.ImageButton; 493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 50ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringertimport java.util.ArrayList; 51ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert/** 533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * The main activity for Quick Search Box. Shows the search UI. 543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertpublic class SearchActivity extends Activity { 573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private static final boolean DBG = true; 590484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert private static final String TAG = "QSB.SearchActivity"; 603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 61fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private static final String SCHEME_CORPUS = "qsb.corpus"; 62fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 63fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public static final String INTENT_ACTION_QSB_AND_SELECT_CORPUS 64fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert = "com.android.quicksearchbox.action.QSB_AND_SELECT_CORPUS"; 653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 66c15f386b167efb3f7559f2f7ee362497040b7fe6Bjorn Bringert // The string used for privateImeOptions to identify to the IME that it should not show 67c15f386b167efb3f7559f2f7ee362497040b7fe6Bjorn Bringert // a microphone button since one already exists in the search dialog. 68c15f386b167efb3f7559f2f7ee362497040b7fe6Bjorn Bringert // TODO: This should move to android-common or something. 69c15f386b167efb3f7559f2f7ee362497040b7fe6Bjorn Bringert private static final String IME_OPTION_NO_MICROPHONE = "nm"; 70c15f386b167efb3f7559f2f7ee362497040b7fe6Bjorn Bringert 719ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Keys for the saved instance state. 72fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private static final String INSTANCE_KEY_CORPUS = "corpus"; 739ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert private static final String INSTANCE_KEY_USER_QUERY = "query"; 74713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 752617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert // Dialog IDs 76fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private static final int CORPUS_SELECTION_DIALOG = 0; 772617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 78ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // Timestamp for last onCreate()/onNewIntent() call, as returned by SystemClock.uptimeMillis(). 79ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private long mStartTime; 80ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // Whether QSB is starting. True between the calls to onCreate()/onNewIntent() and onResume(). 81ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private boolean mStarting; 82ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // True if the user has taken some action, e.g. launching a search, voice search, 83ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // or suggestions, since QSB was last started. 84ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private boolean mTookAction; 85ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 86185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert protected SuggestionsAdapter mSuggestionsAdapter; 87185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected EditText mQueryTextView; 89e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert // True if the query was empty on the previous call to updateQuery() 90e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert protected boolean mQueryWasEmpty = true; 913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected SuggestionsView mSuggestionsView; 93883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert protected SuggestionsFooter mSuggestionsFooter; 943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected ImageButton mSearchGoButton; 963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected ImageButton mVoiceSearchButton; 97a576b1abd602c08dcf0d470facc43fac0243b07cBjorn Bringert protected ImageButton mCorpusIndicator; 983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private Launcher mLauncher; 1003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 101fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpus mCorpus; 1022617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert private Bundle mAppSearchData; 103713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private boolean mUpdateSuggestions; 104713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private String mUserQuery; 105713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private boolean mSelectAll; 1063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** Called when the activity is first created. */ 1083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 1093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onCreate(Bundle savedInstanceState) { 110ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert recordStartTime(); 1113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "onCreate()"); 1123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onCreate(savedInstanceState); 113713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 114e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert setContentView(R.layout.search_activity); 1153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 116816804b67619af133860a1e28e92f58bc642260dBjorn Bringert mSuggestionsAdapter = getQsbApplication().createSuggestionsAdapter(); 117185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 1183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mQueryTextView = (EditText) findViewById(R.id.search_src_text); 1193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSuggestionsView = (SuggestionsView) findViewById(R.id.suggestions); 120782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mSuggestionsView.setSuggestionClickListener(new ClickHandler()); 1217b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mSuggestionsView.setSuggestionSelectionListener(new SelectionHandler()); 122782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mSuggestionsView.setInteractionListener(new InputMethodCloser()); 123713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert mSuggestionsView.setOnKeyListener(new SuggestionsViewKeyListener()); 1247b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mSuggestionsView.setOnFocusChangeListener(new SuggestListFocusListener()); 1253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 126883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert mSuggestionsFooter = getQsbApplication().createSuggestionsFooter(); 127dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert ViewGroup footerFrame = (ViewGroup) findViewById(R.id.footer); 128dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert mSuggestionsFooter.addToContainer(footerFrame); 129883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert 1303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSearchGoButton = (ImageButton) findViewById(R.id.search_go_btn); 1313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mVoiceSearchButton = (ImageButton) findViewById(R.id.search_voice_btn); 132a576b1abd602c08dcf0d470facc43fac0243b07cBjorn Bringert mCorpusIndicator = (ImageButton) findViewById(R.id.corpus_indicator); 1333e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1349ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mLauncher = new Launcher(this); 1353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 136782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mQueryTextView.addTextChangedListener(new SearchTextWatcher()); 137782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mQueryTextView.setOnKeyListener(new QueryTextViewKeyListener()); 1387b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mQueryTextView.setOnFocusChangeListener(new QueryTextViewFocusListener()); 139782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 140fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpusIndicator.setOnClickListener(new CorpusIndicatorClickListener()); 1412617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 142782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mSearchGoButton.setOnClickListener(new SearchGoButtonClickListener()); 143782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 144782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mVoiceSearchButton.setOnClickListener(new VoiceSearchButtonClickListener()); 1457be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert 1467be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert ButtonsKeyListener buttonsKeyListener = new ButtonsKeyListener(); 1477be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert mSearchGoButton.setOnKeyListener(buttonsKeyListener); 1487be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert mVoiceSearchButton.setOnKeyListener(buttonsKeyListener); 149fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpusIndicator.setOnKeyListener(buttonsKeyListener); 150713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 1519ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mUpdateSuggestions = true; 1529ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 1539ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // First get setup from intent 1549ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert Intent intent = getIntent(); 1559ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setupFromIntent(intent); 1569ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Then restore any saved instance state 1579ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert restoreInstanceState(savedInstanceState); 1589ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 159713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert // Do this at the end, to avoid updating the list view when setSource() 160713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert // is called. 161713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert mSuggestionsView.setAdapter(mSuggestionsAdapter); 162dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert mSuggestionsFooter.setAdapter(mSuggestionsAdapter); 1639ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 164713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 1659ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert @Override 1669ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void onNewIntent(Intent intent) { 167ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert recordStartTime(); 1689ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setIntent(intent); 1699ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setupFromIntent(intent); 1709ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 1719ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 172ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private void recordStartTime() { 173ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mStartTime = SystemClock.uptimeMillis(); 174ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mStarting = true; 175ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = false; 176ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 177ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 1789ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void restoreInstanceState(Bundle savedInstanceState) { 1799ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (savedInstanceState == null) return; 180fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String corpusName = savedInstanceState.getString(INSTANCE_KEY_CORPUS); 1819ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert String query = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY); 182fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert setCorpus(getCorpus(corpusName)); 1839ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setUserQuery(query); 184713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 185713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 186713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert @Override 1879ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void onSaveInstanceState(Bundle outState) { 1889ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert super.onSaveInstanceState(outState); 1899ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // We don't save appSearchData, since we always get the value 1909ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // from the intent and the user can't change it. 191fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 192fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String corpusName = mCorpus == null ? null : mCorpus.getName(); 193fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert outState.putString(INSTANCE_KEY_CORPUS, corpusName); 1949ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert outState.putString(INSTANCE_KEY_USER_QUERY, mUserQuery); 195713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 196713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 197713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private void setupFromIntent(Intent intent) { 198713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert if (DBG) Log.d(TAG, "setupFromIntent(" + intent.toUri(0) + ")"); 199fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Corpus corpus = getCorpusFromUri(intent.getData()); 2002617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert String query = intent.getStringExtra(SearchManager.QUERY); 2012617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert Bundle appSearchData = intent.getBundleExtra(SearchManager.APP_DATA); 2022617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 203fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert setCorpus(corpus); 2042617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert setUserQuery(query); 205154017089860da89ec020ed37e502d194253cc67Bjorn Bringert mSelectAll = intent.getBooleanExtra(SearchManager.EXTRA_SELECT_QUERY, false); 206c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert mAppSearchData = appSearchData; 2072617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 208fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (INTENT_ACTION_QSB_AND_SELECT_CORPUS.equals(intent.getAction())) { 20941fe9d1fc461c42907250d44d3537909e4c46a7dBjorn Bringert showCorpusSelectionDialog(); 2102617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 2119ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 2129ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 213fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public static Uri getCorpusUri(Corpus corpus) { 214fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (corpus == null) return null; 215fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return new Uri.Builder() 216fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert .scheme(SCHEME_CORPUS) 217fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert .authority(corpus.getName()) 218fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert .build(); 219fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 220fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 221fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpus getCorpusFromUri(Uri uri) { 222fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (uri == null) return null; 223fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (!SCHEME_CORPUS.equals(uri.getScheme())) return null; 224fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String name = uri.getAuthority(); 225fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getCorpus(name); 226fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 227fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 228fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpus getCorpus(String sourceName) { 2290ccab5903ba2c64ec4cdd33dbcea91b1e279d556Bjorn Bringert if (sourceName == null) return null; 230fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Corpus corpus = getCorpora().getCorpus(sourceName); 231fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (corpus == null) { 232fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Log.w(TAG, "Unknown corpus " + sourceName); 2339ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert return null; 234713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 235fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return corpus; 236713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 237713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 238fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private void setCorpus(Corpus corpus) { 239fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (DBG) Log.d(TAG, "setCorpus(" + corpus + ")"); 240fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpus = corpus; 2419ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert Drawable sourceIcon; 242fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (corpus == null) { 243c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert sourceIcon = getCorpusViewFactory().getGlobalSearchIcon(); 244713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } else { 245fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert sourceIcon = corpus.getCorpusIcon(); 246713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 247fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mSuggestionsAdapter.setCorpus(corpus); 248a576b1abd602c08dcf0d470facc43fac0243b07cBjorn Bringert mCorpusIndicator.setImageDrawable(sourceIcon); 2493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 250e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert updateVoiceSearchButton(getQuery().length() == 0); 2510484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert } 2520484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert 2533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private QsbApplication getQsbApplication() { 2543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return (QsbApplication) getApplication(); 2553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 257fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpora getCorpora() { 258fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getQsbApplication().getCorpora(); 259fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 260fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 261fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private CorpusRanker getCorpusRanker() { 262fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getQsbApplication().getCorpusRanker(); 263713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 264713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 2653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private ShortcutRepository getShortcutRepository() { 2663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return getQsbApplication().getShortcutRepository(); 2673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 269ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private SuggestionsProvider getSuggestionsProvider() { 270fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getQsbApplication().getSuggestionsProvider(mCorpus); 2713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 273c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert private CorpusViewFactory getCorpusViewFactory() { 274c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert return getQsbApplication().getCorpusViewFactory(); 275185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert } 276185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 277ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private Logger getLogger() { 278ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert return getQsbApplication().getLogger(); 279ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 280ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 2813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 2823e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onDestroy() { 2833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "onDestroy()"); 2843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onDestroy(); 285dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert mSuggestionsFooter.setAdapter(null); 286185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert mSuggestionsView.setAdapter(null); // closes mSuggestionsAdapter 2873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 2893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 2903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onStop() { 2919ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (DBG) Log.d(TAG, "onStop()"); 2929ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Close all open suggestion cursors. The query will be redone in onResume() 2933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // if we come back to this activity. 294185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert mSuggestionsAdapter.setSuggestions(null); 29594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney getQsbApplication().getShortcutRefresher().reset(); 2963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onStop(); 2973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 2993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 300b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert protected void onResume() { 3019ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (DBG) Log.d(TAG, "onResume()"); 302b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert super.onResume(); 3039ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setQuery(mUserQuery, mSelectAll); 3049ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Only select everything the first time after creating the activity. 3059ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mSelectAll = false; 3069ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert updateSuggestions(mUserQuery); 307b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert mQueryTextView.requestFocus(); 308ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert if (mStarting) { 309ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mStarting = false; 310ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // Start up latency should not exceed 2^31 ms (~ 25 days). Note that 311ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // SystemClock.uptimeMillis() does not advance during deep sleep. 312ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert int latency = (int) (SystemClock.uptimeMillis() - mStartTime); 3133f71a11f8858b9164ca83e8d2f558dd8a8a5e2deBjorn Bringert String source = getIntent().getStringExtra(Search.SOURCE); 314fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getLogger().logStart(latency, source, mCorpus, 315fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getSuggestionsProvider().getOrderedCorpora()); 316ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 317b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert } 318b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert 319b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert @Override 3203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean onCreateOptionsMenu(Menu menu) { 3213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onCreateOptionsMenu(menu); 32226d85260316193a1aeff5d407d4f32f5297be012Bjorn Bringert SearchSettings.addSearchSettingsMenuItem(this, menu); 3233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return true; 3243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3269ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert /** 3279ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert * Sets the query as typed by the user. Does not update the suggestions 3289ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert * or the text in the query box. 3299ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert */ 3309ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void setUserQuery(String userQuery) { 3319ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (userQuery == null) userQuery = ""; 3329ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mUserQuery = userQuery; 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 376e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert private void updateQueryTextView(boolean queryEmpty) { 377e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert if (queryEmpty) { 378e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setBackgroundResource(R.drawable.textfield_search_empty); 379e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setCompoundDrawablesWithIntrinsicBounds( 380e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert R.drawable.placeholder_google, 0, 0, 0); 381e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setCursorVisible(false); 382e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } else { 383e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setBackgroundResource(R.drawable.textfield_search); 384e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); 385e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setCursorVisible(true); 386e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 387e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 388e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert 389e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert private void updateSearchGoButton(boolean queryEmpty) { 390e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert if (queryEmpty) { 391e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mSearchGoButton.setVisibility(View.GONE); 392e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } else { 393e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mSearchGoButton.setVisibility(View.VISIBLE); 394e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 395e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 396e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert 397e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert protected void updateVoiceSearchButton(boolean queryEmpty) { 398c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert if (queryEmpty && mLauncher.shouldShowVoiceSearch(mCorpus)) { 399e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mVoiceSearchButton.setVisibility(View.VISIBLE); 400e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE); 401e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } else { 402e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mVoiceSearchButton.setVisibility(View.GONE); 403e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setPrivateImeOptions(null); 404e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 405e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 406e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert 40741fe9d1fc461c42907250d44d3537909e4c46a7dBjorn Bringert protected void showCorpusSelectionDialog() { 408fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert showDialog(CORPUS_SELECTION_DIALOG); 4092617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4102617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 41141fe9d1fc461c42907250d44d3537909e4c46a7dBjorn Bringert protected void dismissCorpusSelectionDialog() { 41241fe9d1fc461c42907250d44d3537909e4c46a7dBjorn Bringert dismissDialog(CORPUS_SELECTION_DIALOG); 41341fe9d1fc461c42907250d44d3537909e4c46a7dBjorn Bringert } 4142617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 4152617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert @Override 4162617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert protected Dialog onCreateDialog(int id, Bundle args) { 4172617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert switch (id) { 418fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert case CORPUS_SELECTION_DIALOG: 419fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return createCorpusSelectionDialog(); 4202617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert default: 4212617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert throw new IllegalArgumentException("Unknown dialog: " + id); 4222617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4232617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4242617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 4252617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert @Override 4262617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert protected void onPrepareDialog(int id, Dialog dialog, Bundle args) { 427c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert super.onPrepareDialog(id, dialog, args); 4282617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert switch (id) { 429fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert case CORPUS_SELECTION_DIALOG: 430fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert prepareCorpusSelectionDialog((CorpusSelectionDialog) dialog); 4312617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert break; 4322617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert default: 4332617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert throw new IllegalArgumentException("Unknown dialog: " + id); 4342617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4352617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4362617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 437fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected CorpusSelectionDialog createCorpusSelectionDialog() { 438c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert return new CorpusSelectionDialog(this); 4392617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4402617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 441fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected void prepareCorpusSelectionDialog(CorpusSelectionDialog dialog) { 442fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert dialog.setCorpus(mCorpus); 4432617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert dialog.setQuery(getQuery()); 4442617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert dialog.setAppData(mAppSearchData); 4452617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4462617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 447ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert protected void onSearchClicked(int method) { 4483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String query = getQuery(); 4493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "Search clicked, query=" + query); 450c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert Corpus searchCorpus = getSearchCorpus(); 451c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert if (searchCorpus == null) return; 452c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 453ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = true; 454c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 455c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Log search start 456fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getLogger().logSearch(mCorpus, method, query.length()); 457c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 458c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Create shortcut 459c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert SuggestionData searchShortcut = searchCorpus.createSearchShortcut(query); 460c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert if (searchShortcut != null) { 461c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert DataSuggestionCursor cursor = new DataSuggestionCursor(query); 462c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert cursor.add(searchShortcut); 463c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert getShortcutRepository().reportClick(cursor, 0); 464c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert } 465c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 466c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Start search 467c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert Intent intent = searchCorpus.createSearchIntent(query, mAppSearchData); 468c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert mLauncher.launchIntent(intent); 4693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onVoiceSearchClicked() { 4723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "Voice Search clicked"); 473ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = true; 474c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert Corpus searchCorpus = getSearchCorpus(); 475c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert if (searchCorpus == null) return; 476c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 477c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Log voice search start 478c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert getLogger().logVoiceSearch(searchCorpus); 479ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 480c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Start voice search 481c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert Intent intent = searchCorpus.createVoiceSearchIntent(mAppSearchData); 482c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert mLauncher.launchIntent(intent); 483c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert } 484c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 485c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert /** 486c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert * Gets the corpus to use for any searches. This is the web corpus in "All" mode, 487c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert * and the selected corpus otherwise. 488c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert */ 489c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert protected Corpus getSearchCorpus() { 490c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert if (mCorpus != null) { 491c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert return mCorpus; 492c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert } else { 493c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert Corpus corpus = getCorpora().getWebCorpus(); 494c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert if (corpus == null) { 495c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert Log.e(TAG, "No web corpus"); 496c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert } 497c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert return corpus; 498c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert } 4993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 501fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected SuggestionCursor getSuggestions() { 502fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mSuggestionsAdapter.getCurrentSuggestions(); 503782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 504782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 505fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected boolean launchSuggestion(int position) { 506fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (DBG) Log.d(TAG, "Launching suggestion " + position); 507ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = true; 508fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert SuggestionCursor suggestions = getSuggestions(); 509c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 510c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Log suggestion click 511ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // TODO: This should be just the queried sources, but currently 512ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // all sources are queried 513fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert ArrayList<Corpus> corpora = getCorpusRanker().rankCorpora(getCorpora().getEnabledCorpora()); 514fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getLogger().logSuggestionClick(position, suggestions, corpora); 515ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 516c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Create shortcut 517fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getShortcutRepository().reportClick(suggestions, position); 518c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 519c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Launch intent 520c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert Intent intent = mLauncher.getSuggestionIntent(suggestions, position, mAppSearchData); 521c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert mLauncher.launchIntent(intent); 522c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 5233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return true; 5243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 526fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected boolean onSuggestionLongClicked(int position) { 527fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (DBG) Log.d(TAG, "Long clicked on suggestion " + position); 5283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return false; 5293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 531fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected boolean onSuggestionKeyDown(int position, int keyCode, KeyEvent event) { 532782dd228e78e9294692d639597f96c26283968bbBjorn Bringert // Treat enter or search as a click 533782dd228e78e9294692d639597f96c26283968bbBjorn Bringert if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH) { 534fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return launchSuggestion(position); 535782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 536782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 5377b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (keyCode == KeyEvent.KEYCODE_DPAD_UP 5387b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert && mSuggestionsView.getSelectedItemPosition() == 0) { 5397b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // Moved up from the top suggestion, restore the user query and focus query box 5407b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Up and out"); 5417b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert restoreUserQuery(); 5427b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert return false; // let the framework handle the move 5437b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5447b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 5457b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT 5467b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { 5477b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // Moved left / right from a suggestion, keep current query, move 5487b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // focus to query box, and move cursor to far left / right 5497b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Left/right on a suggestion"); 5507b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert int cursorPos = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mQueryTextView.length(); 5517b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mQueryTextView.setSelection(cursorPos); 5527b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mQueryTextView.requestFocus(); 5537b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // TODO: should we modify the list selection? 5547b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert return true; 5557b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5567b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 557782dd228e78e9294692d639597f96c26283968bbBjorn Bringert return false; 558782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 559782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 5603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onSourceSelected() { 5613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "No suggestion selected"); 5623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert restoreUserQuery(); 5633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 565782dd228e78e9294692d639597f96c26283968bbBjorn Bringert protected int getSelectedPosition() { 566782dd228e78e9294692d639597f96c26283968bbBjorn Bringert return mSuggestionsView.getSelectedPosition(); 567782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 568782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 5693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 5703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Hides the input method. 5713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 5723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void hideInputMethod() { 5733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 5743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (imm != null) { 5753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert imm.hideSoftInputFromWindow(mQueryTextView.getWindowToken(), 0); 5763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5773e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5783e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 5797b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert protected void showInputMethodForQuery() { 5807b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 5817b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (imm != null) { 5827b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert imm.showSoftInput(mQueryTextView, 0); 5837b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5847b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5857b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 5863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 5873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Hides the input method when the suggestions get focus. 5883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 5893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class SuggestListFocusListener implements OnFocusChangeListener { 5903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onFocusChange(View v, boolean focused) { 5917b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Suggestions focus change, now: " + focused); 5927b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (focused) { 5937b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // The suggestions list got focus, hide the input method 5947b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert hideInputMethod(); 5957b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5967b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5977b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5987b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 5997b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert private class QueryTextViewFocusListener implements OnFocusChangeListener { 6007b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert public void onFocusChange(View v, boolean focused) { 6017b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Query focus change, now: " + focused); 6027b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (focused) { 6037b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // The query box got focus, show the input method if the 6047b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // query box got focus? 6057b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert showInputMethodForQuery(); 6063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void startSearchProgress() { 611e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert // TODO: Do we need a progress indicator? 6123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void stopSearchProgress() { 615d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney Drawable animation = mSearchGoButton.getDrawable(); 616d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney if (animation instanceof Animatable) { 617d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney // TODO: Is this needed, or is it done automatically when the 618d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney // animation is removed? 619d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney ((Animatable) animation).stop(); 620d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney } 6213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSearchGoButton.setImageResource(R.drawable.ic_btn_search); 6223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void updateSuggestions(String query) { 6253d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney query = ltrim(query); 6263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert LatencyTracker latency = new LatencyTracker(TAG); 627ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert Suggestions suggestions = getSuggestionsProvider().getSuggestions(query); 6283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert latency.addEvent("getSuggestions_done"); 6293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (!suggestions.isDone()) { 6303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert suggestions.registerDataSetObserver(new ProgressUpdater(suggestions)); 6313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert startSearchProgress(); 632d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney } else { 633d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinney stopSearchProgress(); 6343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 635185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert mSuggestionsAdapter.setSuggestions(suggestions); 6363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert latency.addEvent("shortcuts_shown"); 6373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert long userVisibleLatency = latency.getUserVisibleLatency(); 6383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) { 6393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Log.d(TAG, "User visible latency (shortcuts): " + userVisibleLatency + " ms."); 6403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6437be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert private boolean forwardKeyToQueryTextView(int keyCode, KeyEvent event) { 6447be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert if (!event.isSystem() && !isDpadKey(keyCode)) { 6457be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert if (DBG) Log.d(TAG, "Forwarding key to query box: " + event); 6467be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert if (mQueryTextView.requestFocus()) { 6477be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return mQueryTextView.dispatchKeyEvent(event); 6487be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 6497be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 6507be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return false; 6517be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 6527be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert 6537be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert private boolean isDpadKey(int keyCode) { 6547be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert switch (keyCode) { 6557be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_UP: 6567be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_DOWN: 6577be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_LEFT: 6587be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_RIGHT: 6597be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_CENTER: 6607be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return true; 6617be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert default: 6627be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return false; 6637be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 6647be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 6657be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert 6663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 6673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Filters the suggestions list when the search text changes. 6683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 6693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class SearchTextWatcher implements TextWatcher { 6703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void afterTextChanged(Editable s) { 671e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert boolean empty = s.length() == 0; 672e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert if (empty != mQueryWasEmpty) { 673e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryWasEmpty = empty; 674e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert updateQueryTextView(empty); 675e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert updateSearchGoButton(empty); 676e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert updateVoiceSearchButton(empty); 677e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 6783e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (mUpdateSuggestions) { 6793e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String query = s == null ? "" : s.toString(); 6809ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setUserQuery(query); 6813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert updateSuggestions(query); 6823e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void beforeTextChanged(CharSequence s, int start, int count, int after) { 6863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onTextChanged(CharSequence s, int start, int before, int count) { 6893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 6933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Handles non-text keys in the query text view. 6943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 6953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class QueryTextViewKeyListener implements View.OnKeyListener { 6963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean onKey(View view, int keyCode, KeyEvent event) { 6973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Handle IME search action key 6983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) { 699ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert onSearchClicked(Logger.SEARCH_METHOD_KEYBOARD); 7003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7013e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return false; 7023e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 705782dd228e78e9294692d639597f96c26283968bbBjorn Bringert /** 706782dd228e78e9294692d639597f96c26283968bbBjorn Bringert * Handles key events on the search and voice search buttons, 707782dd228e78e9294692d639597f96c26283968bbBjorn Bringert * by refocusing to EditText. 708782dd228e78e9294692d639597f96c26283968bbBjorn Bringert */ 709782dd228e78e9294692d639597f96c26283968bbBjorn Bringert private class ButtonsKeyListener implements View.OnKeyListener { 710782dd228e78e9294692d639597f96c26283968bbBjorn Bringert public boolean onKey(View v, int keyCode, KeyEvent event) { 7117be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return forwardKeyToQueryTextView(keyCode, event); 712782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 713782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 714782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 715782dd228e78e9294692d639597f96c26283968bbBjorn Bringert /** 716782dd228e78e9294692d639597f96c26283968bbBjorn Bringert * Handles key events on the suggestions list view. 717782dd228e78e9294692d639597f96c26283968bbBjorn Bringert */ 718713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private class SuggestionsViewKeyListener implements View.OnKeyListener { 719782dd228e78e9294692d639597f96c26283968bbBjorn Bringert public boolean onKey(View v, int keyCode, KeyEvent event) { 720782dd228e78e9294692d639597f96c26283968bbBjorn Bringert if (event.getAction() == KeyEvent.ACTION_DOWN) { 721fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert int position = getSelectedPosition(); 722fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (onSuggestionKeyDown(position, keyCode, event)) { 7237be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return true; 724782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 725782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 7267be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return forwardKeyToQueryTextView(keyCode, event); 727782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 728782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 729782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 730185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert private class InputMethodCloser implements SuggestionsView.InteractionListener { 731185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert public void onInteraction() { 732185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert hideInputMethod(); 733185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert } 734185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert } 735185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 736185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert private class ClickHandler implements SuggestionClickListener { 737fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void onSuggestionClicked(int position) { 738fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert launchSuggestion(position); 7393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 741fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public boolean onSuggestionLongClicked(int position) { 742fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return SearchActivity.this.onSuggestionLongClicked(position); 743713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 7443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 7467b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert private class SelectionHandler implements SuggestionSelectionListener { 747fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void onSuggestionSelected(int position) { 748fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert SuggestionCursor suggestions = getSuggestions(); 749fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert suggestions.moveTo(position); 750fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String displayQuery = suggestions.getSuggestionDisplayQuery(); 751fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (TextUtils.isEmpty(displayQuery)) { 752fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert restoreUserQuery(); 753fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } else { 754fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert setQuery(displayQuery, false); 755fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 756fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 757fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 758fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void onNothingSelected() { 759fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // This happens when a suggestion has been selected with the 760fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // dpad / trackball and then a different UI element is touched. 761fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Do nothing, since we want to keep the query of the selection 762fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // in the search box. 7637b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 7647b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 7657b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 7663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 7672617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert * Listens for clicks on the source selector. 7683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 7693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class SearchGoButtonClickListener implements View.OnClickListener { 7703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onClick(View view) { 771ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert onSearchClicked(Logger.SEARCH_METHOD_BUTTON); 7723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 7753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 7762617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert * Listens for clicks on the search button. 7772617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert */ 778fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private class CorpusIndicatorClickListener implements View.OnClickListener { 7792617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert public void onClick(View view) { 78041fe9d1fc461c42907250d44d3537909e4c46a7dBjorn Bringert showCorpusSelectionDialog(); 7812617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 7822617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 7832617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 7842617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert /** 7853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Listens for clicks on the voice search button. 7863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 7873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class VoiceSearchButtonClickListener implements View.OnClickListener { 7883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onClick(View view) { 7893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert onVoiceSearchClicked(); 7903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 7933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 7943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Updates the progress bar when the suggestions adapter changes its progress. 7953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 7963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class ProgressUpdater extends DataSetObserver { 7973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private final Suggestions mSuggestions; 7983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 7993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public ProgressUpdater(Suggestions suggestions) { 8003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSuggestions = suggestions; 8013e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 8023e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 8033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 8043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onChanged() { 8053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (mSuggestions.isDone()) { 8063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert stopSearchProgress(); 8073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 8083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 8093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 810713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 8113d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney private static String ltrim(String text) { 8123d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney int start = 0; 8133d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney int length = text.length(); 8143d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney while (start < length && Character.isWhitespace(text.charAt(start))) { 8153d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney start++; 8163d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney } 8173d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney return start > 0 ? text.substring(start, length) : text; 8183d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney } 8193d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney 8203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert} 821