Home | History | Annotate | Download | only in ui
      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 
     18 package com.android.mail.ui;
     19 
     20 import android.os.Bundle;
     21 
     22 import com.android.mail.analytics.Analytics;
     23 import com.android.mail.utils.LogUtils;
     24 import com.google.common.collect.Lists;
     25 
     26 import java.util.ArrayList;
     27 
     28 /**
     29  * Represents the view mode for the tablet Gmail activity.
     30  * Transitions between modes should be done through this central object, and UI components that are
     31  * dependent on the mode should listen to changes on this object.
     32  */
     33 public class ViewMode {
     34     /**
     35      * A listener for changes on a ViewMode. To listen to mode changes, implement this
     36      * interface and register your object with the single ViewMode held by the ActivityController
     37      * instance. On mode changes, the onViewModeChanged method will be called with the new mode.
     38      */
     39     public interface ModeChangeListener {
     40         /**
     41          * Called when the mode has changed.
     42          */
     43         void onViewModeChanged(int newMode);
     44     }
     45 
     46     /**
     47      * Mode when showing a single conversation.
     48      */
     49     public static final int CONVERSATION = 1;
     50     /**
     51      * Mode when showing a list of conversations
     52      */
     53     public static final int CONVERSATION_LIST = 2;
     54     /**
     55      * Mode when showing results from user search.
     56      */
     57     public static final int SEARCH_RESULTS_LIST = 3;
     58     /**
     59      * Mode when showing results from user search.
     60      */
     61     public static final int SEARCH_RESULTS_CONVERSATION = 4;
     62     /**
     63      * Mode when showing the "waiting for sync" message.
     64      */
     65     public static final int WAITING_FOR_ACCOUNT_INITIALIZATION = 5;
     66     /**
     67      * Mode when showing ads.
     68      */
     69     public static final int AD = 6;
     70     /**
     71      * Uncertain mode. The mode has not been initialized.
     72      */
     73     public static final int UNKNOWN = 0;
     74 
     75     // Key used to save this {@link ViewMode}.
     76     private static final String VIEW_MODE_KEY = "view-mode";
     77     private final ArrayList<ModeChangeListener> mListeners = Lists.newArrayList();
     78     /**
     79      * The actual mode the activity is in. We start out with an UNKNOWN mode, and require entering
     80      * a valid mode after the object has been created.
     81      */
     82     private int mMode = UNKNOWN;
     83 
     84     public static final String LOG_TAG = "ViewMode";
     85 
     86     // friendly names (not user-facing) for each view mode, indexed by ordinal value.
     87     private static final String[] MODE_NAMES = {
     88         "Unknown",
     89         "Conversation",
     90         "Conversation list",
     91         "Search results list",
     92         "Search results conversation",
     93         "Waiting for sync",
     94         "Ad"
     95     };
     96 
     97     public ViewMode() {
     98         // Do nothing
     99     }
    100 
    101     @Override
    102     public String toString() {
    103         return "[mode=" + MODE_NAMES[mMode] + "]";
    104     }
    105 
    106     public String getModeString() {
    107         return MODE_NAMES[mMode];
    108     }
    109 
    110     /**
    111      * Adds a listener from this view mode.
    112      * Must happen in the UI thread.
    113      */
    114     public void addListener(ModeChangeListener listener) {
    115         mListeners.add(listener);
    116     }
    117 
    118     /**
    119      * Dispatches a change event for the mode.
    120      * Always happens in the UI thread.
    121      */
    122     private void dispatchModeChange() {
    123         ArrayList<ModeChangeListener> list = new ArrayList<ModeChangeListener>(mListeners);
    124         for (ModeChangeListener listener : list) {
    125             assert (listener != null);
    126             listener.onViewModeChanged(mMode);
    127         }
    128     }
    129 
    130     /**
    131      * Requests a transition of the mode to show the conversation list as the prominent view.
    132      *
    133      */
    134     public void enterConversationListMode() {
    135         setModeInternal(CONVERSATION_LIST);
    136     }
    137 
    138     /**
    139      * Requests a transition of the mode to show a conversation as the prominent view.
    140      *
    141      */
    142     public void enterConversationMode() {
    143         setModeInternal(CONVERSATION);
    144     }
    145 
    146     /**
    147      * Requests a transition of the mode to show a list of search results as the
    148      * prominent view.
    149      *
    150      */
    151     public void enterSearchResultsListMode() {
    152         setModeInternal(SEARCH_RESULTS_LIST);
    153     }
    154 
    155     /**
    156      * Requests a transition of the mode to show a conversation that was part of
    157      * search results.
    158      *
    159      */
    160     public void enterSearchResultsConversationMode() {
    161         setModeInternal(SEARCH_RESULTS_CONVERSATION);
    162     }
    163 
    164     /**
    165      * Requests a transition of the mode to show the "waiting for sync" messages
    166      *
    167      */
    168     public void enterWaitingForInitializationMode() {
    169         setModeInternal(WAITING_FOR_ACCOUNT_INITIALIZATION);
    170     }
    171 
    172     /**
    173      * Requests a transition of the mode to show an ad.
    174      */
    175     public void enterAdMode() {
    176         setModeInternal(AD);
    177     }
    178 
    179     /**
    180      * @return The current mode.
    181      */
    182     public int getMode() {
    183         return mMode;
    184     }
    185 
    186     /**
    187      * Return whether the current mode is considered a list mode.
    188      */
    189     public boolean isListMode() {
    190         return isListMode(mMode);
    191     }
    192 
    193     public static boolean isListMode(final int mode) {
    194         return mode == CONVERSATION_LIST || mode == SEARCH_RESULTS_LIST;
    195     }
    196 
    197     public boolean isConversationMode() {
    198         return isConversationMode(mMode);
    199     }
    200 
    201     public static boolean isConversationMode(final int mode) {
    202         return mode == CONVERSATION || mode == SEARCH_RESULTS_CONVERSATION;
    203     }
    204 
    205     public static boolean isSearchMode(final int mode) {
    206         return mode == SEARCH_RESULTS_LIST || mode == SEARCH_RESULTS_CONVERSATION;
    207     }
    208 
    209     public boolean isWaitingForSync() {
    210         return isWaitingForSync(mMode);
    211     }
    212 
    213     public static boolean isWaitingForSync(final int mode) {
    214         return mode == WAITING_FOR_ACCOUNT_INITIALIZATION;
    215     }
    216 
    217     public boolean isAdMode() {
    218         return isAdMode(mMode);
    219     }
    220 
    221     public static boolean isAdMode(final int mode) {
    222         return mode == AD;
    223     }
    224 
    225     /**
    226      * Restoring from a saved state restores only the mode. It does not restore the listeners of
    227      * this object.
    228      * @param inState
    229      */
    230     public void handleRestore(Bundle inState) {
    231         if (inState == null) {
    232             return;
    233         }
    234         // Restore the previous mode, and UNKNOWN if nothing exists.
    235         final int newMode = inState.getInt(VIEW_MODE_KEY, UNKNOWN);
    236         if (newMode != UNKNOWN) {
    237             setModeInternal(newMode);
    238         }
    239     }
    240 
    241     /**
    242      * Save the existing mode only. Does not save the existing listeners.
    243      * @param outState
    244      */
    245     public void handleSaveInstanceState(Bundle outState) {
    246         if (outState == null) {
    247             return;
    248         }
    249         outState.putInt(VIEW_MODE_KEY, mMode);
    250     }
    251 
    252     /**
    253      * Removes a listener from this view mode.
    254      * Must happen in the UI thread.
    255      */
    256     public void removeListener(ModeChangeListener listener) {
    257         mListeners.remove(listener);
    258     }
    259 
    260     /**
    261      * Sets the internal mode.
    262      * @return Whether or not a change occurred.
    263      */
    264     private boolean setModeInternal(int mode) {
    265         if (mMode == mode) {
    266             if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) {
    267                 LogUtils.d(LOG_TAG, new Error(), "ViewMode: debouncing change attempt mode=%s",
    268                         mode);
    269             } else {
    270                 LogUtils.i(LOG_TAG, "ViewMode: debouncing change attempt mode=%s", mode);
    271             }
    272             return false;
    273         }
    274 
    275         if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) {
    276             LogUtils.d(LOG_TAG, new Error(), "ViewMode: executing change old=%s new=%s", mMode,
    277                     mode);
    278         } else {
    279             LogUtils.i(LOG_TAG, "ViewMode: executing change old=%s new=%s", mMode, mode);
    280         }
    281 
    282         mMode = mode;
    283         dispatchModeChange();
    284         Analytics.getInstance().sendView("ViewMode" + toString());
    285         return true;
    286     }
    287 }
    288