TabBar.java revision e421c2472744ca7d35906f86204790ee97b91ca2
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; 20import com.android.browser.TabControl.TabChangeListener; 21 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.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 53 private BrowserActivity mBrowserActivity; 54 55 private final int mTabWidthSelected; 56 private final int mTabWidthUnselected; 57 58 private TitleBarXLarge mTitleBar; 59 60 private TabScrollView mTabs; 61 private TabControl mControl; 62 private ImageButton mNewTab; 63 private int mButtonWidth; 64 65 private Map<Tab, TabViewData> mTabMap; 66 67 private boolean mUserRequestedUrlbar; 68 private boolean mTitleVisible; 69 private boolean mShowUrlMode; 70 71 public TabBar(BrowserActivity context, TabControl tabcontrol, TitleBarXLarge titlebar) { 72 super(context); 73 Resources res = context.getResources(); 74 mTabWidthSelected = (int) res.getDimension(R.dimen.tab_width_selected); 75 mTabWidthUnselected = (int) res.getDimension(R.dimen.tab_width_unselected); 76 77 mTitleBar = titlebar; 78 mTitleBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 79 LayoutParams.WRAP_CONTENT)); 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); 87 mNewTab = (ImageButton) findViewById(R.id.newtab); 88 mNewTab.setOnClickListener(this); 89 90 // TODO: Change enabled states based on whether you can go 91 // back/forward. Probably should be done inside onPageStarted. 92 93 // 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; 106 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); 121 } 122 123 public void onClick(View view) { 124 mBrowserActivity.removeComboView(); 125 if (mNewTab == view) { 126 mBrowserActivity.openTabToHomePage(); 127 } else if (mTabs.getSelectedTab() == view) { 128 if (mBrowserActivity.isFakeTitleBarShowing() && !isLoading()) { 129 mBrowserActivity.hideFakeTitleBar(); 130 } else { 131 showUrlBar(); 132 } 133 } else { 134 int ix = mTabs.getChildIndex(view); 135 if (ix >= 0) { 136 mTabs.setSelectedTab(ix); 137 mBrowserActivity.switchToTab(ix); 138 } 139 } 140 } 141 142 private void showUrlBar() { 143 mBrowserActivity.stopScrolling(); 144 mBrowserActivity.showFakeTitleBar(); 145 mUserRequestedUrlbar = true; 146 } 147 148 private void setShowUrlMode(boolean showUrl) { 149 mShowUrlMode = showUrl; 150 } 151 152 // callback after fake titlebar is shown 153 void onShowTitleBar() { 154 setShowUrlMode(false); 155 } 156 157 // callback after fake titlebar is hidden 158 void onHideTitleBar() { 159 setShowUrlMode(!mTitleVisible); 160 Tab tab = mControl.getCurrentTab(); 161 tab.getWebView().requestFocus(); 162 mUserRequestedUrlbar = false; 163 } 164 165 // 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 } 182 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 View mIncognito; 213 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; 225 setGravity(Gravity.CENTER_VERTICAL); 226 setOrientation(LinearLayout.HORIZONTAL); 227 setBackgroundResource(R.drawable.tab_background); 228 LayoutInflater inflater = LayoutInflater.from(mContext); 229 mTabContent = inflater.inflate(R.layout.tab_title, this, true); 230 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); 235 mIncognito = mTabContent.findViewById(R.id.incognito); 236 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 } 264 if (mTabData.mTab != null) { 265 mIncognito.setVisibility( 266 mTabData.mTab.getWebView().isPrivateBrowsingEnabled() ? 267 View.VISIBLE : View.GONE); 268 } 269 } 270 271 @Override 272 public void setActivated(boolean selected) { 273 mSelected = selected; 274 mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE); 275 mTitle.setTextAppearance(mBrowserActivity, mSelected ? 276 R.style.TabTitleSelected : R.style.TabTitleUnselected); 277 setHorizontalFadingEdgeEnabled(!mSelected); 278 setFadingEdgeLength(50); 279 super.setActivated(selected); 280 setLayoutParams(new LayoutParams(selected ? 281 mTabWidthSelected : mTabWidthUnselected, 282 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); 409 } 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); 422 TabView tv = tvd.mTabView; 423 if (tv != null) { 424 mTabs.removeTab(tv); 425 } 426 mTabMap.remove(tab); 427 } 428 429 @Override 430 public void onUrlAndTitle(Tab tab, String url, String title) { 431 TabViewData tvd = mTabMap.get(tab); 432 if (tvd != null) { 433 tvd.setUrlAndTitle(url, title); 434 } 435 } 436 437 @Override 438 public void onPageFinished(Tab tab) { 439 } 440 441 @Override 442 public void onPageStarted(Tab tab) { 443 } 444 445 446 private boolean isLoading() { 447 return mTabMap.get(mControl.getCurrentTab()).mTabView.mInLoad; 448 } 449 450} 451