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