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