TabBar.java revision ed217745066c160f785626e9a15ebe70af5e25e4
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 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; 224 setGravity(Gravity.CENTER_VERTICAL); 225 setOrientation(LinearLayout.HORIZONTAL); 226 setBackgroundResource(R.drawable.tab_background); 227 LayoutInflater inflater = LayoutInflater.from(mContext); 228 mTabContent = inflater.inflate(R.layout.tab_title, this, true); 229 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 ? 271 mTabWidthSelected : mTabWidthUnselected, 272 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); 399 } 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 440} 441