blob: b2c687d24c34ac96d13e86263a99ccca08ac0f02 [file] [log] [blame]
Michael Kolba2b2ba82010-08-04 17:54:03 -07001/*
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 Kolbebba8b42010-09-30 12:57:59 -070019import com.android.browser.ScrollWebView.ScrollListener;
20import com.android.browser.TabControl.TabChangeListener;
21
Michael Kolba2b2ba82010-08-04 17:54:03 -070022import android.content.Context;
23import android.content.res.Resources;
24import android.graphics.Bitmap;
25import android.graphics.Color;
26import android.graphics.drawable.BitmapDrawable;
27import android.graphics.drawable.Drawable;
28import android.graphics.drawable.LayerDrawable;
29import android.graphics.drawable.PaintDrawable;
30import android.view.ContextMenu;
Michael Kolbed217742010-08-10 17:52:34 -070031import android.view.Gravity;
Michael Kolba2b2ba82010-08-04 17:54:03 -070032import android.view.LayoutInflater;
33import android.view.MenuInflater;
34import android.view.View;
35import android.view.View.OnClickListener;
36import android.webkit.WebView;
Michael Kolbed217742010-08-10 17:52:34 -070037import android.widget.ImageButton;
Michael Kolba2b2ba82010-08-04 17:54:03 -070038import android.widget.ImageView;
39import android.widget.LinearLayout;
40import android.widget.TextView;
41
Michael Kolba2b2ba82010-08-04 17:54:03 -070042import java.util.HashMap;
43import java.util.Map;
44
45/**
46 * tabbed title bar for xlarge screen browser
47 */
48public class TabBar extends LinearLayout
49 implements TabChangeListener, ScrollListener, OnClickListener {
50
51 private static final int PROGRESS_MAX = 100;
52
Michael Kolba2b2ba82010-08-04 17:54:03 -070053 private BrowserActivity mBrowserActivity;
54
Michael Kolbed217742010-08-10 17:52:34 -070055 private final int mTabWidthSelected;
56 private final int mTabWidthUnselected;
57
Michael Kolba2b2ba82010-08-04 17:54:03 -070058 private TitleBarXLarge mTitleBar;
59
60 private TabScrollView mTabs;
Michael Kolba2b2ba82010-08-04 17:54:03 -070061 private TabControl mControl;
Michael Kolbebba8b42010-09-30 12:57:59 -070062 private ImageButton mNewTab;
63 private int mButtonWidth;
Michael Kolba2b2ba82010-08-04 17:54:03 -070064
65 private Map<Tab, TabViewData> mTabMap;
66
Michael Kolba2b2ba82010-08-04 17:54:03 -070067 private boolean mUserRequestedUrlbar;
68 private boolean mTitleVisible;
Michael Kolbed217742010-08-10 17:52:34 -070069 private boolean mShowUrlMode;
Michael Kolba2b2ba82010-08-04 17:54:03 -070070
71 public TabBar(BrowserActivity context, TabControl tabcontrol, TitleBarXLarge titlebar) {
72 super(context);
73 Resources res = context.getResources();
Michael Kolbed217742010-08-10 17:52:34 -070074 mTabWidthSelected = (int) res.getDimension(R.dimen.tab_width_selected);
75 mTabWidthUnselected = (int) res.getDimension(R.dimen.tab_width_unselected);
Michael Kolba2b2ba82010-08-04 17:54:03 -070076
77 mTitleBar = titlebar;
78 mTitleBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
79 LayoutParams.WRAP_CONTENT));
Michael Kolba2b2ba82010-08-04 17:54:03 -070080 mTabMap = new HashMap<Tab, TabViewData>();
81 mBrowserActivity = context;
82 mControl = tabcontrol;
83 Resources resources = context.getResources();
84 LayoutInflater factory = LayoutInflater.from(context);
85 factory.inflate(R.layout.tab_bar, this);
86 mTabs = (TabScrollView) findViewById(R.id.tabs);
Michael Kolbebba8b42010-09-30 12:57:59 -070087 mNewTab = (ImageButton) findViewById(R.id.newtab);
88 mNewTab.setOnClickListener(this);
Michael Kolba2b2ba82010-08-04 17:54:03 -070089
90 // TODO: Change enabled states based on whether you can go
91 // back/forward. Probably should be done inside onPageStarted.
92
Michael Kolba2b2ba82010-08-04 17:54:03 -070093 // build tabs
94 int tabcount = mControl.getTabCount();
95 for (int i = 0; i < tabcount; i++) {
96 Tab tab = mControl.getTab(i);
97 TabViewData data = buildTab(tab);
98 TabView tv = buildView(data);
99 }
100 mTabs.setSelectedTab(mControl.getCurrentIndex());
101
102 // register the tab change listener
103 mControl.setOnTabChangeListener(this);
104 mUserRequestedUrlbar = false;
105 mTitleVisible = true;
Michael Kolbebba8b42010-09-30 12:57:59 -0700106 mButtonWidth = -1;
107 }
108
109 @Override
110 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
111 if (mButtonWidth == -1) {
112 mButtonWidth = mNewTab.getMeasuredWidth();
113 }
114 int sw = mTabs.getMeasuredWidth();
115 int w = right-left;
116 if (w-sw < mButtonWidth) {
117 sw = w - mButtonWidth;
118 }
119 mTabs.layout(0, 0, sw, bottom-top );
120 mNewTab.layout(sw, 0, sw+mButtonWidth, bottom-top);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700121 }
122
123 public void onClick(View view) {
Michael Kolbe421c242010-10-04 19:29:01 -0700124 mBrowserActivity.removeComboView();
Michael Kolbebba8b42010-09-30 12:57:59 -0700125 if (mNewTab == view) {
126 mBrowserActivity.openTabToHomePage();
127 } else if (mTabs.getSelectedTab() == view) {
Michael Kolbed217742010-08-10 17:52:34 -0700128 if (mBrowserActivity.isFakeTitleBarShowing() && !isLoading()) {
129 mBrowserActivity.hideFakeTitleBar();
130 } else {
131 showUrlBar();
132 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700133 } else {
Michael Kolbebba8b42010-09-30 12:57:59 -0700134 int ix = mTabs.getChildIndex(view);
135 if (ix >= 0) {
136 mTabs.setSelectedTab(ix);
137 mBrowserActivity.switchToTab(ix);
138 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700139 }
140 }
141
Michael Kolbed217742010-08-10 17:52:34 -0700142 private void showUrlBar() {
143 mBrowserActivity.stopScrolling();
144 mBrowserActivity.showFakeTitleBar();
145 mUserRequestedUrlbar = true;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700146 }
147
Michael Kolbed217742010-08-10 17:52:34 -0700148 private void setShowUrlMode(boolean showUrl) {
149 mShowUrlMode = showUrl;
Michael Kolbed217742010-08-10 17:52:34 -0700150 }
151
152 // callback after fake titlebar is shown
153 void onShowTitleBar() {
154 setShowUrlMode(false);
155 }
156
157 // callback after fake titlebar is hidden
Michael Kolba2b2ba82010-08-04 17:54:03 -0700158 void onHideTitleBar() {
Michael Kolbed217742010-08-10 17:52:34 -0700159 setShowUrlMode(!mTitleVisible);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700160 Tab tab = mControl.getCurrentTab();
161 tab.getWebView().requestFocus();
162 mUserRequestedUrlbar = false;
163 }
164
Michael Kolbed217742010-08-10 17:52:34 -0700165 // webview scroll listener
166
167 @Override
168 public void onScroll(boolean titleVisible) {
169 mTitleVisible = titleVisible;
170 if (!mShowUrlMode && !mTitleVisible && !isLoading()) {
171 if (mUserRequestedUrlbar) {
172 mBrowserActivity.hideFakeTitleBar();
173 } else {
174 setShowUrlMode(true);
175 }
176 } else if (mTitleVisible && !isLoading()) {
177 if (mShowUrlMode) {
178 setShowUrlMode(false);
179 }
180 }
181 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700182
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
190 private TabViewData buildTab(Tab tab) {
191 TabViewData data = new TabViewData(tab);
192 mTabMap.put(tab, data);
193 return data;
194 }
195
196 private TabView buildView(final TabViewData data) {
197 TabView tv = new TabView(mBrowserActivity, data);
198 tv.setTag(data);
199 tv.setOnClickListener(this);
200 mTabs.addTab(tv);
201 return tv;
202 }
203
204 /**
205 * View used in the tab bar
206 */
207 class TabView extends LinearLayout implements OnClickListener {
208
209 TabViewData mTabData;
210 View mTabContent;
211 TextView mTitle;
Michael Kolbae62fd42010-08-18 16:33:28 -0700212 View mIncognito;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700213 ImageView mIconView;
214 ImageView mLock;
215 ImageView mClose;
216 boolean mSelected;
217 boolean mInLoad;
218
219 /**
220 * @param context
221 */
222 public TabView(Context context, TabViewData tab) {
223 super(context);
224 mTabData = tab;
Michael Kolbed217742010-08-10 17:52:34 -0700225 setGravity(Gravity.CENTER_VERTICAL);
226 setOrientation(LinearLayout.HORIZONTAL);
227 setBackgroundResource(R.drawable.tab_background);
Bjorn Bringertb1402a52010-10-12 10:53:12 +0100228 LayoutInflater inflater = LayoutInflater.from(getContext());
Michael Kolbed217742010-08-10 17:52:34 -0700229 mTabContent = inflater.inflate(R.layout.tab_title, this, true);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700230 mTitle = (TextView) mTabContent.findViewById(R.id.title);
231 mIconView = (ImageView) mTabContent.findViewById(R.id.favicon);
232 mLock = (ImageView) mTabContent.findViewById(R.id.lock);
233 mClose = (ImageView) mTabContent.findViewById(R.id.close);
234 mClose.setOnClickListener(this);
Michael Kolbae62fd42010-08-18 16:33:28 -0700235 mIncognito = mTabContent.findViewById(R.id.incognito);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700236 mSelected = false;
237 mInLoad = false;
238 // update the status
239 updateFromData();
240 }
241
242 @Override
243 public void onClick(View v) {
244 if (v == mClose) {
245 closeTab();
246 }
247 }
248
249 private void updateFromData() {
250 mTabData.mTabView = this;
251 if (mTabData.mUrl != null) {
252 setDisplayTitle(mTabData.mUrl);
253 }
254 if (mTabData.mTitle != null) {
255 setDisplayTitle(mTabData.mTitle);
256 }
257 setProgress(mTabData.mProgress);
258 if (mTabData.mIcon != null) {
259 setFavicon(mTabData.mIcon);
260 }
261 if (mTabData.mLock != null) {
262 setLock(mTabData.mLock);
263 }
Michael Kolbae62fd42010-08-18 16:33:28 -0700264 if (mTabData.mTab != null) {
265 mIncognito.setVisibility(
266 mTabData.mTab.getWebView().isPrivateBrowsingEnabled() ?
267 View.VISIBLE : View.GONE);
268 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700269 }
270
271 @Override
Michael Kolbb7b115e2010-09-25 16:59:37 -0700272 public void setActivated(boolean selected) {
Michael Kolba2b2ba82010-08-04 17:54:03 -0700273 mSelected = selected;
274 mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE);
Michael Kolbc7485ae2010-09-03 10:10:58 -0700275 mTitle.setTextAppearance(mBrowserActivity, mSelected ?
276 R.style.TabTitleSelected : R.style.TabTitleUnselected);
277 setHorizontalFadingEdgeEnabled(!mSelected);
278 setFadingEdgeLength(50);
Michael Kolbb7b115e2010-09-25 16:59:37 -0700279 super.setActivated(selected);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700280 setLayoutParams(new LayoutParams(selected ?
Michael Kolbed217742010-08-10 17:52:34 -0700281 mTabWidthSelected : mTabWidthUnselected,
Michael Kolba2b2ba82010-08-04 17:54:03 -0700282 LayoutParams.MATCH_PARENT));
283 }
284
285 void setDisplayTitle(String title) {
286 mTitle.setText(title);
287 }
288
289 void setFavicon(Drawable d) {
290 mIconView.setImageDrawable(d);
291 }
292
293 void setLock(Drawable d) {
294 if (null == d) {
295 mLock.setVisibility(View.GONE);
296 } else {
297 mLock.setImageDrawable(d);
298 mLock.setVisibility(View.VISIBLE);
299 }
300 }
301
302 void setTitleCompoundDrawables(Drawable left, Drawable top,
303 Drawable right, Drawable bottom) {
304 mTitle.setCompoundDrawables(left, top, right, bottom);
305 }
306
307 void setProgress(int newProgress) {
308 if (newProgress >= PROGRESS_MAX) {
309 mInLoad = false;
310 } else {
311 if (!mInLoad && getWindowToken() != null) {
312 mInLoad = true;
313 }
314 }
315 }
316
317 private void closeTab() {
318 if (mTabData.mTab == mControl.getCurrentTab()) {
319 mBrowserActivity.closeCurrentWindow();
320 } else {
321 mBrowserActivity.closeTab(mTabData.mTab);
322 }
323 }
324
325 }
326
327 /**
328 * Store tab state within the title bar
329 */
330 class TabViewData {
331
332 Tab mTab;
333 TabView mTabView;
334 int mProgress;
335 Drawable mIcon;
336 Drawable mLock;
337 String mTitle;
338 String mUrl;
339
340 TabViewData(Tab tab) {
341 mTab = tab;
342 }
343
344 void setUrlAndTitle(String url, String title) {
345 mUrl = url;
346 mTitle = title;
347 if (mTabView != null) {
348 if (title != null) {
349 mTabView.setDisplayTitle(title);
350 } else if (url != null) {
351 mTabView.setDisplayTitle(url);
352 }
353 }
354 }
355
356 void setProgress(int newProgress) {
357 mProgress = newProgress;
358 if (mTabView != null) {
359 mTabView.setProgress(mProgress);
360 }
361 }
362
363 void setFavicon(Bitmap icon) {
364 Drawable[] array = new Drawable[3];
365 array[0] = new PaintDrawable(Color.BLACK);
366 array[1] = new PaintDrawable(Color.WHITE);
367 if (icon == null) {
368// array[2] = mGenericFavicon;
369 } else {
370 array[2] = new BitmapDrawable(icon);
371 }
372 LayerDrawable d = new LayerDrawable(array);
373 d.setLayerInset(1, 1, 1, 1, 1);
374 d.setLayerInset(2, 2, 2, 2, 2);
375 mIcon = d;
376 if (mTabView != null) {
377 mTabView.setFavicon(mIcon);
378 }
379 }
380
381 }
382
383 // TabChangeListener implementation
384
385 @Override
386 public void onCurrentTab(Tab tab) {
387 mTabs.setSelectedTab(mControl.getCurrentIndex());
388 TabViewData tvd = mTabMap.get(tab);
389 if (tvd != null) {
390 tvd.setProgress(tvd.mProgress);
391 // update the scroll state
392 WebView webview = tab.getWebView();
393 onScroll(webview.getVisibleTitleHeight() > 0);
394 }
395 }
396
397 @Override
398 public void onFavicon(Tab tab, Bitmap favicon) {
399 TabViewData tvd = mTabMap.get(tab);
400 if (tvd != null) {
401 tvd.setFavicon(favicon);
402 }
403 }
404
405 @Override
406 public void onNewTab(Tab tab) {
407 TabViewData tvd = buildTab(tab);
408 buildView(tvd);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700409 }
410
411 @Override
412 public void onProgress(Tab tab, int progress) {
413 TabViewData tvd = mTabMap.get(tab);
414 if (tvd != null) {
415 tvd.setProgress(progress);
416 }
417 }
418
419 @Override
420 public void onRemoveTab(Tab tab) {
421 TabViewData tvd = mTabMap.get(tab);
Michael Kolbe2752f72010-10-25 16:50:16 -0700422 if (tvd != null) {
423 TabView tv = tvd.mTabView;
424 if (tv != null) {
425 mTabs.removeTab(tv);
426 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700427 }
428 mTabMap.remove(tab);
429 }
430
431 @Override
432 public void onUrlAndTitle(Tab tab, String url, String title) {
433 TabViewData tvd = mTabMap.get(tab);
434 if (tvd != null) {
435 tvd.setUrlAndTitle(url, title);
436 }
437 }
438
439 @Override
440 public void onPageFinished(Tab tab) {
441 }
442
443 @Override
444 public void onPageStarted(Tab tab) {
445 }
446
447
448 private boolean isLoading() {
449 return mTabMap.get(mControl.getCurrentTab()).mTabView.mInLoad;
450 }
451
Michael Kolba2b2ba82010-08-04 17:54:03 -0700452}