1a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb/*
2a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * Copyright (C) 2010 The Android Open Source Project
3a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb *
4a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
5a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * you may not use this file except in compliance with the License.
6a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * You may obtain a copy of the License at
7a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb *
8a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
9a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb *
10a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * Unless required by applicable law or agreed to in writing, software
11a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
12a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * See the License for the specific language governing permissions and
14a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * limitations under the License.
15a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb */
16a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
17a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbpackage com.android.browser;
18a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
192d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolbimport android.animation.Animator;
202d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolbimport android.animation.Animator.AnimatorListener;
212d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolbimport android.animation.AnimatorSet;
222d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolbimport android.animation.ObjectAnimator;
238233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.Activity;
24a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.content.Context;
25678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolbimport android.content.res.Configuration;
26a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.content.res.Resources;
27a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.graphics.Bitmap;
282b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolbimport android.graphics.BitmapShader;
292b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolbimport android.graphics.Canvas;
30467af0a9e10715b86005992555d1c0a0654d136fMichael Kolbimport android.graphics.Matrix;
312b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolbimport android.graphics.Paint;
322b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolbimport android.graphics.Path;
332b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolbimport android.graphics.Shader;
34a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.graphics.drawable.Drawable;
35ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolbimport android.view.Gravity;
36a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.view.LayoutInflater;
37a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.view.View;
38a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.view.View.OnClickListener;
39ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolbimport android.widget.ImageButton;
40a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.widget.ImageView;
41a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.widget.LinearLayout;
42a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.widget.TextView;
43a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
44a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport java.util.HashMap;
451bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolbimport java.util.List;
46a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport java.util.Map;
47a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
48a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb/**
49a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * tabbed title bar for xlarge screen browser
50a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb */
51b14ff2febe4b6a07a73c875858437c89cf43fc72Michael Kolbpublic class TabBar extends LinearLayout implements OnClickListener {
52a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
53a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    private static final int PROGRESS_MAX = 100;
54a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
558233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Activity mActivity;
568233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private UiController mUiController;
578233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private TabControl mTabControl;
586670653d355fea0ae20dc51f6c693f994c4cbb54Michael Kolb    private XLargeUi mUi;
59a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
60034637c74e84153bd1f7cdd922daaeb9f6af9b8eJohn Reck    private int mTabWidth;
61ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb
62a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    private TabScrollView mTabs;
638233facddcc51865d612a919d450db6954aa48e3Michael Kolb
64ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb    private ImageButton mNewTab;
65ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb    private int mButtonWidth;
66a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
6794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb    private Map<Tab, TabView> mTabMap;
68a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
69c83732158bca4667483ac414f071392698beb82eRomain Guy    private int mCurrentTextureWidth = 0;
70c83732158bca4667483ac414f071392698beb82eRomain Guy    private int mCurrentTextureHeight = 0;
71c83732158bca4667483ac414f071392698beb82eRomain Guy
722b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    private Drawable mActiveDrawable;
732b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    private Drawable mInactiveDrawable;
742b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
75c83732158bca4667483ac414f071392698beb82eRomain Guy    private final Paint mActiveShaderPaint = new Paint();
76c83732158bca4667483ac414f071392698beb82eRomain Guy    private final Paint mInactiveShaderPaint = new Paint();
77dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb    private final Paint mFocusPaint = new Paint();
78c83732158bca4667483ac414f071392698beb82eRomain Guy    private final Matrix mActiveMatrix = new Matrix();
79c83732158bca4667483ac414f071392698beb82eRomain Guy    private final Matrix mInactiveMatrix = new Matrix();
80c83732158bca4667483ac414f071392698beb82eRomain Guy
81c83732158bca4667483ac414f071392698beb82eRomain Guy    private BitmapShader mActiveShader;
82c83732158bca4667483ac414f071392698beb82eRomain Guy    private BitmapShader mInactiveShader;
83c83732158bca4667483ac414f071392698beb82eRomain Guy
842b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    private int mTabOverlap;
855a72f1858c2f73be3558c6cdaa2c84b4c36fa748Michael Kolb    private int mAddTabOverlap;
862b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    private int mTabSliceWidth;
87376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    private boolean mUseQuickControls;
882b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
896670653d355fea0ae20dc51f6c693f994c4cbb54Michael Kolb    public TabBar(Activity activity, UiController controller, XLargeUi ui) {
908233facddcc51865d612a919d450db6954aa48e3Michael Kolb        super(activity);
918233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActivity = activity;
928233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUiController = controller;
938233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mTabControl = mUiController.getTabControl();
948233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi = ui;
958233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Resources res = activity.getResources();
96034637c74e84153bd1f7cdd922daaeb9f6af9b8eJohn Reck        mTabWidth = (int) res.getDimension(R.dimen.tab_width);
972b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mActiveDrawable = res.getDrawable(R.drawable.bg_urlbar);
982b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mInactiveDrawable = res.getDrawable(R.drawable.browsertab_inactive);
99a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
10094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        mTabMap = new HashMap<Tab, TabView>();
1018233facddcc51865d612a919d450db6954aa48e3Michael Kolb        LayoutInflater factory = LayoutInflater.from(activity);
102a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        factory.inflate(R.layout.tab_bar, this);
103f558f0d9372ecf4eeba86dd52bf67f38ff79c0b8Michael Kolb        setPadding(0, (int) res.getDimension(R.dimen.tab_padding_top), 0, 0);
104a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        mTabs = (TabScrollView) findViewById(R.id.tabs);
105ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        mNewTab = (ImageButton) findViewById(R.id.newtab);
106ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        mNewTab.setOnClickListener(this);
107a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
1081bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        updateTabs(mUiController.getTabs());
109ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        mButtonWidth = -1;
1102b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        // tab dimensions
1112b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mTabOverlap = (int) res.getDimension(R.dimen.tab_overlap);
1125a72f1858c2f73be3558c6cdaa2c84b4c36fa748Michael Kolb        mAddTabOverlap = (int) res.getDimension(R.dimen.tab_addoverlap);
1132b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mTabSliceWidth = (int) res.getDimension(R.dimen.tab_slice);
114c83732158bca4667483ac414f071392698beb82eRomain Guy
115c83732158bca4667483ac414f071392698beb82eRomain Guy        mActiveShaderPaint.setStyle(Paint.Style.FILL);
116c83732158bca4667483ac414f071392698beb82eRomain Guy        mActiveShaderPaint.setAntiAlias(true);
117c83732158bca4667483ac414f071392698beb82eRomain Guy
118c83732158bca4667483ac414f071392698beb82eRomain Guy        mInactiveShaderPaint.setStyle(Paint.Style.FILL);
119c83732158bca4667483ac414f071392698beb82eRomain Guy        mInactiveShaderPaint.setAntiAlias(true);
120b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb
121dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb        mFocusPaint.setStyle(Paint.Style.STROKE);
122eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb        mFocusPaint.setStrokeWidth(res.getDimension(R.dimen.tab_focus_stroke));
123dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb        mFocusPaint.setAntiAlias(true);
124dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb        mFocusPaint.setColor(res.getColor(R.color.tabFocusHighlight));
125ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb    }
126ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb
127678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb    @Override
128678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb    public void onConfigurationChanged(Configuration config) {
129678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb        super.onConfigurationChanged(config);
130678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb        Resources res = mActivity.getResources();
131034637c74e84153bd1f7cdd922daaeb9f6af9b8eJohn Reck        mTabWidth = (int) res.getDimension(R.dimen.tab_width);
132678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb        // force update of tab bar
133678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb        mTabs.updateLayout();
134678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb    }
135678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb
136376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    void setUseQuickControls(boolean useQuickControls) {
137376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb        mUseQuickControls = useQuickControls;
138467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb        mNewTab.setVisibility(mUseQuickControls ? View.GONE
139467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                : View.VISIBLE);
140376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    }
141376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb
142376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    int getTabCount() {
143376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb        return mTabMap.size();
144376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    }
145376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb
1461bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb    void updateTabs(List<Tab> tabs) {
1471bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        mTabs.clearTabs();
1481bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        mTabMap.clear();
1491bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        for (Tab tab : tabs) {
15094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            TabView tv = buildTabView(tab);
1512d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            mTabs.addTab(tv);
1521bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        }
153c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        mTabs.setSelectedTab(mTabControl.getCurrentPosition());
1541bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb    }
1551bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb
156ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb    @Override
1572b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    protected void onMeasure(int hspec, int vspec) {
1582b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        super.onMeasure(hspec, vspec);
1592b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        int w = getMeasuredWidth();
1602b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        // adjust for new tab overlap
161467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb        if (!mUseQuickControls) {
1625a72f1858c2f73be3558c6cdaa2c84b4c36fa748Michael Kolb            w -= mAddTabOverlap;
163467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb        }
1642b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        setMeasuredDimension(w, getMeasuredHeight());
1652b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    }
1662b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
1672b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    @Override
168ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
1692b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        // use paddingLeft and paddingTop
1702b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        int pl = getPaddingLeft();
1712b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        int pt = getPaddingTop();
172ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        int sw = mTabs.getMeasuredWidth();
1732b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        int w = right - left - pl;
174b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb        if (mUseQuickControls) {
175b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb            mButtonWidth = 0;
176b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb        } else {
1775a72f1858c2f73be3558c6cdaa2c84b4c36fa748Michael Kolb            mButtonWidth = mNewTab.getMeasuredWidth() - mAddTabOverlap;
178b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb            if (w-sw < mButtonWidth) {
179b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb                sw = w - mButtonWidth;
180b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb            }
181ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        }
1822b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mTabs.layout(pl, pt, pl + sw, bottom - top);
1832b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        // adjust for overlap
184b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb        if (!mUseQuickControls) {
1855a72f1858c2f73be3558c6cdaa2c84b4c36fa748Michael Kolb            mNewTab.layout(pl + sw - mAddTabOverlap, pt,
1865a72f1858c2f73be3558c6cdaa2c84b4c36fa748Michael Kolb                    pl + sw + mButtonWidth - mAddTabOverlap, bottom - top);
187b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb        }
188a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
189a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
190a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onClick(View view) {
191ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        if (mNewTab == view) {
1928233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mUiController.openTabToHomePage();
193ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        } else if (mTabs.getSelectedTab() == view) {
194467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb            if (mUseQuickControls) {
1957cdc4906fc5852297a9a254c3251ad2f4dead6eeMichael Kolb                if (mUi.isTitleBarShowing() && !isLoading()) {
1967cdc4906fc5852297a9a254c3251ad2f4dead6eeMichael Kolb                    mUi.stopEditingUrl();
1977cdc4906fc5852297a9a254c3251ad2f4dead6eeMichael Kolb                    mUi.hideTitleBar();
198467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                } else {
199467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                    mUi.stopWebViewScrolling();
2001f9b3565dbd1911dfe4d9bfd8b833a5ac5f2e0c4Michael Kolb                    mUi.editUrl(false, false);
201467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                }
2027cdc4906fc5852297a9a254c3251ad2f4dead6eeMichael Kolb            } else if (mUi.isTitleBarShowing() && !isLoading()) {
2037cdc4906fc5852297a9a254c3251ad2f4dead6eeMichael Kolb                mUi.stopEditingUrl();
2047cdc4906fc5852297a9a254c3251ad2f4dead6eeMichael Kolb                mUi.hideTitleBar();
205ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            } else {
206ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb                showUrlBar();
207ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            }
208c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        } else if (view instanceof TabView) {
209c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb            final Tab tab = ((TabView) view).mTab;
210ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb            int ix = mTabs.getChildIndex(view);
211ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb            if (ix >= 0) {
212ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb                mTabs.setSelectedTab(ix);
213c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                mUiController.switchToTab(tab);
214ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb            }
215a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
216a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
217a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
218ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    private void showUrlBar() {
2198233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.stopWebViewScrolling();
2207cdc4906fc5852297a9a254c3251ad2f4dead6eeMichael Kolb        mUi.showTitleBar();
221ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    }
222ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb
22394827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb    private TabView buildTabView(Tab tab) {
22494827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tabview = new TabView(mActivity, tab);
22594827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        mTabMap.put(tab, tabview);
22694827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        tabview.setOnClickListener(this);
22794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        return tabview;
228a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
229a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
230c83732158bca4667483ac414f071392698beb82eRomain Guy    private static Bitmap getDrawableAsBitmap(Drawable drawable, int width, int height) {
231c83732158bca4667483ac414f071392698beb82eRomain Guy        Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
232c83732158bca4667483ac414f071392698beb82eRomain Guy        Canvas c = new Canvas(b);
233c83732158bca4667483ac414f071392698beb82eRomain Guy        drawable.setBounds(0, 0, width, height);
234c83732158bca4667483ac414f071392698beb82eRomain Guy        drawable.draw(c);
23543cfe8a4521b5c153055fbfa181940bc56bb3b06Dianne Hackborn        c.setBitmap(null);
236c83732158bca4667483ac414f071392698beb82eRomain Guy        return b;
237b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb    }
238b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb
239a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    /**
240a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb     * View used in the tab bar
241a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb     */
242a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    class TabView extends LinearLayout implements OnClickListener {
243a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
24494827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        Tab mTab;
245a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        View mTabContent;
246a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        TextView mTitle;
247ae62fd48652f989335db21a03d8289ecc5b57e88Michael Kolb        View mIncognito;
248541f55a0178da7c09fb32aa5385effae031ea071John Reck        View mSnapshot;
249a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        ImageView mIconView;
250a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        ImageView mLock;
251a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        ImageView mClose;
252a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        boolean mSelected;
2532b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        Path mPath;
254eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb        Path mFocusPath;
2552b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        int[] mWindowPos;
256a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
257a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        /**
258a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb         * @param context
259a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb         */
26094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        public TabView(Context context, Tab tab) {
261a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            super(context);
2622b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            setWillNotDraw(false);
2632b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            mPath = new Path();
264eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb            mFocusPath = new Path();
2652b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            mWindowPos = new int[2];
26694827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            mTab = tab;
267ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            setGravity(Gravity.CENTER_VERTICAL);
268ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            setOrientation(LinearLayout.HORIZONTAL);
26949f1583aba84ca4a5908b2185c734cf604ebb248Michael Kolb            setPadding(mTabOverlap, 0, mTabSliceWidth, 0);
270b1402a5c3e1617867c58d32d1fe9782cf6de423fBjorn Bringert            LayoutInflater inflater = LayoutInflater.from(getContext());
271ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            mTabContent = inflater.inflate(R.layout.tab_title, this, true);
272a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mTitle = (TextView) mTabContent.findViewById(R.id.title);
273a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mIconView = (ImageView) mTabContent.findViewById(R.id.favicon);
274a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mLock = (ImageView) mTabContent.findViewById(R.id.lock);
275a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mClose = (ImageView) mTabContent.findViewById(R.id.close);
276a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mClose.setOnClickListener(this);
277ae62fd48652f989335db21a03d8289ecc5b57e88Michael Kolb            mIncognito = mTabContent.findViewById(R.id.incognito);
278541f55a0178da7c09fb32aa5385effae031ea071John Reck            mSnapshot = mTabContent.findViewById(R.id.snapshot);
279a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mSelected = false;
280a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            // update the status
28194827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            updateFromTab();
282a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
283a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
284a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        @Override
285a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        public void onClick(View v) {
286a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            if (v == mClose) {
287a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                closeTab();
288a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
289a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
290a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
29194827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        private void updateFromTab() {
29294827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            String displayTitle = mTab.getTitle();
29330c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            if (displayTitle == null) {
29494827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                displayTitle = mTab.getUrl();
295a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
29630c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            setDisplayTitle(displayTitle);
29794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            if (mTab.getFavicon() != null) {
298034637c74e84153bd1f7cdd922daaeb9f6af9b8eJohn Reck                setFavicon(mUi.getFaviconDrawable(mTab.getFavicon()));
299a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
300541f55a0178da7c09fb32aa5385effae031ea071John Reck            updateTabIcons();
301541f55a0178da7c09fb32aa5385effae031ea071John Reck        }
302541f55a0178da7c09fb32aa5385effae031ea071John Reck
303541f55a0178da7c09fb32aa5385effae031ea071John Reck        private void updateTabIcons() {
304541f55a0178da7c09fb32aa5385effae031ea071John Reck            mIncognito.setVisibility(
305541f55a0178da7c09fb32aa5385effae031ea071John Reck                    mTab.isPrivateBrowsingEnabled() ?
306541f55a0178da7c09fb32aa5385effae031ea071John Reck                    View.VISIBLE : View.GONE);
307541f55a0178da7c09fb32aa5385effae031ea071John Reck            mSnapshot.setVisibility(mTab.isSnapshot()
308541f55a0178da7c09fb32aa5385effae031ea071John Reck                    ? View.VISIBLE : View.GONE);
309a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
310a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
311a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        @Override
312b7b115e301334f813275aa13e7a2cc27bf15fe6aMichael Kolb        public void setActivated(boolean selected) {
313a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mSelected = selected;
314a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE);
315034637c74e84153bd1f7cdd922daaeb9f6af9b8eJohn Reck            mIconView.setVisibility(mSelected ? View.GONE : View.VISIBLE);
3168233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mTitle.setTextAppearance(mActivity, mSelected ?
317c7485ae06c6d5d33c57a03d02bbeed54edb3c66fMichael Kolb                    R.style.TabTitleSelected : R.style.TabTitleUnselected);
318c7485ae06c6d5d33c57a03d02bbeed54edb3c66fMichael Kolb            setHorizontalFadingEdgeEnabled(!mSelected);
319b7b115e301334f813275aa13e7a2cc27bf15fe6aMichael Kolb            super.setActivated(selected);
320678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb            updateLayoutParams();
321678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb            setFocusable(!selected);
322678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb            postInvalidate();
323678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb        }
324678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb
325678afc88c00b339950b41e5be9a3e165d580f7bfMichael Kolb        public void updateLayoutParams() {
3262b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();
327034637c74e84153bd1f7cdd922daaeb9f6af9b8eJohn Reck            lp.width = mTabWidth;
3282b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            lp.height =  LayoutParams.MATCH_PARENT;
3292b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            setLayoutParams(lp);
330a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
331a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
332a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        void setDisplayTitle(String title) {
333a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mTitle.setText(title);
334a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
335a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
336a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        void setFavicon(Drawable d) {
337a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mIconView.setImageDrawable(d);
338a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
339a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
340a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        void setLock(Drawable d) {
341a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            if (null == d) {
342a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                mLock.setVisibility(View.GONE);
343a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            } else {
344a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                mLock.setImageDrawable(d);
345a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                mLock.setVisibility(View.VISIBLE);
346a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
347a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
348a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
349a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        private void closeTab() {
35094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            if (mTab == mTabControl.getCurrentTab()) {
3518233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mUiController.closeCurrentTab();
352a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            } else {
35394827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                mUiController.closeTab(mTab);
354a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
355a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
356a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
3572b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        @Override
3582b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        protected void onLayout(boolean changed, int l, int t, int r, int b) {
3592b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            super.onLayout(changed, l, t, r, b);
3602b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            setTabPath(mPath, 0, 0, r - l, b - t);
361eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb            setFocusPath(mFocusPath, 0, 0, r - l, b - t);
3622b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        }
363b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb
3642b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        @Override
3652b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        protected void dispatchDraw(Canvas canvas) {
366c83732158bca4667483ac414f071392698beb82eRomain Guy            if (mCurrentTextureWidth != mUi.getContentWidth() ||
367c83732158bca4667483ac414f071392698beb82eRomain Guy                    mCurrentTextureHeight != getHeight()) {
368c83732158bca4667483ac414f071392698beb82eRomain Guy                mCurrentTextureWidth = mUi.getContentWidth();
369c83732158bca4667483ac414f071392698beb82eRomain Guy                mCurrentTextureHeight = getHeight();
370c83732158bca4667483ac414f071392698beb82eRomain Guy
371c83732158bca4667483ac414f071392698beb82eRomain Guy                if (mCurrentTextureWidth > 0 && mCurrentTextureHeight > 0) {
372c83732158bca4667483ac414f071392698beb82eRomain Guy                    Bitmap activeTexture = getDrawableAsBitmap(mActiveDrawable,
373c83732158bca4667483ac414f071392698beb82eRomain Guy                            mCurrentTextureWidth, mCurrentTextureHeight);
374c83732158bca4667483ac414f071392698beb82eRomain Guy                    Bitmap inactiveTexture = getDrawableAsBitmap(mInactiveDrawable,
375c83732158bca4667483ac414f071392698beb82eRomain Guy                            mCurrentTextureWidth, mCurrentTextureHeight);
376c83732158bca4667483ac414f071392698beb82eRomain Guy
377c83732158bca4667483ac414f071392698beb82eRomain Guy                    mActiveShader = new BitmapShader(activeTexture,
378c83732158bca4667483ac414f071392698beb82eRomain Guy                            Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
379c83732158bca4667483ac414f071392698beb82eRomain Guy                    mActiveShaderPaint.setShader(mActiveShader);
380b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb
381c83732158bca4667483ac414f071392698beb82eRomain Guy                    mInactiveShader = new BitmapShader(inactiveTexture,
382c83732158bca4667483ac414f071392698beb82eRomain Guy                            Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
383c83732158bca4667483ac414f071392698beb82eRomain Guy                    mInactiveShaderPaint.setShader(mInactiveShader);
384c83732158bca4667483ac414f071392698beb82eRomain Guy                }
385c83732158bca4667483ac414f071392698beb82eRomain Guy            }
38605902aa39843613ea93dd0c1b41d561d4ea85ff9Michael Kolb            // add some monkey protection
38705902aa39843613ea93dd0c1b41d561d4ea85ff9Michael Kolb            if ((mActiveShader != null) && (mInactiveShader != null)) {
38805902aa39843613ea93dd0c1b41d561d4ea85ff9Michael Kolb                int state = canvas.save();
38905902aa39843613ea93dd0c1b41d561d4ea85ff9Michael Kolb                getLocationInWindow(mWindowPos);
39005902aa39843613ea93dd0c1b41d561d4ea85ff9Michael Kolb                Paint paint = mSelected ? mActiveShaderPaint : mInactiveShaderPaint;
39105902aa39843613ea93dd0c1b41d561d4ea85ff9Michael Kolb                drawClipped(canvas, paint, mPath, mWindowPos[0]);
39205902aa39843613ea93dd0c1b41d561d4ea85ff9Michael Kolb                canvas.restoreToCount(state);
39305902aa39843613ea93dd0c1b41d561d4ea85ff9Michael Kolb            }
3942b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            super.dispatchDraw(canvas);
3952b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        }
3962b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
397c83732158bca4667483ac414f071392698beb82eRomain Guy        private void drawClipped(Canvas canvas, Paint paint, Path clipPath, int left) {
398c83732158bca4667483ac414f071392698beb82eRomain Guy            // TODO: We should change the matrix/shader only when needed
399c83732158bca4667483ac414f071392698beb82eRomain Guy            final Matrix matrix = mSelected ? mActiveMatrix : mInactiveMatrix;
400c83732158bca4667483ac414f071392698beb82eRomain Guy            matrix.setTranslate(-left, 0.0f);
401c83732158bca4667483ac414f071392698beb82eRomain Guy            (mSelected ? mActiveShader : mInactiveShader).setLocalMatrix(matrix);
402c83732158bca4667483ac414f071392698beb82eRomain Guy            canvas.drawPath(clipPath, paint);
403dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb            if (isFocused()) {
404eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb                canvas.drawPath(mFocusPath, mFocusPaint);
405dc2ee1bfb50b7bec0cf3215e3d298b246dc71101Michael Kolb            }
4062b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        }
4072b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
4082b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        private void setTabPath(Path path, int l, int t, int r, int b) {
4092b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.reset();
4102b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.moveTo(l, b);
4112b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.lineTo(l, t);
4122b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.lineTo(r - mTabSliceWidth, t);
4132b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.lineTo(r, b);
4142b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.close();
4152b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        }
4162b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
417eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb        private void setFocusPath(Path path, int l, int t, int r, int b) {
418eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb            path.reset();
419eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb            path.moveTo(l, b);
420eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb            path.lineTo(l, t);
421eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb            path.lineTo(r - mTabSliceWidth, t);
422eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb            path.lineTo(r, b);
423eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb        }
424eb7001c66f49babd2f52ebeedcf55421ffc2597dMichael Kolb
425a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
426a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
4272d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb    private void animateTabOut(final Tab tab, final TabView tv) {
4282d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        ObjectAnimator scalex = ObjectAnimator.ofFloat(tv, "scaleX", 1.0f, 0.0f);
4292d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        ObjectAnimator scaley = ObjectAnimator.ofFloat(tv, "scaleY", 1.0f, 0.0f);
43049f1583aba84ca4a5908b2185c734cf604ebb248Michael Kolb        ObjectAnimator alpha = ObjectAnimator.ofFloat(tv, "alpha", 1.0f, 0.0f);
4312d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        AnimatorSet animator = new AnimatorSet();
43249f1583aba84ca4a5908b2185c734cf604ebb248Michael Kolb        animator.playTogether(scalex, scaley, alpha);
4332d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        animator.setDuration(150);
4342d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        animator.addListener(new AnimatorListener() {
4352d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4362d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            @Override
4372d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            public void onAnimationCancel(Animator animation) {
4382d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            }
4392d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4402d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            @Override
4412d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            public void onAnimationEnd(Animator animation) {
4422d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb                mTabs.removeTab(tv);
4432d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb                mTabMap.remove(tab);
4448814d738ad840ea66f0e5a4733f53f2e3bd8d0ebMichael Kolb                mUi.onRemoveTabCompleted(tab);
4452d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            }
4462d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4472d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            @Override
4482d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            public void onAnimationRepeat(Animator animation) {
4492d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            }
4502d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4512d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            @Override
4522d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            public void onAnimationStart(Animator animation) {
4532d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            }
4542d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4552d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        });
4562d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        animator.start();
4572d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb    }
4582d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4592d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb    private void animateTabIn(final Tab tab, final TabView tv) {
46049f1583aba84ca4a5908b2185c734cf604ebb248Michael Kolb        ObjectAnimator scalex = ObjectAnimator.ofFloat(tv, "scaleX", 0.0f, 1.0f);
4612d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        scalex.setDuration(150);
4622d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        scalex.addListener(new AnimatorListener() {
4632d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4642d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            @Override
4652d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            public void onAnimationCancel(Animator animation) {
4662d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            }
4672d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4682d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            @Override
4692d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            public void onAnimationEnd(Animator animation) {
4708814d738ad840ea66f0e5a4733f53f2e3bd8d0ebMichael Kolb                mUi.onAddTabCompleted(tab);
4712d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            }
4722d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4732d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            @Override
4742d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            public void onAnimationRepeat(Animator animation) {
4752d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            }
4762d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4772d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            @Override
4782d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            public void onAnimationStart(Animator animation) {
4792d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb                mTabs.addTab(tv);
4802d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            }
4812d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
4822d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        });
4832d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        scalex.start();
4842d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb    }
4852d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb
486a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    // TabChangeListener implementation
487a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
4888233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void onSetActiveTab(Tab tab) {
489c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb        mTabs.setSelectedTab(mTabControl.getTabPosition(tab));
490a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
491a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
492a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onFavicon(Tab tab, Bitmap favicon) {
49394827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = mTabMap.get(tab);
49494827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        if (tv != null) {
495034637c74e84153bd1f7cdd922daaeb9f6af9b8eJohn Reck            tv.setFavicon(mUi.getFaviconDrawable(favicon));
496a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
497a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
498a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
499a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onNewTab(Tab tab) {
50094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = buildTabView(tab);
5012d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        animateTabIn(tab, tv);
502a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
503a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
504a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onRemoveTab(Tab tab) {
50594827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = mTabMap.get(tab);
50694827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        if (tv != null) {
5072d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            animateTabOut(tab, tv);
5082d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb        } else {
5092d59c32ee3fc1ed92d57609998f0430ad7695317Michael Kolb            mTabMap.remove(tab);
510a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
511a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
512a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
513a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onUrlAndTitle(Tab tab, String url, String title) {
51494827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = mTabMap.get(tab);
51594827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        if (tv != null) {
51694827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            if (title != null) {
51794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                tv.setDisplayTitle(title);
51894827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            } else if (url != null) {
51994827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                tv.setDisplayTitle(UrlUtils.stripUrl(url));
52094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            }
521541f55a0178da7c09fb32aa5385effae031ea071John Reck            tv.updateTabIcons();
522a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
523a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
524a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
525a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    private boolean isLoading() {
5261c3a6d2630b372ad2ecbe11f5cf9fcf033a0e365Michael Kolb        Tab tab = mTabControl.getCurrentTab();
5271c3a6d2630b372ad2ecbe11f5cf9fcf033a0e365Michael Kolb        if (tab != null) {
5281c3a6d2630b372ad2ecbe11f5cf9fcf033a0e365Michael Kolb            return tab.inPageLoad();
5298233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else {
5308233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return false;
5318233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
532a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
533a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
534a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb}
535