blob: 52828b301d6cd4e3f668cbe3ac64371cd8f8b674 [file] [log] [blame]
Leon Scroggins0a64ba52009-09-08 15:35:33 -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
Leon Scrogginsa3315562009-09-18 14:21:08 -040019import android.content.Context;
Patrick Scott555c5802009-09-23 08:08:17 -040020import android.graphics.Bitmap;
Patrick Scott49b11f92009-12-14 09:32:13 -050021import android.os.Handler;
Leon Scrogginsa3315562009-09-18 14:21:08 -040022import android.util.AttributeSet;
Leon Scroggins70a153b2010-05-10 17:27:26 -040023import android.util.Log;
Leon Scroggins0a64ba52009-09-08 15:35:33 -040024import android.view.KeyEvent;
25import android.view.LayoutInflater;
26import android.view.View;
27import android.view.ViewGroup;
28import android.widget.AdapterView;
29import android.widget.BaseAdapter;
Leon Scrogginsa3315562009-09-18 14:21:08 -040030import android.widget.ImageView;
Leon Scroggins0a64ba52009-09-08 15:35:33 -040031import android.widget.LinearLayout;
32import android.widget.ListView;
33import android.widget.TextView;
34
35public class ActiveTabsPage extends LinearLayout {
Leon Scroggins70a153b2010-05-10 17:27:26 -040036 private static final String LOGTAG = "TabPicker";
Leon Scroggins0a64ba52009-09-08 15:35:33 -040037 private final BrowserActivity mBrowserActivity;
38 private final LayoutInflater mFactory;
39 private final TabControl mControl;
40 private final TabsListAdapter mAdapter;
41 private final ListView mListView;
42
43 public ActiveTabsPage(BrowserActivity context, TabControl control) {
44 super(context);
45 mBrowserActivity = context;
46 mControl = control;
47 mFactory = LayoutInflater.from(context);
48 mFactory.inflate(R.layout.active_tabs, this);
49 mListView = (ListView) findViewById(R.id.list);
50 mAdapter = new TabsListAdapter();
51 mListView.setAdapter(mAdapter);
52 mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
53 public void onItemClick(AdapterView<?> parent, View view,
54 int position, long id) {
Grace Kloba22ac16e2009-10-07 18:00:23 -070055 if (mControl.canCreateNewTab()) {
Leon Scroggins0a64ba52009-09-08 15:35:33 -040056 position--;
57 }
58 boolean needToAttach = false;
59 if (position == -1) {
60 // Create a new tab
61 mBrowserActivity.openTabToHomePage();
62 } else {
63 // Open the corresponding tab
64 // If the tab is the current one, switchToTab will
65 // do nothing and return, so we need to make sure
66 // it gets attached back to its mContentView in
67 // removeActiveTabPage
68 needToAttach = !mBrowserActivity.switchToTab(position);
69 }
70 mBrowserActivity.removeActiveTabPage(needToAttach);
71 }
72 });
73 }
74
Leon Scrogginsa3315562009-09-18 14:21:08 -040075 /**
76 * Special class to hold the close drawable. Its sole purpose is to allow
77 * the parent to be pressed without being pressed itself. This way the line
78 * of a tab can be pressed, but the close button itself is not.
79 */
80 private static class CloseHolder extends ImageView {
81 public CloseHolder(Context context, AttributeSet attrs) {
82 super(context, attrs);
83 }
84
85 @Override
86 public void setPressed(boolean pressed) {
87 // If the parent is pressed, do not set to pressed.
88 if (pressed && ((View) getParent()).isPressed()) {
89 return;
90 }
91 super.setPressed(pressed);
92 }
93 }
94
Leon Scroggins0a64ba52009-09-08 15:35:33 -040095 private class TabsListAdapter extends BaseAdapter {
Patrick Scott49b11f92009-12-14 09:32:13 -050096 private boolean mNotified = true;
97 private int mReturnedCount;
98 private Handler mHandler = new Handler();
99
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400100 public int getCount() {
101 int count = mControl.getTabCount();
Grace Kloba22ac16e2009-10-07 18:00:23 -0700102 if (mControl.canCreateNewTab()) {
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400103 count++;
104 }
Patrick Scott49b11f92009-12-14 09:32:13 -0500105 // XXX: This is a workaround to be more like a real adapter. Most
106 // adapters call notifyDataSetChanged() whenever the internal data
107 // has changed. Since TabControl is our internal data, we don't
108 // know when that changes.
109 //
110 // Keep track of the last count we returned and whether we called
111 // notifyDataSetChanged(). If we did not initiate a data set
112 // change, and the count is different, send the notify and return
113 // the old count.
114 if (!mNotified && count != mReturnedCount) {
115 notifyChange();
116 return mReturnedCount;
117 }
118 mReturnedCount = count;
119 mNotified = false;
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400120 return count;
121 }
122 public Object getItem(int position) {
123 return null;
124 }
125 public long getItemId(int position) {
126 return position;
127 }
Patrick Scott555c5802009-09-23 08:08:17 -0400128 public int getViewTypeCount() {
129 return 2;
130 }
131 public int getItemViewType(int position) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700132 if (mControl.canCreateNewTab()) {
Patrick Scott555c5802009-09-23 08:08:17 -0400133 position--;
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400134 }
Patrick Scott555c5802009-09-23 08:08:17 -0400135 // Do not recycle the "add new tab" item.
136 return position == -1 ? IGNORE_ITEM_VIEW_TYPE : 1;
137 }
138 public View getView(int position, View convertView, ViewGroup parent) {
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400139 final int tabCount = mControl.getTabCount();
Grace Kloba22ac16e2009-10-07 18:00:23 -0700140 if (mControl.canCreateNewTab()) {
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400141 position--;
142 }
Patrick Scott555c5802009-09-23 08:08:17 -0400143
144 if (convertView == null) {
145 convertView = mFactory.inflate(position == -1 ?
146 R.layout.tab_view_add_tab : R.layout.tab_view, null);
147 }
148
149 if (position != -1) {
150 TextView title =
151 (TextView) convertView.findViewById(R.id.title);
152 TextView url = (TextView) convertView.findViewById(R.id.url);
153 ImageView favicon =
154 (ImageView) convertView.findViewById(R.id.favicon);
155 View close = convertView.findViewById(R.id.close);
Grace Kloba22ac16e2009-10-07 18:00:23 -0700156 Tab tab = mControl.getTab(position);
Leon Scroggins70a153b2010-05-10 17:27:26 -0400157 if (tab.getWebView() == null) {
158 // This means that populatePickerData will have to use the
159 // saved state.
160 Log.w(LOGTAG, "Tab " + position + " has a null WebView and "
161 + (tab.getSavedState() == null ? "null" : "non-null")
162 + " saved state ");
163 }
Grace Kloba22ac16e2009-10-07 18:00:23 -0700164 tab.populatePickerData();
Leon Scroggins70a153b2010-05-10 17:27:26 -0400165 if (tab.getTitle() == null || tab.getTitle().length() == 0) {
166 Log.w(LOGTAG, "Tab " + position + " has no title. "
167 + "Check above in the Logs to see whether it has a "
168 + "null WebView or null WebHistoryItem");
169 }
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400170 title.setText(tab.getTitle());
171 url.setText(tab.getUrl());
Patrick Scott555c5802009-09-23 08:08:17 -0400172 Bitmap icon = tab.getFavicon();
173 if (icon != null) {
174 favicon.setImageBitmap(icon);
175 } else {
176 favicon.setImageResource(R.drawable.app_web_browser_sm);
177 }
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400178 final int closePosition = position;
179 close.setOnClickListener(new View.OnClickListener() {
180 public void onClick(View v) {
181 mBrowserActivity.closeTab(
182 mControl.getTab(closePosition));
183 if (tabCount == 1) {
184 mBrowserActivity.openTabToHomePage();
185 mBrowserActivity.removeActiveTabPage(false);
186 } else {
Patrick Scott49b11f92009-12-14 09:32:13 -0500187 mNotified = true;
188 notifyDataSetChanged();
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400189 }
190 }
191 });
192 }
193 return convertView;
194 }
Patrick Scott49b11f92009-12-14 09:32:13 -0500195
196 void notifyChange() {
197 mHandler.post(new Runnable() {
198 public void run() {
199 mNotified = true;
200 notifyDataSetChanged();
201 }
202 });
203 }
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400204 }
205}