/* * Copyright (C) 2012 Google Inc. * Licensed to The Android Open Source Project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.mail.ui; import android.os.Bundle; import com.android.mail.analytics.Analytics; import com.android.mail.utils.LogUtils; import com.google.common.collect.Lists; import java.util.ArrayList; /** * Represents the view mode for the tablet Gmail activity. * Transitions between modes should be done through this central object, and UI components that are * dependent on the mode should listen to changes on this object. */ public class ViewMode { /** * A listener for changes on a ViewMode. To listen to mode changes, implement this * interface and register your object with the single ViewMode held by the ActivityController * instance. On mode changes, the onViewModeChanged method will be called with the new mode. */ public interface ModeChangeListener { /** * Called when the mode has changed. */ void onViewModeChanged(int newMode); } /** * Mode when showing a single conversation. */ public static final int CONVERSATION = 1; /** * Mode when showing a list of conversations */ public static final int CONVERSATION_LIST = 2; /** * Mode when showing results from user search. */ public static final int SEARCH_RESULTS_LIST = 3; /** * Mode when showing results from user search. */ public static final int SEARCH_RESULTS_CONVERSATION = 4; /** * Mode when showing the "waiting for sync" message. */ public static final int WAITING_FOR_ACCOUNT_INITIALIZATION = 5; /** * Mode when showing ads. */ public static final int AD = 6; /** * Uncertain mode. The mode has not been initialized. */ public static final int UNKNOWN = 0; // Key used to save this {@link ViewMode}. private static final String VIEW_MODE_KEY = "view-mode"; private final ArrayList mListeners = Lists.newArrayList(); /** * The actual mode the activity is in. We start out with an UNKNOWN mode, and require entering * a valid mode after the object has been created. */ private int mMode = UNKNOWN; public static final String LOG_TAG = "ViewMode"; // friendly names (not user-facing) for each view mode, indexed by ordinal value. private static final String[] MODE_NAMES = { "Unknown", "Conversation", "Conversation list", "Search results list", "Search results conversation", "Waiting for sync", "Ad", "Warm welcome" }; public ViewMode() { // Do nothing } @Override public String toString() { return "[mode=" + MODE_NAMES[mMode] + "]"; } public String getModeString() { return MODE_NAMES[mMode]; } /** * Adds a listener from this view mode. * Must happen in the UI thread. */ public void addListener(ModeChangeListener listener) { mListeners.add(listener); } /** * Dispatches a change event for the mode. * Always happens in the UI thread. */ private void dispatchModeChange() { ArrayList list = new ArrayList(mListeners); for (ModeChangeListener listener : list) { assert (listener != null); listener.onViewModeChanged(mMode); } } /** * Requests a transition of the mode to show the conversation list as the prominent view. * */ public void enterConversationListMode() { setModeInternal(CONVERSATION_LIST); } /** * Requests a transition of the mode to show a conversation as the prominent view. * */ public void enterConversationMode() { setModeInternal(CONVERSATION); } /** * Requests a transition of the mode to show a list of search results as the * prominent view. * */ public void enterSearchResultsListMode() { setModeInternal(SEARCH_RESULTS_LIST); } /** * Requests a transition of the mode to show a conversation that was part of * search results. * */ public void enterSearchResultsConversationMode() { setModeInternal(SEARCH_RESULTS_CONVERSATION); } /** * Requests a transition of the mode to show the "waiting for sync" messages * */ public void enterWaitingForInitializationMode() { setModeInternal(WAITING_FOR_ACCOUNT_INITIALIZATION); } /** * Requests a transition of the mode to show an ad. */ public void enterAdMode() { setModeInternal(AD); } /** * @return The current mode. */ public int getMode() { return mMode; } /** * Return whether the current mode is considered a list mode. */ public boolean isListMode() { return isListMode(mMode); } public static boolean isListMode(final int mode) { return mode == CONVERSATION_LIST || mode == SEARCH_RESULTS_LIST; } public boolean isConversationMode() { return isConversationMode(mMode); } public static boolean isConversationMode(final int mode) { return mode == CONVERSATION || mode == SEARCH_RESULTS_CONVERSATION; } public boolean isSearchMode() { return isSearchMode(mMode); } public static boolean isSearchMode(final int mode) { return mode == SEARCH_RESULTS_LIST || mode == SEARCH_RESULTS_CONVERSATION; } public boolean isWaitingForSync() { return isWaitingForSync(mMode); } public static boolean isWaitingForSync(final int mode) { return mode == WAITING_FOR_ACCOUNT_INITIALIZATION; } public boolean isAdMode() { return isAdMode(mMode); } public static boolean isAdMode(final int mode) { return mode == AD; } /** * Restoring from a saved state restores only the mode. It does not restore the listeners of * this object. * @param inState */ public void handleRestore(Bundle inState) { if (inState == null) { return; } // Restore the previous mode, and UNKNOWN if nothing exists. final int newMode = inState.getInt(VIEW_MODE_KEY, UNKNOWN); if (newMode != UNKNOWN) { setModeInternal(newMode); } } /** * Save the existing mode only. Does not save the existing listeners. * @param outState */ public void handleSaveInstanceState(Bundle outState) { if (outState == null) { return; } outState.putInt(VIEW_MODE_KEY, mMode); } /** * Removes a listener from this view mode. * Must happen in the UI thread. */ public void removeListener(ModeChangeListener listener) { mListeners.remove(listener); } /** * Sets the internal mode. * @return Whether or not a change occurred. */ private boolean setModeInternal(int mode) { if (mMode == mode) { if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) { LogUtils.d(LOG_TAG, new Error(), "ViewMode: debouncing change attempt mode=%s", mode); } else { LogUtils.i(LOG_TAG, "ViewMode: debouncing change attempt mode=%s", mode); } return false; } if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) { LogUtils.d(LOG_TAG, new Error(), "ViewMode: executing change old=%s new=%s", mMode, mode); } else { LogUtils.i(LOG_TAG, "ViewMode: executing change old=%s new=%s", mMode, mode); } mMode = mode; dispatchModeChange(); Analytics.getInstance().sendView("ViewMode" + toString()); return true; } }