blob: 873f40b1bc4cffcf19eecbd32ab26771663aeab0 [file] [log] [blame]
Leon Scroggins1f005d32009-08-10 17:36:42 -04001/*
2 * Copyright (C) 2009 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.database.DataSetObserver;
21import android.graphics.drawable.Drawable;
22import android.util.AttributeSet;
23import android.util.Log;
24import android.view.LayoutInflater;
25import android.view.MotionEvent;
26import android.view.View;
27import android.view.ViewGroup;
28import android.webkit.WebView;
29import android.widget.AdapterView;
30import android.widget.Gallery;
31import android.widget.SpinnerAdapter;
32
33import java.util.Vector;
34
35/**
36 * The TitleBarSet holds a TitleBar for each open "tab" in the browser.
37 */
38public class TitleBarSet extends Gallery
39 implements AdapterView.OnItemSelectedListener {
40 private Vector<TitleBar> mTitleBars;
41 private BrowserActivity mBrowserActivity;
Leon Scroggins1f005d32009-08-10 17:36:42 -040042 private int mCount;
43 private TitleAdapter mTitleAdapter;
44 private boolean mIgnoreSelectedListener;
45 private MotionEvent mLastTouchUp;
46
47 public TitleBarSet(Context context) {
48 this(context, null);
49 }
50
51 public TitleBarSet(Context context, AttributeSet attrs) {
52 super(context, attrs);
53 mTitleBars = new Vector<TitleBar>(TabControl.MAX_TABS);
54 mCount = 0;
Leon Scroggins1f005d32009-08-10 17:36:42 -040055 mTitleAdapter = new TitleAdapter();
56 setAdapter(mTitleAdapter);
57 setCallbackDuringFling(false);
58 setCallbackOnUnselectedItemClick(true);
59 setSpacing(0);
60 setOnItemSelectedListener(this);
61 }
62
63 /**
64 * Add a tab/titlebar to our set. Called when BrowserActivity adds a new
65 * Tab to its TabControl.
66 * @param view WebView associated with this tab. Used to determine whether
67 * updates are going to the correct place.
68 * @param selected Whether to set the new tab to be selected.
69 */
70 /* package */ void addTab(WebView view, boolean selected) {
71 if (TabControl.MAX_TABS == mCount) {
72 return;
73 }
74 int newSelection = mCount;
Leon Scrogginsa81a7642009-08-31 17:05:41 -040075 TitleBar titleBar = new TitleBar(getContext(), view, mBrowserActivity);
Leon Scroggins1f005d32009-08-10 17:36:42 -040076 mTitleBars.add(titleBar);
77 mCount++;
Leon Scroggins1f005d32009-08-10 17:36:42 -040078 // Need to refresh our list
79 setAdapter(mTitleAdapter);
80 mIgnoreSelectedListener = true;
81 // No need to call onItemSelected, since the Tab in BrowserActivity has
82 // already been changed.
83 if (selected) {
84 setSelection(newSelection);
85 }
86 mIgnoreSelectedListener = false;
87 }
88
89 /**
90 * Convenience method to get a particular title bar.
91 */
92 private TitleBar getTitleBarAt(int position) {
93 if (position < 0 || position >= mCount) {
94 return null;
95 }
96 return (TitleBar) mTitleBars.elementAt(position);
97 }
98
99 /**
100 * Implementation for OnItemSelectedListener
101 */
102 public void onItemSelected(AdapterView<?> parent, View view, int position,
103 long id) {
104 if (mIgnoreSelectedListener || !(view instanceof TitleBar)) {
105 return;
106 }
107 mBrowserActivity.switchToTab(position);
108 // In case the WebView finished loading while this TitleBar was out of
109 // focus, make sure all its data is up to date
110 TitleBar titleBar = getTitleBarAt(position);
111 WebView webview = titleBar.getWebView();
112 if (webview == null) {
113 // FIXME: Possible that the tab needs to be restored.
114 return;
115 }
116 if (webview.getProgress() == 100) {
117 titleBar.setProgress(100);
118 titleBar.setTitleAndUrl(webview.getTitle(), webview.getUrl());
119 // FIXME: Pass in a bitmap, so we can always update the bitmap
120 // properly
121 //titleBar.setFavicon(webview.getFavicon());
122 }
123 }
124
125 /**
126 * Implementation for OnItemSelectedListener
127 */
128 public void onNothingSelected(AdapterView<?> parent) {
129 // do nothing
130 }
131
132 /**
133 * Override from GestureDetector.OnGestureListener. Store the MotionEvent
134 * so performItemClick can know how to handle the click.
135 */
136 public boolean onSingleTapUp(MotionEvent e) {
137 mLastTouchUp = e;
138 // super.onSingleTapUp will call performItemClick
139 boolean result = super.onSingleTapUp(e);
140 mLastTouchUp = null;
141 return result;
142 }
143
144 /**
145 * Override from View to ensure that the TitleBars get resized to match
146 * the new screen width
147 */
148 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
149 super.onSizeChanged(w, h, oldw, oldh);
Leon Scroggins5a7e6c62009-08-14 16:32:43 -0400150 int selection = getSelectedItemPosition();
Leon Scroggins1f005d32009-08-10 17:36:42 -0400151 // Need to make sure getView gets called again
Leon Scroggins1f005d32009-08-10 17:36:42 -0400152 setAdapter(mTitleAdapter);
Leon Scroggins5a7e6c62009-08-14 16:32:43 -0400153 // Stay on the same tab
154 setCurrentTab(selection);
Leon Scroggins1f005d32009-08-10 17:36:42 -0400155 }
156
157 /**
158 * Override from AdapterView. Using simple OnClickListeners overrides
159 * the GestureDetector.OnGestureListener, so we handle it here.
160 */
161 public boolean performItemClick(View view, int position, long id) {
162 if (!(view instanceof TitleBar)) {
Leon Scroggins1f005d32009-08-10 17:36:42 -0400163 return super.performItemClick(view, position, id);
164 }
165 // If we have no mLastTouchUp, this was not called from onSingleTapUp,
166 // so ignore it.
167 if (null == mLastTouchUp) {
168 return false;
169 }
170 TitleBar titleBar = (TitleBar) view;
171 // If the user clicks on a view which is not selected, the Gallery will
172 // take care of making it selected.
173 if (titleBar != getTitleBarAt(position)) {
174 return false;
175 }
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400176 mBrowserActivity.onSearchRequested();
Leon Scroggins1f005d32009-08-10 17:36:42 -0400177 return true;
178 }
179
180 /**
181 * Remove the tab at the given position.
182 */
183 /* package */ void removeTab(int position) {
Leon Scroggins53fe5812009-09-01 12:33:07 -0400184 int selection = getSelectedItemPosition();
Leon Scroggins1f005d32009-08-10 17:36:42 -0400185 mTitleBars.remove(position);
186 mCount--;
187 // Need to refresh our list
188 setAdapter(mTitleAdapter);
Leon Scroggins53fe5812009-09-01 12:33:07 -0400189 setCurrentTab(selection);
Leon Scroggins1f005d32009-08-10 17:36:42 -0400190 }
191
192 /**
193 * Convenience method to get the currently selected title bar.
194 */
195 private TitleBar selectedTitleBar() {
196 return getTitleBarAt(getSelectedItemPosition());
197 }
198
199 /**
200 * Set the owning BrowserActivity. Necessary so that we can call methods
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400201 * on it. Only called once before adding any title bars.
Leon Scroggins1f005d32009-08-10 17:36:42 -0400202 */
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400203 /* package */ void init(final BrowserActivity ba) {
Leon Scroggins1f005d32009-08-10 17:36:42 -0400204 mBrowserActivity = ba;
Leon Scroggins1f005d32009-08-10 17:36:42 -0400205 }
206
207 /**
208 * Change to the tab at the new position.
209 */
210 /* package */ void setCurrentTab(int position) {
Leon Scroggins53fe5812009-09-01 12:33:07 -0400211 if (position < 0 || position >= mCount) return;
Leon Scroggins1f005d32009-08-10 17:36:42 -0400212 mIgnoreSelectedListener = true;
213 setSelection(position);
214 mIgnoreSelectedListener = false;
215 }
216
217 /**
218 * Update the Favicon of the currently selected tab.
219 * @param d The new Drawable for the Favicon
220 * @param topWindow The WebView which posted the update. If it does not
221 * match the WebView of the currently selected tab, do
222 * nothing, since that tab is not being displayed.
223 */
224 /* package */ void setFavicon(Drawable d, WebView topWindow) {
225 TitleBar current = selectedTitleBar();
226 if (current != null && current.getWebView() == topWindow) {
227 current.setFavicon(d);
228 }
229 }
230
231 /**
232 * Update the lock icon of the currently selected tab.
233 * @param d The new Drawable for the lock icon
234 * @param topWindow The WebView which posted the update. If it does not
235 * match the WebView of the currently selected tab, do
236 * nothing, since that tab is not being displayed.
237 */
238 /* package */ void setLock(Drawable d, WebView topWindow) {
239 TitleBar current = selectedTitleBar();
240 if (current != null && current.getWebView() == topWindow) {
241 current.setLock(d);
242 }
243 }
244 /**
245 * Update the progress of the currently selected tab.
246 * @param newProgress The progress, between 0 and 100, of the current tab.
247 * @param topWindow The WebView which posted the update. If it does not
248 * match the WebView of the currently selected tab, do
249 * nothing, since that tab is not being displayed.
250 */
251 /* package */ void setProgress(int newProgress, WebView topWindow) {
252 TitleBar current = selectedTitleBar();
253 if (current != null && current.getWebView() == topWindow) {
254 current.setProgress(newProgress);
255 }
256 }
257 /**
258 * Update the title and URL of the currently selected tab.
259 * @param title The title of the webpage
260 * @param url The URL of the webpage
261 * @param topWindow The WebView which posted the update. If it does not
262 * match the WebView of the currently selected tab, do
263 * nothing, since that tab is not being displayed.
264 */
265 /* package */ void setTitleAndUrl(CharSequence title, CharSequence url,
266 WebView topWindow) {
267 TitleBar current = selectedTitleBar();
268 if (current != null && current.getWebView() == topWindow) {
269 current.setTitleAndUrl(title, url);
270 }
271 }
272
273 // FIXME: Remove
274 /* package */ void setToTabPicker() {
275 TitleBar current = selectedTitleBar();
276 if (current != null) {
277 current.setToTabPicker();
278 }
279 }
280
281 /**
282 * Custom adapter which provides the TitleBars and the NewButton to the
283 * Gallery.
284 */
285 private class TitleAdapter implements SpinnerAdapter {
286 public View getDropDownView(int position, View convertView,
287 ViewGroup parent) {
288 return null;
289 }
290 public void registerDataSetObserver(DataSetObserver observer) {}
291 public void unregisterDataSetObserver(DataSetObserver observer) {}
292 public int getCount() {
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400293 return mCount;
Leon Scroggins1f005d32009-08-10 17:36:42 -0400294 }
295 public Object getItem(int position) {
296 return null;
297 }
298 public long getItemId(int position) {
299 return position;
300 }
301 public boolean hasStableIds() {
302 return true;
303 }
304 public View getView(int position, View convertView, ViewGroup parent) {
Leon Scroggins1f005d32009-08-10 17:36:42 -0400305 TitleBar titleBar = getTitleBarAt(position);
306 Gallery.LayoutParams lp;
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400307 int desiredWidth = TitleBarSet.this.getWidth();
Leon Scroggins1f005d32009-08-10 17:36:42 -0400308 ViewGroup.LayoutParams old = titleBar.getLayoutParams();
309 if (old == null || !(old instanceof Gallery.LayoutParams)) {
310 lp = new Gallery.LayoutParams(desiredWidth,
311 ViewGroup.LayoutParams.WRAP_CONTENT);
312 titleBar.setLayoutParams(lp);
313 } else {
314 lp = (Gallery.LayoutParams) old;
315 if (lp.width != desiredWidth) {
316 lp.width = desiredWidth;
317 titleBar.setLayoutParams(lp);
318 requestLayout();
319 }
320 }
321 return titleBar;
322 }
323 public int getItemViewType(int position) {
324 // We are managing our own views.
325 return AdapterView.ITEM_VIEW_TYPE_IGNORE;
326 }
327 public int getViewTypeCount() {
328 return 1;
329 }
330 public boolean isEmpty() {
331 // Will never be empty, because the NewButton is always there
332 // (though sometimes disabled).
333 return false;
334 }
335 }
336}