TabBar.java revision c7485ae06c6d5d33c57a03d02bbeed54edb3c66f
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.browser;
18
19import android.content.Context;
20import android.content.res.Resources;
21import android.graphics.Bitmap;
22import android.graphics.Color;
23import android.graphics.drawable.BitmapDrawable;
24import android.graphics.drawable.Drawable;
25import android.graphics.drawable.LayerDrawable;
26import android.graphics.drawable.PaintDrawable;
27import android.view.ContextMenu;
28import android.view.Gravity;
29import android.view.LayoutInflater;
30import android.view.MenuInflater;
31import android.view.View;
32import android.view.View.OnClickListener;
33import android.webkit.WebView;
34import android.widget.ImageButton;
35import android.widget.ImageView;
36import android.widget.LinearLayout;
37import android.widget.TextView;
38
39import com.android.browser.ScrollWebView.ScrollListener;
40import com.android.browser.TabControl.TabChangeListener;
41
42import java.util.HashMap;
43import java.util.Map;
44
45/**
46 * tabbed title bar for xlarge screen browser
47 */
48public class TabBar extends LinearLayout
49        implements TabChangeListener, ScrollListener, OnClickListener {
50
51    private static final int PROGRESS_MAX = 100;
52
53    private BrowserActivity mBrowserActivity;
54
55    private final int mTabWidthSelected;
56    private final int mTabWidthUnselected;
57
58    private TitleBarXLarge mTitleBar;
59
60    private TabScrollView mTabs;
61    private TabControl mControl;
62
63    private Map<Tab, TabViewData> mTabMap;
64
65    private float mDensityScale;
66    private boolean mUserRequestedUrlbar;
67    private boolean mTitleVisible;
68    private boolean mShowUrlMode;
69
70    public TabBar(BrowserActivity context, TabControl tabcontrol, TitleBarXLarge titlebar) {
71        super(context);
72        Resources res = context.getResources();
73        mTabWidthSelected = (int) res.getDimension(R.dimen.tab_width_selected);
74        mTabWidthUnselected = (int) res.getDimension(R.dimen.tab_width_unselected);
75
76        mTitleBar = titlebar;
77        mTitleBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
78                LayoutParams.WRAP_CONTENT));
79        mDensityScale = context.getResources().getDisplayMetrics().density;
80        mTabMap = new HashMap<Tab, TabViewData>();
81        mBrowserActivity = context;
82        mControl = tabcontrol;
83        Resources resources = context.getResources();
84        LayoutInflater factory = LayoutInflater.from(context);
85        factory.inflate(R.layout.tab_bar, this);
86        mTabs = (TabScrollView) findViewById(R.id.tabs);
87
88        // TODO: Change enabled states based on whether you can go
89        // back/forward.  Probably should be done inside onPageStarted.
90
91        // build tabs
92        int tabcount = mControl.getTabCount();
93        for (int i = 0; i < tabcount; i++) {
94            Tab tab = mControl.getTab(i);
95            TabViewData data = buildTab(tab);
96            TabView tv = buildView(data);
97        }
98        mTabs.setSelectedTab(mControl.getCurrentIndex());
99
100        // register the tab change listener
101        mControl.setOnTabChangeListener(this);
102        mUserRequestedUrlbar = false;
103        mTitleVisible = true;
104    }
105
106    public void onClick(View view) {
107        if (mTabs.getSelectedTab() == view) {
108            if (mBrowserActivity.isFakeTitleBarShowing() && !isLoading()) {
109                mBrowserActivity.hideFakeTitleBar();
110            } else {
111                showUrlBar();
112            }
113            // temporarily disabled
114            // mTitleBar.requestUrlInputFocus();
115        } else {
116            TabViewData data = (TabViewData) view.getTag();
117            int ix = mControl.getTabIndex(data.mTab);
118            mTabs.setSelectedTab(ix);
119            mBrowserActivity.switchToTab(ix);
120        }
121    }
122
123    private void showUrlBar() {
124        mBrowserActivity.stopScrolling();
125        mBrowserActivity.showFakeTitleBar();
126        mUserRequestedUrlbar = true;
127    }
128
129    private void setShowUrlMode(boolean showUrl) {
130        mShowUrlMode = showUrl;
131    }
132
133    // callback after fake titlebar is shown
134    void onShowTitleBar() {
135        setShowUrlMode(false);
136    }
137
138    // callback after fake titlebar is hidden
139    void onHideTitleBar() {
140        setShowUrlMode(!mTitleVisible);
141        Tab tab = mControl.getCurrentTab();
142        tab.getWebView().requestFocus();
143        mUserRequestedUrlbar = false;
144    }
145
146    // webview scroll listener
147
148    @Override
149    public void onScroll(boolean titleVisible) {
150        mTitleVisible = titleVisible;
151        if (!mShowUrlMode && !mTitleVisible && !isLoading()) {
152            if (mUserRequestedUrlbar) {
153                mBrowserActivity.hideFakeTitleBar();
154            } else {
155                setShowUrlMode(true);
156            }
157        } else if (mTitleVisible && !isLoading()) {
158            if (mShowUrlMode) {
159                setShowUrlMode(false);
160            }
161        }
162    }
163
164    @Override
165    public void createContextMenu(ContextMenu menu) {
166        MenuInflater inflater = mBrowserActivity.getMenuInflater();
167        inflater.inflate(R.menu.title_context, menu);
168        mBrowserActivity.onCreateContextMenu(menu, this, null);
169    }
170
171    private TabViewData buildTab(Tab tab) {
172        TabViewData data = new TabViewData(tab);
173        mTabMap.put(tab, data);
174        return data;
175    }
176
177    private TabView buildView(final TabViewData data) {
178        TabView tv = new TabView(mBrowserActivity, data);
179        tv.setTag(data);
180        tv.setOnClickListener(this);
181        mTabs.addTab(tv);
182        return tv;
183    }
184
185    /**
186     * View used in the tab bar
187     */
188    class TabView extends LinearLayout implements OnClickListener {
189
190        TabViewData mTabData;
191        View mTabContent;
192        TextView mTitle;
193        View mIncognito;
194        ImageView mIconView;
195        ImageView mLock;
196        ImageView mClose;
197        boolean mSelected;
198        boolean mInLoad;
199
200        /**
201         * @param context
202         */
203        public TabView(Context context, TabViewData tab) {
204            super(context);
205            mTabData = tab;
206            setGravity(Gravity.CENTER_VERTICAL);
207            setOrientation(LinearLayout.HORIZONTAL);
208            setBackgroundResource(R.drawable.tab_background);
209            LayoutInflater inflater = LayoutInflater.from(mContext);
210            mTabContent = inflater.inflate(R.layout.tab_title, this, true);
211            mTitle = (TextView) mTabContent.findViewById(R.id.title);
212            mIconView = (ImageView) mTabContent.findViewById(R.id.favicon);
213            mLock = (ImageView) mTabContent.findViewById(R.id.lock);
214            mClose = (ImageView) mTabContent.findViewById(R.id.close);
215            mClose.setOnClickListener(this);
216            mIncognito = mTabContent.findViewById(R.id.incognito);
217            mSelected = false;
218            mInLoad = false;
219            // update the status
220            updateFromData();
221        }
222
223        @Override
224        public void onClick(View v) {
225            if (v == mClose) {
226                closeTab();
227            }
228        }
229
230        private void updateFromData() {
231            mTabData.mTabView = this;
232            if (mTabData.mUrl != null) {
233                setDisplayTitle(mTabData.mUrl);
234            }
235            if (mTabData.mTitle != null) {
236                setDisplayTitle(mTabData.mTitle);
237            }
238            setProgress(mTabData.mProgress);
239            if (mTabData.mIcon != null) {
240                setFavicon(mTabData.mIcon);
241            }
242            if (mTabData.mLock != null) {
243                setLock(mTabData.mLock);
244            }
245            if (mTabData.mTab != null) {
246                mIncognito.setVisibility(
247                        mTabData.mTab.getWebView().isPrivateBrowsingEnabled() ?
248                        View.VISIBLE : View.GONE);
249            }
250        }
251
252        @Override
253        public void setSelected(boolean selected) {
254            mSelected = selected;
255            mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE);
256            mTitle.setTextAppearance(mBrowserActivity, mSelected ?
257                    R.style.TabTitleSelected : R.style.TabTitleUnselected);
258            setHorizontalFadingEdgeEnabled(!mSelected);
259            setFadingEdgeLength(50);
260            super.setSelected(selected);
261            setLayoutParams(new LayoutParams(selected ?
262                    mTabWidthSelected : mTabWidthUnselected,
263                    LayoutParams.MATCH_PARENT));
264        }
265
266        void setDisplayTitle(String title) {
267            mTitle.setText(title);
268        }
269
270        void setFavicon(Drawable d) {
271            mIconView.setImageDrawable(d);
272        }
273
274        void setLock(Drawable d) {
275            if (null == d) {
276                mLock.setVisibility(View.GONE);
277            } else {
278                mLock.setImageDrawable(d);
279                mLock.setVisibility(View.VISIBLE);
280            }
281        }
282
283        void setTitleCompoundDrawables(Drawable left, Drawable top,
284                Drawable right, Drawable bottom) {
285            mTitle.setCompoundDrawables(left, top, right, bottom);
286        }
287
288        void setProgress(int newProgress) {
289            if (newProgress >= PROGRESS_MAX) {
290                mInLoad = false;
291            } else {
292                if (!mInLoad && getWindowToken() != null) {
293                    mInLoad = true;
294                }
295            }
296        }
297
298        private void closeTab() {
299            if (mTabData.mTab == mControl.getCurrentTab()) {
300                mBrowserActivity.closeCurrentWindow();
301            } else {
302                mBrowserActivity.closeTab(mTabData.mTab);
303            }
304        }
305
306    }
307
308    /**
309     * Store tab state within the title bar
310     */
311    class TabViewData {
312
313        Tab mTab;
314        TabView mTabView;
315        int mProgress;
316        Drawable mIcon;
317        Drawable mLock;
318        String mTitle;
319        String mUrl;
320
321        TabViewData(Tab tab) {
322            mTab = tab;
323        }
324
325        void setUrlAndTitle(String url, String title) {
326            mUrl = url;
327            mTitle = title;
328            if (mTabView != null) {
329                if (title != null) {
330                    mTabView.setDisplayTitle(title);
331                } else if (url != null) {
332                    mTabView.setDisplayTitle(url);
333                }
334            }
335        }
336
337        void setProgress(int newProgress) {
338            mProgress = newProgress;
339            if (mTabView != null) {
340                mTabView.setProgress(mProgress);
341            }
342        }
343
344        void setFavicon(Bitmap icon) {
345            Drawable[] array = new Drawable[3];
346            array[0] = new PaintDrawable(Color.BLACK);
347            array[1] = new PaintDrawable(Color.WHITE);
348            if (icon == null) {
349//                array[2] = mGenericFavicon;
350            } else {
351                array[2] = new BitmapDrawable(icon);
352            }
353            LayerDrawable d = new LayerDrawable(array);
354            d.setLayerInset(1, 1, 1, 1, 1);
355            d.setLayerInset(2, 2, 2, 2, 2);
356            mIcon = d;
357            if (mTabView != null) {
358                mTabView.setFavicon(mIcon);
359            }
360        }
361
362    }
363
364    // TabChangeListener implementation
365
366    @Override
367    public void onCurrentTab(Tab tab) {
368        mTabs.setSelectedTab(mControl.getCurrentIndex());
369        TabViewData tvd = mTabMap.get(tab);
370        if (tvd != null) {
371            tvd.setProgress(tvd.mProgress);
372            // update the scroll state
373            WebView webview = tab.getWebView();
374            onScroll(webview.getVisibleTitleHeight() > 0);
375        }
376    }
377
378    @Override
379    public void onFavicon(Tab tab, Bitmap favicon) {
380        TabViewData tvd = mTabMap.get(tab);
381        if (tvd != null) {
382            tvd.setFavicon(favicon);
383        }
384    }
385
386    @Override
387    public void onNewTab(Tab tab) {
388        TabViewData tvd = buildTab(tab);
389        buildView(tvd);
390    }
391
392    @Override
393    public void onProgress(Tab tab, int progress) {
394        TabViewData tvd = mTabMap.get(tab);
395        if (tvd != null) {
396            tvd.setProgress(progress);
397        }
398    }
399
400    @Override
401    public void onRemoveTab(Tab tab) {
402        TabViewData tvd = mTabMap.get(tab);
403        TabView tv = tvd.mTabView;
404        if (tv != null) {
405            mTabs.removeTab(tv);
406        }
407        mTabMap.remove(tab);
408    }
409
410    @Override
411    public void onUrlAndTitle(Tab tab, String url, String title) {
412        TabViewData tvd = mTabMap.get(tab);
413        if (tvd != null) {
414            tvd.setUrlAndTitle(url, title);
415        }
416    }
417
418    @Override
419    public void onPageFinished(Tab tab) {
420    }
421
422    @Override
423    public void onPageStarted(Tab tab) {
424    }
425
426
427    private boolean isLoading() {
428        return mTabMap.get(mControl.getCurrentTab()).mTabView.mInLoad;
429    }
430
431}
432