blob: aa8b79f2a5acc9d2bf5dfcc960ed0d1a50d0a9be [file] [log] [blame]
John Reck0f602f32011-07-07 15:38:43 -07001/*
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 */
16package com.android.browser;
17
18import android.app.SearchManager;
19import android.content.Context;
20import android.content.Intent;
21import android.graphics.Bitmap;
22import android.graphics.drawable.Drawable;
23import android.os.Bundle;
24import android.speech.RecognizerResultsIntent;
25import android.util.AttributeSet;
26import android.view.KeyEvent;
27import android.view.Menu;
28import android.view.MenuItem;
29import android.view.View;
30import android.view.View.OnClickListener;
31import android.view.View.OnFocusChangeListener;
32import android.webkit.WebView;
33import android.widget.ImageView;
34import android.widget.LinearLayout;
35import android.widget.PopupMenu;
36import android.widget.PopupMenu.OnMenuItemClickListener;
37
38import com.android.browser.UI.DropdownChangeListener;
39import com.android.browser.UrlInputView.UrlInputListener;
40import com.android.browser.autocomplete.SuggestedTextController.TextChangeWatcher;
41
42import java.util.List;
43
44public class NavigationBarBase extends LinearLayout implements OnClickListener,
45 OnMenuItemClickListener, UrlInputListener, OnFocusChangeListener,
46 TextChangeWatcher {
47
48 protected BaseUi mBaseUi;
49 protected TitleBar mTitleBar;
50 protected UiController mUiController;
51 protected UrlInputView mUrlInput;
52 protected boolean mInVoiceMode = false;
53
54 private ImageView mFavicon;
55 private ImageView mLockIcon;
56 private View mUaSwitcher;
57
58 public NavigationBarBase(Context context) {
59 super(context);
60 }
61
62 public NavigationBarBase(Context context, AttributeSet attrs) {
63 super(context, attrs);
64 }
65
66 public NavigationBarBase(Context context, AttributeSet attrs, int defStyle) {
67 super(context, attrs, defStyle);
68 }
69
70 @Override
71 protected void onFinishInflate() {
72 super.onFinishInflate();
73 mLockIcon = (ImageView) findViewById(R.id.lock);
74 mFavicon = (ImageView) findViewById(R.id.favicon);
75 mUrlInput = (UrlInputView) findViewById(R.id.url);
76 mUrlInput.setUrlInputListener(this);
John Reck0f602f32011-07-07 15:38:43 -070077 mUrlInput.setOnFocusChangeListener(this);
78 mUrlInput.setSelectAllOnFocus(true);
79 mUrlInput.addQueryTextWatcher(this);
80 }
81
82 public void setTitleBar(TitleBar titleBar) {
83 mTitleBar = titleBar;
84 mBaseUi = mTitleBar.getUi();
85 mUiController = mTitleBar.getUiController();
Michael Kolbb2e91fd2011-07-14 13:47:29 -070086 mUrlInput.setController(mUiController);
John Reck0f602f32011-07-07 15:38:43 -070087 }
88
89 public void setLock(Drawable d) {
90 if (mLockIcon == null) return;
91 if (d == null) {
92 mLockIcon.setVisibility(View.GONE);
93 } else {
94 mLockIcon.setImageDrawable(d);
95 mLockIcon.setVisibility(View.VISIBLE);
96 }
97 }
98
99 public void setFavicon(Bitmap icon) {
100 if (mFavicon == null) return;
101 mFavicon.setImageDrawable(mBaseUi.getFaviconDrawable(icon));
102 }
103
104 public void setUaSwitcher(View v) {
105 if (mUaSwitcher != null) {
106 mUaSwitcher.setOnClickListener(null);
107 }
108 mUaSwitcher = v;
109 mUaSwitcher.setOnClickListener(this);
110 }
111
112 @Override
113 public void onClick(View v) {
114 if (mUaSwitcher == v) {
115 BrowserSettings settings = BrowserSettings.getInstance();
116 WebView web = mTitleBar.getCurrentWebView();
117 if (web == null) return;
118 boolean desktop = settings.hasDesktopUseragent(web);
119 PopupMenu popup = new PopupMenu(mContext, mUaSwitcher);
120 Menu menu = popup.getMenu();
121 popup.getMenuInflater().inflate(R.menu.ua_switcher, menu);
122 menu.findItem(R.id.ua_mobile_menu_id).setChecked(!desktop);
123 menu.findItem(R.id.ua_desktop_menu_id).setChecked(desktop);
John Reckeac25cd2011-08-11 16:03:32 -0700124 Tab tab = mUiController.getCurrentTab();
125 MenuItem saveSnapshot = menu.findItem(R.id.save_snapshot_menu_id);
126 saveSnapshot.setVisible(tab != null && !tab.isSnapshot());
127 MenuItem find = menu.findItem(R.id.find_menu_id);
128 find.setVisible(tab != null && !tab.isSnapshot());
John Reck0f602f32011-07-07 15:38:43 -0700129 popup.setOnMenuItemClickListener(this);
130 popup.show();
131 }
132 }
133
134 @Override
135 public boolean onMenuItemClick(MenuItem item) {
136 BrowserSettings settings = BrowserSettings.getInstance();
137 WebView web = mTitleBar.getCurrentWebView();
138 if (web == null) return false;
139 boolean desktop = settings.hasDesktopUseragent(web);
140 switch (item.getItemId()) {
141 case R.id.ua_mobile_menu_id:
142 if (desktop) {
143 settings.toggleDesktopUseragent(web);
144 web.loadUrl(web.getOriginalUrl());
145 }
146 return true;
147 case R.id.ua_desktop_menu_id:
148 if (!desktop) {
149 settings.toggleDesktopUseragent(web);
150 web.loadUrl(web.getOriginalUrl());
151 }
152 return true;
153 }
154 return false;
155 }
156
157 @Override
158 public void onFocusChange(View view, boolean hasFocus) {
159 // if losing focus and not in touch mode, leave as is
160 if (hasFocus || view.isInTouchMode() || mUrlInput.needsUpdate()) {
161 setFocusState(hasFocus);
162 }
163 if (hasFocus) {
164 mBaseUi.showTitleBar();
165 mUrlInput.forceIme();
166 if (mInVoiceMode) {
167 mUrlInput.forceFilter();
168 }
169 } else if (!mUrlInput.needsUpdate()) {
170 mUrlInput.dismissDropDown();
171 mUrlInput.hideIME();
172 if (mUrlInput.getText().length() == 0) {
173 Tab currentTab = mUiController.getTabControl().getCurrentTab();
174 if (currentTab != null) {
John Reck434e9f82011-08-10 18:16:52 -0700175 setDisplayTitle(currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700176 }
177 }
178 mBaseUi.suggestHideTitleBar();
179 }
180 mUrlInput.clearNeedsUpdate();
181 }
182
183 protected void setFocusState(boolean focus) {
184 }
185
186 protected void setSearchMode(boolean voiceSearchEnabled) {}
187
188 public boolean isEditingUrl() {
189 return mUrlInput.hasFocus();
190 }
191
192 void stopEditingUrl() {
193 mUrlInput.clearFocus();
194 }
195
196 void setDisplayTitle(String title) {
197 if (!isEditingUrl()) {
198 mUrlInput.setText(title, false);
199 }
200 }
201
202 // UrlInput text watcher
203
204 @Override
205 public void onTextChanged(String newText) {
206 if (mUrlInput.hasFocus()) {
207 // clear voice mode when user types
208 setInVoiceMode(false, null);
209 }
210 }
211
212 // voicesearch
213
214 public void setInVoiceMode(boolean voicemode, List<String> voiceResults) {
215 mInVoiceMode = voicemode;
216 mUrlInput.setVoiceResults(voiceResults);
217 }
218
219 void setIncognitoMode(boolean incognito) {
220 mUrlInput.setIncognitoMode(incognito);
221 }
222
223 void clearCompletions() {
224 mUrlInput.setSuggestedText(null);
225 }
226
227 // UrlInputListener implementation
228
229 /**
230 * callback from suggestion dropdown
231 * user selected a suggestion
232 */
233 @Override
234 public void onAction(String text, String extra, String source) {
235 mUiController.getCurrentTopWebView().requestFocus();
236 if (UrlInputView.TYPED.equals(source)) {
237 String url = UrlUtils.smartUrlFilter(text, false);
238 Tab t = mBaseUi.getActiveTab();
239 // Only shortcut javascript URIs for now, as there is special
240 // logic in UrlHandler for other schemas
241 if (url != null && t != null && url.startsWith("javascript:")) {
242 mUiController.loadUrl(t, url);
243 setDisplayTitle(text);
244 return;
245 }
246 }
247 Intent i = new Intent();
248 String action = null;
249 if (UrlInputView.VOICE.equals(source)) {
250 action = RecognizerResultsIntent.ACTION_VOICE_SEARCH_RESULTS;
251 source = null;
252 } else {
253 action = Intent.ACTION_SEARCH;
254 }
255 i.setAction(action);
256 i.putExtra(SearchManager.QUERY, text);
257 if (extra != null) {
258 i.putExtra(SearchManager.EXTRA_DATA_KEY, extra);
259 }
260 if (source != null) {
261 Bundle appData = new Bundle();
262 appData.putString(com.android.common.Search.SOURCE, source);
263 i.putExtra(SearchManager.APP_DATA, appData);
264 }
265 mUiController.handleNewIntent(i);
266 setDisplayTitle(text);
267 }
268
269 @Override
270 public void onDismiss() {
271 final Tab currentTab = mBaseUi.getActiveTab();
272 mBaseUi.hideTitleBar();
273 post(new Runnable() {
274 public void run() {
275 clearFocus();
276 if ((currentTab != null) && !mInVoiceMode) {
277 setDisplayTitle(currentTab.getUrl());
278 }
279 }
280 });
281 }
282
283 /**
284 * callback from the suggestion dropdown
285 * copy text to input field and stay in edit mode
286 */
287 @Override
288 public void onCopySuggestion(String text) {
289 mUrlInput.setText(text, true);
290 if (text != null) {
291 mUrlInput.setSelection(text.length());
292 }
293 }
294
295 public void setCurrentUrlIsBookmark(boolean isBookmark) {
296 }
297
298 @Override
299 public boolean dispatchKeyEventPreIme(KeyEvent evt) {
300 if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) {
301 // catch back key in order to do slightly more cleanup than usual
302 mUrlInput.clearFocus();
303 return true;
304 }
305 return super.dispatchKeyEventPreIme(evt);
306 }
307
308 void registerDropdownChangeListener(DropdownChangeListener d) {
309 mUrlInput.registerDropdownChangeListener(d);
310 }
311
312 /**
313 * called from the Ui when the user wants to edit
314 * @param clearInput clear the input field
315 */
316 void startEditingUrl(boolean clearInput) {
317 // editing takes preference of progress
318 setVisibility(View.VISIBLE);
319 if (mTitleBar.useQuickControls()) {
320 mTitleBar.getProgressView().setVisibility(View.GONE);
321 }
322 if (!mUrlInput.hasFocus()) {
323 mUrlInput.requestFocus();
324 }
325 if (clearInput) {
326 mUrlInput.setText("");
327 } else if (mInVoiceMode) {
328 mUrlInput.showDropDown();
329 }
330 }
331
332 public void onProgressStarted() {
333 }
334
335 public void onProgressStopped() {
336 }
337
338}