blob: b5ba3b5255e1e1da61bb8abb728a5d1f4e361335 [file] [log] [blame]
/*
* 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<ModeChangeListener> 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"
};
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<ModeChangeListener> list = new ArrayList<ModeChangeListener>(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 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;
}
}