blob: 9217ef2a99e55696b16fdd44f5965ec992799b49 [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 Kolbebba8b42010-09-30 12:57:59 -0700124 if (mNewTab == view) {
125 mBrowserActivity.openTabToHomePage();
126 } else if (mTabs.getSelectedTab() == view) {
Michael Kolbed217742010-08-10 17:52:34 -0700127 if (mBrowserActivity.isFakeTitleBarShowing() && !isLoading()) {
128 mBrowserActivity.hideFakeTitleBar();
129 } else {
130 showUrlBar();
131 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700132 } else {
Michael Kolbebba8b42010-09-30 12:57:59 -0700133 int ix = mTabs.getChildIndex(view);
134 if (ix >= 0) {
135 mTabs.setSelectedTab(ix);
136 mBrowserActivity.switchToTab(ix);
137 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700138 }
139 }
140
Michael Kolbed217742010-08-10 17:52:34 -0700141 private void showUrlBar() {
142 mBrowserActivity.stopScrolling();
143 mBrowserActivity.showFakeTitleBar();
144 mUserRequestedUrlbar = true;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700145 }
146
Michael Kolbed217742010-08-10 17:52:34 -0700147 private void setShowUrlMode(boolean showUrl) {
148 mShowUrlMode = showUrl;
Michael Kolbed217742010-08-10 17:52:34 -0700149 }
150
151 // callback after fake titlebar is shown
152 void onShowTitleBar() {
153 setShowUrlMode(false);
154 }
155
156 // callback after fake titlebar is hidden
Michael Kolba2b2ba82010-08-04 17:54:03 -0700157 void onHideTitleBar() {
Michael Kolbed217742010-08-10 17:52:34 -0700158 setShowUrlMode(!mTitleVisible);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700159 Tab tab = mControl.getCurrentTab();
160 tab.getWebView().requestFocus();
161 mUserRequestedUrlbar = false;
162 }
163
Michael Kolbed217742010-08-10 17:52:34 -0700164 // webview scroll listener
165
166 @Override
167 public void onScroll(boolean titleVisible) {
168 mTitleVisible = titleVisible;
169 if (!mShowUrlMode && !mTitleVisible && !isLoading()) {
170 if (mUserRequestedUrlbar) {
171 mBrowserActivity.hideFakeTitleBar();
172 } else {
173 setShowUrlMode(true);
174 }
175 } else if (mTitleVisible && !isLoading()) {
176 if (mShowUrlMode) {
177 setShowUrlMode(false);
178 }
179 }
180 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700181
182 @Override
183 public void createContextMenu(ContextMenu menu) {
184 MenuInflater inflater = mBrowserActivity.getMenuInflater();
185 inflater.inflate(R.menu.title_context, menu);
186 mBrowserActivity.onCreateContextMenu(menu, this, null);
187 }
188
189 private TabViewData buildTab(Tab tab) {
190 TabViewData data = new TabViewData(tab);
191 mTabMap.put(tab, data);
192 return data;
193 }
194
195 private TabView buildView(final TabViewData data) {
196 TabView tv = new TabView(mBrowserActivity, data);
197 tv.setTag(data);
198 tv.setOnClickListener(this);
199 mTabs.addTab(tv);
200 return tv;
201 }
202
203 /**
204 * View used in the tab bar
205 */
206 class TabView extends LinearLayout implements OnClickListener {
207
208 TabViewData mTabData;
209 View mTabContent;
210 TextView mTitle;
Michael Kolbae62fd42010-08-18 16:33:28 -0700211 View mIncognito;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700212 ImageView mIconView;
213 ImageView mLock;
214 ImageView mClose;
215 boolean mSelected;
216 boolean mInLoad;
217
218 /**
219 * @param context
220 */
221 public TabView(Context context, TabViewData tab) {
222 super(context);
223 mTabData = tab;
Michael Kolbed217742010-08-10 17:52:34 -0700224 setGravity(Gravity.CENTER_VERTICAL);
225 setOrientation(LinearLayout.HORIZONTAL);
226 setBackgroundResource(R.drawable.tab_background);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700227 LayoutInflater inflater = LayoutInflater.from(mContext);
Michael Kolbed217742010-08-10 17:52:34 -0700228 mTabContent = inflater.inflate(R.layout.tab_title, this, true);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700229 mTitle = (TextView) mTabContent.findViewById(R.id.title);
230 mIconView = (ImageView) mTabContent.findViewById(R.id.favicon);
231 mLock = (ImageView) mTabContent.findViewById(R.id.lock);
232 mClose = (ImageView) mTabContent.findViewById(R.id.close);
233 mClose.setOnClickListener(this);
Michael Kolbae62fd42010-08-18 16:33:28 -0700234 mIncognito = mTabContent.findViewById(R.id.incognito);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700235 mSelected = false;
236 mInLoad = false;
237 // update the status
238 updateFromData();
239 }
240
241 @Override
242 public void onClick(View v) {
243 if (v == mClose) {
244 closeTab();
245 }
246 }
247
248 private void updateFromData() {
249 mTabData.mTabView = this;
250 if (mTabData.mUrl != null) {
251 setDisplayTitle(mTabData.mUrl);
252 }
253 if (mTabData.mTitle != null) {
254 setDisplayTitle(mTabData.mTitle);
255 }
256 setProgress(mTabData.mProgress);
257 if (mTabData.mIcon != null) {
258 setFavicon(mTabData.mIcon);
259 }
260 if (mTabData.mLock != null) {
261 setLock(mTabData.mLock);
262 }
Michael Kolbae62fd42010-08-18 16:33:28 -0700263 if (mTabData.mTab != null) {
264 mIncognito.setVisibility(
265 mTabData.mTab.getWebView().isPrivateBrowsingEnabled() ?
266 View.VISIBLE : View.GONE);
267 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700268 }
269
270 @Override
Michael Kolbb7b115e2010-09-25 16:59:37 -0700271 public void setActivated(boolean selected) {
Michael Kolba2b2ba82010-08-04 17:54:03 -0700272 mSelected = selected;
273 mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE);
Michael Kolbc7485ae2010-09-03 10:10:58 -0700274 mTitle.setTextAppearance(mBrowserActivity, mSelected ?
275 R.style.TabTitleSelected : R.style.TabTitleUnselected);
276 setHorizontalFadingEdgeEnabled(!mSelected);
277 setFadingEdgeLength(50);
Michael Kolbb7b115e2010-09-25 16:59:37 -0700278 super.setActivated(selected);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700279 setLayoutParams(new LayoutParams(selected ?
Michael Kolbed217742010-08-10 17:52:34 -0700280 mTabWidthSelected : mTabWidthUnselected,
Michael Kolba2b2ba82010-08-04 17:54:03 -0700281 LayoutParams.MATCH_PARENT));
282 }
283
284 void setDisplayTitle(String title) {
285 mTitle.setText(title);
286 }
287
288 void setFavicon(Drawable d) {
289 mIconView.setImageDrawable(d);
290 }
291
292 void setLock(Drawable d) {
293 if (null == d) {
294 mLock.setVisibility(View.GONE);
295 } else {
296 mLock.setImageDrawable(d);
297 mLock.setVisibility(View.VISIBLE);
298 }
299 }
300
301 void setTitleCompoundDrawables(Drawable left, Drawable top,
302 Drawable right, Drawable bottom) {
303 mTitle.setCompoundDrawables(left, top, right, bottom);
304 }
305
306 void setProgress(int newProgress) {
307 if (newProgress >= PROGRESS_MAX) {
308 mInLoad = false;
309 } else {
310 if (!mInLoad && getWindowToken() != null) {
311 mInLoad = true;
312 }
313 }
314 }
315
316 private void closeTab() {
317 if (mTabData.mTab == mControl.getCurrentTab()) {
318 mBrowserActivity.closeCurrentWindow();
319 } else {
320 mBrowserActivity.closeTab(mTabData.mTab);
321 }
322 }
323
324 }
325
326 /**
327 * Store tab state within the title bar
328 */
329 class TabViewData {
330
331 Tab mTab;
332 TabView mTabView;
333 int mProgress;
334 Drawable mIcon;
335 Drawable mLock;
336 String mTitle;
337 String mUrl;
338
339 TabViewData(Tab tab) {
340 mTab = tab;
341 }
342
343 void setUrlAndTitle(String url, String title) {
344 mUrl = url;
345 mTitle = title;
346 if (mTabView != null) {
347 if (title != null) {
348 mTabView.setDisplayTitle(title);
349 } else if (url != null) {
350 mTabView.setDisplayTitle(url);
351 }
352 }
353 }
354
355 void setProgress(int newProgress) {
356 mProgress = newProgress;
357 if (mTabView != null) {
358 mTabView.setProgress(mProgress);
359 }
360 }
361
362 void setFavicon(Bitmap icon) {
363 Drawable[] array = new Drawable[3];
364 array[0] = new PaintDrawable(Color.BLACK);
365 array[1] = new PaintDrawable(Color.WHITE);
366 if (icon == null) {
367// array[2] = mGenericFavicon;
368 } else {
369 array[2] = new BitmapDrawable(icon);
370 }
371 LayerDrawable d = new LayerDrawable(array);
372 d.setLayerInset(1, 1, 1, 1, 1);
373 d.setLayerInset(2, 2, 2, 2, 2);
374 mIcon = d;
375 if (mTabView != null) {
376 mTabView.setFavicon(mIcon);
377 }
378 }
379
380 }
381
382 // TabChangeListener implementation
383
384 @Override
385 public void onCurrentTab(Tab tab) {
386 mTabs.setSelectedTab(mControl.getCurrentIndex());
387 TabViewData tvd = mTabMap.get(tab);
388 if (tvd != null) {
389 tvd.setProgress(tvd.mProgress);
390 // update the scroll state
391 WebView webview = tab.getWebView();
392 onScroll(webview.getVisibleTitleHeight() > 0);
393 }
394 }
395
396 @Override
397 public void onFavicon(Tab tab, Bitmap favicon) {
398 TabViewData tvd = mTabMap.get(tab);
399 if (tvd != null) {
400 tvd.setFavicon(favicon);
401 }
402 }
403
404 @Override
405 public void onNewTab(Tab tab) {
406 TabViewData tvd = buildTab(tab);
407 buildView(tvd);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700408 }
409
410 @Override
411 public void onProgress(Tab tab, int progress) {
412 TabViewData tvd = mTabMap.get(tab);
413 if (tvd != null) {
414 tvd.setProgress(progress);
415 }
416 }
417
418 @Override
419 public void onRemoveTab(Tab tab) {
420 TabViewData tvd = mTabMap.get(tab);
421 TabView tv = tvd.mTabView;
422 if (tv != null) {
423 mTabs.removeTab(tv);
424 }
425 mTabMap.remove(tab);
426 }
427
428 @Override
429 public void onUrlAndTitle(Tab tab, String url, String title) {
430 TabViewData tvd = mTabMap.get(tab);
431 if (tvd != null) {
432 tvd.setUrlAndTitle(url, title);
433 }
434 }
435
436 @Override
437 public void onPageFinished(Tab tab) {
438 }
439
440 @Override
441 public void onPageStarted(Tab tab) {
442 }
443
444
445 private boolean isLoading() {
446 return mTabMap.get(mControl.getCurrentTab()).mTabView.mInLoad;
447 }
448
Michael Kolba2b2ba82010-08-04 17:54:03 -0700449}