TabBar.java revision ef0742696d31a3661414089446ff9a3ddd786639
1/* 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 com.android.browser.ScrollWebView.ScrollListener; 20 21import android.app.Activity; 22import 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; 31import android.view.Gravity; 32import android.view.LayoutInflater; 33import android.view.MenuInflater; 34import android.view.View; 35import android.view.View.OnClickListener; 36import android.webkit.WebView; 37import android.widget.ImageButton; 38import android.widget.ImageView; 39import android.widget.LinearLayout; 40import android.widget.TextView; 41 42import java.util.HashMap; 43import java.util.List; 44import java.util.Map; 45 46/** 47 * tabbed title bar for xlarge screen browser 48 */ 49public class TabBar extends LinearLayout 50 implements ScrollListener, OnClickListener { 51 52 private static final int PROGRESS_MAX = 100; 53 54 private Activity mActivity; 55 private UiController mUiController; 56 private TabControl mTabControl; 57 private BaseUi mUi; 58 59 private final int mTabWidthSelected; 60 private final int mTabWidthUnselected; 61 62 private TabScrollView mTabs; 63 64 private ImageButton mNewTab; 65 private int mButtonWidth; 66 67 private Map<Tab, TabViewData> mTabMap; 68 69 private boolean mUserRequestedUrlbar; 70 private boolean mTitleVisible; 71 private boolean mShowUrlMode; 72 private boolean mHasReceivedTitle; 73 74 private Drawable mGenericFavicon; 75 private String mLoadingText; 76 77 public TabBar(Activity activity, UiController controller, BaseUi ui) { 78 super(activity); 79 mActivity = activity; 80 mUiController = controller; 81 mTabControl = mUiController.getTabControl(); 82 mUi = ui; 83 Resources res = activity.getResources(); 84 mTabWidthSelected = (int) res.getDimension(R.dimen.tab_width_selected); 85 mTabWidthUnselected = (int) res.getDimension(R.dimen.tab_width_unselected); 86 87 mTabMap = new HashMap<Tab, TabViewData>(); 88 Resources resources = activity.getResources(); 89 LayoutInflater factory = LayoutInflater.from(activity); 90 factory.inflate(R.layout.tab_bar, this); 91 mTabs = (TabScrollView) findViewById(R.id.tabs); 92 mNewTab = (ImageButton) findViewById(R.id.newtab); 93 mNewTab.setOnClickListener(this); 94 mGenericFavicon = res.getDrawable(R.drawable.app_web_browser_sm); 95 mLoadingText = res.getString(R.string.title_bar_loading); 96 97 // TODO: Change enabled states based on whether you can go 98 // back/forward. Probably should be done inside onPageStarted. 99 100 updateTabs(mUiController.getTabs()); 101 102 mUserRequestedUrlbar = false; 103 mTitleVisible = true; 104 mButtonWidth = -1; 105 } 106 107 void updateTabs(List<Tab> tabs) { 108 mTabs.clearTabs(); 109 mTabMap.clear(); 110 for (Tab tab : tabs) { 111 TabViewData data = buildTab(tab); 112 TabView tv = buildView(data); 113 } 114 mTabs.setSelectedTab(mTabControl.getCurrentIndex()); 115 } 116 117 @Override 118 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 119 if (mButtonWidth == -1) { 120 mButtonWidth = mNewTab.getMeasuredWidth(); 121 } 122 int sw = mTabs.getMeasuredWidth(); 123 int w = right-left; 124 if (w-sw < mButtonWidth) { 125 sw = w - mButtonWidth; 126 } 127 mTabs.layout(0, 0, sw, bottom-top ); 128 mNewTab.layout(sw, 0, sw+mButtonWidth, bottom-top); 129 } 130 131 public void onClick(View view) { 132 mUi.hideComboView(); 133 if (mNewTab == view) { 134 mUiController.openTabToHomePage(); 135 } else if (mTabs.getSelectedTab() == view) { 136 if (mUi.isFakeTitleBarShowing() && !isLoading()) { 137 mUi.hideFakeTitleBar(); 138 } else { 139 showUrlBar(); 140 } 141 } else { 142 int ix = mTabs.getChildIndex(view); 143 if (ix >= 0) { 144 mTabs.setSelectedTab(ix); 145 mUiController.switchToTab(ix); 146 } 147 } 148 } 149 150 private void showUrlBar() { 151 mUi.stopWebViewScrolling(); 152 mUi.showFakeTitleBar(); 153 mUserRequestedUrlbar = true; 154 } 155 156 private void setShowUrlMode(boolean showUrl) { 157 mShowUrlMode = showUrl; 158 } 159 160 // callback after fake titlebar is shown 161 void onShowTitleBar() { 162 setShowUrlMode(false); 163 } 164 165 // callback after fake titlebar is hidden 166 void onHideTitleBar() { 167 setShowUrlMode(!mTitleVisible); 168 Tab tab = mTabControl.getCurrentTab(); 169 tab.getWebView().requestFocus(); 170 mUserRequestedUrlbar = false; 171 } 172 173 // webview scroll listener 174 175 @Override 176 public void onScroll(boolean titleVisible) { 177 // isLoading is using the current tab, which initially might not be set yet 178 if (mTabControl.getCurrentTab() != null) { 179 mTitleVisible = titleVisible; 180 if (!mShowUrlMode && !mTitleVisible && !isLoading()) { 181 if (mUserRequestedUrlbar) { 182 mUi.hideFakeTitleBar(); 183 } else { 184 setShowUrlMode(true); 185 } 186 } else if (mTitleVisible && !isLoading()) { 187 if (mShowUrlMode) { 188 setShowUrlMode(false); 189 } 190 } 191 } 192 } 193 194 @Override 195 public void createContextMenu(ContextMenu menu) { 196 MenuInflater inflater = mActivity.getMenuInflater(); 197 inflater.inflate(R.menu.title_context, menu); 198 mActivity.onCreateContextMenu(menu, this, null); 199 } 200 201 private TabViewData buildTab(Tab tab) { 202 TabViewData data = new TabViewData(tab); 203 mTabMap.put(tab, data); 204 return data; 205 } 206 207 private TabView buildView(final TabViewData data) { 208 TabView tv = new TabView(mActivity, data); 209 tv.setTag(data); 210 tv.setOnClickListener(this); 211 mTabs.addTab(tv); 212 return tv; 213 } 214 215 /** 216 * View used in the tab bar 217 */ 218 class TabView extends LinearLayout implements OnClickListener { 219 220 TabViewData mTabData; 221 View mTabContent; 222 TextView mTitle; 223 View mIncognito; 224 ImageView mIconView; 225 ImageView mLock; 226 ImageView mClose; 227 boolean mSelected; 228 boolean mInLoad; 229 230 /** 231 * @param context 232 */ 233 public TabView(Context context, TabViewData tab) { 234 super(context); 235 mTabData = tab; 236 setGravity(Gravity.CENTER_VERTICAL); 237 setOrientation(LinearLayout.HORIZONTAL); 238 setBackgroundResource(R.drawable.tab_background); 239 LayoutInflater inflater = LayoutInflater.from(getContext()); 240 mTabContent = inflater.inflate(R.layout.tab_title, this, true); 241 mTitle = (TextView) mTabContent.findViewById(R.id.title); 242 mIconView = (ImageView) mTabContent.findViewById(R.id.favicon); 243 mLock = (ImageView) mTabContent.findViewById(R.id.lock); 244 mClose = (ImageView) mTabContent.findViewById(R.id.close); 245 mClose.setOnClickListener(this); 246 mIncognito = mTabContent.findViewById(R.id.incognito); 247 mSelected = false; 248 mInLoad = false; 249 // update the status 250 updateFromData(); 251 } 252 253 @Override 254 public void onClick(View v) { 255 if (v == mClose) { 256 closeTab(); 257 } 258 } 259 260 private void updateFromData() { 261 mTabData.mTabView = this; 262 if (mTabData.mUrl != null) { 263 setDisplayTitle(mTabData.mUrl); 264 } 265 if (mTabData.mTitle != null) { 266 setDisplayTitle(mTabData.mTitle); 267 } 268 setProgress(mTabData.mProgress); 269 if (mTabData.mIcon != null) { 270 setFavicon(mTabData.mIcon); 271 } 272 if (mTabData.mLock != null) { 273 setLock(mTabData.mLock); 274 } 275 if (mTabData.mTab != null) { 276 mIncognito.setVisibility( 277 mTabData.mTab.isPrivateBrowsingEnabled() ? 278 View.VISIBLE : View.GONE); 279 } 280 } 281 282 @Override 283 public void setActivated(boolean selected) { 284 mSelected = selected; 285 mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE); 286 mTitle.setTextAppearance(mActivity, mSelected ? 287 R.style.TabTitleSelected : R.style.TabTitleUnselected); 288 setHorizontalFadingEdgeEnabled(!mSelected); 289 setFadingEdgeLength(50); 290 super.setActivated(selected); 291 setLayoutParams(new LayoutParams(selected ? 292 mTabWidthSelected : mTabWidthUnselected, 293 LayoutParams.MATCH_PARENT)); 294 } 295 296 void setDisplayTitle(String title) { 297 mTitle.setText(title); 298 } 299 300 void setFavicon(Drawable d) { 301 mIconView.setImageDrawable(d); 302 } 303 304 void setLock(Drawable d) { 305 if (null == d) { 306 mLock.setVisibility(View.GONE); 307 } else { 308 mLock.setImageDrawable(d); 309 mLock.setVisibility(View.VISIBLE); 310 } 311 } 312 313 void setProgress(int newProgress) { 314 if (newProgress >= PROGRESS_MAX) { 315 mInLoad = false; 316 } else { 317 if (!mInLoad && getWindowToken() != null) { 318 mInLoad = true; 319 } 320 } 321 } 322 323 private void closeTab() { 324 if (mTabData.mTab == mTabControl.getCurrentTab()) { 325 mUiController.closeCurrentTab(); 326 } else { 327 mUiController.closeTab(mTabData.mTab); 328 } 329 } 330 331 } 332 333 /** 334 * Store tab state within the title bar 335 */ 336 class TabViewData { 337 338 Tab mTab; 339 TabView mTabView; 340 int mProgress; 341 Drawable mIcon; 342 Drawable mLock; 343 String mTitle; 344 String mUrl; 345 346 TabViewData(Tab tab) { 347 mTab = tab; 348 WebView web = tab.getWebView(); 349 if (web != null) { 350 setUrlAndTitle(web.getUrl(), web.getTitle()); 351 } 352 } 353 354 void setUrlAndTitle(String url, String title) { 355 mUrl = url; 356 mTitle = title; 357 if (mTabView != null) { 358 if (title != null) { 359 mTabView.setDisplayTitle(title); 360 } else if (url != null) { 361 mTabView.setDisplayTitle(UrlUtils.stripUrl(url)); 362 } 363 } 364 } 365 366 void setProgress(int newProgress) { 367 mProgress = newProgress; 368 if (mTabView != null) { 369 mTabView.setProgress(mProgress); 370 } 371 } 372 373 void setFavicon(Bitmap icon) { 374 Drawable[] array = new Drawable[3]; 375 array[0] = new PaintDrawable(Color.BLACK); 376 array[1] = new PaintDrawable(Color.WHITE); 377 if (icon == null) { 378 array[2] = mGenericFavicon; 379 } else { 380 array[2] = new BitmapDrawable(icon); 381 } 382 LayerDrawable d = new LayerDrawable(array); 383 d.setLayerInset(1, 1, 1, 1, 1); 384 d.setLayerInset(2, 2, 2, 2, 2); 385 mIcon = d; 386 if (mTabView != null) { 387 mTabView.setFavicon(mIcon); 388 } 389 } 390 391 } 392 393 // TabChangeListener implementation 394 395 public void onSetActiveTab(Tab tab) { 396 mTabs.setSelectedTab(mTabControl.getTabIndex(tab)); 397 TabViewData tvd = mTabMap.get(tab); 398 if (tvd != null) { 399 tvd.setProgress(tvd.mProgress); 400 // update the scroll state 401 WebView webview = tab.getWebView(); 402 onScroll(webview.getVisibleTitleHeight() > 0); 403 } 404 } 405 406 public void onFavicon(Tab tab, Bitmap favicon) { 407 TabViewData tvd = mTabMap.get(tab); 408 if (tvd != null) { 409 tvd.setFavicon(favicon); 410 } 411 } 412 413 public void onNewTab(Tab tab) { 414 TabViewData tvd = buildTab(tab); 415 buildView(tvd); 416 } 417 418 public void onProgress(Tab tab, int progress) { 419 TabViewData tvd = mTabMap.get(tab); 420 if (tvd != null) { 421 tvd.setProgress(progress); 422 } 423 } 424 425 public void onRemoveTab(Tab tab) { 426 TabViewData tvd = mTabMap.get(tab); 427 if (tvd != null) { 428 TabView tv = tvd.mTabView; 429 if (tv != null) { 430 mTabs.removeTab(tv); 431 } 432 } 433 mTabMap.remove(tab); 434 } 435 436 public void onUrlAndTitle(Tab tab, String url, String title) { 437 mHasReceivedTitle = true; 438 TabViewData tvd = mTabMap.get(tab); 439 if (tvd != null) { 440 tvd.setUrlAndTitle(url, title); 441 } 442 } 443 444 public void onPageFinished(Tab tab) { 445 if (!mHasReceivedTitle) { 446 TabViewData tvd = mTabMap.get(tab); 447 if (tvd != null) { 448 tvd.setUrlAndTitle(tvd.mUrl, null); 449 } 450 } 451 } 452 453 public void onPageStarted(Tab tab, String url, Bitmap favicon) { 454 mHasReceivedTitle = false; 455 TabViewData tvd = mTabMap.get(tab); 456 if (tvd != null) { 457 tvd.setFavicon(favicon); 458 tvd.setUrlAndTitle(url, mLoadingText); 459 } 460 } 461 462 private boolean isLoading() { 463 TabViewData tvd = mTabMap.get(mTabControl.getCurrentTab()); 464 if ((tvd != null) && (tvd.mTabView != null)) { 465 return tvd.mTabView.mInLoad; 466 } else { 467 return false; 468 } 469 } 470 471} 472