TabBar.java revision b4cafc564e00d422dde6d286fdc2df971180ab51
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
19ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolbimport com.android.browser.ScrollWebView.ScrollListener;
20ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb
218233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.Activity;
22a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.content.Context;
23a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.content.res.Resources;
24a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.graphics.Bitmap;
252b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolbimport android.graphics.BitmapShader;
262b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolbimport android.graphics.Canvas;
27a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.graphics.Color;
28467af0a9e10715b86005992555d1c0a0654d136fMichael Kolbimport android.graphics.Matrix;
292b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolbimport android.graphics.Paint;
302b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolbimport android.graphics.Path;
312b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolbimport android.graphics.Shader;
32a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.graphics.drawable.BitmapDrawable;
33a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.graphics.drawable.Drawable;
34a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.graphics.drawable.LayerDrawable;
35a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.graphics.drawable.PaintDrawable;
36a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.view.ContextMenu;
37ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolbimport android.view.Gravity;
38a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.view.LayoutInflater;
39a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.view.MenuInflater;
40a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.view.View;
41a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.view.View.OnClickListener;
42a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.webkit.WebView;
43ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolbimport android.widget.ImageButton;
44a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.widget.ImageView;
45a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.widget.LinearLayout;
46a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport android.widget.TextView;
47a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
48a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport java.util.HashMap;
491bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolbimport java.util.List;
50a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbimport java.util.Map;
51a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
52a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb/**
53a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb * tabbed title bar for xlarge screen browser
54a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb */
55a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolbpublic class TabBar extends LinearLayout
568233facddcc51865d612a919d450db6954aa48e3Michael Kolb        implements ScrollListener, OnClickListener {
57a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
58a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    private static final int PROGRESS_MAX = 100;
59a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
608233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Activity mActivity;
618233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private UiController mUiController;
628233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private TabControl mTabControl;
636670653d355fea0ae20dc51f6c693f994c4cbb54Michael Kolb    private XLargeUi mUi;
64a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
65ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    private final int mTabWidthSelected;
66ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    private final int mTabWidthUnselected;
67ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb
68a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    private TabScrollView mTabs;
698233facddcc51865d612a919d450db6954aa48e3Michael Kolb
70ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb    private ImageButton mNewTab;
71ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb    private int mButtonWidth;
72a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
7394827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb    private Map<Tab, TabView> mTabMap;
74a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
75a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb    private int mVisibleTitleHeight;
76a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
77aff60fb04857e9f9883d357939074b2eafc111e7John Reck    private Drawable mGenericFavicon;
78aff60fb04857e9f9883d357939074b2eafc111e7John Reck
79c83732158bca4667483ac414f071392698beb82eRomain Guy    private int mCurrentTextureWidth = 0;
80c83732158bca4667483ac414f071392698beb82eRomain Guy    private int mCurrentTextureHeight = 0;
81c83732158bca4667483ac414f071392698beb82eRomain Guy
822b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    private Drawable mActiveDrawable;
832b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    private Drawable mInactiveDrawable;
842b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
85c83732158bca4667483ac414f071392698beb82eRomain Guy    private final Paint mActiveShaderPaint = new Paint();
86c83732158bca4667483ac414f071392698beb82eRomain Guy    private final Paint mInactiveShaderPaint = new Paint();
87c83732158bca4667483ac414f071392698beb82eRomain Guy    private final Matrix mActiveMatrix = new Matrix();
88c83732158bca4667483ac414f071392698beb82eRomain Guy    private final Matrix mInactiveMatrix = new Matrix();
89c83732158bca4667483ac414f071392698beb82eRomain Guy
90c83732158bca4667483ac414f071392698beb82eRomain Guy    private BitmapShader mActiveShader;
91c83732158bca4667483ac414f071392698beb82eRomain Guy    private BitmapShader mInactiveShader;
92c83732158bca4667483ac414f071392698beb82eRomain Guy
932b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    private int mTabOverlap;
942b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    private int mTabSliceWidth;
952b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    private int mTabPadding;
96376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    private boolean mUseQuickControls;
972b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
986670653d355fea0ae20dc51f6c693f994c4cbb54Michael Kolb    public TabBar(Activity activity, UiController controller, XLargeUi ui) {
998233facddcc51865d612a919d450db6954aa48e3Michael Kolb        super(activity);
1008233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActivity = activity;
1018233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUiController = controller;
1028233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mTabControl = mUiController.getTabControl();
1038233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi = ui;
1048233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Resources res = activity.getResources();
105ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb        mTabWidthSelected = (int) res.getDimension(R.dimen.tab_width_selected);
106ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb        mTabWidthUnselected = (int) res.getDimension(R.dimen.tab_width_unselected);
1072b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mActiveDrawable = res.getDrawable(R.drawable.bg_urlbar);
1082b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mInactiveDrawable = res.getDrawable(R.drawable.browsertab_inactive);
109a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
11094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        mTabMap = new HashMap<Tab, TabView>();
11194827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        Resources resources = activity.getResources();
1128233facddcc51865d612a919d450db6954aa48e3Michael Kolb        LayoutInflater factory = LayoutInflater.from(activity);
113a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        factory.inflate(R.layout.tab_bar, this);
1142b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        setPadding(12, 12, 0, 0);
115a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        mTabs = (TabScrollView) findViewById(R.id.tabs);
116ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        mNewTab = (ImageButton) findViewById(R.id.newtab);
117ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        mNewTab.setOnClickListener(this);
118aff60fb04857e9f9883d357939074b2eafc111e7John Reck        mGenericFavicon = res.getDrawable(R.drawable.app_web_browser_sm);
1192b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        setChildrenDrawingOrderEnabled(true);
120a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
121a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        // TODO: Change enabled states based on whether you can go
122a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        // back/forward.  Probably should be done inside onPageStarted.
123a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
1241bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        updateTabs(mUiController.getTabs());
125a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
126a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb        mVisibleTitleHeight = 1;
127ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        mButtonWidth = -1;
1282b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        // tab dimensions
1292b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mTabOverlap = (int) res.getDimension(R.dimen.tab_overlap);
1302b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mTabSliceWidth = (int) res.getDimension(R.dimen.tab_slice);
1312b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mTabPadding = (int) res.getDimension(R.dimen.tab_padding);
132c83732158bca4667483ac414f071392698beb82eRomain Guy
133c83732158bca4667483ac414f071392698beb82eRomain Guy        mActiveShaderPaint.setStyle(Paint.Style.FILL);
134c83732158bca4667483ac414f071392698beb82eRomain Guy        mActiveShaderPaint.setAntiAlias(true);
135c83732158bca4667483ac414f071392698beb82eRomain Guy
136c83732158bca4667483ac414f071392698beb82eRomain Guy        mInactiveShaderPaint.setStyle(Paint.Style.FILL);
137c83732158bca4667483ac414f071392698beb82eRomain Guy        mInactiveShaderPaint.setAntiAlias(true);
138b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb
139ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb    }
140ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb
141376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    void setUseQuickControls(boolean useQuickControls) {
142376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb        mUseQuickControls = useQuickControls;
143467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb        mNewTab.setVisibility(mUseQuickControls ? View.GONE
144467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                : View.VISIBLE);
145376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    }
146376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb
147376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    int getTabCount() {
148376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb        return mTabMap.size();
149376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    }
150376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb
1511bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb    void updateTabs(List<Tab> tabs) {
1521bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        mTabs.clearTabs();
1531bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        mTabMap.clear();
1541bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        for (Tab tab : tabs) {
15594827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            TabView tv = buildTabView(tab);
1561bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        }
1571bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb        mTabs.setSelectedTab(mTabControl.getCurrentIndex());
1581bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb    }
1591bf231334fd4bda8dbde5b9a0345c756a213b3a2Michael Kolb
160ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb    @Override
1612b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    protected void onMeasure(int hspec, int vspec) {
1622b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        super.onMeasure(hspec, vspec);
1632b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        int w = getMeasuredWidth();
1642b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        // adjust for new tab overlap
165467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb        if (!mUseQuickControls) {
166467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb            w -= mTabOverlap;
167467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb        }
1682b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        setMeasuredDimension(w, getMeasuredHeight());
1692b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    }
1702b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
1712b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    @Override
172ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
1732b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        // use paddingLeft and paddingTop
1742b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        int pl = getPaddingLeft();
1752b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        int pt = getPaddingTop();
176ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        int sw = mTabs.getMeasuredWidth();
1772b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        int w = right - left - pl;
178b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb        if (mUseQuickControls) {
179b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb            mButtonWidth = 0;
180b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb        } else {
181b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb            mButtonWidth = mNewTab.getMeasuredWidth() - mTabOverlap;
182b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb            if (w-sw < mButtonWidth) {
183b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb                sw = w - mButtonWidth;
184b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb            }
185ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        }
1862b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        mTabs.layout(pl, pt, pl + sw, bottom - top);
1872b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        // adjust for overlap
188b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb        if (!mUseQuickControls) {
189b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb            mNewTab.layout(pl + sw - mTabOverlap, pt,
190b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb                    pl + sw + mButtonWidth - mTabOverlap, bottom - top);
191b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb        }
192a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
193a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
194a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onClick(View view) {
1958233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.hideComboView();
196ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        if (mNewTab == view) {
1978233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mUiController.openTabToHomePage();
198ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb        } else if (mTabs.getSelectedTab() == view) {
199467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb            if (mUseQuickControls) {
200467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                if (mUi.isFakeTitleBarShowing() && !isLoading()) {
201467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                    mUi.hideFakeTitleBar();
202467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                } else {
203467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                    mUi.stopWebViewScrolling();
204467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                    mUi.showFakeTitleBarAndEdit();
205467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb                }
206467af0a9e10715b86005992555d1c0a0654d136fMichael Kolb            } else if (mUi.isFakeTitleBarShowing() && !isLoading()) {
2078233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mUi.hideFakeTitleBar();
208ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            } else {
209ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb                showUrlBar();
210ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            }
211a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        } else {
212ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb            int ix = mTabs.getChildIndex(view);
213ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb            if (ix >= 0) {
214ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb                mTabs.setSelectedTab(ix);
2158233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mUiController.switchToTab(ix);
216ebba8b4e9dc4f78764d6cfb26738b54d04bc9d27Michael Kolb            }
217a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
218a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
219a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
220ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    private void showUrlBar() {
2218233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.stopWebViewScrolling();
2228233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mUi.showFakeTitleBar();
223ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    }
224ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb
225376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb    void showTitleBarIndicator(boolean show) {
226a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb        Tab tab = mTabControl.getCurrentTab();
227a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb        if (tab != null) {
22894827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            TabView tv = mTabMap.get(tab);
22994827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            if (tv != null) {
23094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                tv.showIndicator(show);
231a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb            }
232a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb        }
233ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    }
234ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb
235ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    // callback after fake titlebar is shown
236a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    void onShowTitleBar() {
237a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb        showTitleBarIndicator(false);
238a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
239a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
240ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    // callback after fake titlebar is hidden
241a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    void onHideTitleBar() {
242a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb        showTitleBarIndicator(mVisibleTitleHeight == 0);
2438233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Tab tab = mTabControl.getCurrentTab();
244a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        tab.getWebView().requestFocus();
245a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
246a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
247ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    // webview scroll listener
248ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb
249ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    @Override
250a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb    public void onScroll(int visibleTitleHeight) {
251376b54116e38b3b94c4d64663d1bff38352b0e59Michael Kolb        if (mUseQuickControls) return;
2528233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // isLoading is using the current tab, which initially might not be set yet
253dcf911c7cb1c3eeb8b073d69c2ccd96e6179b4a8John Reck        if (mTabControl.getCurrentTab() != null
254dcf911c7cb1c3eeb8b073d69c2ccd96e6179b4a8John Reck                && !isLoading()) {
255dcf911c7cb1c3eeb8b073d69c2ccd96e6179b4a8John Reck            if (visibleTitleHeight == 0) {
256dcf911c7cb1c3eeb8b073d69c2ccd96e6179b4a8John Reck                mUi.hideFakeTitleBar();
257dcf911c7cb1c3eeb8b073d69c2ccd96e6179b4a8John Reck                showTitleBarIndicator(true);
258dcf911c7cb1c3eeb8b073d69c2ccd96e6179b4a8John Reck            } else {
259a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb                showTitleBarIndicator(false);
260ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            }
261ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb        }
262a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb        mVisibleTitleHeight = visibleTitleHeight;
263ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb    }
264a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
265a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    @Override
266a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void createContextMenu(ContextMenu menu) {
2678233facddcc51865d612a919d450db6954aa48e3Michael Kolb        MenuInflater inflater = mActivity.getMenuInflater();
268a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        inflater.inflate(R.menu.title_context, menu);
2698233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActivity.onCreateContextMenu(menu, this, null);
270a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
271a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
27294827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb    private TabView buildTabView(Tab tab) {
27394827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tabview = new TabView(mActivity, tab);
27494827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        mTabMap.put(tab, tabview);
27594827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        tabview.setOnClickListener(this);
27694827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        mTabs.addTab(tabview);
27794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        return tabview;
278a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
279a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
2802b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    @Override
2812b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    protected int getChildDrawingOrder(int count, int i) {
2822b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        // reverse
2832b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        return count - 1 - i;
2842b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb    }
2852b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
286c83732158bca4667483ac414f071392698beb82eRomain Guy    private static Bitmap getDrawableAsBitmap(Drawable drawable, int width, int height) {
287c83732158bca4667483ac414f071392698beb82eRomain Guy        Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
288c83732158bca4667483ac414f071392698beb82eRomain Guy        Canvas c = new Canvas(b);
289c83732158bca4667483ac414f071392698beb82eRomain Guy        drawable.setBounds(0, 0, width, height);
290c83732158bca4667483ac414f071392698beb82eRomain Guy        drawable.draw(c);
291c83732158bca4667483ac414f071392698beb82eRomain Guy        return b;
292b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb    }
293b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb
294a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    /**
295a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb     * View used in the tab bar
296a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb     */
297a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    class TabView extends LinearLayout implements OnClickListener {
298a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
29994827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        Tab mTab;
300a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        View mTabContent;
301a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        TextView mTitle;
302a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb        View mIndicator;
303ae62fd48652f989335db21a03d8289ecc5b57e88Michael Kolb        View mIncognito;
304a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        ImageView mIconView;
305a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        ImageView mLock;
306a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        ImageView mClose;
307a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        boolean mSelected;
308a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        boolean mInLoad;
3092b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        Path mPath;
3102b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        int[] mWindowPos;
311a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
312a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        /**
313a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb         * @param context
314a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb         */
31594827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        public TabView(Context context, Tab tab) {
316a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            super(context);
3172b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            setWillNotDraw(false);
3182b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            mPath = new Path();
3192b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            mWindowPos = new int[2];
32094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            mTab = tab;
321ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            setGravity(Gravity.CENTER_VERTICAL);
322ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            setOrientation(LinearLayout.HORIZONTAL);
323a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb            setPadding(mTabPadding, 0, 0, 0);
324b1402a5c3e1617867c58d32d1fe9782cf6de423fBjorn Bringert            LayoutInflater inflater = LayoutInflater.from(getContext());
325ed217745066c160f785626e9a15ebe70af5e25e4Michael Kolb            mTabContent = inflater.inflate(R.layout.tab_title, this, true);
326a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mTitle = (TextView) mTabContent.findViewById(R.id.title);
327a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mIconView = (ImageView) mTabContent.findViewById(R.id.favicon);
328a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mLock = (ImageView) mTabContent.findViewById(R.id.lock);
329a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mClose = (ImageView) mTabContent.findViewById(R.id.close);
330a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mClose.setOnClickListener(this);
331ae62fd48652f989335db21a03d8289ecc5b57e88Michael Kolb            mIncognito = mTabContent.findViewById(R.id.incognito);
332a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb            mIndicator = mTabContent.findViewById(R.id.chevron);
333a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mSelected = false;
334a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mInLoad = false;
335a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            // update the status
33694827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            updateFromTab();
337a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
338a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
339a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb        void showIndicator(boolean show) {
3406a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb            if (mSelected) {
3416a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb                mIndicator.setVisibility(show ? View.VISIBLE : View.GONE);
3426a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb            } else {
3436a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb                mIndicator.setVisibility(View.GONE);
3446a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb            }
345a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb        }
346a0e2a75fdba703260c02838c96d9d4008e914a1dMichael Kolb
347a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        @Override
348a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        public void onClick(View v) {
349a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            if (v == mClose) {
350a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                closeTab();
351a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
352a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
353a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
35494827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        private void updateFromTab() {
35594827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            String displayTitle = mTab.getTitle();
35630c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            if (displayTitle == null) {
35794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                displayTitle = mTab.getUrl();
358a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
35930c714c853a4239e72ab1e238ce2a92472d06ab0John Reck            setDisplayTitle(displayTitle);
36094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            setProgress(mTab.getLoadProgress());
36194827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            if (mTab.getFavicon() != null) {
36294827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                setFavicon(renderFavicon(mTab.getFavicon()));
363a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
36494827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            if (mTab != null) {
365ae62fd48652f989335db21a03d8289ecc5b57e88Michael Kolb                mIncognito.setVisibility(
36694827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                        mTab.isPrivateBrowsingEnabled() ?
367ae62fd48652f989335db21a03d8289ecc5b57e88Michael Kolb                        View.VISIBLE : View.GONE);
368ae62fd48652f989335db21a03d8289ecc5b57e88Michael Kolb            }
369a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
370a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
371a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        @Override
372b7b115e301334f813275aa13e7a2cc27bf15fe6aMichael Kolb        public void setActivated(boolean selected) {
373a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mSelected = selected;
374a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE);
3756a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb            mIndicator.setVisibility(View.GONE);
3768233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mTitle.setTextAppearance(mActivity, mSelected ?
377c7485ae06c6d5d33c57a03d02bbeed54edb3c66fMichael Kolb                    R.style.TabTitleSelected : R.style.TabTitleUnselected);
378c7485ae06c6d5d33c57a03d02bbeed54edb3c66fMichael Kolb            setHorizontalFadingEdgeEnabled(!mSelected);
379b7b115e301334f813275aa13e7a2cc27bf15fe6aMichael Kolb            super.setActivated(selected);
3802b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();
3812b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            lp.width = selected ? mTabWidthSelected : mTabWidthUnselected;
3822b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            lp.height =  LayoutParams.MATCH_PARENT;
3832b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            setLayoutParams(lp);
384a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
385a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
386a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        void setDisplayTitle(String title) {
387a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mTitle.setText(title);
388a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
389a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
390a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        void setFavicon(Drawable d) {
391a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            mIconView.setImageDrawable(d);
392a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
393a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
394a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        void setLock(Drawable d) {
395a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            if (null == d) {
396a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                mLock.setVisibility(View.GONE);
397a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            } else {
398a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                mLock.setImageDrawable(d);
399a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                mLock.setVisibility(View.VISIBLE);
400a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
401a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
402a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
403a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        void setProgress(int newProgress) {
404a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            if (newProgress >= PROGRESS_MAX) {
405a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                mInLoad = false;
406a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            } else {
407a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                if (!mInLoad && getWindowToken() != null) {
408a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                    mInLoad = true;
409a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb                }
410a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
411a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
412a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
413a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        private void closeTab() {
41494827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            if (mTab == mTabControl.getCurrentTab()) {
4158233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mUiController.closeCurrentTab();
416a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            } else {
41794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                mUiController.closeTab(mTab);
418a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            }
419a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
420a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
4212b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        @Override
4222b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        protected void onLayout(boolean changed, int l, int t, int r, int b) {
4232b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            super.onLayout(changed, l, t, r, b);
4242b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            setTabPath(mPath, 0, 0, r - l, b - t);
4252b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        }
426b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb
4272b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        @Override
4282b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        protected void dispatchDraw(Canvas canvas) {
429c83732158bca4667483ac414f071392698beb82eRomain Guy            if (mCurrentTextureWidth != mUi.getContentWidth() ||
430c83732158bca4667483ac414f071392698beb82eRomain Guy                    mCurrentTextureHeight != getHeight()) {
431c83732158bca4667483ac414f071392698beb82eRomain Guy                mCurrentTextureWidth = mUi.getContentWidth();
432c83732158bca4667483ac414f071392698beb82eRomain Guy                mCurrentTextureHeight = getHeight();
433c83732158bca4667483ac414f071392698beb82eRomain Guy
434c83732158bca4667483ac414f071392698beb82eRomain Guy                if (mCurrentTextureWidth > 0 && mCurrentTextureHeight > 0) {
435c83732158bca4667483ac414f071392698beb82eRomain Guy                    Bitmap activeTexture = getDrawableAsBitmap(mActiveDrawable,
436c83732158bca4667483ac414f071392698beb82eRomain Guy                            mCurrentTextureWidth, mCurrentTextureHeight);
437c83732158bca4667483ac414f071392698beb82eRomain Guy                    Bitmap inactiveTexture = getDrawableAsBitmap(mInactiveDrawable,
438c83732158bca4667483ac414f071392698beb82eRomain Guy                            mCurrentTextureWidth, mCurrentTextureHeight);
439c83732158bca4667483ac414f071392698beb82eRomain Guy
440c83732158bca4667483ac414f071392698beb82eRomain Guy                    mActiveShader = new BitmapShader(activeTexture,
441c83732158bca4667483ac414f071392698beb82eRomain Guy                            Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
442c83732158bca4667483ac414f071392698beb82eRomain Guy                    mActiveShaderPaint.setShader(mActiveShader);
443b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb
444c83732158bca4667483ac414f071392698beb82eRomain Guy                    mInactiveShader = new BitmapShader(inactiveTexture,
445c83732158bca4667483ac414f071392698beb82eRomain Guy                            Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
446c83732158bca4667483ac414f071392698beb82eRomain Guy                    mInactiveShaderPaint.setShader(mInactiveShader);
447c83732158bca4667483ac414f071392698beb82eRomain Guy                }
448c83732158bca4667483ac414f071392698beb82eRomain Guy            }
449b4cafc564e00d422dde6d286fdc2df971180ab51Michael Kolb
4502b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            int state = canvas.save();
4512b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            getLocationInWindow(mWindowPos);
452c83732158bca4667483ac414f071392698beb82eRomain Guy            Paint paint = mSelected ? mActiveShaderPaint : mInactiveShaderPaint;
453c83732158bca4667483ac414f071392698beb82eRomain Guy            drawClipped(canvas, paint, mPath, mWindowPos[0]);
4542b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            canvas.restoreToCount(state);
4552b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            super.dispatchDraw(canvas);
4562b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        }
4572b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
458c83732158bca4667483ac414f071392698beb82eRomain Guy        private void drawClipped(Canvas canvas, Paint paint, Path clipPath, int left) {
459c83732158bca4667483ac414f071392698beb82eRomain Guy            // TODO: We should change the matrix/shader only when needed
460c83732158bca4667483ac414f071392698beb82eRomain Guy            final Matrix matrix = mSelected ? mActiveMatrix : mInactiveMatrix;
461c83732158bca4667483ac414f071392698beb82eRomain Guy            matrix.setTranslate(-left, 0.0f);
462c83732158bca4667483ac414f071392698beb82eRomain Guy            (mSelected ? mActiveShader : mInactiveShader).setLocalMatrix(matrix);
463c83732158bca4667483ac414f071392698beb82eRomain Guy            canvas.drawPath(clipPath, paint);
4642b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        }
4652b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
4662b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        private void setTabPath(Path path, int l, int t, int r, int b) {
4672b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.reset();
4682b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.moveTo(l, b);
4692b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.lineTo(l, t);
4702b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.lineTo(r - mTabSliceWidth, t);
4712b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.lineTo(r, b);
4722b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb            path.close();
4732b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb        }
4742b5a13ab55991f55ab7afb107e4401c6fbb5ad64Michael Kolb
475a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
476a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
47794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb    private Drawable renderFavicon(Bitmap icon) {
47894827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        Drawable[] array = new Drawable[3];
47994827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        array[0] = new PaintDrawable(Color.BLACK);
48094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        array[1] = new PaintDrawable(Color.WHITE);
48194827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        if (icon == null) {
48294827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            array[2] = mGenericFavicon;
48394827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        } else {
48494827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            array[2] = new BitmapDrawable(icon);
485a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
48694827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        LayerDrawable d = new LayerDrawable(array);
48794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        d.setLayerInset(1, 1, 1, 1, 1);
48894827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        d.setLayerInset(2, 2, 2, 2, 2);
48994827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        return d;
490a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
491a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
492a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    // TabChangeListener implementation
493a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
4948233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void onSetActiveTab(Tab tab) {
4958233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mTabs.setSelectedTab(mTabControl.getTabIndex(tab));
49694827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = mTabMap.get(tab);
49794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        if (tv != null) {
49894827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            tv.setProgress(tv.mTab.getLoadProgress());
499a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            // update the scroll state
500a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb            WebView webview = tab.getWebView();
5016a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb            if (webview != null) {
5026a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb                int h = webview.getVisibleTitleHeight();
5036a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb                mVisibleTitleHeight = h -1;
5046a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb                onScroll(h);
5056a85e2ae52f5e7592731cfcf1b98639ea2a03b62Michael Kolb            }
506a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
507a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
508a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
509a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onFavicon(Tab tab, Bitmap favicon) {
51094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = mTabMap.get(tab);
51194827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        if (tv != null) {
51294827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            tv.setFavicon(renderFavicon(favicon));
513a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
514a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
515a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
516a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onNewTab(Tab tab) {
51794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = buildTabView(tab);
518a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
519a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
520a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onProgress(Tab tab, int progress) {
52194827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = mTabMap.get(tab);
52294827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        if (tv != null) {
52394827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            tv.setProgress(progress);
524a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
525a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
526a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
527a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onRemoveTab(Tab tab) {
52894827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = mTabMap.get(tab);
52994827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        if (tv != null) {
53094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            mTabs.removeTab(tv);
531a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
532a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        mTabMap.remove(tab);
533a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
534a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
535a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    public void onUrlAndTitle(Tab tab, String url, String title) {
53694827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = mTabMap.get(tab);
53794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        if (tv != null) {
53894827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            if (title != null) {
53994827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                tv.setDisplayTitle(title);
54094827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            } else if (url != null) {
54194827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb                tv.setDisplayTitle(UrlUtils.stripUrl(url));
54294827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            }
543a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb        }
544a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
545a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
546a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    private boolean isLoading() {
54794827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        TabView tv = mTabMap.get(mTabControl.getCurrentTab());
54894827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb        if (tv != null) {
54994827b6f22830ba06a66a77d3c9da9143e6ecd12Michael Kolb            return tv.mInLoad;
5508233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else {
5518233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return false;
5528233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
553a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb    }
554a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb
555a2b2ba8da913f26c820e49d3e43158e2fe6ebebaMichael Kolb}
556