TabBar.java revision ae62fd48652f989335db21a03d8289ecc5b57e88
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 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; 28import android.view.Gravity; 29import android.view.LayoutInflater; 30import android.view.MenuInflater; 31import android.view.View; 32import android.view.View.OnClickListener; 33import android.webkit.WebView; 34import android.widget.ImageButton; 35import 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 53 private BrowserActivity mBrowserActivity; 54 55 private final int mTabWidthSelected; 56 private final int mTabWidthUnselected; 57 58 private final Drawable mShowUrlDrawable; 59 private final Drawable mHideUrlDrawable; 60 61 private TitleBarXLarge mTitleBar; 62 63 private TabScrollView mTabs; 64 private ImageButton mShowUrlButton; 65 private TabControl mControl; 66 67 private Map<Tab, TabViewData> mTabMap; 68 69 private float mDensityScale; 70 private boolean mUserRequestedUrlbar; 71 private boolean mTitleVisible; 72 private boolean mShowUrlMode; 73 74 public TabBar(BrowserActivity context, TabControl tabcontrol, TitleBarXLarge titlebar) { 75 super(context); 76 Resources res = context.getResources(); 77 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); 81 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); 93 mShowUrlButton = (ImageButton) findViewById(R.id.showurl); 94 95 // TODO: Change enabled states based on whether you can go 96 // back/forward. Probably should be done inside onPageStarted. 97 98 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) { 117 if (mShowUrlMode) { 118 showUrlBar(); 119 } else if (!isLoading()) { 120 ScrollWebView swv = (ScrollWebView) mControl.getCurrentWebView(); 121 swv.hideEmbeddedTitleBar(); 122 mBrowserActivity.hideFakeTitleBar(); 123 } 124 } else if (mTabs.getSelectedTab() == view) { 125 if (mBrowserActivity.isFakeTitleBarShowing() && !isLoading()) { 126 mBrowserActivity.hideFakeTitleBar(); 127 } else { 128 showUrlBar(); 129 } 130 // temporarily disabled 131 // mTitleBar.requestUrlInputFocus(); 132 } 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 140 private void showUrlBar() { 141 mBrowserActivity.stopScrolling(); 142 mBrowserActivity.showFakeTitleBar(); 143 mUserRequestedUrlbar = true; 144 } 145 146 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 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 setSelected(boolean selected) { 273 mSelected = selected; 274 mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE); 275 mTitle.setTextColor(mSelected ? Color.BLACK : Color.GRAY); 276 super.setSelected(selected); 277 setLayoutParams(new LayoutParams(selected ? 278 mTabWidthSelected : mTabWidthUnselected, 279 LayoutParams.MATCH_PARENT)); 280 } 281 282 void setDisplayTitle(String title) { 283 mTitle.setText(title); 284 } 285 286 void setFavicon(Drawable d) { 287 mIconView.setImageDrawable(d); 288 } 289 290 void setLock(Drawable d) { 291 if (null == d) { 292 mLock.setVisibility(View.GONE); 293 } else { 294 mLock.setImageDrawable(d); 295 mLock.setVisibility(View.VISIBLE); 296 } 297 } 298 299 void setTitleCompoundDrawables(Drawable left, Drawable top, 300 Drawable right, Drawable bottom) { 301 mTitle.setCompoundDrawables(left, top, right, bottom); 302 } 303 304 void setProgress(int newProgress) { 305 if (newProgress >= PROGRESS_MAX) { 306 mInLoad = false; 307 } else { 308 if (!mInLoad && getWindowToken() != null) { 309 mInLoad = true; 310 } 311 } 312 } 313 314 private void closeTab() { 315 if (mTabData.mTab == mControl.getCurrentTab()) { 316 mBrowserActivity.closeCurrentWindow(); 317 } else { 318 mBrowserActivity.closeTab(mTabData.mTab); 319 } 320 } 321 322 } 323 324 /** 325 * Store tab state within the title bar 326 */ 327 class TabViewData { 328 329 Tab mTab; 330 TabView mTabView; 331 int mProgress; 332 Drawable mIcon; 333 Drawable mLock; 334 String mTitle; 335 String mUrl; 336 337 TabViewData(Tab tab) { 338 mTab = tab; 339 } 340 341 void setUrlAndTitle(String url, String title) { 342 mUrl = url; 343 mTitle = title; 344 if (mTabView != null) { 345 if (title != null) { 346 mTabView.setDisplayTitle(title); 347 } else if (url != null) { 348 mTabView.setDisplayTitle(url); 349 } 350 } 351 } 352 353 void setProgress(int newProgress) { 354 mProgress = newProgress; 355 if (mTabView != null) { 356 mTabView.setProgress(mProgress); 357 } 358 } 359 360 void setFavicon(Bitmap icon) { 361 Drawable[] array = new Drawable[3]; 362 array[0] = new PaintDrawable(Color.BLACK); 363 array[1] = new PaintDrawable(Color.WHITE); 364 if (icon == null) { 365// array[2] = mGenericFavicon; 366 } else { 367 array[2] = new BitmapDrawable(icon); 368 } 369 LayerDrawable d = new LayerDrawable(array); 370 d.setLayerInset(1, 1, 1, 1, 1); 371 d.setLayerInset(2, 2, 2, 2, 2); 372 mIcon = d; 373 if (mTabView != null) { 374 mTabView.setFavicon(mIcon); 375 } 376 } 377 378 } 379 380 // TabChangeListener implementation 381 382 @Override 383 public void onCurrentTab(Tab tab) { 384 mTabs.setSelectedTab(mControl.getCurrentIndex()); 385 TabViewData tvd = mTabMap.get(tab); 386 if (tvd != null) { 387 tvd.setProgress(tvd.mProgress); 388 // update the scroll state 389 WebView webview = tab.getWebView(); 390 onScroll(webview.getVisibleTitleHeight() > 0); 391 } 392 } 393 394 @Override 395 public void onFavicon(Tab tab, Bitmap favicon) { 396 TabViewData tvd = mTabMap.get(tab); 397 if (tvd != null) { 398 tvd.setFavicon(favicon); 399 } 400 } 401 402 @Override 403 public void onNewTab(Tab tab) { 404 TabViewData tvd = buildTab(tab); 405 buildView(tvd); 406 } 407 408 @Override 409 public void onProgress(Tab tab, int progress) { 410 TabViewData tvd = mTabMap.get(tab); 411 if (tvd != null) { 412 tvd.setProgress(progress); 413 } 414 } 415 416 @Override 417 public void onRemoveTab(Tab tab) { 418 TabViewData tvd = mTabMap.get(tab); 419 TabView tv = tvd.mTabView; 420 if (tv != null) { 421 mTabs.removeTab(tv); 422 } 423 mTabMap.remove(tab); 424 } 425 426 @Override 427 public void onUrlAndTitle(Tab tab, String url, String title) { 428 TabViewData tvd = mTabMap.get(tab); 429 if (tvd != null) { 430 tvd.setUrlAndTitle(url, title); 431 } 432 } 433 434 @Override 435 public void onPageFinished(Tab tab) { 436 } 437 438 @Override 439 public void onPageStarted(Tab tab) { 440 } 441 442 443 private boolean isLoading() { 444 return mTabMap.get(mControl.getCurrentTab()).mTabView.mInLoad; 445 } 446 447} 448