// 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.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 side by * side and the entire strip will scroll. Tabs will never completely overlap each other. */ public class ScrollingStripStacker extends StripStacker { @Override public void setTabOffsets(int selectedIndex, StripLayoutTab[] indexOrderedTabs, float tabStackWidth, int maxTabsToStack, float tabOverlapWidth, float stripLeftMargin, float stripRightMargin, float stripWidth, boolean inReorderMode) { for (int i = 0; i < indexOrderedTabs.length; i++) { StripLayoutTab tab = indexOrderedTabs[i]; tab.setDrawX(tab.getIdealX()); tab.setDrawY(tab.getOffsetY()); tab.setVisiblePercentage(1.f); tab.setContentOffsetX(0.f); } } @Override public float computeNewTabButtonOffset(StripLayoutTab[] indexOrderedTabs, float tabOverlapWidth, float stripLeftMargin, float stripRightMargin, float stripWidth, float newTabButtonWidth) { return LocalizationUtils.isLayoutRtl() ? computeNewTabButtonOffsetRtl(indexOrderedTabs, tabOverlapWidth, stripRightMargin, stripWidth, newTabButtonWidth) : computeNewTabButtonOffsetLtr(indexOrderedTabs, tabOverlapWidth, stripLeftMargin, stripWidth); } @Override public void performOcclusionPass(int selectedIndex, StripLayoutTab[] indexOrderedTabs, float stripWidth) { for (int i = 0; i < indexOrderedTabs.length; i++) { StripLayoutTab tab = indexOrderedTabs[i]; tab.setVisible((tab.getDrawX() + tab.getWidth()) >= 0 && tab.getDrawX() <= stripWidth); } } private float computeNewTabButtonOffsetLtr(StripLayoutTab[] indexOrderedTabs, float tabOverlapWidth, float stripLeftMargin, float stripWidth) { float rightEdge = stripLeftMargin; int numTabs = indexOrderedTabs.length; // Need to look at the last two tabs to determine the new tab position in case the last // tab is dying. int i = numTabs > 0 ? ((numTabs >= 2) ? numTabs - 2 : numTabs - 1) : 0; for (; i < numTabs; i++) { StripLayoutTab tab = indexOrderedTabs[i]; float layoutWidth; if (tab.isDying()) { // If a tab is dying, adjust the tab width by the width weight so that the new // tab button slides to the left with the closing tab. layoutWidth = tab.getWidth() * tab.getWidthWeight(); } else { // If a tab is being created, disregard its width weight so the new tab button // doesn't end up positioned too far to the left. If a tab is neither being // created or dying, its width width weight is 1.0 and can also be ignored. layoutWidth = tab.getWidth(); } rightEdge = Math.max(tab.getDrawX() + layoutWidth, rightEdge); } // 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 stripRightMargin, float stripWidth, float newTabButtonWidth) { float leftEdge = stripWidth - stripRightMargin; int numTabs = indexOrderedTabs.length; if (numTabs >= 1) { StripLayoutTab tab = indexOrderedTabs[numTabs - 1]; leftEdge = Math.min(tab.getDrawX(), leftEdge); } // 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; } }