blob: cf82e015ac8cbf6cec99731b7b633487b5f6b644 [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
Michael Kolb2d59c322011-01-25 13:18:55 -080019import android.animation.Animator;
20import android.animation.Animator.AnimatorListener;
21import android.animation.AnimatorSet;
22import android.animation.ObjectAnimator;
Michael Kolb8233fac2010-10-26 16:08:53 -070023import android.app.Activity;
Michael Kolba2b2ba82010-08-04 17:54:03 -070024import android.content.Context;
Michael Kolb678afc82011-05-17 14:52:41 -070025import android.content.res.Configuration;
Michael Kolba2b2ba82010-08-04 17:54:03 -070026import android.content.res.Resources;
27import android.graphics.Bitmap;
Michael Kolb2b5a13a2010-12-09 14:13:42 -080028import android.graphics.BitmapShader;
29import android.graphics.Canvas;
Michael Kolb467af0a2011-01-11 13:09:49 -080030import android.graphics.Matrix;
Michael Kolb2b5a13a2010-12-09 14:13:42 -080031import android.graphics.Paint;
32import android.graphics.Path;
33import android.graphics.Shader;
Michael Kolba2b2ba82010-08-04 17:54:03 -070034import android.graphics.drawable.Drawable;
Michael Kolbed217742010-08-10 17:52:34 -070035import android.view.Gravity;
Michael Kolba2b2ba82010-08-04 17:54:03 -070036import android.view.LayoutInflater;
Michael Kolba2b2ba82010-08-04 17:54:03 -070037import android.view.View;
38import android.view.View.OnClickListener;
Michael Kolbed217742010-08-10 17:52:34 -070039import android.widget.ImageButton;
Michael Kolba2b2ba82010-08-04 17:54:03 -070040import android.widget.ImageView;
41import android.widget.LinearLayout;
42import android.widget.TextView;
43
Michael Kolba2b2ba82010-08-04 17:54:03 -070044import java.util.HashMap;
Michael Kolb1bf23132010-11-19 12:55:12 -080045import java.util.List;
Michael Kolba2b2ba82010-08-04 17:54:03 -070046import java.util.Map;
47
48/**
49 * tabbed title bar for xlarge screen browser
50 */
Michael Kolbb14ff2f2011-07-01 15:33:56 -070051public class TabBar extends LinearLayout implements OnClickListener {
Michael Kolba2b2ba82010-08-04 17:54:03 -070052
53 private static final int PROGRESS_MAX = 100;
54
Michael Kolb8233fac2010-10-26 16:08:53 -070055 private Activity mActivity;
56 private UiController mUiController;
57 private TabControl mTabControl;
Michael Kolb66706532010-12-12 19:50:22 -080058 private XLargeUi mUi;
Michael Kolba2b2ba82010-08-04 17:54:03 -070059
John Reck034637c2011-08-11 11:34:44 -070060 private int mTabWidth;
Michael Kolbed217742010-08-10 17:52:34 -070061
Michael Kolba2b2ba82010-08-04 17:54:03 -070062 private TabScrollView mTabs;
Michael Kolb8233fac2010-10-26 16:08:53 -070063
Michael Kolbebba8b42010-09-30 12:57:59 -070064 private ImageButton mNewTab;
65 private int mButtonWidth;
Michael Kolba2b2ba82010-08-04 17:54:03 -070066
Michael Kolb94827b62011-01-08 14:23:45 -080067 private Map<Tab, TabView> mTabMap;
Michael Kolba2b2ba82010-08-04 17:54:03 -070068
Romain Guyc8373212011-01-07 19:15:16 -080069 private int mCurrentTextureWidth = 0;
70 private int mCurrentTextureHeight = 0;
71
Michael Kolb2b5a13a2010-12-09 14:13:42 -080072 private Drawable mActiveDrawable;
73 private Drawable mInactiveDrawable;
74
Romain Guyc8373212011-01-07 19:15:16 -080075 private final Paint mActiveShaderPaint = new Paint();
76 private final Paint mInactiveShaderPaint = new Paint();
Michael Kolbdc2ee1b2011-02-14 14:34:40 -080077 private final Paint mFocusPaint = new Paint();
Romain Guyc8373212011-01-07 19:15:16 -080078 private final Matrix mActiveMatrix = new Matrix();
79 private final Matrix mInactiveMatrix = new Matrix();
80
81 private BitmapShader mActiveShader;
82 private BitmapShader mInactiveShader;
83
Michael Kolb2b5a13a2010-12-09 14:13:42 -080084 private int mTabOverlap;
Michael Kolb5a72f182011-01-13 20:35:06 -080085 private int mAddTabOverlap;
Michael Kolb2b5a13a2010-12-09 14:13:42 -080086 private int mTabSliceWidth;
Michael Kolb376b5412010-12-15 11:52:57 -080087 private boolean mUseQuickControls;
Michael Kolb2b5a13a2010-12-09 14:13:42 -080088
Michael Kolb66706532010-12-12 19:50:22 -080089 public TabBar(Activity activity, UiController controller, XLargeUi ui) {
Michael Kolb8233fac2010-10-26 16:08:53 -070090 super(activity);
91 mActivity = activity;
92 mUiController = controller;
93 mTabControl = mUiController.getTabControl();
94 mUi = ui;
95 Resources res = activity.getResources();
John Reck034637c2011-08-11 11:34:44 -070096 mTabWidth = (int) res.getDimension(R.dimen.tab_width);
Michael Kolb2b5a13a2010-12-09 14:13:42 -080097 mActiveDrawable = res.getDrawable(R.drawable.bg_urlbar);
98 mInactiveDrawable = res.getDrawable(R.drawable.browsertab_inactive);
Michael Kolba2b2ba82010-08-04 17:54:03 -070099
Michael Kolb94827b62011-01-08 14:23:45 -0800100 mTabMap = new HashMap<Tab, TabView>();
Michael Kolb8233fac2010-10-26 16:08:53 -0700101 LayoutInflater factory = LayoutInflater.from(activity);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700102 factory.inflate(R.layout.tab_bar, this);
Michael Kolbf558f0d2011-01-13 19:24:18 -0800103 setPadding(0, (int) res.getDimension(R.dimen.tab_padding_top), 0, 0);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700104 mTabs = (TabScrollView) findViewById(R.id.tabs);
Michael Kolbebba8b42010-09-30 12:57:59 -0700105 mNewTab = (ImageButton) findViewById(R.id.newtab);
106 mNewTab.setOnClickListener(this);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700107
Michael Kolb1bf23132010-11-19 12:55:12 -0800108 updateTabs(mUiController.getTabs());
Michael Kolbebba8b42010-09-30 12:57:59 -0700109 mButtonWidth = -1;
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800110 // tab dimensions
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800111 mTabOverlap = (int) res.getDimension(R.dimen.tab_overlap);
Michael Kolb5a72f182011-01-13 20:35:06 -0800112 mAddTabOverlap = (int) res.getDimension(R.dimen.tab_addoverlap);
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800113 mTabSliceWidth = (int) res.getDimension(R.dimen.tab_slice);
Romain Guyc8373212011-01-07 19:15:16 -0800114
115 mActiveShaderPaint.setStyle(Paint.Style.FILL);
116 mActiveShaderPaint.setAntiAlias(true);
117
118 mInactiveShaderPaint.setStyle(Paint.Style.FILL);
119 mInactiveShaderPaint.setAntiAlias(true);
Michael Kolbb4cafc52011-01-12 16:55:04 -0800120
Michael Kolbdc2ee1b2011-02-14 14:34:40 -0800121 mFocusPaint.setStyle(Paint.Style.STROKE);
Michael Kolbeb7001c2011-02-16 16:07:33 -0800122 mFocusPaint.setStrokeWidth(res.getDimension(R.dimen.tab_focus_stroke));
Michael Kolbdc2ee1b2011-02-14 14:34:40 -0800123 mFocusPaint.setAntiAlias(true);
124 mFocusPaint.setColor(res.getColor(R.color.tabFocusHighlight));
Michael Kolbebba8b42010-09-30 12:57:59 -0700125 }
126
Michael Kolb678afc82011-05-17 14:52:41 -0700127 @Override
128 public void onConfigurationChanged(Configuration config) {
129 super.onConfigurationChanged(config);
130 Resources res = mActivity.getResources();
John Reck034637c2011-08-11 11:34:44 -0700131 mTabWidth = (int) res.getDimension(R.dimen.tab_width);
Michael Kolb678afc82011-05-17 14:52:41 -0700132 // force update of tab bar
133 mTabs.updateLayout();
134 }
135
Michael Kolb376b5412010-12-15 11:52:57 -0800136 void setUseQuickControls(boolean useQuickControls) {
137 mUseQuickControls = useQuickControls;
Michael Kolb467af0a2011-01-11 13:09:49 -0800138 mNewTab.setVisibility(mUseQuickControls ? View.GONE
139 : View.VISIBLE);
Michael Kolb376b5412010-12-15 11:52:57 -0800140 }
141
142 int getTabCount() {
143 return mTabMap.size();
144 }
145
Michael Kolb1bf23132010-11-19 12:55:12 -0800146 void updateTabs(List<Tab> tabs) {
147 mTabs.clearTabs();
148 mTabMap.clear();
149 for (Tab tab : tabs) {
Michael Kolb94827b62011-01-08 14:23:45 -0800150 TabView tv = buildTabView(tab);
Michael Kolb2d59c322011-01-25 13:18:55 -0800151 mTabs.addTab(tv);
Michael Kolb1bf23132010-11-19 12:55:12 -0800152 }
Michael Kolbc831b632011-05-11 09:30:34 -0700153 mTabs.setSelectedTab(mTabControl.getCurrentPosition());
Michael Kolb1bf23132010-11-19 12:55:12 -0800154 }
155
Michael Kolbebba8b42010-09-30 12:57:59 -0700156 @Override
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800157 protected void onMeasure(int hspec, int vspec) {
158 super.onMeasure(hspec, vspec);
159 int w = getMeasuredWidth();
160 // adjust for new tab overlap
Michael Kolb467af0a2011-01-11 13:09:49 -0800161 if (!mUseQuickControls) {
Michael Kolb5a72f182011-01-13 20:35:06 -0800162 w -= mAddTabOverlap;
Michael Kolb467af0a2011-01-11 13:09:49 -0800163 }
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800164 setMeasuredDimension(w, getMeasuredHeight());
165 }
166
167 @Override
Michael Kolbebba8b42010-09-30 12:57:59 -0700168 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800169 // use paddingLeft and paddingTop
170 int pl = getPaddingLeft();
171 int pt = getPaddingTop();
Michael Kolbebba8b42010-09-30 12:57:59 -0700172 int sw = mTabs.getMeasuredWidth();
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800173 int w = right - left - pl;
Michael Kolbb4cafc52011-01-12 16:55:04 -0800174 if (mUseQuickControls) {
175 mButtonWidth = 0;
176 } else {
Michael Kolb5a72f182011-01-13 20:35:06 -0800177 mButtonWidth = mNewTab.getMeasuredWidth() - mAddTabOverlap;
Michael Kolbb4cafc52011-01-12 16:55:04 -0800178 if (w-sw < mButtonWidth) {
179 sw = w - mButtonWidth;
180 }
Michael Kolbebba8b42010-09-30 12:57:59 -0700181 }
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800182 mTabs.layout(pl, pt, pl + sw, bottom - top);
183 // adjust for overlap
Michael Kolbb4cafc52011-01-12 16:55:04 -0800184 if (!mUseQuickControls) {
Michael Kolb5a72f182011-01-13 20:35:06 -0800185 mNewTab.layout(pl + sw - mAddTabOverlap, pt,
186 pl + sw + mButtonWidth - mAddTabOverlap, bottom - top);
Michael Kolbb4cafc52011-01-12 16:55:04 -0800187 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700188 }
189
190 public void onClick(View view) {
Michael Kolbebba8b42010-09-30 12:57:59 -0700191 if (mNewTab == view) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700192 mUiController.openTabToHomePage();
Michael Kolbebba8b42010-09-30 12:57:59 -0700193 } else if (mTabs.getSelectedTab() == view) {
Michael Kolb467af0a2011-01-11 13:09:49 -0800194 if (mUseQuickControls) {
Michael Kolb7cdc4902011-02-03 17:54:40 -0800195 if (mUi.isTitleBarShowing() && !isLoading()) {
196 mUi.stopEditingUrl();
197 mUi.hideTitleBar();
Michael Kolb467af0a2011-01-11 13:09:49 -0800198 } else {
199 mUi.stopWebViewScrolling();
Michael Kolb1f9b3562012-04-24 14:38:34 -0700200 mUi.editUrl(false, false);
Michael Kolb467af0a2011-01-11 13:09:49 -0800201 }
Michael Kolb7cdc4902011-02-03 17:54:40 -0800202 } else if (mUi.isTitleBarShowing() && !isLoading()) {
203 mUi.stopEditingUrl();
204 mUi.hideTitleBar();
Michael Kolbed217742010-08-10 17:52:34 -0700205 } else {
206 showUrlBar();
207 }
Michael Kolbc831b632011-05-11 09:30:34 -0700208 } else if (view instanceof TabView) {
209 final Tab tab = ((TabView) view).mTab;
Michael Kolbebba8b42010-09-30 12:57:59 -0700210 int ix = mTabs.getChildIndex(view);
211 if (ix >= 0) {
212 mTabs.setSelectedTab(ix);
Michael Kolbc831b632011-05-11 09:30:34 -0700213 mUiController.switchToTab(tab);
Michael Kolbebba8b42010-09-30 12:57:59 -0700214 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700215 }
216 }
217
Michael Kolbed217742010-08-10 17:52:34 -0700218 private void showUrlBar() {
Michael Kolb8233fac2010-10-26 16:08:53 -0700219 mUi.stopWebViewScrolling();
Michael Kolb7cdc4902011-02-03 17:54:40 -0800220 mUi.showTitleBar();
Michael Kolba2b2ba82010-08-04 17:54:03 -0700221 }
222
Michael Kolb94827b62011-01-08 14:23:45 -0800223 private TabView buildTabView(Tab tab) {
224 TabView tabview = new TabView(mActivity, tab);
225 mTabMap.put(tab, tabview);
226 tabview.setOnClickListener(this);
Michael Kolb94827b62011-01-08 14:23:45 -0800227 return tabview;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700228 }
229
Romain Guyc8373212011-01-07 19:15:16 -0800230 private static Bitmap getDrawableAsBitmap(Drawable drawable, int width, int height) {
231 Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
232 Canvas c = new Canvas(b);
233 drawable.setBounds(0, 0, width, height);
234 drawable.draw(c);
Dianne Hackborn43cfe8a2011-08-02 16:59:35 -0700235 c.setBitmap(null);
Romain Guyc8373212011-01-07 19:15:16 -0800236 return b;
Michael Kolbb4cafc52011-01-12 16:55:04 -0800237 }
238
Michael Kolba2b2ba82010-08-04 17:54:03 -0700239 /**
240 * View used in the tab bar
241 */
242 class TabView extends LinearLayout implements OnClickListener {
243
Michael Kolb94827b62011-01-08 14:23:45 -0800244 Tab mTab;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700245 View mTabContent;
246 TextView mTitle;
Michael Kolbae62fd42010-08-18 16:33:28 -0700247 View mIncognito;
John Reck541f55a2011-06-07 16:34:43 -0700248 View mSnapshot;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700249 ImageView mIconView;
250 ImageView mLock;
251 ImageView mClose;
252 boolean mSelected;
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800253 Path mPath;
Michael Kolbeb7001c2011-02-16 16:07:33 -0800254 Path mFocusPath;
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800255 int[] mWindowPos;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700256
257 /**
258 * @param context
259 */
Michael Kolb94827b62011-01-08 14:23:45 -0800260 public TabView(Context context, Tab tab) {
Michael Kolba2b2ba82010-08-04 17:54:03 -0700261 super(context);
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800262 setWillNotDraw(false);
263 mPath = new Path();
Michael Kolbeb7001c2011-02-16 16:07:33 -0800264 mFocusPath = new Path();
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800265 mWindowPos = new int[2];
Michael Kolb94827b62011-01-08 14:23:45 -0800266 mTab = tab;
Michael Kolbed217742010-08-10 17:52:34 -0700267 setGravity(Gravity.CENTER_VERTICAL);
268 setOrientation(LinearLayout.HORIZONTAL);
Michael Kolb49f15832011-01-25 15:02:27 -0800269 setPadding(mTabOverlap, 0, mTabSliceWidth, 0);
Bjorn Bringertb1402a52010-10-12 10:53:12 +0100270 LayoutInflater inflater = LayoutInflater.from(getContext());
Michael Kolbed217742010-08-10 17:52:34 -0700271 mTabContent = inflater.inflate(R.layout.tab_title, this, true);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700272 mTitle = (TextView) mTabContent.findViewById(R.id.title);
273 mIconView = (ImageView) mTabContent.findViewById(R.id.favicon);
274 mLock = (ImageView) mTabContent.findViewById(R.id.lock);
275 mClose = (ImageView) mTabContent.findViewById(R.id.close);
276 mClose.setOnClickListener(this);
Michael Kolbae62fd42010-08-18 16:33:28 -0700277 mIncognito = mTabContent.findViewById(R.id.incognito);
John Reck541f55a2011-06-07 16:34:43 -0700278 mSnapshot = mTabContent.findViewById(R.id.snapshot);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700279 mSelected = false;
Michael Kolba2b2ba82010-08-04 17:54:03 -0700280 // update the status
Michael Kolb94827b62011-01-08 14:23:45 -0800281 updateFromTab();
Michael Kolba2b2ba82010-08-04 17:54:03 -0700282 }
283
284 @Override
285 public void onClick(View v) {
286 if (v == mClose) {
287 closeTab();
288 }
289 }
290
Michael Kolb94827b62011-01-08 14:23:45 -0800291 private void updateFromTab() {
292 String displayTitle = mTab.getTitle();
John Reck30c714c2010-12-16 17:30:34 -0800293 if (displayTitle == null) {
Michael Kolb94827b62011-01-08 14:23:45 -0800294 displayTitle = mTab.getUrl();
Michael Kolba2b2ba82010-08-04 17:54:03 -0700295 }
John Reck30c714c2010-12-16 17:30:34 -0800296 setDisplayTitle(displayTitle);
Michael Kolb94827b62011-01-08 14:23:45 -0800297 if (mTab.getFavicon() != null) {
John Reck034637c2011-08-11 11:34:44 -0700298 setFavicon(mUi.getFaviconDrawable(mTab.getFavicon()));
Michael Kolba2b2ba82010-08-04 17:54:03 -0700299 }
John Reck541f55a2011-06-07 16:34:43 -0700300 updateTabIcons();
301 }
302
303 private void updateTabIcons() {
304 mIncognito.setVisibility(
305 mTab.isPrivateBrowsingEnabled() ?
306 View.VISIBLE : View.GONE);
307 mSnapshot.setVisibility(mTab.isSnapshot()
308 ? View.VISIBLE : View.GONE);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700309 }
310
311 @Override
Michael Kolbb7b115e2010-09-25 16:59:37 -0700312 public void setActivated(boolean selected) {
Michael Kolba2b2ba82010-08-04 17:54:03 -0700313 mSelected = selected;
314 mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE);
John Reck034637c2011-08-11 11:34:44 -0700315 mIconView.setVisibility(mSelected ? View.GONE : View.VISIBLE);
Michael Kolb8233fac2010-10-26 16:08:53 -0700316 mTitle.setTextAppearance(mActivity, mSelected ?
Michael Kolbc7485ae2010-09-03 10:10:58 -0700317 R.style.TabTitleSelected : R.style.TabTitleUnselected);
318 setHorizontalFadingEdgeEnabled(!mSelected);
Michael Kolbb7b115e2010-09-25 16:59:37 -0700319 super.setActivated(selected);
Michael Kolb678afc82011-05-17 14:52:41 -0700320 updateLayoutParams();
Michael Kolbdc2ee1b2011-02-14 14:34:40 -0800321 setFocusable(!selected);
322 postInvalidate();
Michael Kolba2b2ba82010-08-04 17:54:03 -0700323 }
324
Michael Kolb678afc82011-05-17 14:52:41 -0700325 public void updateLayoutParams() {
326 LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();
John Reck034637c2011-08-11 11:34:44 -0700327 lp.width = mTabWidth;
Michael Kolb678afc82011-05-17 14:52:41 -0700328 lp.height = LayoutParams.MATCH_PARENT;
329 setLayoutParams(lp);
330 }
331
Michael Kolba2b2ba82010-08-04 17:54:03 -0700332 void setDisplayTitle(String title) {
333 mTitle.setText(title);
334 }
335
336 void setFavicon(Drawable d) {
337 mIconView.setImageDrawable(d);
338 }
339
340 void setLock(Drawable d) {
341 if (null == d) {
342 mLock.setVisibility(View.GONE);
343 } else {
344 mLock.setImageDrawable(d);
345 mLock.setVisibility(View.VISIBLE);
346 }
347 }
348
Michael Kolba2b2ba82010-08-04 17:54:03 -0700349 private void closeTab() {
Michael Kolb94827b62011-01-08 14:23:45 -0800350 if (mTab == mTabControl.getCurrentTab()) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700351 mUiController.closeCurrentTab();
Michael Kolba2b2ba82010-08-04 17:54:03 -0700352 } else {
Michael Kolb94827b62011-01-08 14:23:45 -0800353 mUiController.closeTab(mTab);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700354 }
355 }
356
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800357 @Override
358 protected void onLayout(boolean changed, int l, int t, int r, int b) {
359 super.onLayout(changed, l, t, r, b);
360 setTabPath(mPath, 0, 0, r - l, b - t);
Michael Kolbeb7001c2011-02-16 16:07:33 -0800361 setFocusPath(mFocusPath, 0, 0, r - l, b - t);
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800362 }
Michael Kolbb4cafc52011-01-12 16:55:04 -0800363
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800364 @Override
365 protected void dispatchDraw(Canvas canvas) {
Romain Guyc8373212011-01-07 19:15:16 -0800366 if (mCurrentTextureWidth != mUi.getContentWidth() ||
367 mCurrentTextureHeight != getHeight()) {
368 mCurrentTextureWidth = mUi.getContentWidth();
369 mCurrentTextureHeight = getHeight();
370
371 if (mCurrentTextureWidth > 0 && mCurrentTextureHeight > 0) {
372 Bitmap activeTexture = getDrawableAsBitmap(mActiveDrawable,
373 mCurrentTextureWidth, mCurrentTextureHeight);
374 Bitmap inactiveTexture = getDrawableAsBitmap(mInactiveDrawable,
375 mCurrentTextureWidth, mCurrentTextureHeight);
376
377 mActiveShader = new BitmapShader(activeTexture,
378 Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
379 mActiveShaderPaint.setShader(mActiveShader);
Michael Kolbb4cafc52011-01-12 16:55:04 -0800380
Romain Guyc8373212011-01-07 19:15:16 -0800381 mInactiveShader = new BitmapShader(inactiveTexture,
382 Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
383 mInactiveShaderPaint.setShader(mInactiveShader);
384 }
385 }
Michael Kolb05902aa2011-02-22 17:43:38 -0800386 // add some monkey protection
387 if ((mActiveShader != null) && (mInactiveShader != null)) {
388 int state = canvas.save();
389 getLocationInWindow(mWindowPos);
390 Paint paint = mSelected ? mActiveShaderPaint : mInactiveShaderPaint;
391 drawClipped(canvas, paint, mPath, mWindowPos[0]);
392 canvas.restoreToCount(state);
393 }
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800394 super.dispatchDraw(canvas);
395 }
396
Romain Guyc8373212011-01-07 19:15:16 -0800397 private void drawClipped(Canvas canvas, Paint paint, Path clipPath, int left) {
398 // TODO: We should change the matrix/shader only when needed
399 final Matrix matrix = mSelected ? mActiveMatrix : mInactiveMatrix;
400 matrix.setTranslate(-left, 0.0f);
401 (mSelected ? mActiveShader : mInactiveShader).setLocalMatrix(matrix);
402 canvas.drawPath(clipPath, paint);
Michael Kolbdc2ee1b2011-02-14 14:34:40 -0800403 if (isFocused()) {
Michael Kolbeb7001c2011-02-16 16:07:33 -0800404 canvas.drawPath(mFocusPath, mFocusPaint);
Michael Kolbdc2ee1b2011-02-14 14:34:40 -0800405 }
Michael Kolb2b5a13a2010-12-09 14:13:42 -0800406 }
407
408 private void setTabPath(Path path, int l, int t, int r, int b) {
409 path.reset();
410 path.moveTo(l, b);
411 path.lineTo(l, t);
412 path.lineTo(r - mTabSliceWidth, t);
413 path.lineTo(r, b);
414 path.close();
415 }
416
Michael Kolbeb7001c2011-02-16 16:07:33 -0800417 private void setFocusPath(Path path, int l, int t, int r, int b) {
418 path.reset();
419 path.moveTo(l, b);
420 path.lineTo(l, t);
421 path.lineTo(r - mTabSliceWidth, t);
422 path.lineTo(r, b);
423 }
424
Michael Kolba2b2ba82010-08-04 17:54:03 -0700425 }
426
Michael Kolb2d59c322011-01-25 13:18:55 -0800427 private void animateTabOut(final Tab tab, final TabView tv) {
428 ObjectAnimator scalex = ObjectAnimator.ofFloat(tv, "scaleX", 1.0f, 0.0f);
429 ObjectAnimator scaley = ObjectAnimator.ofFloat(tv, "scaleY", 1.0f, 0.0f);
Michael Kolb49f15832011-01-25 15:02:27 -0800430 ObjectAnimator alpha = ObjectAnimator.ofFloat(tv, "alpha", 1.0f, 0.0f);
Michael Kolb2d59c322011-01-25 13:18:55 -0800431 AnimatorSet animator = new AnimatorSet();
Michael Kolb49f15832011-01-25 15:02:27 -0800432 animator.playTogether(scalex, scaley, alpha);
Michael Kolb2d59c322011-01-25 13:18:55 -0800433 animator.setDuration(150);
434 animator.addListener(new AnimatorListener() {
435
436 @Override
437 public void onAnimationCancel(Animator animation) {
438 }
439
440 @Override
441 public void onAnimationEnd(Animator animation) {
442 mTabs.removeTab(tv);
443 mTabMap.remove(tab);
Michael Kolb8814d732011-01-26 11:22:30 -0800444 mUi.onRemoveTabCompleted(tab);
Michael Kolb2d59c322011-01-25 13:18:55 -0800445 }
446
447 @Override
448 public void onAnimationRepeat(Animator animation) {
449 }
450
451 @Override
452 public void onAnimationStart(Animator animation) {
453 }
454
455 });
456 animator.start();
457 }
458
459 private void animateTabIn(final Tab tab, final TabView tv) {
Michael Kolb49f15832011-01-25 15:02:27 -0800460 ObjectAnimator scalex = ObjectAnimator.ofFloat(tv, "scaleX", 0.0f, 1.0f);
Michael Kolb2d59c322011-01-25 13:18:55 -0800461 scalex.setDuration(150);
462 scalex.addListener(new AnimatorListener() {
463
464 @Override
465 public void onAnimationCancel(Animator animation) {
466 }
467
468 @Override
469 public void onAnimationEnd(Animator animation) {
Michael Kolb8814d732011-01-26 11:22:30 -0800470 mUi.onAddTabCompleted(tab);
Michael Kolb2d59c322011-01-25 13:18:55 -0800471 }
472
473 @Override
474 public void onAnimationRepeat(Animator animation) {
475 }
476
477 @Override
478 public void onAnimationStart(Animator animation) {
479 mTabs.addTab(tv);
480 }
481
482 });
483 scalex.start();
484 }
485
Michael Kolba2b2ba82010-08-04 17:54:03 -0700486 // TabChangeListener implementation
487
Michael Kolb8233fac2010-10-26 16:08:53 -0700488 public void onSetActiveTab(Tab tab) {
Michael Kolbc831b632011-05-11 09:30:34 -0700489 mTabs.setSelectedTab(mTabControl.getTabPosition(tab));
Michael Kolba2b2ba82010-08-04 17:54:03 -0700490 }
491
Michael Kolba2b2ba82010-08-04 17:54:03 -0700492 public void onFavicon(Tab tab, Bitmap favicon) {
Michael Kolb94827b62011-01-08 14:23:45 -0800493 TabView tv = mTabMap.get(tab);
494 if (tv != null) {
John Reck034637c2011-08-11 11:34:44 -0700495 tv.setFavicon(mUi.getFaviconDrawable(favicon));
Michael Kolba2b2ba82010-08-04 17:54:03 -0700496 }
497 }
498
Michael Kolba2b2ba82010-08-04 17:54:03 -0700499 public void onNewTab(Tab tab) {
Michael Kolb94827b62011-01-08 14:23:45 -0800500 TabView tv = buildTabView(tab);
Michael Kolb2d59c322011-01-25 13:18:55 -0800501 animateTabIn(tab, tv);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700502 }
503
Michael Kolba2b2ba82010-08-04 17:54:03 -0700504 public void onRemoveTab(Tab tab) {
Michael Kolb94827b62011-01-08 14:23:45 -0800505 TabView tv = mTabMap.get(tab);
506 if (tv != null) {
Michael Kolb2d59c322011-01-25 13:18:55 -0800507 animateTabOut(tab, tv);
508 } else {
509 mTabMap.remove(tab);
Michael Kolba2b2ba82010-08-04 17:54:03 -0700510 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700511 }
512
Michael Kolba2b2ba82010-08-04 17:54:03 -0700513 public void onUrlAndTitle(Tab tab, String url, String title) {
Michael Kolb94827b62011-01-08 14:23:45 -0800514 TabView tv = mTabMap.get(tab);
515 if (tv != null) {
516 if (title != null) {
517 tv.setDisplayTitle(title);
518 } else if (url != null) {
519 tv.setDisplayTitle(UrlUtils.stripUrl(url));
520 }
John Reck541f55a2011-06-07 16:34:43 -0700521 tv.updateTabIcons();
Michael Kolba2b2ba82010-08-04 17:54:03 -0700522 }
523 }
524
Michael Kolba2b2ba82010-08-04 17:54:03 -0700525 private boolean isLoading() {
Michael Kolb1c3a6d22011-12-15 15:28:49 -0800526 Tab tab = mTabControl.getCurrentTab();
527 if (tab != null) {
528 return tab.inPageLoad();
Michael Kolb8233fac2010-10-26 16:08:53 -0700529 } else {
530 return false;
531 }
Michael Kolba2b2ba82010-08-04 17:54:03 -0700532 }
533
Michael Kolba2b2ba82010-08-04 17:54:03 -0700534}