blob: 2de7787127c7f0faa29b3f5facc427e33afe1720 [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 Scroggins0a64ba52009-09-08 15:35:33 -040023import android.view.KeyEvent;
24import android.view.LayoutInflater;
25import android.view.View;
26import android.view.ViewGroup;
27import android.widget.AdapterView;
28import android.widget.BaseAdapter;
Leon Scrogginsa3315562009-09-18 14:21:08 -040029import android.widget.ImageView;
Leon Scroggins0a64ba52009-09-08 15:35:33 -040030import android.widget.LinearLayout;
31import android.widget.ListView;
32import android.widget.TextView;
33
34public class ActiveTabsPage extends LinearLayout {
35 private final BrowserActivity mBrowserActivity;
36 private final LayoutInflater mFactory;
37 private final TabControl mControl;
38 private final TabsListAdapter mAdapter;
39 private final ListView mListView;
40
41 public ActiveTabsPage(BrowserActivity context, TabControl control) {
42 super(context);
43 mBrowserActivity = context;
44 mControl = control;
45 mFactory = LayoutInflater.from(context);
46 mFactory.inflate(R.layout.active_tabs, this);
47 mListView = (ListView) findViewById(R.id.list);
48 mAdapter = new TabsListAdapter();
49 mListView.setAdapter(mAdapter);
50 mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
51 public void onItemClick(AdapterView<?> parent, View view,
52 int position, long id) {
Grace Kloba22ac16e2009-10-07 18:00:23 -070053 if (mControl.canCreateNewTab()) {
Leon Scroggins0a64ba52009-09-08 15:35:33 -040054 position--;
55 }
56 boolean needToAttach = false;
57 if (position == -1) {
58 // Create a new tab
59 mBrowserActivity.openTabToHomePage();
60 } else {
61 // Open the corresponding tab
62 // If the tab is the current one, switchToTab will
63 // do nothing and return, so we need to make sure
64 // it gets attached back to its mContentView in
65 // removeActiveTabPage
66 needToAttach = !mBrowserActivity.switchToTab(position);
67 }
68 mBrowserActivity.removeActiveTabPage(needToAttach);
69 }
70 });
71 }
72
Leon Scrogginsa3315562009-09-18 14:21:08 -040073 /**
74 * Special class to hold the close drawable. Its sole purpose is to allow
75 * the parent to be pressed without being pressed itself. This way the line
76 * of a tab can be pressed, but the close button itself is not.
77 */
78 private static class CloseHolder extends ImageView {
79 public CloseHolder(Context context, AttributeSet attrs) {
80 super(context, attrs);
81 }
82
83 @Override
84 public void setPressed(boolean pressed) {
85 // If the parent is pressed, do not set to pressed.
86 if (pressed && ((View) getParent()).isPressed()) {
87 return;
88 }
89 super.setPressed(pressed);
90 }
91 }
92
Leon Scroggins0a64ba52009-09-08 15:35:33 -040093 private class TabsListAdapter extends BaseAdapter {
Patrick Scott49b11f92009-12-14 09:32:13 -050094 private boolean mNotified = true;
95 private int mReturnedCount;
96 private Handler mHandler = new Handler();
97
Leon Scroggins0a64ba52009-09-08 15:35:33 -040098 public int getCount() {
99 int count = mControl.getTabCount();
Grace Kloba22ac16e2009-10-07 18:00:23 -0700100 if (mControl.canCreateNewTab()) {
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400101 count++;
102 }
Patrick Scott49b11f92009-12-14 09:32:13 -0500103 // XXX: This is a workaround to be more like a real adapter. Most
104 // adapters call notifyDataSetChanged() whenever the internal data
105 // has changed. Since TabControl is our internal data, we don't
106 // know when that changes.
107 //
108 // Keep track of the last count we returned and whether we called
109 // notifyDataSetChanged(). If we did not initiate a data set
110 // change, and the count is different, send the notify and return
111 // the old count.
112 if (!mNotified && count != mReturnedCount) {
113 notifyChange();
114 return mReturnedCount;
115 }
116 mReturnedCount = count;
117 mNotified = false;
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400118 return count;
119 }
120 public Object getItem(int position) {
121 return null;
122 }
123 public long getItemId(int position) {
124 return position;
125 }
Patrick Scott555c5802009-09-23 08:08:17 -0400126 public int getViewTypeCount() {
127 return 2;
128 }
129 public int getItemViewType(int position) {
Grace Kloba22ac16e2009-10-07 18:00:23 -0700130 if (mControl.canCreateNewTab()) {
Patrick Scott555c5802009-09-23 08:08:17 -0400131 position--;
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400132 }
Patrick Scott555c5802009-09-23 08:08:17 -0400133 // Do not recycle the "add new tab" item.
134 return position == -1 ? IGNORE_ITEM_VIEW_TYPE : 1;
135 }
136 public View getView(int position, View convertView, ViewGroup parent) {
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400137 final int tabCount = mControl.getTabCount();
Grace Kloba22ac16e2009-10-07 18:00:23 -0700138 if (mControl.canCreateNewTab()) {
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400139 position--;
140 }
Patrick Scott555c5802009-09-23 08:08:17 -0400141
142 if (convertView == null) {
143 convertView = mFactory.inflate(position == -1 ?
144 R.layout.tab_view_add_tab : R.layout.tab_view, null);
145 }
146
147 if (position != -1) {
148 TextView title =
149 (TextView) convertView.findViewById(R.id.title);
150 TextView url = (TextView) convertView.findViewById(R.id.url);
151 ImageView favicon =
152 (ImageView) convertView.findViewById(R.id.favicon);
153 View close = convertView.findViewById(R.id.close);
Grace Kloba22ac16e2009-10-07 18:00:23 -0700154 Tab tab = mControl.getTab(position);
155 tab.populatePickerData();
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400156 title.setText(tab.getTitle());
157 url.setText(tab.getUrl());
Patrick Scott555c5802009-09-23 08:08:17 -0400158 Bitmap icon = tab.getFavicon();
159 if (icon != null) {
160 favicon.setImageBitmap(icon);
161 } else {
162 favicon.setImageResource(R.drawable.app_web_browser_sm);
163 }
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400164 final int closePosition = position;
165 close.setOnClickListener(new View.OnClickListener() {
166 public void onClick(View v) {
167 mBrowserActivity.closeTab(
168 mControl.getTab(closePosition));
169 if (tabCount == 1) {
170 mBrowserActivity.openTabToHomePage();
171 mBrowserActivity.removeActiveTabPage(false);
172 } else {
Patrick Scott49b11f92009-12-14 09:32:13 -0500173 mNotified = true;
174 notifyDataSetChanged();
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400175 }
176 }
177 });
178 }
179 return convertView;
180 }
Patrick Scott49b11f92009-12-14 09:32:13 -0500181
182 void notifyChange() {
183 mHandler.post(new Runnable() {
184 public void run() {
185 mNotified = true;
186 notifyDataSetChanged();
187 }
188 });
189 }
Leon Scroggins0a64ba52009-09-08 15:35:33 -0400190 }
191}