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