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