blob: 58ea9900d6097524422a35681e3b8b19cc544377 [file] [log] [blame]
Evan Millar7911ff52009-07-21 15:55:18 -07001/*
Evan Millar5f4af702009-08-11 11:12:00 -07002 * Copyright (C) 2009 The Android Open Source Project
Evan Millar7911ff52009-07-21 15:55:18 -07003 *
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.contacts;
18
Evan Millar5f4af702009-08-11 11:12:00 -070019import java.util.ArrayList;
20
Evan Millar7911ff52009-07-21 15:55:18 -070021import com.android.contacts.ScrollingTabWidget.OnTabSelectionChangedListener;
Evan Millar5f4af702009-08-11 11:12:00 -070022import com.android.contacts.model.ContactsSource;
Jeff Sharkey3f0b7b82009-08-12 11:28:53 -070023import com.android.contacts.util.NotifyingAsyncQueryHandler;
Evan Millar5f4af702009-08-11 11:12:00 -070024import com.android.contacts.model.Sources;
Evan Millar1ea3bf72009-07-30 13:46:19 -070025import com.android.internal.widget.ContactHeaderWidget;
Evan Millar7911ff52009-07-21 15:55:18 -070026
27import android.app.Activity;
28import android.content.ContentUris;
Evan Millar7911ff52009-07-21 15:55:18 -070029import android.content.Context;
Evan Millar5f4af702009-08-11 11:12:00 -070030import android.content.Entity;
31import android.content.EntityIterator;
Evan Millar7911ff52009-07-21 15:55:18 -070032import android.content.Intent;
Evan Millar5f4af702009-08-11 11:12:00 -070033import android.content.pm.PackageManager;
Evan Millar7911ff52009-07-21 15:55:18 -070034import android.database.Cursor;
Evan Millar7911ff52009-07-21 15:55:18 -070035import android.graphics.drawable.Drawable;
36import android.net.Uri;
37import android.os.Bundle;
Evan Millar5f4af702009-08-11 11:12:00 -070038import android.os.RemoteException;
Evan Millar7911ff52009-07-21 15:55:18 -070039import android.provider.ContactsContract.RawContacts;
Evan Millar7911ff52009-07-21 15:55:18 -070040import android.util.Log;
41import android.util.SparseArray;
42import android.view.LayoutInflater;
43import android.view.View;
Jeff Sharkey14f61ab2009-08-05 21:02:37 -070044import android.view.ViewGroup;
Evan Millar7911ff52009-07-21 15:55:18 -070045import android.view.Window;
Evan Millar7911ff52009-07-21 15:55:18 -070046import android.widget.ImageView;
47import android.widget.TextView;
48
49/**
50 * The base Activity class for viewing and editing a contact.
51 */
Jeff Sharkey3f0b7b82009-08-12 11:28:53 -070052public abstract class BaseContactCardActivity extends Activity implements
53 NotifyingAsyncQueryHandler.AsyncQueryListener, OnTabSelectionChangedListener {
Evan Millar7911ff52009-07-21 15:55:18 -070054
55 private static final String TAG = "BaseContactCardActivity";
56
57 private SparseArray<Long> mTabRawContactIdMap;
58 protected Uri mUri;
Evan Millar7911ff52009-07-21 15:55:18 -070059 protected ScrollingTabWidget mTabWidget;
Evan Millar1ea3bf72009-07-30 13:46:19 -070060 protected ContactHeaderWidget mContactHeaderWidget;
Evan Millar7911ff52009-07-21 15:55:18 -070061 private NotifyingAsyncQueryHandler mHandler;
Evan Millar7911ff52009-07-21 15:55:18 -070062
63 protected LayoutInflater mInflater;
64
65 //Projection used for the query that determines which tabs to add.
66 protected static final String[] TAB_PROJECTION = new String[] {
67 RawContacts._ID,
68 RawContacts.ACCOUNT_NAME,
69 RawContacts.ACCOUNT_TYPE
70 };
71 protected static final int TAB_CONTACT_ID_COLUMN_INDEX = 0;
72 protected static final int TAB_ACCOUNT_NAME_COLUMN_INDEX = 1;
73 protected static final int TAB_ACCOUNT_TYPE_COLUMN_INDEX = 2;
74
Evan Millar1ea3bf72009-07-30 13:46:19 -070075 private static final int TOKEN_TABS = 0;
Evan Millar7911ff52009-07-21 15:55:18 -070076
77 @Override
78 protected void onCreate(Bundle icicle) {
79 super.onCreate(icicle);
80
81 mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
82
83 final Intent intent = getIntent();
84 mUri = intent.getData();
Evan Millar7911ff52009-07-21 15:55:18 -070085
86 requestWindowFeature(Window.FEATURE_NO_TITLE);
87 setContentView(R.layout.contact_card_layout);
88
Evan Millar1ea3bf72009-07-30 13:46:19 -070089 mContactHeaderWidget = (ContactHeaderWidget) findViewById(R.id.contact_header_widget);
90 mContactHeaderWidget.showStar(true);
91 mContactHeaderWidget.bindFromContactId(ContentUris.parseId(mUri));
Evan Millar7911ff52009-07-21 15:55:18 -070092 mTabWidget = (ScrollingTabWidget) findViewById(R.id.tab_widget);
Evan Millar7911ff52009-07-21 15:55:18 -070093
94 mTabWidget.setTabSelectionListener(this);
Evan Millar5f4af702009-08-11 11:12:00 -070095 mTabWidget.setVisibility(View.INVISIBLE);
Evan Millar7911ff52009-07-21 15:55:18 -070096 mTabRawContactIdMap = new SparseArray<Long>();
97
Evan Millar7911ff52009-07-21 15:55:18 -070098 mHandler = new NotifyingAsyncQueryHandler(this, this);
99
Jeff Sharkey3f0b7b82009-08-12 11:28:53 -0700100 // TODO: turn this into async call instead of blocking ui
Evan Millar5f4af702009-08-11 11:12:00 -0700101 asyncSetupTabs();
102 }
103
104 private void asyncSetupTabs() {
Dmitri Plotnikov8832a642009-08-06 17:24:34 -0700105 long contactId = ContentUris.parseId(mUri);
Evan Millar5f4af702009-08-11 11:12:00 -0700106 mHandler.startQueryEntities(TOKEN_TABS, null,
107 RawContacts.CONTENT_URI, RawContacts.CONTACT_ID + "=" + contactId, null, null);
Evan Millar7911ff52009-07-21 15:55:18 -0700108 }
109
110 /**
111 * Return the contactId associated with the tab at an index.
112 *
113 * @param index The index of the tab in question.
114 * @return The contactId associated with the tab at the specified index.
115 */
116 protected long getTabRawContactId(int index) {
117 return mTabRawContactIdMap.get(index);
118 }
119
120 /** {@inheritDoc} */
Evan Millar5f4af702009-08-11 11:12:00 -0700121 public void onQueryEntitiesComplete(int token, Object cookie, EntityIterator iterator) {
Evan Millar7911ff52009-07-21 15:55:18 -0700122 try{
Evan Millar1ea3bf72009-07-30 13:46:19 -0700123 if (token == TOKEN_TABS) {
Evan Millar7911ff52009-07-21 15:55:18 -0700124 clearCurrentTabs();
Evan Millar5f4af702009-08-11 11:12:00 -0700125 bindTabs(readEntities(iterator));
Evan Millar7911ff52009-07-21 15:55:18 -0700126 }
127 } finally {
Evan Millar5f4af702009-08-11 11:12:00 -0700128 if (iterator != null) {
129 iterator.close();
Evan Millar1ea3bf72009-07-30 13:46:19 -0700130 }
Evan Millar7911ff52009-07-21 15:55:18 -0700131 }
132 }
133
Evan Millar5f4af702009-08-11 11:12:00 -0700134 /** {@inheritDoc} */
135 public void onQueryComplete(int token, Object cookie, Cursor cursor) {
136 // Emtpy
137 }
138
139 private ArrayList<Entity> readEntities(EntityIterator iterator) {
140 ArrayList<Entity> entities = new ArrayList<Entity>();
141 try {
142 while (iterator.hasNext()) {
143 entities.add(iterator.next());
144 }
145 } catch (RemoteException e) {
146 }
147
148 return entities;
149 }
150
Evan Millar7911ff52009-07-21 15:55:18 -0700151 /**
152 * Adds a tab for each {@link RawContact} associated with this contact.
153 * Override this method if you want to additional tabs and/or different
154 * tabs for your activity.
155 *
Evan Millar5f4af702009-08-11 11:12:00 -0700156 * @param entities An {@link ArrayList} of {@link Entity}s of all the RawContacts
157 * associated with the contact being displayed.
Evan Millar7911ff52009-07-21 15:55:18 -0700158 */
Evan Millar5f4af702009-08-11 11:12:00 -0700159 protected void bindTabs(ArrayList<Entity> entities) {
Jeff Sharkey3f0b7b82009-08-12 11:28:53 -0700160 final Sources sources = Sources.getInstance(this);
161
Evan Millar5f4af702009-08-11 11:12:00 -0700162 for (Entity entity : entities) {
163 final String accountType = entity.getEntityValues().
164 getAsString(RawContacts.ACCOUNT_TYPE);
165 final Long rawContactId = entity.getEntityValues().
166 getAsLong(RawContacts._ID);
Jeff Sharkey3f0b7b82009-08-12 11:28:53 -0700167
168 // TODO: ensure inflation on background task so we don't block UI thread here
169 final ContactsSource source = sources.getInflatedSource(accountType,
170 ContactsSource.LEVEL_SUMMARY);
Evan Millar5f4af702009-08-11 11:12:00 -0700171 addTab(rawContactId, createTabIndicatorView(mTabWidget, source));
Evan Millar7911ff52009-07-21 15:55:18 -0700172 }
Evan Millar5f4af702009-08-11 11:12:00 -0700173 mTabWidget.setCurrentTab(0);
174 mTabWidget.setVisibility(View.VISIBLE);
175 mTabWidget.postInvalidate();
Evan Millar7911ff52009-07-21 15:55:18 -0700176 }
177
Evan Millar5f4af702009-08-11 11:12:00 -0700178
Evan Millar7911ff52009-07-21 15:55:18 -0700179 /**
180 * Add a tab to be displayed in the {@link ScrollingTabWidget}.
181 *
182 * @param contactId The contact id associated with the tab.
183 * @param label A label to display in the tab indicator.
184 * @param icon An icon to display in the tab indicator.
185 */
186 protected void addTab(long contactId, String label, Drawable icon) {
Jeff Sharkey14f61ab2009-08-05 21:02:37 -0700187 addTab(contactId, createTabIndicatorView(mTabWidget, label, icon));
Evan Millar7911ff52009-07-21 15:55:18 -0700188 }
189
190 /**
191 * Add a tab to be displayed in the {@link ScrollingTabWidget}.
192 *
193 * @param contactId The contact id associated with the tab.
194 * @param view A view to use as the tab indicator.
195 */
Evan Millar5f4af702009-08-11 11:12:00 -0700196 protected void addTab(long rawContactId, View view) {
197 mTabRawContactIdMap.put(mTabWidget.getTabCount(), rawContactId);
Evan Millar7911ff52009-07-21 15:55:18 -0700198 mTabWidget.addTab(view);
199 }
200
201
202 protected void clearCurrentTabs() {
203 mTabRawContactIdMap.clear();
204 mTabWidget.removeAllTabs();
205 }
206
207 /**
208 * Makes the default tab selection. This is called after the tabs have been
209 * bound for the first time, and whenever a new intent is received. Override
210 * this method if you want to customize the default tab behavior.
211 */
212 protected void selectDefaultTab() {
213 // Select the first tab.
214 mTabWidget.setCurrentTab(0);
215 }
216
217 @Override
218 public void onNewIntent(Intent newIntent) {
219 setIntent(newIntent);
220 selectDefaultTab();
221 mUri = newIntent.getData();
222 }
223
224 /**
225 * Utility for creating a standard tab indicator view.
226 *
Evan Millar5f4af702009-08-11 11:12:00 -0700227 * @param parent The parent ViewGroup to attach the new view to.
Evan Millar7911ff52009-07-21 15:55:18 -0700228 * @param label The label to display in the tab indicator. If null, not label will be displayed.
229 * @param icon The icon to display. If null, no icon will be displayed.
230 * @return The tab indicator View.
231 */
Jeff Sharkey14f61ab2009-08-05 21:02:37 -0700232 public static View createTabIndicatorView(ViewGroup parent, CharSequence label, Drawable icon) {
233 final LayoutInflater inflater = (LayoutInflater)parent.getContext().getSystemService(
234 Context.LAYOUT_INFLATER_SERVICE);
235 final View tabIndicator = inflater.inflate(R.layout.tab_indicator, parent, false);
Evan Millar7911ff52009-07-21 15:55:18 -0700236
237 final TextView tv = (TextView) tabIndicator.findViewById(R.id.tab_title);
238 tv.setText(label);
239
240 final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.tab_icon);
241 iconView.setImageDrawable(icon);
242
243 return tabIndicator;
244 }
245
Evan Millar5f4af702009-08-11 11:12:00 -0700246 /**
247 * Utility for creating a standard tab indicator view.
248 *
249 * @param context The label to display in the tab indicator. If null, not label will be displayed.
250 * @param parent The parent ViewGroup to attach the new view to.
251 * @param source The {@link ContactsSource} to build the tab view from.
252 * @return The tab indicator View.
253 */
254 public static View createTabIndicatorView(ViewGroup parent, ContactsSource source) {
255 Drawable icon = null;
256 if (source != null) {
257 final String packageName = source.resPackageName;
258 if (source.iconRes > 0) {
259 try {
260 final Context authContext = parent.getContext().
261 createPackageContext(packageName, 0);
262 icon = authContext.getResources().getDrawable(source.iconRes);
263
264 } catch (PackageManager.NameNotFoundException e) {
265 Log.d(TAG, "error getting the Package Context for " + packageName, e);
266 }
267 }
268 }
269 return createTabIndicatorView(parent, null, icon);
270 }
Evan Millar7911ff52009-07-21 15:55:18 -0700271}