| Index: chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/CascadingStripStacker.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/CascadingStripStacker.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/CascadingStripStacker.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..555b21c3d29588f3ae2be4660402d08c579df2b0
|
| --- /dev/null
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/CascadingStripStacker.java
|
| @@ -0,0 +1,183 @@
|
| +// Copyright 2016 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.overlays.strip;
|
| +
|
| +import org.chromium.chrome.browser.util.MathUtils;
|
| +import org.chromium.ui.base.LocalizationUtils;
|
| +
|
| +/**
|
| + * A stacker that tells the {@link StripLayoutHelper} how to layer the tabs for the
|
| + * {@link StaticLayout} when the available window width is >= 600dp. Tabs will be stacked with the
|
| + * focused tab in front with tabs cascading back to each side.
|
| + */
|
| +public class CascadingStripStacker extends StripStacker {
|
| + @Override
|
| + public void setTabOffsets(int selectedIndex, StripLayoutTab[] indexOrderedTabs,
|
| + float tabStackWidth, int maxTabsToStack, float tabOverlapWidth, float stripLeftMargin,
|
| + float stripRightMargin, float stripWidth, boolean inReorderMode) {
|
| + // 1. Calculate the size of the selected tab. This is used later to figure out how
|
| + // occluded the tabs are.
|
| + final StripLayoutTab selTab = selectedIndex >= 0 ? indexOrderedTabs[selectedIndex] : null;
|
| + final float selTabWidth = selTab != null ? selTab.getWidth() : 0;
|
| + final float selTabVisibleSize = selTabWidth - tabStackWidth - tabOverlapWidth;
|
| +
|
| + for (int i = 0; i < indexOrderedTabs.length; i++) {
|
| + StripLayoutTab tab = indexOrderedTabs[i];
|
| +
|
| + float posX = tab.getIdealX();
|
| +
|
| + // 2. Calculate how many tabs are stacked on the left or the right, giving us an idea
|
| + // of where we can stack this current tab.
|
| + int leftStackCount = (i < selectedIndex) ? Math.min(i, maxTabsToStack)
|
| + : Math.min(maxTabsToStack, selectedIndex)
|
| + + Math.min(maxTabsToStack, i - selectedIndex);
|
| +
|
| + int rightStackCount = (i >= selectedIndex)
|
| + ? Math.min(indexOrderedTabs.length - 1 - i, maxTabsToStack)
|
| + : Math.min(indexOrderedTabs.length - 1 - selectedIndex, maxTabsToStack)
|
| + + Math.min(selectedIndex - i, maxTabsToStack);
|
| +
|
| + if (LocalizationUtils.isLayoutRtl()) {
|
| + int oldLeft = leftStackCount;
|
| + leftStackCount = rightStackCount;
|
| + rightStackCount = oldLeft;
|
| + }
|
| +
|
| + // 3. Calculate the proper draw position for the tab. Clamp based on stacking
|
| + // rules.
|
| + float minDrawX = tabStackWidth * leftStackCount + stripLeftMargin;
|
| + float maxDrawX = stripWidth - tabStackWidth * rightStackCount - stripRightMargin;
|
| +
|
| + float drawX =
|
| + MathUtils.clamp(posX + tab.getOffsetX(), minDrawX, maxDrawX - tab.getWidth());
|
| +
|
| + // TODO(dtrainor): Don't set drawX if the tab is closing?
|
| + tab.setDrawX(drawX);
|
| + tab.setDrawY(tab.getOffsetY());
|
| +
|
| + // 4. Calculate how visible this tab is.
|
| + float visiblePercentage = 1.f;
|
| + if (i != selectedIndex) {
|
| + final float effectiveTabWidth = Math.max(tab.getWidth(), 1.f);
|
| + final boolean leftStack =
|
| + LocalizationUtils.isLayoutRtl() ? i > selectedIndex : i < selectedIndex;
|
| + final float minVisible = !leftStack ? minDrawX + selTabVisibleSize : minDrawX;
|
| + final float maxVisible = leftStack ? maxDrawX - selTabVisibleSize : maxDrawX;
|
| +
|
| + final float clippedTabWidth =
|
| + Math.min(posX + effectiveTabWidth, maxVisible) - Math.max(posX, minVisible);
|
| + visiblePercentage = MathUtils.clamp(clippedTabWidth / effectiveTabWidth, 0.f, 1.f);
|
| + }
|
| + tab.setVisiblePercentage(visiblePercentage);
|
| +
|
| + // 5. Calculate which index we start sliding content for.
|
| + // When reordering, we don't want to slide the content of the adjacent tabs.
|
| + int contentOffsetIndex = inReorderMode ? selectedIndex + 1 : selectedIndex;
|
| +
|
| + // 6. Calculate how much the tab is overlapped on the left side or right for RTL.
|
| + float hiddenAmount = 0.f;
|
| + if (i > contentOffsetIndex && i > 0) {
|
| + // 6.a. Get the effective right edge of the previous tab.
|
| + final StripLayoutTab prevTab = indexOrderedTabs[i - 1];
|
| + final float prevLayoutWidth =
|
| + (prevTab.getWidth() - tabOverlapWidth) * prevTab.getWidthWeight();
|
| + float prevTabRight = prevTab.getDrawX();
|
| + if (!LocalizationUtils.isLayoutRtl()) prevTabRight += prevLayoutWidth;
|
| +
|
| + // 6.b. Subtract our current draw X from the previous tab's right edge and
|
| + // get the percentage covered.
|
| + hiddenAmount = Math.max(prevTabRight - drawX, 0);
|
| + if (LocalizationUtils.isLayoutRtl()) {
|
| + // Invert The amount because we're RTL.
|
| + hiddenAmount = prevLayoutWidth - hiddenAmount;
|
| + }
|
| + }
|
| +
|
| + tab.setContentOffsetX(hiddenAmount);
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + public float computeNewTabButtonOffset(StripLayoutTab[] indexOrderedTabs,
|
| + float tabOverlapWidth, float stripLeftMargin, float stripRightMargin, float stripWidth,
|
| + float newTabButtonWidth) {
|
| + return LocalizationUtils.isLayoutRtl()
|
| + ? computeNewTabButtonOffsetRtl(indexOrderedTabs, tabOverlapWidth, stripLeftMargin,
|
| + stripRightMargin, stripWidth, newTabButtonWidth)
|
| + : computeNewTabButtonOffsetLtr(indexOrderedTabs, tabOverlapWidth,
|
| + stripLeftMargin, stripRightMargin, stripWidth);
|
| + }
|
| +
|
| + @Override
|
| + public void performOcclusionPass(int selectedIndex, StripLayoutTab[] indexOrderedTabs,
|
| + float stripWidth) {
|
| + for (int i = 1; i < indexOrderedTabs.length; i++) {
|
| + StripLayoutTab prevTab = indexOrderedTabs[i - 1];
|
| + StripLayoutTab currTab = indexOrderedTabs[i];
|
| +
|
| + if ((int) prevTab.getDrawY() == (int) currTab.getDrawY()
|
| + && (int) prevTab.getDrawX() == (int) currTab.getDrawX()) {
|
| + if (i <= selectedIndex) {
|
| + prevTab.setVisible(false);
|
| + } else if (i > selectedIndex) {
|
| + currTab.setVisible(false);
|
| + }
|
| + } else if ((int) prevTab.getDrawX() != (int) currTab.getDrawX()) {
|
| + if (i <= selectedIndex) {
|
| + prevTab.setVisible(true);
|
| + } else if (i > selectedIndex) {
|
| + currTab.setVisible(true);
|
| + }
|
| + }
|
| +
|
| + if (i == selectedIndex) currTab.setVisible(true);
|
| +
|
| + // If index 0 is selected, this line is required to set its visibility correctly.
|
| + if (i - 1 == selectedIndex) prevTab.setVisible(true);
|
| + }
|
| + }
|
| +
|
| + private float computeNewTabButtonOffsetLtr(StripLayoutTab[] indexOrderedTabs,
|
| + float tabOverlapWidth, float stripLeftMargin, float stripRightMargin,
|
| + float stripWidth) {
|
| + float rightEdge = stripLeftMargin;
|
| +
|
| + for (int i = 0; i < indexOrderedTabs.length; i++) {
|
| + StripLayoutTab tab = indexOrderedTabs[i];
|
| + float layoutWidth = (tab.getWidth() - tabOverlapWidth) * tab.getWidthWeight();
|
| + rightEdge = Math.max(tab.getDrawX() + layoutWidth, rightEdge);
|
| + }
|
| +
|
| + rightEdge = Math.min(rightEdge + tabOverlapWidth, stripWidth - stripRightMargin);
|
| +
|
| + // Adjust the right edge by the tab overlap width so that the new tab button is nestled
|
| + // closer to the tab.
|
| + rightEdge -= tabOverlapWidth / 2;
|
| +
|
| + // The draw X position for the new tab button is the rightEdge of the tab strip.
|
| + return rightEdge;
|
| + }
|
| +
|
| + private float computeNewTabButtonOffsetRtl(StripLayoutTab[] indexOrderedTabs,
|
| + float tabOverlapWidth, float stripLeftMargin, float stripRightMargin, float stripWidth,
|
| + float newTabButtonWidth) {
|
| + float leftEdge = stripWidth - stripRightMargin;
|
| +
|
| + for (int i = 0; i < indexOrderedTabs.length; i++) {
|
| + StripLayoutTab tab = indexOrderedTabs[i];
|
| + leftEdge = Math.min(tab.getDrawX(), leftEdge);
|
| + }
|
| +
|
| + leftEdge = Math.max(leftEdge, stripLeftMargin);
|
| +
|
| + // Adjust the left edge by the tab overlap width so that the new tab button is nestled
|
| + // closer to the tab.
|
| + leftEdge += tabOverlapWidth / 2;
|
| +
|
| + // The draw X position for the new tab button is the left edge of the tab strip minus
|
| + // the new tab button width.
|
| + return leftEdge - newTabButtonWidth;
|
| + }
|
| +}
|
|
|