blob: cf0f27ca43bdf87343ed920a3ebed54826ebdd4c [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
19import android.content.Context;
20import android.content.res.Resources;
21import android.graphics.Bitmap;
22import android.graphics.Color;
23import android.graphics.drawable.BitmapDrawable;
24import android.graphics.drawable.Drawable;
25import android.graphics.drawable.LayerDrawable;
26import android.graphics.drawable.PaintDrawable;
27import android.view.ContextMenu;
Michael Kolbed217742010-08-10 17:52:34 -070028import android.view.Gravity;
Michael Kolba2b2ba82010-08-04 17:54:03 -070029import android.view.LayoutInflater;
30import android.view.MenuInflater;
31import android.view.View;
32import android.view.View.OnClickListener;
33import android.webkit.WebView;
Michael Kolbed217742010-08-10 17:52:34 -070034import android.widget.ImageButton;
Michael Kolba2b2ba82010-08-04 17:54:03 -070035import android.widget.ImageView;
36import android.widget.LinearLayout;
37import android.widget.TextView;
38
39import com.android.browser.ScrollWebView.ScrollListener;
40import com.android.browser.TabControl.TabChangeListener;
41
42import 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;
62
63 private Map<Tab, TabViewData> mTabMap;
64
65 private float mDensityScale;
66 private boolean mUserRequestedUrlbar;
67 private boolean mTitleVisible;
Michael Kolbed217742010-08-10 17:52:34 -070068 private boolean mShowUrlMode;
Michael Kolba2b2ba82010-08-04 17:54:03 -070069
70 public TabBar(BrowserActivity context, TabControl tabcontrol, TitleBarXLarge titlebar) {
71 super(context);
72 Resources res = context.getResources();
Michael Kolbed217742010-08-10 17:52:34 -070073 mTabWidthSelected = (int) res.getDimension(R.dimen.tab_width_selected);
74 mTabWidthUnselected = (int) res.getDimension(R.dimen.tab_width_unselected);
Michael Kolba2b2ba82010-08-04 17:54:03 -070075
76 mTitleBar = titlebar;
77 mTitleBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
78 LayoutParams.WRAP_CONTENT));
79 mDensityScale = context.getResources().getDisplayMetrics().density;
80 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 Kolba2b2ba82010-08-04 17:54:03 -070087
88 // TODO: Change enabled states based on whether you can go
89 // back/forward. Probably should be done inside onPageStarted.
90
Michael Kolba2b2ba82010-08-04 17:54:03 -070091 // build tabs
92 int tabcount = mControl.getTabCount();
93 for (int i = 0; i < tabcount; i++) {
94 Tab tab = mControl.getTab(i);
95 TabViewData data = buildTab(tab);
96 TabView tv = buildView(data);
97 }
98 mTabs.setSelectedTab(mControl.getCurrentIndex());
99
100 // register the tab change listener
101 mControl.setOnTabChangeListener(this);
102 mUserRequestedUrlbar = false;
103 mTitleVisible = true;
104 }
105
106 public void onClick(View view) {
Michael Kolbc7485ae2010-09-03 10:10:58 -0700107 if (mTabs.getSelectedTab() == view) {
Michael Kolbed217742010-08-10 17:52:34 -0700108 if (mBrowserActivity.isFakeTitleBarShowing() && !isLoading()) {
109 mBrowserActivity.hideFakeTitleBar();
110 } else {
111 showUrlBar();
112 }
113 // temporarily disabled
114 // mTitleBar.requestUrlInputFocus();
Michael Kolba2b2ba82010-08-04 17:54:03 -0700115 } else {
116 TabViewData data = (TabViewData) view.getTag();
117 int ix = mControl.getTabIndex(data.mTab);
118 mTabs.setSelectedTab(ix);
119 mBrowserActivity.switchToTab(ix);
120 }
121 }
122
Michael Kolbed217742010-08-10 17:52:34 -0700123 private void showUrlBar() {
124 mBrowserActivity.stopScrolling();
125 mBrowserActivity.showFakeTitleBar();
126 mUserRequestedUrlbar = true;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700127 }
128
Michael Kolbed217742010-08-10 17:52:34 -0700129 private void setShowUrlMode(boolean showUrl) {
130 mShowUrlMode = showUrl;
Michael Kolbed217742010-08-10 17:52:34 -0700131 }
132
133 // callback after fake titlebar is shown
134 void onShowTitleBar() {
135 setShowUrlMode(false);
136 }
137
138 // callback after fake titlebar is hidden
Michael Kolba2b2ba82010-08-04 17:54:03 -0700139 void onHideTitleBar() {
Michael Kolbed217742010-08-10 17:52:34 -0700140 setShowUrlMode(!mTitleVisible);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700141 Tab tab = mControl.getCurrentTab();
142 tab.getWebView().requestFocus();
143 mUserRequestedUrlbar = false;
144 }
145
Michael Kolbed217742010-08-10 17:52:34 -0700146 // webview scroll listener
147
148 @Override
149 public void onScroll(boolean titleVisible) {
150 mTitleVisible = titleVisible;
151 if (!mShowUrlMode && !mTitleVisible && !isLoading()) {
152 if (mUserRequestedUrlbar) {
153 mBrowserActivity.hideFakeTitleBar();
154 } else {
155 setShowUrlMode(true);
156 }
157 } else if (mTitleVisible && !isLoading()) {
158 if (mShowUrlMode) {
159 setShowUrlMode(false);
160 }
161 }
162 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700163
164 @Override
165 public void createContextMenu(ContextMenu menu) {
166 MenuInflater inflater = mBrowserActivity.getMenuInflater();
167 inflater.inflate(R.menu.title_context, menu);
168 mBrowserActivity.onCreateContextMenu(menu, this, null);
169 }
170
171 private TabViewData buildTab(Tab tab) {
172 TabViewData data = new TabViewData(tab);
173 mTabMap.put(tab, data);
174 return data;
175 }
176
177 private TabView buildView(final TabViewData data) {
178 TabView tv = new TabView(mBrowserActivity, data);
179 tv.setTag(data);
180 tv.setOnClickListener(this);
181 mTabs.addTab(tv);
182 return tv;
183 }
184
185 /**
186 * View used in the tab bar
187 */
188 class TabView extends LinearLayout implements OnClickListener {
189
190 TabViewData mTabData;
191 View mTabContent;
192 TextView mTitle;
Michael Kolbae62fd42010-08-18 16:33:28 -0700193 View mIncognito;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700194 ImageView mIconView;
195 ImageView mLock;
196 ImageView mClose;
197 boolean mSelected;
198 boolean mInLoad;
199
200 /**
201 * @param context
202 */
203 public TabView(Context context, TabViewData tab) {
204 super(context);
205 mTabData = tab;
Michael Kolbed217742010-08-10 17:52:34 -0700206 setGravity(Gravity.CENTER_VERTICAL);
207 setOrientation(LinearLayout.HORIZONTAL);
208 setBackgroundResource(R.drawable.tab_background);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700209 LayoutInflater inflater = LayoutInflater.from(mContext);
Michael Kolbed217742010-08-10 17:52:34 -0700210 mTabContent = inflater.inflate(R.layout.tab_title, this, true);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700211 mTitle = (TextView) mTabContent.findViewById(R.id.title);
212 mIconView = (ImageView) mTabContent.findViewById(R.id.favicon);
213 mLock = (ImageView) mTabContent.findViewById(R.id.lock);
214 mClose = (ImageView) mTabContent.findViewById(R.id.close);
215 mClose.setOnClickListener(this);
Michael Kolbae62fd42010-08-18 16:33:28 -0700216 mIncognito = mTabContent.findViewById(R.id.incognito);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700217 mSelected = false;
218 mInLoad = false;
219 // update the status
220 updateFromData();
221 }
222
223 @Override
224 public void onClick(View v) {
225 if (v == mClose) {
226 closeTab();
227 }
228 }
229
230 private void updateFromData() {
231 mTabData.mTabView = this;
232 if (mTabData.mUrl != null) {
233 setDisplayTitle(mTabData.mUrl);
234 }
235 if (mTabData.mTitle != null) {
236 setDisplayTitle(mTabData.mTitle);
237 }
238 setProgress(mTabData.mProgress);
239 if (mTabData.mIcon != null) {
240 setFavicon(mTabData.mIcon);
241 }
242 if (mTabData.mLock != null) {
243 setLock(mTabData.mLock);
244 }
Michael Kolbae62fd42010-08-18 16:33:28 -0700245 if (mTabData.mTab != null) {
246 mIncognito.setVisibility(
247 mTabData.mTab.getWebView().isPrivateBrowsingEnabled() ?
248 View.VISIBLE : View.GONE);
249 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700250 }
251
252 @Override
253 public void setSelected(boolean selected) {
254 mSelected = selected;
255 mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE);
Michael Kolbc7485ae2010-09-03 10:10:58 -0700256 mTitle.setTextAppearance(mBrowserActivity, mSelected ?
257 R.style.TabTitleSelected : R.style.TabTitleUnselected);
258 setHorizontalFadingEdgeEnabled(!mSelected);
259 setFadingEdgeLength(50);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700260 super.setSelected(selected);
261 setLayoutParams(new LayoutParams(selected ?
Michael Kolbed217742010-08-10 17:52:34 -0700262 mTabWidthSelected : mTabWidthUnselected,
Michael Kolba2b2ba82010-08-04 17:54:03 -0700263 LayoutParams.MATCH_PARENT));
264 }
265
266 void setDisplayTitle(String title) {
267 mTitle.setText(title);
268 }
269
270 void setFavicon(Drawable d) {
271 mIconView.setImageDrawable(d);
272 }
273
274 void setLock(Drawable d) {
275 if (null == d) {
276 mLock.setVisibility(View.GONE);
277 } else {
278 mLock.setImageDrawable(d);
279 mLock.setVisibility(View.VISIBLE);
280 }
281 }
282
283 void setTitleCompoundDrawables(Drawable left, Drawable top,
284 Drawable right, Drawable bottom) {
285 mTitle.setCompoundDrawables(left, top, right, bottom);
286 }
287
288 void setProgress(int newProgress) {
289 if (newProgress >= PROGRESS_MAX) {
290 mInLoad = false;
291 } else {
292 if (!mInLoad && getWindowToken() != null) {
293 mInLoad = true;
294 }
295 }
296 }
297
298 private void closeTab() {
299 if (mTabData.mTab == mControl.getCurrentTab()) {
300 mBrowserActivity.closeCurrentWindow();
301 } else {
302 mBrowserActivity.closeTab(mTabData.mTab);
303 }
304 }
305
306 }
307
308 /**
309 * Store tab state within the title bar
310 */
311 class TabViewData {
312
313 Tab mTab;
314 TabView mTabView;
315 int mProgress;
316 Drawable mIcon;
317 Drawable mLock;
318 String mTitle;
319 String mUrl;
320
321 TabViewData(Tab tab) {
322 mTab = tab;
323 }
324
325 void setUrlAndTitle(String url, String title) {
326 mUrl = url;
327 mTitle = title;
328 if (mTabView != null) {
329 if (title != null) {
330 mTabView.setDisplayTitle(title);
331 } else if (url != null) {
332 mTabView.setDisplayTitle(url);
333 }
334 }
335 }
336
337 void setProgress(int newProgress) {
338 mProgress = newProgress;
339 if (mTabView != null) {
340 mTabView.setProgress(mProgress);
341 }
342 }
343
344 void setFavicon(Bitmap icon) {
345 Drawable[] array = new Drawable[3];
346 array[0] = new PaintDrawable(Color.BLACK);
347 array[1] = new PaintDrawable(Color.WHITE);
348 if (icon == null) {
349// array[2] = mGenericFavicon;
350 } else {
351 array[2] = new BitmapDrawable(icon);
352 }
353 LayerDrawable d = new LayerDrawable(array);
354 d.setLayerInset(1, 1, 1, 1, 1);
355 d.setLayerInset(2, 2, 2, 2, 2);
356 mIcon = d;
357 if (mTabView != null) {
358 mTabView.setFavicon(mIcon);
359 }
360 }
361
362 }
363
364 // TabChangeListener implementation
365
366 @Override
367 public void onCurrentTab(Tab tab) {
368 mTabs.setSelectedTab(mControl.getCurrentIndex());
369 TabViewData tvd = mTabMap.get(tab);
370 if (tvd != null) {
371 tvd.setProgress(tvd.mProgress);
372 // update the scroll state
373 WebView webview = tab.getWebView();
374 onScroll(webview.getVisibleTitleHeight() > 0);
375 }
376 }
377
378 @Override
379 public void onFavicon(Tab tab, Bitmap favicon) {
380 TabViewData tvd = mTabMap.get(tab);
381 if (tvd != null) {
382 tvd.setFavicon(favicon);
383 }
384 }
385
386 @Override
387 public void onNewTab(Tab tab) {
388 TabViewData tvd = buildTab(tab);
389 buildView(tvd);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700390 }
391
392 @Override
393 public void onProgress(Tab tab, int progress) {
394 TabViewData tvd = mTabMap.get(tab);
395 if (tvd != null) {
396 tvd.setProgress(progress);
397 }
398 }
399
400 @Override
401 public void onRemoveTab(Tab tab) {
402 TabViewData tvd = mTabMap.get(tab);
403 TabView tv = tvd.mTabView;
404 if (tv != null) {
405 mTabs.removeTab(tv);
406 }
407 mTabMap.remove(tab);
408 }
409
410 @Override
411 public void onUrlAndTitle(Tab tab, String url, String title) {
412 TabViewData tvd = mTabMap.get(tab);
413 if (tvd != null) {
414 tvd.setUrlAndTitle(url, title);
415 }
416 }
417
418 @Override
419 public void onPageFinished(Tab tab) {
420 }
421
422 @Override
423 public void onPageStarted(Tab tab) {
424 }
425
426
427 private boolean isLoading() {
428 return mTabMap.get(mControl.getCurrentTab()).mTabView.mInLoad;
429 }
430
Michael Kolba2b2ba82010-08-04 17:54:03 -0700431}