TwoPaneController.java revision d2ca51ac0c0727ae924259918ac6f25b3f8ce571
1/******************************************************************************* 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 20import com.android.mail.ConversationListContext; 21import com.android.mail.R; 22import com.android.mail.providers.Account; 23import com.android.mail.providers.Conversation; 24import com.android.mail.utils.LogUtils; 25 26import android.app.Fragment; 27import android.app.FragmentTransaction; 28import android.os.Bundle; 29import android.view.Window; 30 31/** 32 * Controller for one-pane Mail activity. One Pane is used for phones, where screen real estate is 33 * limited. 34 */ 35 36// Called OnePaneActivityController in Gmail. 37public final class TwoPaneController extends AbstractActivityController { 38 private boolean mJumpToFirstConversation; 39 private TwoPaneLayout mLayout; 40 41 /** 42 * @param activity 43 * @param viewMode 44 */ 45 public TwoPaneController(MailActivity activity, ViewMode viewMode) { 46 super(activity, viewMode); 47 } 48 49 /** 50 * Display the conversation list fragment. 51 * @param show 52 */ 53 private void initializeConversationListFragment(boolean show) { 54 if (show) { 55 mViewMode.enterConversationListMode(); 56 } 57 renderConversationList(); 58 } 59 60 /** 61 * Render the conversation list in the correct pane. 62 */ 63 private void renderConversationList() { 64 FragmentTransaction fragmentTransaction = mActivity.getFragmentManager().beginTransaction(); 65 // Use cross fading animation. 66 fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); 67 Fragment conversationListFragment = ConversationListFragment 68 .newInstance(mConvListContext); 69 fragmentTransaction.replace(R.id.conversation_list_pane, conversationListFragment); 70 fragmentTransaction.commitAllowingStateLoss(); 71 } 72 73 /** 74 * Render the folder list in the correct pane. 75 */ 76 private void renderFolderList() { 77 FolderListFragment folderListFragment = FolderListFragment.newInstance(this, 78 mAccount.folderListUri); 79 FragmentTransaction fragmentTransaction = mActivity.getFragmentManager().beginTransaction(); 80 fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 81 fragmentTransaction.replace(R.id.folders_pane, folderListFragment); 82 fragmentTransaction.commitAllowingStateLoss(); 83 // Since we are showing the folder list, we are at the start of the view 84 // stack. 85 resetActionBarIcon(); 86 attachFolderList(folderListFragment); 87 } 88 89 @Override 90 protected boolean isConversationListVisible() { 91 // TODO(viki): Auto-generated method stub 92 return false; 93 } 94 95 @Override 96 public void showConversationList(ConversationListContext context) { 97 initializeConversationListFragment(true); 98 } 99 100 @Override 101 public void showFolderList() { 102 // On two-pane layouts, showing the folder list takes you to the top level of the 103 // application, which is the same as pressing the Up button 104 onUpPressed(); 105 } 106 107 @Override 108 public boolean onCreate(Bundle savedState) { 109 mActivity.setContentView(R.layout.two_pane_activity); 110 mLayout = (TwoPaneLayout) mActivity.findViewById(R.id.two_pane_activity); 111 if (mLayout == null) { 112 LogUtils.d(LOG_TAG, "mLayout is null!"); 113 } 114 mLayout.initializeLayout(mActivity.getApplicationContext()); 115 116 // The tablet layout needs to refer to mode changes. 117 mViewMode.addListener(mLayout); 118 // The activity controller needs to listen to layout changes. 119 mLayout.setListener(this); 120 final boolean isParentInitialized = super.onCreate(savedState); 121 return isParentInitialized; 122 } 123 124 @Override 125 public void onAccountChanged(Account account) { 126 super.onAccountChanged(account); 127 renderFolderList(); 128 } 129 130 @Override 131 public void onViewModeChanged(int newMode) { 132 super.onViewModeChanged(newMode); 133 if (newMode != ViewMode.CONVERSATION) { 134 // Clear this flag if the user jumps out of conversation mode 135 // before a load completes. 136 mJumpToFirstConversation = false; 137 } 138 resetActionBarIcon(); 139 } 140 141 @Override 142 public void resetActionBarIcon() { 143 if (mViewMode.getMode() == ViewMode.CONVERSATION_LIST) { 144 mActionBarView.removeBackButton(); 145 } else { 146 mActionBarView.setBackButton(); 147 } 148 } 149 150 @Override 151 public void showConversation(Conversation conversation) { 152 mViewMode.enterConversationMode(); 153 Fragment convFragment = ConversationViewFragment.newInstance(mAccount, conversation); 154 FragmentTransaction fragmentTransaction = mActivity.getFragmentManager().beginTransaction(); 155 fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 156 fragmentTransaction.replace(R.id.conversation_pane, convFragment); 157 fragmentTransaction.commitAllowingStateLoss(); 158 } 159 160 /** 161 * Show the conversation list if it can be shown in the current orientation. 162 * @return true if the conversation list was shown 163 */ 164 private boolean unhideConversationList(){ 165 // Find if the conversation list can be shown 166 final boolean isConversationListShowable = 167 (mViewMode.getMode() == ViewMode.CONVERSATION && 168 mLayout.isConversationListCollapsible()); 169 if (isConversationListShowable) { 170 return mLayout.uncollapseList(); 171 } 172 return false; 173 } 174 175 /** 176 * Up works as follows: 177 * 1) If the user is in a conversation and: 178 * a) the conversation list is hidden (portrait mode), shows the conv list and 179 * stays in conversation view mode. 180 * b) the conversation list is shown, goes back to conversation list mode. 181 * 2) If the user is in search results, up exits search. 182 * mode and returns the user to whatever view they were in when they began search. 183 * 3) If the user is in conversation list mode, there is no up. 184 */ 185 @Override 186 public boolean onUpPressed() { 187 int mode = mViewMode.getMode(); 188 if (mode == ViewMode.CONVERSATION) { 189 if (!mLayout.isConversationListVisible()) { 190 unhideConversationList(); 191 } else { 192 mActivity.onBackPressed(); 193 } 194 } else if (mode == ViewMode.SEARCH_RESULTS) { 195 mActivity.finish(); 196 } 197 return true; 198 } 199 200 @Override 201 public boolean onBackPressed() { 202 popView(false); 203 return true; 204 } 205 206 /** 207 * Pops the "view stack" to the last screen the user was viewing. 208 * 209 * @param preventClose Whether to prevent closing the app if the stack is empty. 210 */ 211 protected void popView(boolean preventClose) { 212 // If the user is in search query entry mode, or the user is viewing search results, exit 213 // the mode. 214 if (mConvListContext != null && mConvListContext.isSearchResult()) { 215 mActivity.finish(); 216 } else if (mViewMode.getMode() == ViewMode.CONVERSATION) { 217 // Go to conversation list. 218 mViewMode.enterConversationListMode(); 219 } else { 220 // There is nothing else to pop off the stack. 221 if (!preventClose) { 222 mActivity.finish(); 223 } 224 } 225 } 226} 227