TabBar.java revision ed217745066c160f785626e9a15ebe70af5e25e4
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        ImageView mIconView;
213        ImageView mLock;
214        ImageView mClose;
215        boolean mSelected;
216        boolean mInLoad;
217
218        /**
219         * @param context
220         */
221        public TabView(Context context, TabViewData tab) {
222            super(context);
223            mTabData = tab;
224            setGravity(Gravity.CENTER_VERTICAL);
225            setOrientation(LinearLayout.HORIZONTAL);
226            setBackgroundResource(R.drawable.tab_background);
227            LayoutInflater inflater = LayoutInflater.from(mContext);
228            mTabContent = inflater.inflate(R.layout.tab_title, this, true);
229            mTitle = (TextView) mTabContent.findViewById(R.id.title);
230            mIconView = (ImageView) mTabContent.findViewById(R.id.favicon);
231            mLock = (ImageView) mTabContent.findViewById(R.id.lock);
232            mClose = (ImageView) mTabContent.findViewById(R.id.close);
233            mClose.setOnClickListener(this);
234            mSelected = false;
235            mInLoad = false;
236            // update the status
237            updateFromData();
238        }
239
240        @Override
241        public void onClick(View v) {
242            if (v == mClose) {
243                closeTab();
244            }
245        }
246
247        private void updateFromData() {
248            mTabData.mTabView = this;
249            if (mTabData.mUrl != null) {
250                setDisplayTitle(mTabData.mUrl);
251            }
252            if (mTabData.mTitle != null) {
253                setDisplayTitle(mTabData.mTitle);
254            }
255            setProgress(mTabData.mProgress);
256            if (mTabData.mIcon != null) {
257                setFavicon(mTabData.mIcon);
258            }
259            if (mTabData.mLock != null) {
260                setLock(mTabData.mLock);
261            }
262        }
263
264        @Override
265        public void setSelected(boolean selected) {
266            mSelected = selected;
267            mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE);
268            mTitle.setTextColor(mSelected ? Color.BLACK : Color.GRAY);
269            super.setSelected(selected);
270            setLayoutParams(new LayoutParams(selected ?
271                    mTabWidthSelected : mTabWidthUnselected,
272                    LayoutParams.MATCH_PARENT));
273        }
274
275        void setDisplayTitle(String title) {
276            mTitle.setText(title);
277        }
278
279        void setFavicon(Drawable d) {
280            mIconView.setImageDrawable(d);
281        }
282
283        void setLock(Drawable d) {
284            if (null == d) {
285                mLock.setVisibility(View.GONE);
286            } else {
287                mLock.setImageDrawable(d);
288                mLock.setVisibility(View.VISIBLE);
289            }
290        }
291
292        void setTitleCompoundDrawables(Drawable left, Drawable top,
293                Drawable right, Drawable bottom) {
294            mTitle.setCompoundDrawables(left, top, right, bottom);
295        }
296
297        void setProgress(int newProgress) {
298            if (newProgress >= PROGRESS_MAX) {
299                mInLoad = false;
300            } else {
301                if (!mInLoad && getWindowToken() != null) {
302                    mInLoad = true;
303                }
304            }
305        }
306
307        private void closeTab() {
308            if (mTabData.mTab == mControl.getCurrentTab()) {
309                mBrowserActivity.closeCurrentWindow();
310            } else {
311                mBrowserActivity.closeTab(mTabData.mTab);
312            }
313        }
314
315    }
316
317    /**
318     * Store tab state within the title bar
319     */
320    class TabViewData {
321
322        Tab mTab;
323        TabView mTabView;
324        int mProgress;
325        Drawable mIcon;
326        Drawable mLock;
327        String mTitle;
328        String mUrl;
329
330        TabViewData(Tab tab) {
331            mTab = tab;
332        }
333
334        void setUrlAndTitle(String url, String title) {
335            mUrl = url;
336            mTitle = title;
337            if (mTabView != null) {
338                if (title != null) {
339                    mTabView.setDisplayTitle(title);
340                } else if (url != null) {
341                    mTabView.setDisplayTitle(url);
342                }
343            }
344        }
345
346        void setProgress(int newProgress) {
347            mProgress = newProgress;
348            if (mTabView != null) {
349                mTabView.setProgress(mProgress);
350            }
351        }
352
353        void setFavicon(Bitmap icon) {
354            Drawable[] array = new Drawable[3];
355            array[0] = new PaintDrawable(Color.BLACK);
356            array[1] = new PaintDrawable(Color.WHITE);
357            if (icon == null) {
358//                array[2] = mGenericFavicon;
359            } else {
360                array[2] = new BitmapDrawable(icon);
361            }
362            LayerDrawable d = new LayerDrawable(array);
363            d.setLayerInset(1, 1, 1, 1, 1);
364            d.setLayerInset(2, 2, 2, 2, 2);
365            mIcon = d;
366            if (mTabView != null) {
367                mTabView.setFavicon(mIcon);
368            }
369        }
370
371    }
372
373    // TabChangeListener implementation
374
375    @Override
376    public void onCurrentTab(Tab tab) {
377        mTabs.setSelectedTab(mControl.getCurrentIndex());
378        TabViewData tvd = mTabMap.get(tab);
379        if (tvd != null) {
380            tvd.setProgress(tvd.mProgress);
381            // update the scroll state
382            WebView webview = tab.getWebView();
383            onScroll(webview.getVisibleTitleHeight() > 0);
384        }
385    }
386
387    @Override
388    public void onFavicon(Tab tab, Bitmap favicon) {
389        TabViewData tvd = mTabMap.get(tab);
390        if (tvd != null) {
391            tvd.setFavicon(favicon);
392        }
393    }
394
395    @Override
396    public void onNewTab(Tab tab) {
397        TabViewData tvd = buildTab(tab);
398        buildView(tvd);
399    }
400
401    @Override
402    public void onProgress(Tab tab, int progress) {
403        TabViewData tvd = mTabMap.get(tab);
404        if (tvd != null) {
405            tvd.setProgress(progress);
406        }
407    }
408
409    @Override
410    public void onRemoveTab(Tab tab) {
411        TabViewData tvd = mTabMap.get(tab);
412        TabView tv = tvd.mTabView;
413        if (tv != null) {
414            mTabs.removeTab(tv);
415        }
416        mTabMap.remove(tab);
417    }
418
419    @Override
420    public void onUrlAndTitle(Tab tab, String url, String title) {
421        TabViewData tvd = mTabMap.get(tab);
422        if (tvd != null) {
423            tvd.setUrlAndTitle(url, title);
424        }
425    }
426
427    @Override
428    public void onPageFinished(Tab tab) {
429    }
430
431    @Override
432    public void onPageStarted(Tab tab) {
433    }
434
435
436    private boolean isLoading() {
437        return mTabMap.get(mControl.getCurrentTab()).mTabView.mInLoad;
438    }
439
440}
441