blob: e2c3edc4547000308eb0e9e8864f035ec94e6bbe [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.compositor.layouts.phone;
import android.content.Context;
import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabList;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelUtils;
import java.util.ArrayList;
/**
* Layout that displays all normal tabs in one stack and all incognito tabs in a second.
*/
public class StackLayout extends StackLayoutBase {
// One stack for normal tabs and one stack for incognito tabs.
private static final int NUM_STACKS = 2;
public static final int NORMAL_STACK_INDEX = 0;
public static final int INCOGNITO_STACK_INDEX = 1;
/** Whether the current fling animation is the result of switching stacks. */
private boolean mFlingFromModelChange;
/**
* @param context The current Android's context.
* @param updateHost The {@link LayoutUpdateHost} view for this layout.
* @param renderHost The {@link LayoutRenderHost} view for this layout.
*/
public StackLayout(Context context, LayoutUpdateHost updateHost, LayoutRenderHost renderHost) {
super(context, updateHost, renderHost);
}
@Override
public void setTabModelSelector(TabModelSelector modelSelector, TabContentManager manager) {
super.setTabModelSelector(modelSelector, manager);
ArrayList<TabList> tabLists = new ArrayList<TabList>();
tabLists.add(modelSelector.getModel(false));
tabLists.add(modelSelector.getModel(true));
setTabLists(tabLists);
}
@Override
protected int getTabStackIndex(int tabId) {
if (tabId == Tab.INVALID_TAB_ID) {
if (mTemporarySelectedStack != INVALID_STACK_INDEX) return mTemporarySelectedStack;
return mTabModelSelector.isIncognitoSelected() ? INCOGNITO_STACK_INDEX
: NORMAL_STACK_INDEX;
} else {
return TabModelUtils.getTabById(mTabModelSelector.getModel(true), tabId) != null
? INCOGNITO_STACK_INDEX
: NORMAL_STACK_INDEX;
}
}
@Override
public void onTabClosing(long time, int id) {
super.onTabClosing(time, id);
// Just in case we closed the last tab of a stack we need to trigger the overlap animation.
startMarginAnimation(true);
// Animate the stack to leave incognito mode.
if (!mStacks.get(INCOGNITO_STACK_INDEX).isDisplayable()) onTabModelSwitched(false);
}
@Override
public void onTabsAllClosing(long time, boolean incognito) {
super.onTabsAllClosing(time, incognito);
getTabStackAtIndex(incognito ? INCOGNITO_STACK_INDEX : NORMAL_STACK_INDEX)
.tabsAllClosingEffect(time);
// trigger the overlap animation.
startMarginAnimation(true);
// Animate the stack to leave incognito mode.
if (!mStacks.get(INCOGNITO_STACK_INDEX).isDisplayable()) onTabModelSwitched(false);
}
@Override
public void onTabClosureCancelled(long time, int id, boolean incognito) {
super.onTabClosureCancelled(time, id, incognito);
getTabStackAtIndex(incognito ? INCOGNITO_STACK_INDEX : NORMAL_STACK_INDEX)
.undoClosure(time, id);
}
@Override
public void onTabCreated(long time, int id, int tabIndex, int sourceId, boolean newIsIncognito,
boolean background, float originX, float originY) {
super.onTabCreated(
time, id, tabIndex, sourceId, newIsIncognito, background, originX, originY);
onTabModelSwitched(newIsIncognito);
}
@Override
public void onTabModelSwitched(boolean toIncognitoTabModel) {
flingStacks(toIncognitoTabModel ? INCOGNITO_STACK_INDEX : NORMAL_STACK_INDEX);
mFlingFromModelChange = true;
}
@Override
protected void onAnimationFinished() {
super.onAnimationFinished();
mFlingFromModelChange = false;
if (mTemporarySelectedStack != INVALID_STACK_INDEX) {
mTabModelSelector.selectModel(mTemporarySelectedStack == INCOGNITO_STACK_INDEX);
mTemporarySelectedStack = INVALID_STACK_INDEX;
}
}
@Override
protected int getMinRenderedScrollOffset() {
if (mStacks.get(INCOGNITO_STACK_INDEX).isDisplayable() || mFlingFromModelChange) return -1;
return 0;
}
@Override
public void uiRequestingCloseTab(long time, int id) {
super.uiRequestingCloseTab(time, id);
int incognitoCount = mTabModelSelector.getModel(true).getCount();
TabModel model = mTabModelSelector.getModelForTabId(id);
if (model != null && model.isIncognito()) incognitoCount--;
boolean incognitoVisible = incognitoCount > 0;
// Make sure we show/hide both stacks depending on which tab we're closing.
startMarginAnimation(true, incognitoVisible);
if (!incognitoVisible) onTabModelSwitched(false);
}
@Override
protected @SwipeMode int computeInputMode(long time, float x, float y, float dx, float dy) {
if (mStacks.size() == 2 && !mStacks.get(1).isDisplayable()) return SWIPE_MODE_SEND_TO_STACK;
return super.computeInputMode(time, x, y, dx, dy);
}
}