SearchActivity.java revision 4ef1338a23b040df2ef180c48ff85e14a9d70906
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; 283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.app.SearchManager; 293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.content.Intent; 30d7a95801d20a9405b4ab9c9b4beecd106e880166Bryan Mawhinneyimport android.graphics.drawable.Drawable; 31fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.net.Uri; 323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.os.Bundle; 334ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringertimport android.os.Handler; 343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.text.Editable; 353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.text.TextUtils; 363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.text.TextWatcher; 373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.util.Log; 383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.KeyEvent; 393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.Menu; 403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.View; 41883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringertimport android.view.ViewGroup; 423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.View.OnFocusChangeListener; 433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.inputmethod.InputMethodManager; 443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.widget.EditText; 453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.widget.ImageButton; 463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 47e06b7cbf55301a24cfd7525a91107e3cd2c9f48eBjorn Bringertimport java.util.Collection; 4847d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringertimport java.util.Collections; 4947d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringertimport java.util.List; 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 65c15f386b167efb3f7559f2f7ee362497040b7fe6Bjorn Bringert // The string used for privateImeOptions to identify to the IME that it should not show 66c15f386b167efb3f7559f2f7ee362497040b7fe6Bjorn Bringert // a microphone button since one already exists in the search dialog. 67c15f386b167efb3f7559f2f7ee362497040b7fe6Bjorn Bringert // TODO: This should move to android-common or something. 68c15f386b167efb3f7559f2f7ee362497040b7fe6Bjorn Bringert private static final String IME_OPTION_NO_MICROPHONE = "nm"; 69c15f386b167efb3f7559f2f7ee362497040b7fe6Bjorn Bringert 709ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Keys for the saved instance state. 71fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private static final String INSTANCE_KEY_CORPUS = "corpus"; 729ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert private static final String INSTANCE_KEY_USER_QUERY = "query"; 73713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 74f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert // Measures time from for last onCreate()/onNewIntent() call. 75f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert private LatencyTracker mStartLatencyTracker; 76ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // Whether QSB is starting. True between the calls to onCreate()/onNewIntent() and onResume(). 77ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private boolean mStarting; 78ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // True if the user has taken some action, e.g. launching a search, voice search, 79ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // or suggestions, since QSB was last started. 80ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private boolean mTookAction; 81ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 82f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert private CorpusSelectionDialog mCorpusSelectionDialog; 83f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert 84185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert protected SuggestionsAdapter mSuggestionsAdapter; 85185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected EditText mQueryTextView; 87e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert // True if the query was empty on the previous call to updateQuery() 88e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert protected boolean mQueryWasEmpty = true; 893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected SuggestionsView mSuggestionsView; 91883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert protected SuggestionsFooter mSuggestionsFooter; 923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected ImageButton mSearchGoButton; 943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected ImageButton mVoiceSearchButton; 95a576b1abd602c08dcf0d470facc43fac0243b07cBjorn Bringert protected ImageButton mCorpusIndicator; 963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private Launcher mLauncher; 983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 99fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpus mCorpus; 1002617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert private Bundle mAppSearchData; 101713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private boolean mUpdateSuggestions; 102713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private String mUserQuery; 103713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private boolean mSelectAll; 1043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1054ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert private Handler mUpdateSuggestionsHandler = new Handler(); 1064ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert private Runnable mUpdateSuggestionsTask = new Runnable() { 1074ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert public void run() { 1084ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert updateSuggestions(getQuery()); 1094ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert } 1104ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert }; 1114ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert 1123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** Called when the activity is first created. */ 1133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 1143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onCreate(Bundle savedInstanceState) { 115ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert recordStartTime(); 1163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "onCreate()"); 1173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onCreate(savedInstanceState); 118713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 119e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert setContentView(R.layout.search_activity); 1203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 121816804b67619af133860a1e28e92f58bc642260dBjorn Bringert mSuggestionsAdapter = getQsbApplication().createSuggestionsAdapter(); 122185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 1233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mQueryTextView = (EditText) findViewById(R.id.search_src_text); 1243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSuggestionsView = (SuggestionsView) findViewById(R.id.suggestions); 125782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mSuggestionsView.setSuggestionClickListener(new ClickHandler()); 1267b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mSuggestionsView.setSuggestionSelectionListener(new SelectionHandler()); 127782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mSuggestionsView.setInteractionListener(new InputMethodCloser()); 128713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert mSuggestionsView.setOnKeyListener(new SuggestionsViewKeyListener()); 1297b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mSuggestionsView.setOnFocusChangeListener(new SuggestListFocusListener()); 1303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 131883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert mSuggestionsFooter = getQsbApplication().createSuggestionsFooter(); 132dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert ViewGroup footerFrame = (ViewGroup) findViewById(R.id.footer); 133dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert mSuggestionsFooter.addToContainer(footerFrame); 134883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert 1353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSearchGoButton = (ImageButton) findViewById(R.id.search_go_btn); 1363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mVoiceSearchButton = (ImageButton) findViewById(R.id.search_voice_btn); 137a576b1abd602c08dcf0d470facc43fac0243b07cBjorn Bringert mCorpusIndicator = (ImageButton) findViewById(R.id.corpus_indicator); 1383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1399ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mLauncher = new Launcher(this); 1403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 141782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mQueryTextView.addTextChangedListener(new SearchTextWatcher()); 142782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mQueryTextView.setOnKeyListener(new QueryTextViewKeyListener()); 1437b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mQueryTextView.setOnFocusChangeListener(new QueryTextViewFocusListener()); 144782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 145fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpusIndicator.setOnClickListener(new CorpusIndicatorClickListener()); 1462617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 147782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mSearchGoButton.setOnClickListener(new SearchGoButtonClickListener()); 148782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 149782dd228e78e9294692d639597f96c26283968bbBjorn Bringert mVoiceSearchButton.setOnClickListener(new VoiceSearchButtonClickListener()); 1507be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert 1517be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert ButtonsKeyListener buttonsKeyListener = new ButtonsKeyListener(); 1527be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert mSearchGoButton.setOnKeyListener(buttonsKeyListener); 1537be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert mVoiceSearchButton.setOnKeyListener(buttonsKeyListener); 154fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpusIndicator.setOnKeyListener(buttonsKeyListener); 155713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 1569ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mUpdateSuggestions = true; 1579ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 1589ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // First get setup from intent 1599ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert Intent intent = getIntent(); 1609ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setupFromIntent(intent); 1619ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Then restore any saved instance state 1629ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert restoreInstanceState(savedInstanceState); 1639ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 164713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert // Do this at the end, to avoid updating the list view when setSource() 165713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert // is called. 166713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert mSuggestionsView.setAdapter(mSuggestionsAdapter); 167dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert mSuggestionsFooter.setAdapter(mSuggestionsAdapter); 1689ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 169713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 1709ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert @Override 1719ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void onNewIntent(Intent intent) { 172ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert recordStartTime(); 1739ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setIntent(intent); 1749ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setupFromIntent(intent); 1759ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 1769ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 177ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private void recordStartTime() { 178f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert mStartLatencyTracker = new LatencyTracker(); 179ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mStarting = true; 180ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = false; 181ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 182ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 1839ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void restoreInstanceState(Bundle savedInstanceState) { 1849ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (savedInstanceState == null) return; 185fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String corpusName = savedInstanceState.getString(INSTANCE_KEY_CORPUS); 1869ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert String query = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY); 187fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert setCorpus(getCorpus(corpusName)); 1889ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setUserQuery(query); 189713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 190713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 191713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert @Override 1929ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void onSaveInstanceState(Bundle outState) { 1939ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert super.onSaveInstanceState(outState); 1949ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // We don't save appSearchData, since we always get the value 1959ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // from the intent and the user can't change it. 196fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 197fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String corpusName = mCorpus == null ? null : mCorpus.getName(); 198fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert outState.putString(INSTANCE_KEY_CORPUS, corpusName); 1999ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert outState.putString(INSTANCE_KEY_USER_QUERY, mUserQuery); 200713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 201713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 202713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private void setupFromIntent(Intent intent) { 203713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert if (DBG) Log.d(TAG, "setupFromIntent(" + intent.toUri(0) + ")"); 204fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Corpus corpus = getCorpusFromUri(intent.getData()); 2052617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert String query = intent.getStringExtra(SearchManager.QUERY); 2062617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert Bundle appSearchData = intent.getBundleExtra(SearchManager.APP_DATA); 2072617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 208fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert setCorpus(corpus); 2092617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert setUserQuery(query); 210154017089860da89ec020ed37e502d194253cc67Bjorn Bringert mSelectAll = intent.getBooleanExtra(SearchManager.EXTRA_SELECT_QUERY, false); 211c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert mAppSearchData = appSearchData; 2122617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 213fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (INTENT_ACTION_QSB_AND_SELECT_CORPUS.equals(intent.getAction())) { 21441fe9d1fc461c42907250d44d3537909e4c46a7dBjorn Bringert showCorpusSelectionDialog(); 2152617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 2169ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 2179ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 218fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public static Uri getCorpusUri(Corpus corpus) { 219fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (corpus == null) return null; 220fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return new Uri.Builder() 221fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert .scheme(SCHEME_CORPUS) 222fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert .authority(corpus.getName()) 223fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert .build(); 224fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 225fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 226fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpus getCorpusFromUri(Uri uri) { 227fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (uri == null) return null; 228fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (!SCHEME_CORPUS.equals(uri.getScheme())) return null; 229fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String name = uri.getAuthority(); 230fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getCorpus(name); 231fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 232fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 233fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpus getCorpus(String sourceName) { 2340ccab5903ba2c64ec4cdd33dbcea91b1e279d556Bjorn Bringert if (sourceName == null) return null; 235fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Corpus corpus = getCorpora().getCorpus(sourceName); 236fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (corpus == null) { 237fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Log.w(TAG, "Unknown corpus " + sourceName); 2389ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert return null; 239713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 240fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return corpus; 241713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 242713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 243fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private void setCorpus(Corpus corpus) { 244fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (DBG) Log.d(TAG, "setCorpus(" + corpus + ")"); 245fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mCorpus = corpus; 2469ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert Drawable sourceIcon; 247fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (corpus == null) { 248c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert sourceIcon = getCorpusViewFactory().getGlobalSearchIcon(); 249713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } else { 250fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert sourceIcon = corpus.getCorpusIcon(); 251713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 252fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mSuggestionsAdapter.setCorpus(corpus); 253a576b1abd602c08dcf0d470facc43fac0243b07cBjorn Bringert mCorpusIndicator.setImageDrawable(sourceIcon); 2543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 2555691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert updateUi(getQuery().length() == 0); 2560484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert } 2570484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert 2583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private QsbApplication getQsbApplication() { 2593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return (QsbApplication) getApplication(); 2603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 2624ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert private Config getConfig() { 2634ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert return getQsbApplication().getConfig(); 2644ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert } 2654ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert 266fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Corpora getCorpora() { 267fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getQsbApplication().getCorpora(); 268fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 269fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 2703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private ShortcutRepository getShortcutRepository() { 2713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return getQsbApplication().getShortcutRepository(); 2723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 274ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private SuggestionsProvider getSuggestionsProvider() { 27547d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert return getQsbApplication().getSuggestionsProvider(); 27647d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert } 27747d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert 27847d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert private CorpusRanker getCorpusRanker() { 27947d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert return getQsbApplication().getCorpusRanker(); 2803e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 282c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert private CorpusViewFactory getCorpusViewFactory() { 283c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert return getQsbApplication().getCorpusViewFactory(); 284185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert } 285185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 286ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private Logger getLogger() { 287ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert return getQsbApplication().getLogger(); 288ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 289ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 2903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 2913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onDestroy() { 2923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "onDestroy()"); 2933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onDestroy(); 294dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert mSuggestionsFooter.setAdapter(null); 295185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert mSuggestionsView.setAdapter(null); // closes mSuggestionsAdapter 2963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 2983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 2993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onStop() { 3009ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (DBG) Log.d(TAG, "onStop()"); 301f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert if (!mTookAction) { 302f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert // TODO: This gets logged when starting other activities, e.g. by opening he search 303f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert // settings, or clicking a notification in the status bar. 304f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert getLogger().logExit(getCurrentSuggestions(), getQuery().length()); 305f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert } 3069ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Close all open suggestion cursors. The query will be redone in onResume() 3073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // if we come back to this activity. 308185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert mSuggestionsAdapter.setSuggestions(null); 30994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney getQsbApplication().getShortcutRefresher().reset(); 310f69873ae02e6d8f8a550f5fa43b5b1f2cbea96ffBjorn Bringert dismissCorpusSelectionDialog(); 3113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onStop(); 3123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 315b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert protected void onResume() { 3169ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (DBG) Log.d(TAG, "onResume()"); 317b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert super.onResume(); 3189ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setQuery(mUserQuery, mSelectAll); 3199ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Only select everything the first time after creating the activity. 3209ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mSelectAll = false; 3219ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert updateSuggestions(mUserQuery); 322b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert mQueryTextView.requestFocus(); 323ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert if (mStarting) { 324ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mStarting = false; 3253f71a11f8858b9164ca83e8d2f558dd8a8a5e2deBjorn Bringert String source = getIntent().getStringExtra(Search.SOURCE); 326f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert List<Corpus> rankedCorpora = getCorpusRanker().getRankedCorpora(); 327f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert int latency = mStartLatencyTracker.getLatency(); 328f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert getLogger().logStart(latency, source, mCorpus, rankedCorpora); 329ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 330b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert } 331b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert 332b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert @Override 3333e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean onCreateOptionsMenu(Menu menu) { 3343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onCreateOptionsMenu(menu); 33526d85260316193a1aeff5d407d4f32f5297be012Bjorn Bringert SearchSettings.addSearchSettingsMenuItem(this, menu); 3363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return true; 3373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3399ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert /** 3409ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert * Sets the query as typed by the user. Does not update the suggestions 3419ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert * or the text in the query box. 3429ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert */ 3439ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void setUserQuery(String userQuery) { 3449ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (userQuery == null) userQuery = ""; 3459ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert mUserQuery = userQuery; 3469ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 3479ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 348713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert protected String getQuery() { 3493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert CharSequence q = mQueryTextView.getText(); 3503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return q == null ? "" : q.toString(); 3513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 3543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Restores the query entered by the user. 3553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 3563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void restoreUserQuery() { 3573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "Restoring query to '" + mUserQuery + "'"); 3583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert setQuery(mUserQuery, false); 3593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 3623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Sets the text in the query box. Does not update the suggestions, 3633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * and does not change the saved user-entered query. 3643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * {@link #restoreUserQuery()} will restore the query to the last 3653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * user-entered query. 3663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 3673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void setQuery(String query, boolean selectAll) { 3683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mUpdateSuggestions = false; 3693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mQueryTextView.setText(query); 3703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert setTextSelection(selectAll); 3713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mUpdateSuggestions = true; 3723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 3753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Sets the text selection in the query text view. 3763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 3773e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * @param selectAll If {@code true}, selects the entire query. 3783e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * If {@false}, no characters are selected, and the cursor is placed 3793e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * at the end of the query. 3803e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 3813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void setTextSelection(boolean selectAll) { 3823e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (selectAll) { 3835691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert mQueryTextView.selectAll(); 3843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } else { 3853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mQueryTextView.setSelection(mQueryTextView.length()); 3863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3895691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert private void updateUi(boolean queryEmpty) { 3905691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert updateQueryTextView(queryEmpty); 3915691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert updateSearchGoButton(queryEmpty); 3925691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert updateVoiceSearchButton(queryEmpty); 3935691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert } 3945691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert 395e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert private void updateQueryTextView(boolean queryEmpty) { 396e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert if (queryEmpty) { 3975691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert if (mCorpus == null || mCorpus.isWebCorpus()) { 3985691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert mQueryTextView.setBackgroundResource(R.drawable.textfield_search_empty_google); 3995691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert mQueryTextView.setHint(null); 4005691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert } else { 4015691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert mQueryTextView.setBackgroundResource(R.drawable.textfield_search_empty); 4025691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert mQueryTextView.setHint(mCorpus.getHint()); 4035691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert } 404e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } else { 405e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setBackgroundResource(R.drawable.textfield_search); 406e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 407e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 408e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert 409e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert private void updateSearchGoButton(boolean queryEmpty) { 410e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert if (queryEmpty) { 411e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mSearchGoButton.setVisibility(View.GONE); 412e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } else { 413e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mSearchGoButton.setVisibility(View.VISIBLE); 414e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 415e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 416e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert 417e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert protected void updateVoiceSearchButton(boolean queryEmpty) { 418c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert if (queryEmpty && mLauncher.shouldShowVoiceSearch(mCorpus)) { 419e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mVoiceSearchButton.setVisibility(View.VISIBLE); 420e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE); 421e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } else { 422e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mVoiceSearchButton.setVisibility(View.GONE); 423e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryTextView.setPrivateImeOptions(null); 424e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 425e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 426e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert 42741fe9d1fc461c42907250d44d3537909e4c46a7dBjorn Bringert protected void showCorpusSelectionDialog() { 428f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert if (mCorpusSelectionDialog == null) { 429f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert mCorpusSelectionDialog = new CorpusSelectionDialog(this); 430f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert mCorpusSelectionDialog.setOwnerActivity(this); 431f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert mCorpusSelectionDialog.setOnCorpusSelectedListener(new CorpusSelectionListener()); 4322617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 433f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert mCorpusSelectionDialog.show(mCorpus); 4342617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4352617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 436f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert protected void dismissCorpusSelectionDialog() { 437f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert if (mCorpusSelectionDialog != null) { 438f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert mCorpusSelectionDialog.dismiss(); 4392617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4402617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 4412617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 442ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert protected void onSearchClicked(int method) { 4433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String query = getQuery(); 4443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "Search clicked, query=" + query); 445eba26da75665ac3b9a411e74267395f332ff851aBjorn Bringert 446eba26da75665ac3b9a411e74267395f332ff851aBjorn Bringert // Don't do empty queries 447eba26da75665ac3b9a411e74267395f332ff851aBjorn Bringert if (TextUtils.getTrimmedLength(query) == 0) return; 448eba26da75665ac3b9a411e74267395f332ff851aBjorn Bringert 449535931433926d342c6277034cad91143ae28b72dBjorn Bringert Corpus searchCorpus = mLauncher.getSearchCorpus(getCorpora(), mCorpus); 450c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert if (searchCorpus == null) return; 451c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 452ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = true; 453c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 454c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Log search start 455fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getLogger().logSearch(mCorpus, method, query.length()); 456c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 457c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Create shortcut 458c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert SuggestionData searchShortcut = searchCorpus.createSearchShortcut(query); 459c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert if (searchShortcut != null) { 460c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert DataSuggestionCursor cursor = new DataSuggestionCursor(query); 461c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert cursor.add(searchShortcut); 462c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert getShortcutRepository().reportClick(cursor, 0); 463c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert } 464c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 465c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Start search 466c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert Intent intent = searchCorpus.createSearchIntent(query, mAppSearchData); 467c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert mLauncher.launchIntent(intent); 4683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onVoiceSearchClicked() { 4713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "Voice Search clicked"); 472535931433926d342c6277034cad91143ae28b72dBjorn Bringert Corpus searchCorpus = mLauncher.getSearchCorpus(getCorpora(), mCorpus); 473c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert if (searchCorpus == null) return; 474c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 475535931433926d342c6277034cad91143ae28b72dBjorn Bringert mTookAction = true; 476535931433926d342c6277034cad91143ae28b72dBjorn 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 485e06b7cbf55301a24cfd7525a91107e3cd2c9f48eBjorn Bringert protected SuggestionCursor getCurrentSuggestions() { 486fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mSuggestionsAdapter.getCurrentSuggestions(); 487782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 488782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 489fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected boolean launchSuggestion(int position) { 490fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (DBG) Log.d(TAG, "Launching suggestion " + position); 491ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = true; 492e06b7cbf55301a24cfd7525a91107e3cd2c9f48eBjorn Bringert 493e06b7cbf55301a24cfd7525a91107e3cd2c9f48eBjorn Bringert SuggestionCursor suggestions = getCurrentSuggestions(); 494c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 495c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Log suggestion click 496e06b7cbf55301a24cfd7525a91107e3cd2c9f48eBjorn Bringert Collection<Corpus> corpora = mSuggestionsAdapter.getSuggestions().getIncludedCorpora(); 497fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getLogger().logSuggestionClick(position, suggestions, corpora); 498ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 499c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Create shortcut 500fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getShortcutRepository().reportClick(suggestions, position); 501c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 502c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Launch intent 503c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert Intent intent = mLauncher.getSuggestionIntent(suggestions, position, mAppSearchData); 504c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert mLauncher.launchIntent(intent); 505c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 5063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return true; 5073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 509fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected boolean onSuggestionLongClicked(int position) { 510fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (DBG) Log.d(TAG, "Long clicked on suggestion " + position); 5113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return false; 5123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 514fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected boolean onSuggestionKeyDown(int position, int keyCode, KeyEvent event) { 515782dd228e78e9294692d639597f96c26283968bbBjorn Bringert // Treat enter or search as a click 516782dd228e78e9294692d639597f96c26283968bbBjorn Bringert if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH) { 517fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return launchSuggestion(position); 518782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 519782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 5207b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (keyCode == KeyEvent.KEYCODE_DPAD_UP 5217b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert && mSuggestionsView.getSelectedItemPosition() == 0) { 5227b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // Moved up from the top suggestion, restore the user query and focus query box 5237b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Up and out"); 5247b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert restoreUserQuery(); 5257b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert return false; // let the framework handle the move 5267b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5277b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 5287b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT 5297b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { 5307b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // Moved left / right from a suggestion, keep current query, move 5317b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // focus to query box, and move cursor to far left / right 5327b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Left/right on a suggestion"); 5334afd6f1587b1c2f3686190d55f1640ecfba03699Bjorn Bringert String query = getQuery(); 5344afd6f1587b1c2f3686190d55f1640ecfba03699Bjorn Bringert int cursorPos = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : query.length(); 5357b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mQueryTextView.setSelection(cursorPos); 5367b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert mQueryTextView.requestFocus(); 5374afd6f1587b1c2f3686190d55f1640ecfba03699Bjorn Bringert updateSuggestions(query); 5387b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert return true; 5397b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5407b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 541782dd228e78e9294692d639597f96c26283968bbBjorn Bringert return false; 542782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 543782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 5443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onSourceSelected() { 5453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "No suggestion selected"); 5463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert restoreUserQuery(); 5473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 549782dd228e78e9294692d639597f96c26283968bbBjorn Bringert protected int getSelectedPosition() { 550782dd228e78e9294692d639597f96c26283968bbBjorn Bringert return mSuggestionsView.getSelectedPosition(); 551782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 552782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 5533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 5543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Hides the input method. 5553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 5563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void hideInputMethod() { 5573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 5583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (imm != null) { 5593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert imm.hideSoftInputFromWindow(mQueryTextView.getWindowToken(), 0); 5603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 5637b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert protected void showInputMethodForQuery() { 5647b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 5657b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (imm != null) { 5666c8a8cb66ccf57347c7aed4260132d342b242b0fBjorn Bringert imm.showSoftInput(mQueryTextView, InputMethodManager.SHOW_IMPLICIT); 5677b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5687b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5697b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 5703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 5713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Hides the input method when the suggestions get focus. 5723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 5733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class SuggestListFocusListener implements OnFocusChangeListener { 5743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onFocusChange(View v, boolean focused) { 5757b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Suggestions focus change, now: " + focused); 5767b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (focused) { 5777b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // The suggestions list got focus, hide the input method 5787b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert hideInputMethod(); 5797b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5807b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5817b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 5827b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 5837b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert private class QueryTextViewFocusListener implements OnFocusChangeListener { 5847b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert public void onFocusChange(View v, boolean focused) { 5857b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (DBG) Log.d(TAG, "Query focus change, now: " + focused); 5867b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert if (focused) { 5877b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // The query box got focus, show the input method if the 5887b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert // query box got focus? 5897b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert showInputMethodForQuery(); 5903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 5933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 59447d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert private List<Corpus> getCorporaToQuery() { 59547d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert if (mCorpus == null) { 59647d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert return getCorpusRanker().getRankedCorpora(); 59747d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert } else { 59847d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert return Collections.singletonList(mCorpus); 59947d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert } 60047d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert } 60147d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert 6024ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert private void updateSuggestionsBuffered() { 6034ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert mUpdateSuggestionsHandler.removeCallbacks(mUpdateSuggestionsTask); 6044ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert long delay = getConfig().getTypingUpdateSuggestionsDelayMillis(); 6054ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert mUpdateSuggestionsHandler.postDelayed(mUpdateSuggestionsTask, delay); 6064ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert } 6074ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert 6083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private void updateSuggestions(String query) { 6093d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney query = ltrim(query); 61047d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert List<Corpus> corporaToQuery = getCorporaToQuery(); 61147d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert Suggestions suggestions = getSuggestionsProvider().getSuggestions(query, corporaToQuery); 612185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert mSuggestionsAdapter.setSuggestions(suggestions); 6133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6157be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert private boolean forwardKeyToQueryTextView(int keyCode, KeyEvent event) { 6167be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert if (!event.isSystem() && !isDpadKey(keyCode)) { 6177be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert if (DBG) Log.d(TAG, "Forwarding key to query box: " + event); 6187be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert if (mQueryTextView.requestFocus()) { 6197be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return mQueryTextView.dispatchKeyEvent(event); 6207be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 6217be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 6227be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return false; 6237be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 6247be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert 6257be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert private boolean isDpadKey(int keyCode) { 6267be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert switch (keyCode) { 6277be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_UP: 6287be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_DOWN: 6297be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_LEFT: 6307be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_RIGHT: 6317be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert case KeyEvent.KEYCODE_DPAD_CENTER: 6327be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return true; 6337be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert default: 6347be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return false; 6357be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 6367be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert } 6377be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert 6383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 6393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Filters the suggestions list when the search text changes. 6403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 6413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class SearchTextWatcher implements TextWatcher { 6423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void afterTextChanged(Editable s) { 643e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert boolean empty = s.length() == 0; 644e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert if (empty != mQueryWasEmpty) { 645e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert mQueryWasEmpty = empty; 6465691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert updateUi(empty); 647e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 6483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (mUpdateSuggestions) { 6493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String query = s == null ? "" : s.toString(); 6509ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setUserQuery(query); 6514ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert updateSuggestionsBuffered(); 6523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void beforeTextChanged(CharSequence s, int start, int count, int after) { 6563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onTextChanged(CharSequence s, int start, int before, int count) { 6593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 6623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 6633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Handles non-text keys in the query text view. 6643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 6653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class QueryTextViewKeyListener implements View.OnKeyListener { 6663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean onKey(View view, int keyCode, KeyEvent event) { 6673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Handle IME search action key 6683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) { 669ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert onSearchClicked(Logger.SEARCH_METHOD_KEYBOARD); 6703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return false; 6723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 6743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 675782dd228e78e9294692d639597f96c26283968bbBjorn Bringert /** 676782dd228e78e9294692d639597f96c26283968bbBjorn Bringert * Handles key events on the search and voice search buttons, 677782dd228e78e9294692d639597f96c26283968bbBjorn Bringert * by refocusing to EditText. 678782dd228e78e9294692d639597f96c26283968bbBjorn Bringert */ 679782dd228e78e9294692d639597f96c26283968bbBjorn Bringert private class ButtonsKeyListener implements View.OnKeyListener { 680782dd228e78e9294692d639597f96c26283968bbBjorn Bringert public boolean onKey(View v, int keyCode, KeyEvent event) { 6817be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return forwardKeyToQueryTextView(keyCode, event); 682782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 683782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 684782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 685782dd228e78e9294692d639597f96c26283968bbBjorn Bringert /** 686782dd228e78e9294692d639597f96c26283968bbBjorn Bringert * Handles key events on the suggestions list view. 687782dd228e78e9294692d639597f96c26283968bbBjorn Bringert */ 688713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private class SuggestionsViewKeyListener implements View.OnKeyListener { 689782dd228e78e9294692d639597f96c26283968bbBjorn Bringert public boolean onKey(View v, int keyCode, KeyEvent event) { 690782dd228e78e9294692d639597f96c26283968bbBjorn Bringert if (event.getAction() == KeyEvent.ACTION_DOWN) { 691fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert int position = getSelectedPosition(); 692fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (onSuggestionKeyDown(position, keyCode, event)) { 6937be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return true; 694782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 695782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 6967be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert return forwardKeyToQueryTextView(keyCode, event); 697782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 698782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 699782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 700185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert private class InputMethodCloser implements SuggestionsView.InteractionListener { 701185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert public void onInteraction() { 702185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert hideInputMethod(); 703185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert } 704185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert } 705185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 706185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert private class ClickHandler implements SuggestionClickListener { 707fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void onSuggestionClicked(int position) { 708fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert launchSuggestion(position); 7093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 711fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public boolean onSuggestionLongClicked(int position) { 712fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return SearchActivity.this.onSuggestionLongClicked(position); 713713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 7143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 7167b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert private class SelectionHandler implements SuggestionSelectionListener { 717fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void onSuggestionSelected(int position) { 718e06b7cbf55301a24cfd7525a91107e3cd2c9f48eBjorn Bringert SuggestionCursor suggestions = getCurrentSuggestions(); 719fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert suggestions.moveTo(position); 720fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String displayQuery = suggestions.getSuggestionDisplayQuery(); 721fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (TextUtils.isEmpty(displayQuery)) { 722fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert restoreUserQuery(); 723fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } else { 724fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert setQuery(displayQuery, false); 725fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 726fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 727fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 728fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void onNothingSelected() { 729fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // This happens when a suggestion has been selected with the 730fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // dpad / trackball and then a different UI element is touched. 731fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Do nothing, since we want to keep the query of the selection 732fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // in the search box. 7337b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 7347b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert } 7357b9d59cd76eecd7645072c6728e2faf9ff9e180aBjorn Bringert 7363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 7372617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert * Listens for clicks on the source selector. 7383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 7393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class SearchGoButtonClickListener implements View.OnClickListener { 7403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onClick(View view) { 741ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert onSearchClicked(Logger.SEARCH_METHOD_BUTTON); 7423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 7453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 7462617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert * Listens for clicks on the search button. 7472617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert */ 748fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private class CorpusIndicatorClickListener implements View.OnClickListener { 7492617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert public void onClick(View view) { 75041fe9d1fc461c42907250d44d3537909e4c46a7dBjorn Bringert showCorpusSelectionDialog(); 7512617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 752f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert } 753f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert 754f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert private class CorpusSelectionListener 755f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert implements CorpusSelectionDialog.OnCorpusSelectedListener { 756f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert public void onCorpusSelected(Corpus corpus) { 757f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert setCorpus(corpus); 758f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert updateSuggestions(getQuery()); 759f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert mQueryTextView.requestFocus(); 760f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert } 7612617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 7622617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 7632617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert /** 7643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Listens for clicks on the voice search button. 7653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 7663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private class VoiceSearchButtonClickListener implements View.OnClickListener { 7673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onClick(View view) { 7683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert onVoiceSearchClicked(); 7693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 7713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 7723d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney private static String ltrim(String text) { 7733d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney int start = 0; 7743d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney int length = text.length(); 7753d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney while (start < length && Character.isWhitespace(text.charAt(start))) { 7763d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney start++; 7773d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney } 7783d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney return start > 0 ? text.substring(start, length) : text; 7793d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney } 7803d382f0ca49a8150d504cf2629124a7f13175e1eBryan Mawhinney 7813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert} 782