blob: fd6d67b00cb2056e616d9a79b049b4754c4f93fc [file] [log] [blame]
Leon Scroggins571b3762010-05-26 10:25:01 -04001/*
2 * Copyright (C) 2010 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
17package com.android.browser;
18
Michael Kolbfe251992010-07-08 15:41:55 -070019import android.app.SearchManager;
Leon Scroggins571b3762010-05-26 10:25:01 -040020import android.content.Context;
Michael Kolbfe251992010-07-08 15:41:55 -070021import android.content.Intent;
22import android.content.res.Configuration;
Leon Scroggins571b3762010-05-26 10:25:01 -040023import android.content.res.Resources;
Michael Kolbfe251992010-07-08 15:41:55 -070024import android.graphics.Bitmap;
25import android.graphics.Color;
26import android.graphics.drawable.BitmapDrawable;
Leon Scroggins571b3762010-05-26 10:25:01 -040027import android.graphics.drawable.Drawable;
Michael Kolbfe251992010-07-08 15:41:55 -070028import android.graphics.drawable.LayerDrawable;
29import android.graphics.drawable.PaintDrawable;
Leon Scroggins571b3762010-05-26 10:25:01 -040030import android.view.ContextMenu;
31import android.view.LayoutInflater;
32import android.view.MenuInflater;
33import android.view.View;
34import android.widget.ImageView;
Michael Kolbfe251992010-07-08 15:41:55 -070035import android.widget.LinearLayout;
Leon Scroggins571b3762010-05-26 10:25:01 -040036import android.widget.TextView;
37
Michael Kolbfe251992010-07-08 15:41:55 -070038import com.android.browser.TabControl.TabChangeListener;
39import com.android.browser.UrlInputView.UrlInputListener;
40
41import java.util.HashMap;
42import java.util.Map;
Leon Scroggins571b3762010-05-26 10:25:01 -040043
44/**
Michael Kolbfe251992010-07-08 15:41:55 -070045 * tabbed title bar for xlarge screen browser
Leon Scroggins571b3762010-05-26 10:25:01 -040046 */
Michael Kolbfe251992010-07-08 15:41:55 -070047public class TitleBarXLarge extends TitleBarBase
48 implements TabChangeListener, UrlInputListener {
Leon Scroggins571b3762010-05-26 10:25:01 -040049
Michael Kolbfe251992010-07-08 15:41:55 -070050 private static final int PROGRESS_MAX = 100;
Leon Scroggins571b3762010-05-26 10:25:01 -040051
Michael Kolbfe251992010-07-08 15:41:55 -070052 private static final int TAB_WIDTH_SELECTED = 400;
53 private static final int TAB_WIDTH_UNSELECTED = 150;
54
55 private BrowserActivity mBrowserActivity;
56 private Drawable mStopDrawable;
57 private Drawable mReloadDrawable;
58 private Drawable mSelectedBackground;
59 private Drawable mUnselectedBackground;
60
61 private View mBackButton;
62 private View mForwardButton;
63 private View mStar;
64 private View mMenu;
65 private View mAllButton;
66 private TabScrollView mTabs;
67 private View mNewButton;
68 private TabControl mControl;
69 private UrlInputView mUrlView;
70
71 private boolean mIsInLandscape;
72 private Map<Tab, TabViewData> mTabMap;
73
74 private float mDensityScale;
75
76 public TitleBarXLarge(BrowserActivity context, TabControl tabcontrol) {
Leon Scroggins571b3762010-05-26 10:25:01 -040077 super(context);
Michael Kolbfe251992010-07-08 15:41:55 -070078 mDensityScale = context.getResources().getDisplayMetrics().density;
79 mTabMap = new HashMap<Tab, TabViewData>();
Leon Scroggins571b3762010-05-26 10:25:01 -040080 mBrowserActivity = context;
Michael Kolbfe251992010-07-08 15:41:55 -070081 mControl = tabcontrol;
82 Resources resources = context.getResources();
83 mSelectedBackground = resources.getDrawable(R.drawable.tab_selected_bg);
84 mUnselectedBackground = resources.getDrawable(R.drawable.tab_unselected_bg);
85 mStopDrawable = resources.getDrawable(R.drawable.progress_stop);
Leon Scroggins571b3762010-05-26 10:25:01 -040086 mReloadDrawable = resources.getDrawable(R.drawable.ic_reload);
Michael Kolbfe251992010-07-08 15:41:55 -070087 rebuildLayout(context, true);
88 // register the tab change listener
89 mControl.setOnTabChangeListener(this);
90 }
Leon Scroggins571b3762010-05-26 10:25:01 -040091
Michael Kolbfe251992010-07-08 15:41:55 -070092 void rebuildLayout() {
93 rebuildLayout(mBrowserActivity, false);
94 }
Leon Scroggins571b3762010-05-26 10:25:01 -040095
Michael Kolbfe251992010-07-08 15:41:55 -070096 private void rebuildLayout(Context context, boolean rebuildData) {
97 removeAllViews();
98 LayoutInflater factory = LayoutInflater.from(context);
99 factory.inflate(R.layout.title_bar_tabbed, this);
100
101 mTabs = (TabScrollView) findViewById(R.id.tabs);
102 mNewButton = findViewById(R.id.newtab);
103 mUrlView = (UrlInputView) findViewById(R.id.editurl);
104 mAllButton = findViewById(R.id.all_btn);
105 // TODO: Change enabled states based on whether you can go
Leon Scroggins571b3762010-05-26 10:25:01 -0400106 // back/forward. Probably should be done inside onPageStarted.
107 mBackButton = findViewById(R.id.back);
108 mForwardButton = findViewById(R.id.forward);
109 mStar = findViewById(R.id.star);
110 mMenu = findViewById(R.id.menu);
111 View.OnClickListener listener = new View.OnClickListener() {
Michael Kolbfe251992010-07-08 15:41:55 -0700112 public void onClick(View v) {
113 if (mBackButton == v) {
114 mBrowserActivity.getTopWindow().goBack();
115 } else if (mForwardButton == v) {
116 mBrowserActivity.getTopWindow().goForward();
117 } else if (mStar == v) {
118 mBrowserActivity.promptAddOrInstallBookmark();
119 } else if (mMenu == v) {
120 mBrowserActivity.openOptionsMenu();
121 } else if (mAllButton == v) {
122 // TODO: Show the new bookmarks/windows view.
123 mBrowserActivity.bookmarksOrHistoryPicker(false);
124 } else if (mNewButton == v) {
125 mBrowserActivity.openTabToHomePage();
Leon Scroggins571b3762010-05-26 10:25:01 -0400126 }
Michael Kolbfe251992010-07-08 15:41:55 -0700127 }
Leon Scroggins571b3762010-05-26 10:25:01 -0400128 };
129 mBackButton.setOnClickListener(listener);
130 mForwardButton.setOnClickListener(listener);
131 mStar.setOnClickListener(listener);
Leon Scroggins571b3762010-05-26 10:25:01 -0400132 mAllButton.setOnClickListener(listener);
133 mMenu.setOnClickListener(listener);
Michael Kolbfe251992010-07-08 15:41:55 -0700134 mNewButton.setOnClickListener(listener);
135
136 mIsInLandscape = mBrowserActivity.getResources().getConfiguration().orientation
137 == Configuration.ORIENTATION_LANDSCAPE;
138 mUrlView.setVisibility(mIsInLandscape ? View.GONE : View.VISIBLE);
139 mUrlView.setUrlInputListener(this);
140 buildTabs(rebuildData);
141 // ensure title bar state
142 onCurrentTab(mControl.getCurrentTab());
143 }
144
145 void showUrlEditor(TabViewData tabdata) {
146 mUrlView.setVisibility(View.VISIBLE);
147 if (mIsInLandscape) {
148 mTabs.setVisibility(View.GONE);
149 mUrlView.requestFocus();
150 mUrlView.forceIme();
151 }
152 }
153
154 void hideUrlEditor() {
155 Tab tab = mControl.getCurrentTab();
156 if (mIsInLandscape) {
157 mUrlView.setVisibility(View.GONE);
158 mTabs.setVisibility(View.VISIBLE);
159 } else {
160 // portrait mode
161 mUrlView.setText(tab.getWebView().getUrl());
162 }
163 tab.getWebView().requestFocus();
164 }
165
166
167 // UrlInputListener implementation
168
169 @Override
170 public void onAction(String text) {
171 hideUrlEditor();
172 Intent i = new Intent();
173 i.setAction(Intent.ACTION_SEARCH);
174 i.putExtra(SearchManager.QUERY, text);
175 mBrowserActivity.onNewIntent(i);
176 }
177
178 @Override
179 public void onDismiss() {
180 hideUrlEditor();
Leon Scroggins571b3762010-05-26 10:25:01 -0400181 }
182
183 @Override
184 public void createContextMenu(ContextMenu menu) {
185 MenuInflater inflater = mBrowserActivity.getMenuInflater();
186 inflater.inflate(R.menu.title_context, menu);
187 mBrowserActivity.onCreateContextMenu(menu, this, null);
188 }
189
Michael Kolbfe251992010-07-08 15:41:55 -0700190 @Override
191 /* package */ void setLock(Drawable d) {
192 // TODO: handle in tab specific callback
193 }
194
195 @Override
196 /* package */ void setFavicon(Bitmap icon) {
197 // this is handled in the tab specific callback
Leon Scroggins571b3762010-05-26 10:25:01 -0400198 }
199
200 /**
Michael Kolbfe251992010-07-08 15:41:55 -0700201 * Update the progress, from 0 to 100.
Leon Scroggins571b3762010-05-26 10:25:01 -0400202 */
Michael Kolbfe251992010-07-08 15:41:55 -0700203 @Override
204 /* package */ void setProgress(int newProgress) {
205 // this is handled in tab specific callback
206 }
207
208 @Override
Leon Scroggins571b3762010-05-26 10:25:01 -0400209 /* package */ void setDisplayTitle(String title) {
Michael Kolbfe251992010-07-08 15:41:55 -0700210 // this is done in tab specific callback
211 }
212
213 private void buildTabs(boolean needsRebuilding) {
214 mTabs.clearTabs();
215 for (int i = 0; i < mControl.getTabCount(); i++) {
216 Tab tab = mControl.getTab(i);
217 TabViewData data = buildTab(needsRebuilding, tab);
218 TabView tv = buildView(data);
219 }
220 mTabs.setSelectedTab(mControl.getCurrentIndex());
221 }
222
223 private TabViewData buildTab(boolean needsRebuilding, Tab tab) {
224 TabViewData data = null;
225 if (needsRebuilding) {
226 data = new TabViewData(tab);
227 mTabMap.put(tab, data);
Leon Scroggins571b3762010-05-26 10:25:01 -0400228 } else {
Michael Kolbfe251992010-07-08 15:41:55 -0700229 data = mTabMap.get(tab);
230 }
231 return data;
232 }
233
234 private TabView buildView(final TabViewData data) {
235 TabView tv = new TabView(mBrowserActivity, data);
236 tv.setOnClickListener(new OnClickListener() {
237 @Override
238 public void onClick(View v) {
239 if (mTabs.getSelectedTab() == v) {
240 showUrlEditor(data);
241 } else {
242 int ix = mControl.getTabIndex(data.mTab);
243 mTabs.setSelectedTab(ix);
244 mBrowserActivity.switchToTab(ix);
245 }
246 }
247 });
248 mTabs.addTab(tv);
249 return tv;
250 }
251
252 /**
253 * the views used in the tab bar
254 */
255 class TabView extends LinearLayout {
256
257 TabViewData mTabData;
258 View mTabContent;
259 TextView mTitle;
260 ImageView mIconView;
261 ImageView mLock;
262 CircularProgressView mStop;
263 ImageView mClose;
264 boolean mSelected;
265 boolean mInLoad;
266
267 /**
268 * @param context
269 */
270 public TabView(Context context, TabViewData tab) {
271 super(context);
272 mTabData = tab;
273 LayoutInflater inflater = LayoutInflater.from(mContext);
274 mTabContent = inflater.inflate(R.layout.tab_title, this);
275 mTitle = (TextView) mTabContent.findViewById(R.id.title);
276 mIconView = (ImageView) mTabContent.findViewById(R.id.favicon);
277 mLock = (ImageView) mTabContent.findViewById(R.id.lock);
278 mStop = (CircularProgressView) mTabContent.findViewById(R.id.stop);
279 mStop.setMaxProgress(PROGRESS_MAX);
280 mClose = (ImageView) mTabContent.findViewById(R.id.close);
281 mClose.setOnClickListener(new OnClickListener() {
282 @Override
283 public void onClick(View v) {
284 closeTab();
285 }
286 });
287 mStop.setOnClickListener(new OnClickListener() {
288 @Override
289 public void onClick(View v) {
290 if (mInLoad) {
291 mBrowserActivity.stopLoading();
292 } else {
293 mBrowserActivity.getTopWindow().reload();
294 }
295 }
296 });
297 mSelected = false;
298 mInLoad = false;
299 // update the status
300 updateFromData();
301 }
302
303 private void updateFromData() {
304 mTabData.mTabView = this;
305 if (mTabData.mUrl != null) {
306 setDisplayTitle(mTabData.mUrl);
307 }
308 if (mTabData.mTitle != null) {
309 setDisplayTitle(mTabData.mTitle);
310 }
311 setProgress(mTabData.mProgress);
312 if (mTabData.mIcon != null) {
313 setFavicon(mTabData.mIcon);
314 }
315 if (mTabData.mLock != null) {
316 setLock(mTabData.mLock);
317 }
318 }
319
320 @Override
321 public void setSelected(boolean selected) {
322 mSelected = selected;
323 mStop.setVisibility(mSelected ? View.VISIBLE : View.GONE);
324 mIconView.setVisibility(mSelected ? View.VISIBLE : View.GONE);
325 super.setSelected(selected);
326 setBackgroundDrawable(selected ? mSelectedBackground
327 : mUnselectedBackground);
328 setLayoutParams(new LayoutParams(selected ?
329 (int) (TAB_WIDTH_SELECTED * mDensityScale)
330 : (int) (TAB_WIDTH_UNSELECTED * mDensityScale),
331 LayoutParams.WRAP_CONTENT));
332 }
333
334 void setDisplayTitle(String title) {
Leon Scroggins571b3762010-05-26 10:25:01 -0400335 mTitle.setText(title);
336 }
Michael Kolbfe251992010-07-08 15:41:55 -0700337
338 void setFavicon(Drawable d) {
339 mIconView.setImageDrawable(d);
340 }
341
342 void setLock(Drawable d) {
343 if (null == d) {
344 mLock.setVisibility(View.GONE);
345 } else {
346 mLock.setImageDrawable(d);
347 mLock.setVisibility(View.VISIBLE);
348 }
349 }
350
351 void setTitleCompoundDrawables(Drawable left, Drawable top,
352 Drawable right, Drawable bottom) {
353 mTitle.setCompoundDrawables(left, top, right, bottom);
354 }
355
356 void setProgress(int newProgress) {
357 mStop.setProgress(newProgress);
358 if (newProgress >= PROGRESS_MAX) {
359 mInLoad = false;
360 mStop.setImageDrawable(mReloadDrawable);
361 } else {
362 if (!mInLoad && getWindowToken() != null) {
363 // checking the window token lets us be sure that we
364 // are attached to a window before starting the animation,
365 // preventing a potential race condition
366 // (fix for bug http://b/2115736)
367 mInLoad = true;
368 mStop.setImageDrawable(mStopDrawable);
369 }
370 }
371 }
372
373 private void closeTab() {
374 if (mTabData.mTab == mControl.getCurrentTab()) {
375 mBrowserActivity.closeCurrentWindow();
376 } else {
377 mBrowserActivity.closeTab(mTabData.mTab);
378 }
379 }
380
381 }
382
383 /**
384 * class to store tab state within the title bar
385 */
386 class TabViewData {
387
388 Tab mTab;
389 TabView mTabView;
390 int mProgress;
391 Drawable mIcon;
392 Drawable mLock;
393 String mTitle;
394 String mUrl;
395
396 TabViewData(Tab tab) {
397 mTab = tab;
398 }
399
400 void setUrlAndTitle(String url, String title) {
401 mUrl = url;
402 mTitle = title;
403 if (mTabView != null) {
404 if (title != null) {
405 mTabView.setDisplayTitle(title);
406 } else if (url != null) {
407 mTabView.setDisplayTitle(url);
408 }
409 }
410 }
411
412 void setProgress(int newProgress) {
413 mProgress = newProgress;
414 if (mTabView != null) {
415 mTabView.setProgress(mProgress);
416 }
417 }
418
419 void setFavicon(Bitmap icon) {
420 Drawable[] array = new Drawable[3];
421 array[0] = new PaintDrawable(Color.BLACK);
422 array[1] = new PaintDrawable(Color.WHITE);
423 if (icon == null) {
424 array[2] = mGenericFavicon;
425 } else {
426 array[2] = new BitmapDrawable(icon);
427 }
428 LayerDrawable d = new LayerDrawable(array);
429 d.setLayerInset(1, 1, 1, 1, 1);
430 d.setLayerInset(2, 2, 2, 2, 2);
431 mIcon = d;
432 if (mTabView != null) {
433 mTabView.setFavicon(mIcon);
434 }
435 }
436
437 }
438
439 // TabChangeListener implementation
440
441 @Override
442 public void onCurrentTab(Tab tab) {
443 mTabs.setSelectedTab(mControl.getCurrentIndex());
444 TabViewData tvd = mTabMap.get(tab);
445 if (tvd != null) {
446 if (tvd.mUrl != null) {
447 mUrlView.setText(tvd.mUrl);
448 }
449 setProgress(tvd.mProgress);
450 }
451 }
452
453 @Override
454 public void onFavicon(Tab tab, Bitmap favicon) {
455 TabViewData tvd = mTabMap.get(tab);
456 if (tvd != null) {
457 tvd.setFavicon(favicon);
458 }
459 }
460
461 @Override
462 public void onNewTab(Tab tab) {
463 TabViewData tvd = buildTab(true, tab);
464 buildView(tvd);
465 }
466
467 @Override
468 public void onProgress(Tab tab, int progress) {
469 TabViewData tvd = mTabMap.get(tab);
470 if (tvd != null) {
471 tvd.setProgress(progress);
472 }
473 if (tab == mControl.getCurrentTab()) {
474 setProgress(progress);
475 }
476 }
477
478 @Override
479 public void onRemoveTab(Tab tab) {
480 TabViewData tvd = mTabMap.get(tab);
481 TabView tv = tvd.mTabView;
482 if (tv != null) {
483 mTabs.removeTab(tv);
484 }
485 mTabMap.remove(tab);
486 }
487
488 @Override
489 public void onUrlAndTitle(Tab tab, String url, String title) {
490 TabViewData tvd = mTabMap.get(tab);
491 if (tvd != null) {
492 tvd.setUrlAndTitle(url, title);
493 }
494 if ((url != null) && (tab == mControl.getCurrentTab())) {
495 mUrlView.setText(url);
496 }
497 }
498
499 @Override
500 public void onPageFinished(Tab tab) {
501 }
502
503 @Override
504 public void onPageStarted(Tab tab) {
Leon Scroggins571b3762010-05-26 10:25:01 -0400505 }
506
507}