blob: 640e5c06b918cd9d95fc4b2bd0cb6df8c3e752b0 [file] [log] [blame]
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -08001/*******************************************************************************
2 * Copyright (C) 2012 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *******************************************************************************/
17
18package com.android.mail.ui;
19
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080020import android.app.ActionBar;
Vikram Aggarwalb9e1a352012-01-24 15:23:38 -080021import android.app.ActionBar.LayoutParams;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080022import android.app.Activity;
23import android.app.Dialog;
Vikram Aggarwal80aeac52012-02-07 15:27:20 -080024import android.content.ContentResolver;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080025import android.content.Context;
Vikram Aggarwal7dedb952012-02-16 16:10:23 -080026import android.content.CursorLoader;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080027import android.content.Intent;
Vikram Aggarwal7dedb952012-02-16 16:10:23 -080028import android.content.Loader;
Vikram Aggarwal80aeac52012-02-07 15:27:20 -080029import android.database.Cursor;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080030import android.os.Bundle;
31import android.view.ActionMode;
32import android.view.KeyEvent;
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080033import android.view.LayoutInflater;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080034import android.view.Menu;
Mindy Pereira28d5f722012-02-15 12:32:40 -080035import android.view.MenuInflater;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080036import android.view.MenuItem;
37import android.view.MotionEvent;
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080038import android.widget.LinearLayout;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080039
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080040import com.android.mail.R;
Vikram Aggarwalb9e1a352012-01-24 15:23:38 -080041import com.android.mail.ConversationListContext;
Mindy Pereira9b875682012-02-15 18:10:54 -080042import com.android.mail.compose.ComposeActivity;
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080043import com.android.mail.providers.Account;
Vikram Aggarwal80aeac52012-02-07 15:27:20 -080044import com.android.mail.providers.AccountCacheProvider;
Mindy Pereira9b875682012-02-15 18:10:54 -080045import com.android.mail.providers.Conversation;
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -080046import com.android.mail.providers.Folder;
Vikram Aggarwal80aeac52012-02-07 15:27:20 -080047import com.android.mail.providers.UIProvider;
Vikram Aggarwalfa131a22012-02-02 13:56:22 -080048import com.android.mail.utils.Utils;
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -080049
50/**
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080051 * This is an abstract implementation of the Activity Controller. This class knows how to
52 * respond to menu items, state changes, layout changes, etc. It weaves together the views and
53 * listeners, dispatching actions to the respective underlying classes.
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -080054 *
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080055 * <p>Even though this class is abstract, it should provide default implementations for most, if
56 * not all the methods in the ActivityController interface. This makes the task of the subclasses
57 * easier: OnePaneActivityController and TwoPaneActivityController can be concise when the common
58 * functionality is in AbstractActivityController.
59 *</p>
60 * <p>
61 * In the Gmail codebase, this was called BaseActivityController</p>
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -080062 */
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080063public abstract class AbstractActivityController implements ActivityController {
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080064 private static final String SAVED_CONVERSATION = "saved-conversation";
65 private static final String SAVED_CONVERSATION_POSITION = "saved-conv-pos";
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080066 // Keys for serialization of various information in Bundles.
67 private static final String SAVED_LIST_CONTEXT = "saved-list-context";
Vikram Aggarwald7a12cd2012-02-03 09:36:20 -080068 /**
69 * Are we on a tablet device or not.
70 */
71 public final boolean IS_TABLET_DEVICE;
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080072
Vikram Aggarwald7a12cd2012-02-03 09:36:20 -080073 protected Account mAccount;
Mindy Pereira28e0c342012-02-17 15:05:13 -080074 protected Folder mFolder;
Vikram Aggarwald7a12cd2012-02-03 09:36:20 -080075 protected ActionBarView mActionBarView;
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080076 protected final RestrictedActivity mActivity;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080077 protected final Context mContext;
Vikram Aggarwal80aeac52012-02-07 15:27:20 -080078 protected ConversationListContext mConvListContext;
Mindy Pereira9b875682012-02-15 18:10:54 -080079 protected Conversation mCurrentConversation;
Vikram Aggarwald7a12cd2012-02-03 09:36:20 -080080
Vikram Aggarwalb9e1a352012-01-24 15:23:38 -080081 protected ConversationListFragment mConversationListFragment;
Vikram Aggarwalfa131a22012-02-02 13:56:22 -080082 /**
83 * The current mode of the application. All changes in mode are initiated by the activity
84 * controller. View mode changes are propagated to classes that attach themselves as listeners
85 * of view mode changes.
86 */
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -080087 protected final ViewMode mViewMode;
Vikram Aggarwal80aeac52012-02-07 15:27:20 -080088 protected ContentResolver mResolver;
Mindy Pereira0825efd2012-02-15 17:30:32 -080089 protected FolderListFragment mFolderListFragment;
Mindy Pereira9b875682012-02-15 18:10:54 -080090 protected ConversationViewFragment mConversationViewFragment;
Vikram Aggarwal7dedb952012-02-16 16:10:23 -080091 protected boolean isLoaderInitialized = false;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080092
93 public AbstractActivityController(MailActivity activity, ViewMode viewMode) {
94 mActivity = activity;
95 mViewMode = viewMode;
96 mContext = activity.getApplicationContext();
Vikram Aggarwald7a12cd2012-02-03 09:36:20 -080097 IS_TABLET_DEVICE = Utils.useTabletUI(mContext);
Vikram Aggarwala55b36c2012-01-13 11:45:02 -080098 }
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -080099
100 @Override
Vikram Aggarwal2175d0a2012-02-17 16:04:23 -0800101 public synchronized void attachConversationList(ConversationListFragment fragment) {
102 // If there is an existing fragment, unregister it
103 if (mConversationListFragment != null) {
104 mViewMode.removeListener(mConversationListFragment);
105 }
106 mConversationListFragment = fragment;
107 // If the current fragment is non-null, add it as a listener.
108 if (fragment != null) {
109 mViewMode.addListener(mConversationListFragment);
110 }
Vikram Aggarwalb9e1a352012-01-24 15:23:38 -0800111 }
112
113 @Override
Vikram Aggarwal2175d0a2012-02-17 16:04:23 -0800114 public synchronized void attachFolderList(FolderListFragment fragment) {
115 // If there is an existing fragment, unregister it
116 if (mFolderListFragment != null) {
117 mViewMode.removeListener(mFolderListFragment);
118 }
119 mFolderListFragment = fragment;
120 if (fragment != null) {
121 mViewMode.addListener(mFolderListFragment);
122 }
Mindy Pereira555140c2012-02-15 14:55:29 -0800123 }
124
125 @Override
Mindy Pereira9b875682012-02-15 18:10:54 -0800126 public void attachConversationView(ConversationViewFragment conversationViewFragment) {
127 mConversationViewFragment = conversationViewFragment;
128 }
129
130 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800131 public void clearSubject() {
132 // TODO(viki): Auto-generated method stub
133
134 }
135
136 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800137 public void enterSearchMode() {
138 // TODO(viki): Auto-generated method stub
139
140 }
141
142 @Override
143 public void exitSearchMode() {
144 // TODO(viki): Auto-generated method stub
145
146 }
147
148 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800149 public String getCurrentAccount() {
150 // TODO(viki): Auto-generated method stub
151 return null;
152 }
153
154 @Override
155 public ConversationListContext getCurrentListContext() {
156 // TODO(viki): Auto-generated method stub
157 return null;
158 }
159
160 @Override
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -0800161 public String getHelpContext() {
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800162 return "Mail";
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -0800163 }
164
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800165 @Override
Vikram Aggarwald7a12cd2012-02-03 09:36:20 -0800166 public int getMode() {
167 return mViewMode.getMode();
168 }
169
170 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800171 public String getUnshownSubject(String subject) {
172 // Calculate how much of the subject is shown, and return the remaining.
173 return null;
174 }
175
176 @Override
177 public void handleConversationLoadError() {
178 // TODO(viki): Auto-generated method stub
179
180 }
181
182 @Override
183 public void handleSearchRequested() {
184 // TODO(viki): Auto-generated method stub
185
186 }
187
188 /**
189 * Initialize the action bar. This is not visible to OnePaneController and TwoPaneController so
190 * they cannot override this behavior.
191 */
192 private void initCustomActionBarView() {
193 ActionBar actionBar = mActivity.getActionBar();
194 mActionBarView = (MailActionBar) LayoutInflater.from(mContext).inflate(
195 R.layout.actionbar_view, null);
196
197 if (actionBar != null && mActionBarView != null) {
198 // Why have a different variable for the same thing? We should apply the same actions
199 // on mActionBarView instead.
200 // mSubjectDisplayer = (ConversationSubjectDisplayer) mActionBarView;
201 mActionBarView.initialize(mActivity, this, mViewMode, actionBar);
202 actionBar.setCustomView((LinearLayout) mActionBarView, new ActionBar.LayoutParams(
203 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
204 actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
205 ActionBar.DISPLAY_SHOW_CUSTOM
206 | ActionBar.DISPLAY_SHOW_TITLE);
207 }
208 }
209
210 /**
211 * Returns whether the conversation list fragment is visible or not. Different layouts will have
212 * their own notion on the visibility of fragments, so this method needs to be overriden.
213 * @return
214 */
215 protected abstract boolean isConversationListVisible();
216
217 @Override
Mindy Pereira28e0c342012-02-17 15:05:13 -0800218 public void onAccountChanged(Account account) {
Mindy Pereira28d5f722012-02-15 12:32:40 -0800219 if (!account.equals(mAccount)) {
220 mAccount = account;
221
222 final Intent intent = mActivity.getIntent();
223 // TODO(viki): Show the list context from Intent
224 mConvListContext = ConversationListContext.forIntent(mContext, mAccount, intent);
Mindy Pereira28e0c342012-02-17 15:05:13 -0800225 mFolder = mConvListContext.mFolder;
Mindy Pereira28d5f722012-02-15 12:32:40 -0800226 showConversationList(mConvListContext);
227 mViewMode.enterConversationListMode();
228 }
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800229 }
230
231 @Override
Mindy Pereira28e0c342012-02-17 15:05:13 -0800232 public void onFolderChanged(Folder folder) {
233 if (!folder.equals(mFolder)) {
234 mFolder = folder;
235 final Intent intent = mActivity.getIntent();
236 intent.putExtra(ConversationListContext.EXTRA_FOLDER, mFolder);
237 // TODO(viki): Show the list context from Intent
238 mConvListContext = ConversationListContext.forIntent(mContext, mAccount, intent);
239 // Instead of this, switch to the conversation list mode and have that do the right
240 // things automatically.
241 showConversationList(mConvListContext);
242 mViewMode.enterConversationListMode();
243 }
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800244 }
245
246 @Override
247 public void onActionModeFinished(ActionMode mode) {
248 // TODO(viki): Auto-generated method stub
249
250 }
251
252 @Override
253 public void onActionModeStarted(ActionMode mode) {
254 // TODO(viki): Auto-generated method stub
255
256 }
257
258 @Override
259 public void onActivityResult(int requestCode, int resultCode, Intent data) {
260 // TODO(viki): Auto-generated method stub
261
262 }
263
264 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800265 public void onConversationListVisibilityChanged(boolean visible) {
266 // TODO(viki): Auto-generated method stub
267
268 }
269
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -0800270 /**
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800271 * By default, doing nothing is right. A two-pane controller will need to
272 * override this.
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -0800273 */
274 @Override
275 public void onConversationVisibilityChanged(boolean visible) {
276 // Do nothing.
277 return;
278 }
279
280 @Override
Vikram Aggarwald7a12cd2012-02-03 09:36:20 -0800281 public boolean onCreate(Bundle savedState) {
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800282 // Initialize the action bar view.
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800283 initCustomActionBarView();
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800284 final Intent intent = mActivity.getIntent();
Vikram Aggarwal7dedb952012-02-16 16:10:23 -0800285 // Get a Loader to the Account
286 mActivity.getLoaderManager().initLoader(0, null, this);
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800287 // Allow shortcut keys to function for the ActionBar and menus.
288 mActivity.setDefaultKeyMode(Activity.DEFAULT_KEYS_SHORTCUT);
Vikram Aggarwal80aeac52012-02-07 15:27:20 -0800289 mResolver = mActivity.getContentResolver();
Vikram Aggarwal2175d0a2012-02-17 16:04:23 -0800290
291 // All the individual UI components listen for ViewMode changes. This simplifies the
292 // amount of logic in the AbstractActivityController, but increases the possibility of
293 // timing-related bugs.
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800294 mViewMode.addListener(this);
Vikram Aggarwal2175d0a2012-02-17 16:04:23 -0800295 assert (mActionBarView != null);
296 mViewMode.addListener(mActionBarView);
297
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800298 restoreState(savedState);
Vikram Aggarwald7a12cd2012-02-03 09:36:20 -0800299 return true;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800300 }
301
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800302 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800303 public Dialog onCreateDialog(int id, Bundle bundle) {
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800304 // TODO(viki): Auto-generated method stub
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800305 return null;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800306 }
307
308 @Override
309 public boolean onCreateOptionsMenu(Menu menu) {
Mindy Pereira28d5f722012-02-15 12:32:40 -0800310 MenuInflater inflater = mActivity.getMenuInflater();
Mindy Pereiraf5acda42012-02-15 20:13:59 -0800311 inflater.inflate(mActionBarView.getOptionsMenuId(), menu);
Mindy Pereira28d5f722012-02-15 12:32:40 -0800312 return true;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800313 }
314
315 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800316 public void onEndBulkOperation() {
317 // TODO(viki): Auto-generated method stub
318
319 }
320
321 @Override
Vikram Aggarwalb9e1a352012-01-24 15:23:38 -0800322 public boolean onKeyDown(int keyCode, KeyEvent event) {
323 // TODO(viki): Auto-generated method stub
324 return false;
325 }
326
327 @Override
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800328 public boolean onOptionsItemSelected(MenuItem item) {
Mindy Pereira28d5f722012-02-15 12:32:40 -0800329 int id = item.getItemId();
Mindy Pereira9b875682012-02-15 18:10:54 -0800330 boolean handled = true;
Mindy Pereira28d5f722012-02-15 12:32:40 -0800331 switch (id) {
Mindy Pereiraf5acda42012-02-15 20:13:59 -0800332 case android.R.id.home:
333 onUpPressed();
334 break;
Mindy Pereira9b875682012-02-15 18:10:54 -0800335 case R.id.compose:
336 ComposeActivity.compose(mActivity.getActivityContext(), mAccount);
337 break;
Mindy Pereira28d5f722012-02-15 12:32:40 -0800338 case R.id.show_all_folders:
339 showFolderList();
340 break;
Mindy Pereira28e0c342012-02-17 15:05:13 -0800341 case R.id.refresh:
342 requestFolderRefresh();
343 break;
Mindy Pereira9b875682012-02-15 18:10:54 -0800344 default:
345 handled = false;
346 break;
Mindy Pereira28d5f722012-02-15 12:32:40 -0800347 }
Mindy Pereira9b875682012-02-15 18:10:54 -0800348 return handled;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800349 }
350
Mindy Pereira28e0c342012-02-17 15:05:13 -0800351 private void requestFolderRefresh() {
352 if (mFolder != null) {
353 new AsyncRefreshTask(mContext, mFolder).execute();
354 }
355 }
356
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800357 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800358 public void onPause() {
Vikram Aggarwal7dedb952012-02-16 16:10:23 -0800359 isLoaderInitialized = false;
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800360 }
361
362 @Override
363 public void onPrepareDialog(int id, Dialog dialog, Bundle bundle) {
364 // TODO(viki): Auto-generated method stub
365
366 }
367
368 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800369 public boolean onPrepareOptionsMenu(Menu menu) {
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800370 // TODO(viki): Auto-generated method stub
371 return false;
372 }
373
374 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800375 public void onResume() {
376 // TODO(viki): Auto-generated method stub
Vikram Aggarwald247dc92012-02-10 15:49:01 -0800377 // mBatchConversations.addObserver(this);
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800378 if (mActionBarView != null) {
379 mActionBarView.onResume();
380 }
381 }
382
383 @Override
384 public void onSaveInstanceState(Bundle outState) {
Vikram Aggarwal80aeac52012-02-07 15:27:20 -0800385 if (mConvListContext != null) {
386 outState.putBundle(SAVED_LIST_CONTEXT, mConvListContext.toBundle());
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800387 }
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800388 }
389
390 @Override
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800391 public void onSearchRequested() {
392 // TODO(viki): Auto-generated method stub
393
394 }
395
396 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800397 public void onStartBulkOperation() {
398 // TODO(viki): Auto-generated method stub
399
400 }
401
402 @Override
403 public void onStartDragMode() {
404 // TODO(viki): Auto-generated method stub
405
406 }
407
408 @Override
409 public void onStop() {
410 // TODO(viki): Auto-generated method stub
411
412 }
413
414 @Override
415 public void onStopDragMode() {
416 // TODO(viki): Auto-generated method stub
417
418 }
419
Vikram Aggarwalfa131a22012-02-02 13:56:22 -0800420 /**
421 * {@inheritDoc}
422 *
423 * Subclasses must override this to listen to mode changes from the ViewMode. Subclasses
424 * <b>must</b> call the parent's onViewModeChanged since the parent will handle common state
425 * changes.
426 */
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800427 @Override
Vikram Aggarwalfa131a22012-02-02 13:56:22 -0800428 public void onViewModeChanged(int newMode) {
429 // Perform any mode specific work here.
430 // reset the action bar icon based on the mode. Why don't the individual controllers do
431 // this themselves?
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800432
Vikram Aggarwalfa131a22012-02-02 13:56:22 -0800433 // On conversation list mode, clean up the conversation.
434 if (newMode == ViewMode.CONVERSATION_LIST) {
435 // Clean up the conversation here.
436 }
437
438 // We don't want to invalidate the options menu when switching to conversation
439 // mode, as it will happen when the conversation finishes loading.
440 if (newMode != ViewMode.CONVERSATION) {
441 mActivity.invalidateOptionsMenu();
442 }
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800443 }
444
445 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800446 public void onWindowFocusChanged(boolean hasFocus) {
447 // TODO(viki): Auto-generated method stub
448
449 }
450
451 @Override
452 public void reloadSearch(String string) {
453 // TODO(viki): Auto-generated method stub
454
455 }
456
457 /**
458 * @param savedState
459 */
460 protected void restoreListContext(Bundle savedState) {
461 // TODO(viki): Auto-generated method stub
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800462 Bundle listContextBundle = savedState.getBundle(SAVED_LIST_CONTEXT);
463 if (listContextBundle != null) {
Vikram Aggarwal80aeac52012-02-07 15:27:20 -0800464 mConvListContext = ConversationListContext.forBundle(listContextBundle);
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800465 }
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800466 }
467
468 /**
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800469 * Restore the state from the previous bundle. Subclasses should call this method from the
470 * parent class, since it performs important UI initialization.
471 * @param savedState
472 */
473 protected void restoreState(Bundle savedState) {
474 if (savedState != null) {
475 restoreListContext(savedState);
Vikram Aggarwal8b152632012-02-03 14:58:45 -0800476 // Restore the list context
477 restoreListContext(savedState);
478
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800479 // Attach the menu handler here.
Vikram Aggarwalfa131a22012-02-02 13:56:22 -0800480
481 // Restore the view mode
482 mViewMode.handleRestore(savedState);
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800483 }
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800484 }
485
486 @Override
487 public void setSubject(String subject) {
488 // Do something useful with the subject. This requires changing the
489 // conversation view's subject text.
490 }
491
492 @Override
Vikram Aggarwal1ddcf0f2012-01-13 11:45:02 -0800493 public void startActionBarStatusCursorLoader(String account) {
494 // TODO(viki): Auto-generated method stub
495
496 }
497
498 @Override
499 public void stopActionBarStatusCursorLoader(String account) {
Vikram Aggarwala55b36c2012-01-13 11:45:02 -0800500 // TODO(viki): Auto-generated method stub
501
502 }
Vikram Aggarwal7d602882012-02-07 15:01:20 -0800503
504 @Override
505 public void toggleStar(boolean toggleOn, long conversationId, long maxMessageId) {
506 // TODO(viki): Auto-generated method stub
507
508 }
509
510 @Override
Mindy Pereira9b875682012-02-15 18:10:54 -0800511 public void onConversationSelected(Conversation conversation) {
512 mCurrentConversation = conversation;
513 showConversation(mCurrentConversation);
514 mViewMode.enterConversationMode();
Vikram Aggarwal7d602882012-02-07 15:01:20 -0800515 }
Mindy Pereira555140c2012-02-15 14:55:29 -0800516
517 @Override
Vikram Aggarwal7dedb952012-02-16 16:10:23 -0800518 public Loader<Cursor> onCreateLoader(int id, Bundle args) {
519 // Create a loader to listen in on account changes.
520 return new CursorLoader(mContext, AccountCacheProvider.getAccountsUri(),
521 UIProvider.ACCOUNTS_PROJECTION, null, null, null);
522 }
523
524 /**
525 * Return whether the given account exists in the cursor.
526 * @param accountCursor
527 * @param account
528 * @return true if the account exists in the account cursor, false otherwise.
529 */
530 private boolean existsInCursor(Cursor accountCursor, Account account) {
531 accountCursor.moveToFirst();
532 do {
533 if (account.equals(new Account(accountCursor)))
534 return true;
535 } while (accountCursor.moveToNext());
536 return false;
537 }
538
539 /**
540 * Update the accounts on the device. This currently loads the first account in the list.
541 * @param loader
542 * @param data
543 * @return true if the update was successful, false otherwise
544 */
545 private boolean updateAccounts(Loader<Cursor> loader, Cursor accounts) {
546 // Load the first account in the absence of any other information.
547 if (accounts == null || !accounts.moveToFirst()) {
548 return false;
549 }
550 mAccount = new Account(accounts);
551 final Intent intent = mActivity.getIntent();
552 mConvListContext = ConversationListContext.forIntent(mContext, mAccount, intent);
Mindy Pereira28e0c342012-02-17 15:05:13 -0800553 mFolder = mConvListContext.mFolder;
Vikram Aggarwal7dedb952012-02-16 16:10:23 -0800554 // TODO(viki): Rely on the ViewMode transition to do the right things automatically. The
555 // next line should be unnecessary.
556 showConversationList(mConvListContext);
557 mViewMode.enterConversationListMode();
558 return true;
559 }
560
561 @Override
562 public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
563 // We want to reinitialize only if we haven't ever been initialized, or if the current
564 // account has vanished.
565 if (!isLoaderInitialized || !existsInCursor(data, mAccount)) {
566 isLoaderInitialized = updateAccounts(loader, data);
567 }
568 }
569
570 @Override
571 public void onLoaderReset(Loader<Cursor> loader) {
572 // Do nothing for now, since we don't have any state. When a load is finished, the
573 // onLoadFinished will be called and we will be fine.
574 }
Mindy Pereira674afa42012-02-17 14:05:24 -0800575
576
577 @Override
578 public void onTouchEvent(MotionEvent event) {
579 if (event.getAction() == MotionEvent.ACTION_DOWN) {
580 int mode = mViewMode.getMode();
581 if (mode == ViewMode.CONVERSATION_LIST) {
582 mConversationListFragment.onTouchEvent(event);
583 } else if (mode == ViewMode.CONVERSATION) {
584 mConversationViewFragment.onTouchEvent(event);
585 }
586 }
587 }
Vikram Aggarwal4a5c5302012-01-12 15:07:13 -0800588}