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