1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.browser; 17 18 import android.app.SearchManager; 19 import android.content.Context; 20 import android.content.Intent; 21 import android.graphics.Bitmap; 22 import android.graphics.drawable.Drawable; 23 import android.os.Bundle; 24 import android.speech.RecognizerResultsIntent; 25 import android.util.AttributeSet; 26 import android.view.KeyEvent; 27 import android.view.View; 28 import android.view.View.OnClickListener; 29 import android.view.View.OnFocusChangeListener; 30 import android.widget.ImageView; 31 import android.widget.LinearLayout; 32 33 import com.android.browser.UI.DropdownChangeListener; 34 import com.android.browser.UrlInputView.UrlInputListener; 35 import com.android.browser.autocomplete.SuggestedTextController.TextChangeWatcher; 36 37 import java.util.List; 38 39 public class NavigationBarBase extends LinearLayout implements 40 OnClickListener, UrlInputListener, OnFocusChangeListener, 41 TextChangeWatcher { 42 43 protected BaseUi mBaseUi; 44 protected TitleBar mTitleBar; 45 protected UiController mUiController; 46 protected UrlInputView mUrlInput; 47 protected boolean mInVoiceMode = false; 48 49 private ImageView mFavicon; 50 private ImageView mLockIcon; 51 52 public NavigationBarBase(Context context) { 53 super(context); 54 } 55 56 public NavigationBarBase(Context context, AttributeSet attrs) { 57 super(context, attrs); 58 } 59 60 public NavigationBarBase(Context context, AttributeSet attrs, int defStyle) { 61 super(context, attrs, defStyle); 62 } 63 64 @Override 65 protected void onFinishInflate() { 66 super.onFinishInflate(); 67 mLockIcon = (ImageView) findViewById(R.id.lock); 68 mFavicon = (ImageView) findViewById(R.id.favicon); 69 mUrlInput = (UrlInputView) findViewById(R.id.url); 70 mUrlInput.setUrlInputListener(this); 71 mUrlInput.setOnFocusChangeListener(this); 72 mUrlInput.setSelectAllOnFocus(true); 73 mUrlInput.addQueryTextWatcher(this); 74 } 75 76 public void setTitleBar(TitleBar titleBar) { 77 mTitleBar = titleBar; 78 mBaseUi = mTitleBar.getUi(); 79 mUiController = mTitleBar.getUiController(); 80 mUrlInput.setController(mUiController); 81 } 82 83 public void setLock(Drawable d) { 84 if (mLockIcon == null) return; 85 if (d == null) { 86 mLockIcon.setVisibility(View.GONE); 87 } else { 88 mLockIcon.setImageDrawable(d); 89 mLockIcon.setVisibility(View.VISIBLE); 90 } 91 } 92 93 public void setFavicon(Bitmap icon) { 94 if (mFavicon == null) return; 95 mFavicon.setImageDrawable(mBaseUi.getFaviconDrawable(icon)); 96 } 97 98 @Override 99 public void onClick(View v) { 100 } 101 102 @Override 103 public void onFocusChange(View view, boolean hasFocus) { 104 // if losing focus and not in touch mode, leave as is 105 if (hasFocus || view.isInTouchMode() || mUrlInput.needsUpdate()) { 106 setFocusState(hasFocus); 107 } 108 if (hasFocus) { 109 mBaseUi.showTitleBar(); 110 mUrlInput.forceIme(); 111 if (mInVoiceMode) { 112 mUrlInput.forceFilter(); 113 } 114 } else if (!mUrlInput.needsUpdate()) { 115 mUrlInput.dismissDropDown(); 116 mUrlInput.hideIME(); 117 if (mUrlInput.getText().length() == 0) { 118 Tab currentTab = mUiController.getTabControl().getCurrentTab(); 119 if (currentTab != null) { 120 setDisplayTitle(currentTab.getUrl()); 121 } 122 } 123 mBaseUi.suggestHideTitleBar(); 124 } 125 mUrlInput.clearNeedsUpdate(); 126 } 127 128 protected void setFocusState(boolean focus) { 129 } 130 131 protected void setSearchMode(boolean voiceSearchEnabled) {} 132 133 public boolean isEditingUrl() { 134 return mUrlInput.hasFocus(); 135 } 136 137 void stopEditingUrl() { 138 mUrlInput.clearFocus(); 139 } 140 141 void setDisplayTitle(String title) { 142 if (!isEditingUrl()) { 143 mUrlInput.setText(title, false); 144 } 145 } 146 147 // UrlInput text watcher 148 149 @Override 150 public void onTextChanged(String newText) { 151 if (mUrlInput.hasFocus()) { 152 // clear voice mode when user types 153 setInVoiceMode(false, null); 154 } 155 } 156 157 // voicesearch 158 159 public void setInVoiceMode(boolean voicemode, List<String> voiceResults) { 160 mInVoiceMode = voicemode; 161 mUrlInput.setVoiceResults(voiceResults); 162 } 163 164 void setIncognitoMode(boolean incognito) { 165 mUrlInput.setIncognitoMode(incognito); 166 } 167 168 void clearCompletions() { 169 mUrlInput.setSuggestedText(null); 170 } 171 172 // UrlInputListener implementation 173 174 /** 175 * callback from suggestion dropdown 176 * user selected a suggestion 177 */ 178 @Override 179 public void onAction(String text, String extra, String source) { 180 mUiController.getCurrentTopWebView().requestFocus(); 181 if (UrlInputView.TYPED.equals(source)) { 182 String url = UrlUtils.smartUrlFilter(text, false); 183 Tab t = mBaseUi.getActiveTab(); 184 // Only shortcut javascript URIs for now, as there is special 185 // logic in UrlHandler for other schemas 186 if (url != null && t != null && url.startsWith("javascript:")) { 187 mUiController.loadUrl(t, url); 188 setDisplayTitle(text); 189 return; 190 } 191 } 192 Intent i = new Intent(); 193 String action = null; 194 if (UrlInputView.VOICE.equals(source)) { 195 action = RecognizerResultsIntent.ACTION_VOICE_SEARCH_RESULTS; 196 source = null; 197 } else { 198 action = Intent.ACTION_SEARCH; 199 } 200 i.setAction(action); 201 i.putExtra(SearchManager.QUERY, text); 202 if (extra != null) { 203 i.putExtra(SearchManager.EXTRA_DATA_KEY, extra); 204 } 205 if (source != null) { 206 Bundle appData = new Bundle(); 207 appData.putString(com.android.common.Search.SOURCE, source); 208 i.putExtra(SearchManager.APP_DATA, appData); 209 } 210 mUiController.handleNewIntent(i); 211 setDisplayTitle(text); 212 } 213 214 @Override 215 public void onDismiss() { 216 final Tab currentTab = mBaseUi.getActiveTab(); 217 mBaseUi.hideTitleBar(); 218 post(new Runnable() { 219 public void run() { 220 clearFocus(); 221 if ((currentTab != null) && !mInVoiceMode) { 222 setDisplayTitle(currentTab.getUrl()); 223 } 224 } 225 }); 226 } 227 228 /** 229 * callback from the suggestion dropdown 230 * copy text to input field and stay in edit mode 231 */ 232 @Override 233 public void onCopySuggestion(String text) { 234 mUrlInput.setText(text, true); 235 if (text != null) { 236 mUrlInput.setSelection(text.length()); 237 } 238 } 239 240 public void setCurrentUrlIsBookmark(boolean isBookmark) { 241 } 242 243 @Override 244 public boolean dispatchKeyEventPreIme(KeyEvent evt) { 245 if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) { 246 // catch back key in order to do slightly more cleanup than usual 247 mUrlInput.clearFocus(); 248 return true; 249 } 250 return super.dispatchKeyEventPreIme(evt); 251 } 252 253 void registerDropdownChangeListener(DropdownChangeListener d) { 254 mUrlInput.registerDropdownChangeListener(d); 255 } 256 257 /** 258 * called from the Ui when the user wants to edit 259 * @param clearInput clear the input field 260 */ 261 void startEditingUrl(boolean clearInput) { 262 // editing takes preference of progress 263 setVisibility(View.VISIBLE); 264 if (mTitleBar.useQuickControls()) { 265 mTitleBar.getProgressView().setVisibility(View.GONE); 266 } 267 if (!mUrlInput.hasFocus()) { 268 mUrlInput.requestFocus(); 269 } 270 if (clearInput) { 271 mUrlInput.setText(""); 272 } else if (mInVoiceMode) { 273 mUrlInput.showDropDown(); 274 } 275 } 276 277 public void onProgressStarted() { 278 } 279 280 public void onProgressStopped() { 281 } 282 283 public boolean isMenuShowing() { 284 return false; 285 } 286 287 public void onTabDataChanged(Tab tab) { 288 } 289 290 } 291