blob: 6fc919e23d9152a5eafd32c0b390155f575e62d2 [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
58 private final Drawable mShowUrlDrawable;
59 private final Drawable mHideUrlDrawable;
Michael Kolba2b2ba82010-08-04 17:54:03 -070060
61 private TitleBarXLarge mTitleBar;
62
63 private TabScrollView mTabs;
Michael Kolbed217742010-08-10 17:52:34 -070064 private ImageButton mShowUrlButton;
Michael Kolba2b2ba82010-08-04 17:54:03 -070065 private TabControl mControl;
66
67 private Map<Tab, TabViewData> mTabMap;
68
69 private float mDensityScale;
70 private boolean mUserRequestedUrlbar;
71 private boolean mTitleVisible;
Michael Kolbed217742010-08-10 17:52:34 -070072 private boolean mShowUrlMode;
Michael Kolba2b2ba82010-08-04 17:54:03 -070073
74 public TabBar(BrowserActivity context, TabControl tabcontrol, TitleBarXLarge titlebar) {
75 super(context);
76 Resources res = context.getResources();
Michael Kolbed217742010-08-10 17:52:34 -070077 mTabWidthSelected = (int) res.getDimension(R.dimen.tab_width_selected);
78 mTabWidthUnselected = (int) res.getDimension(R.dimen.tab_width_unselected);
79 mShowUrlDrawable = res.getDrawable(R.drawable.ic_menu_showurl);
80 mHideUrlDrawable = res.getDrawable(R.drawable.ic_menu_hideurl);
Michael Kolba2b2ba82010-08-04 17:54:03 -070081
82 mTitleBar = titlebar;
83 mTitleBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
84 LayoutParams.WRAP_CONTENT));
85 mDensityScale = context.getResources().getDisplayMetrics().density;
86 mTabMap = new HashMap<Tab, TabViewData>();
87 mBrowserActivity = context;
88 mControl = tabcontrol;
89 Resources resources = context.getResources();
90 LayoutInflater factory = LayoutInflater.from(context);
91 factory.inflate(R.layout.tab_bar, this);
92 mTabs = (TabScrollView) findViewById(R.id.tabs);
Michael Kolbed217742010-08-10 17:52:34 -070093 mShowUrlButton = (ImageButton) findViewById(R.id.showurl);
Michael Kolba2b2ba82010-08-04 17:54:03 -070094
95 // TODO: Change enabled states based on whether you can go
96 // back/forward. Probably should be done inside onPageStarted.
97
Michael Kolba2b2ba82010-08-04 17:54:03 -070098 mShowUrlButton.setOnClickListener(this);
99
100 // build tabs
101 int tabcount = mControl.getTabCount();
102 for (int i = 0; i < tabcount; i++) {
103 Tab tab = mControl.getTab(i);
104 TabViewData data = buildTab(tab);
105 TabView tv = buildView(data);
106 }
107 mTabs.setSelectedTab(mControl.getCurrentIndex());
108
109 // register the tab change listener
110 mControl.setOnTabChangeListener(this);
111 mUserRequestedUrlbar = false;
112 mTitleVisible = true;
113 }
114
115 public void onClick(View view) {
116 if (mShowUrlButton == view) {
Michael Kolbed217742010-08-10 17:52:34 -0700117 if (mShowUrlMode) {
118 showUrlBar();
119 } else if (!isLoading()) {
120 ScrollWebView swv = (ScrollWebView) mControl.getCurrentWebView();
121 swv.hideEmbeddedTitleBar();
122 mBrowserActivity.hideFakeTitleBar();
123 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700124 } else if (mTabs.getSelectedTab() == view) {
Michael Kolbed217742010-08-10 17:52:34 -0700125 if (mBrowserActivity.isFakeTitleBarShowing() && !isLoading()) {
126 mBrowserActivity.hideFakeTitleBar();
127 } else {
128 showUrlBar();
129 }
130 // temporarily disabled
131 // mTitleBar.requestUrlInputFocus();
Michael Kolba2b2ba82010-08-04 17:54:03 -0700132 } else {
133 TabViewData data = (TabViewData) view.getTag();
134 int ix = mControl.getTabIndex(data.mTab);
135 mTabs.setSelectedTab(ix);
136 mBrowserActivity.switchToTab(ix);
137 }
138 }
139
Michael Kolbed217742010-08-10 17:52:34 -0700140 private void showUrlBar() {
141 mBrowserActivity.stopScrolling();
142 mBrowserActivity.showFakeTitleBar();
143 mUserRequestedUrlbar = true;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700144 }
145
Michael Kolbed217742010-08-10 17:52:34 -0700146 private void setShowUrlMode(boolean showUrl) {
147 mShowUrlMode = showUrl;
148 Drawable newDrawable = mShowUrlMode ? mShowUrlDrawable : mHideUrlDrawable;
149 mShowUrlButton.setImageDrawable(newDrawable);
150 }
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;
212 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);
234 mSelected = false;
235 mInLoad = false;
236 // update the status
237 updateFromData();
238 }
239
240 @Override
241 public void onClick(View v) {
242 if (v == mClose) {
243 closeTab();
244 }
245 }
246
247 private void updateFromData() {
248 mTabData.mTabView = this;
249 if (mTabData.mUrl != null) {
250 setDisplayTitle(mTabData.mUrl);
251 }
252 if (mTabData.mTitle != null) {
253 setDisplayTitle(mTabData.mTitle);
254 }
255 setProgress(mTabData.mProgress);
256 if (mTabData.mIcon != null) {
257 setFavicon(mTabData.mIcon);
258 }
259 if (mTabData.mLock != null) {
260 setLock(mTabData.mLock);
261 }
262 }
263
264 @Override
265 public void setSelected(boolean selected) {
266 mSelected = selected;
267 mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE);
268 mTitle.setTextColor(mSelected ? Color.BLACK : Color.GRAY);
269 super.setSelected(selected);
270 setLayoutParams(new LayoutParams(selected ?
Michael Kolbed217742010-08-10 17:52:34 -0700271 mTabWidthSelected : mTabWidthUnselected,
Michael Kolba2b2ba82010-08-04 17:54:03 -0700272 LayoutParams.MATCH_PARENT));
273 }
274
275 void setDisplayTitle(String title) {
276 mTitle.setText(title);
277 }
278
279 void setFavicon(Drawable d) {
280 mIconView.setImageDrawable(d);
281 }
282
283 void setLock(Drawable d) {
284 if (null == d) {
285 mLock.setVisibility(View.GONE);
286 } else {
287 mLock.setImageDrawable(d);
288 mLock.setVisibility(View.VISIBLE);
289 }
290 }
291
292 void setTitleCompoundDrawables(Drawable left, Drawable top,
293 Drawable right, Drawable bottom) {
294 mTitle.setCompoundDrawables(left, top, right, bottom);
295 }
296
297 void setProgress(int newProgress) {
298 if (newProgress >= PROGRESS_MAX) {
299 mInLoad = false;
300 } else {
301 if (!mInLoad && getWindowToken() != null) {
302 mInLoad = true;
303 }
304 }
305 }
306
307 private void closeTab() {
308 if (mTabData.mTab == mControl.getCurrentTab()) {
309 mBrowserActivity.closeCurrentWindow();
310 } else {
311 mBrowserActivity.closeTab(mTabData.mTab);
312 }
313 }
314
315 }
316
317 /**
318 * Store tab state within the title bar
319 */
320 class TabViewData {
321
322 Tab mTab;
323 TabView mTabView;
324 int mProgress;
325 Drawable mIcon;
326 Drawable mLock;
327 String mTitle;
328 String mUrl;
329
330 TabViewData(Tab tab) {
331 mTab = tab;
332 }
333
334 void setUrlAndTitle(String url, String title) {
335 mUrl = url;
336 mTitle = title;
337 if (mTabView != null) {
338 if (title != null) {
339 mTabView.setDisplayTitle(title);
340 } else if (url != null) {
341 mTabView.setDisplayTitle(url);
342 }
343 }
344 }
345
346 void setProgress(int newProgress) {
347 mProgress = newProgress;
348 if (mTabView != null) {
349 mTabView.setProgress(mProgress);
350 }
351 }
352
353 void setFavicon(Bitmap icon) {
354 Drawable[] array = new Drawable[3];
355 array[0] = new PaintDrawable(Color.BLACK);
356 array[1] = new PaintDrawable(Color.WHITE);
357 if (icon == null) {
358// array[2] = mGenericFavicon;
359 } else {
360 array[2] = new BitmapDrawable(icon);
361 }
362 LayerDrawable d = new LayerDrawable(array);
363 d.setLayerInset(1, 1, 1, 1, 1);
364 d.setLayerInset(2, 2, 2, 2, 2);
365 mIcon = d;
366 if (mTabView != null) {
367 mTabView.setFavicon(mIcon);
368 }
369 }
370
371 }
372
373 // TabChangeListener implementation
374
375 @Override
376 public void onCurrentTab(Tab tab) {
377 mTabs.setSelectedTab(mControl.getCurrentIndex());
378 TabViewData tvd = mTabMap.get(tab);
379 if (tvd != null) {
380 tvd.setProgress(tvd.mProgress);
381 // update the scroll state
382 WebView webview = tab.getWebView();
383 onScroll(webview.getVisibleTitleHeight() > 0);
384 }
385 }
386
387 @Override
388 public void onFavicon(Tab tab, Bitmap favicon) {
389 TabViewData tvd = mTabMap.get(tab);
390 if (tvd != null) {
391 tvd.setFavicon(favicon);
392 }
393 }
394
395 @Override
396 public void onNewTab(Tab tab) {
397 TabViewData tvd = buildTab(tab);
398 buildView(tvd);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700399 }
400
401 @Override
402 public void onProgress(Tab tab, int progress) {
403 TabViewData tvd = mTabMap.get(tab);
404 if (tvd != null) {
405 tvd.setProgress(progress);
406 }
407 }
408
409 @Override
410 public void onRemoveTab(Tab tab) {
411 TabViewData tvd = mTabMap.get(tab);
412 TabView tv = tvd.mTabView;
413 if (tv != null) {
414 mTabs.removeTab(tv);
415 }
416 mTabMap.remove(tab);
417 }
418
419 @Override
420 public void onUrlAndTitle(Tab tab, String url, String title) {
421 TabViewData tvd = mTabMap.get(tab);
422 if (tvd != null) {
423 tvd.setUrlAndTitle(url, title);
424 }
425 }
426
427 @Override
428 public void onPageFinished(Tab tab) {
429 }
430
431 @Override
432 public void onPageStarted(Tab tab) {
433 }
434
435
436 private boolean isLoading() {
437 return mTabMap.get(mControl.getCurrentTab()).mTabView.mInLoad;
438 }
439
Michael Kolba2b2ba82010-08-04 17:54:03 -0700440}