package com.apple.laf;
import java.awt.*;
import javax.swing.SwingConstants;
class AquaTabbedPaneTabState {
static final int FIXED_SCROLL_TAB_LENGTH = 27;
protected final Rectangle leftScrollTabRect = new Rectangle();
protected final Rectangle rightScrollTabRect = new Rectangle();
protected int numberOfVisibleTabs = 0;
protected int[] visibleTabList = new int[10];
protected int lastLeftmostTab;
protected int lastReturnAt;
private boolean needsScrollers;
private boolean hasMoreLeftTabs;
private boolean hasMoreRightTabs;
private final AquaTabbedPaneUI pane;
protected AquaTabbedPaneTabState(final AquaTabbedPaneUI pane) {
this.pane = pane;
}
protected int getIndex(final int i) {
if (i >= visibleTabList.length) return Integer.MIN_VALUE;
return visibleTabList[i];
}
protected void init(final int tabCount) {
if (tabCount < 1) needsScrollers = false;
if (tabCount == visibleTabList.length) return;
final int[] tempVisibleTabs = new int[tabCount];
System.arraycopy(visibleTabList, 0, tempVisibleTabs, 0, Math.min(visibleTabList.length, tabCount));
visibleTabList = tempVisibleTabs;
}
int getTotal() {
return numberOfVisibleTabs;
}
boolean needsScrollTabs() {
return needsScrollers;
}
void setNeedsScrollers(final boolean needsScrollers) {
this.needsScrollers = needsScrollers;
}
boolean needsLeftScrollTab() {
return hasMoreLeftTabs;
}
boolean needsRightScrollTab() {
return hasMoreRightTabs;
}
Rectangle getLeftScrollTabRect() {
return leftScrollTabRect;
}
Rectangle getRightScrollTabRect() {
return rightScrollTabRect;
}
boolean isBefore(final int i) {
if (numberOfVisibleTabs == 0) return true;
if (i < visibleTabList[0]) return true;
return false;
}
boolean isAfter(final int i) {
if (i > visibleTabList[numberOfVisibleTabs - 1]) return true;
return false;
}
private void addToEnd(final int idToAdd, final int length) {
visibleTabList[length] = idToAdd;
}
private void addToBeginning(final int idToAdd, final int length) {
System.arraycopy(visibleTabList, 0, visibleTabList, 1, length);
visibleTabList[0] = idToAdd;
}
void relayoutForScrolling(final Rectangle[] rects, final int startX, final int startY, final int returnAt, final int selectedIndex, final boolean verticalTabRuns, final int tabCount, final boolean isLeftToRight) {
if (!needsScrollers) {
hasMoreLeftTabs = false;
hasMoreRightTabs = false;
return;
}
if (verticalTabRuns) {
rightScrollTabRect.height = FIXED_SCROLL_TAB_LENGTH;
leftScrollTabRect.height = FIXED_SCROLL_TAB_LENGTH;
} else {
rightScrollTabRect.width = FIXED_SCROLL_TAB_LENGTH;
leftScrollTabRect.width = FIXED_SCROLL_TAB_LENGTH;
}
final boolean sizeChanged = returnAt != lastReturnAt;
if (pane.popupSelectionChanged || sizeChanged) {
pane.popupSelectionChanged = false;
lastLeftmostTab = -1;
}
int right = selectedIndex;
int left = selectedIndex - 1;
if (lastLeftmostTab >= 0) {
right = lastLeftmostTab;
left = -1;
} else if (selectedIndex < 0) {
right = 0;
left = -1;
}
int remainingSpace = returnAt - pane.tabAreaInsets.right - pane.tabAreaInsets.left - FIXED_SCROLL_TAB_LENGTH * 2;
int visibleCount = 0;
final Rectangle firstRect = rects[right];
if ((verticalTabRuns ? firstRect.height : firstRect.width) > remainingSpace) {
addToEnd(right, visibleCount);
if (verticalTabRuns) {
firstRect.height = remainingSpace;
} else {
firstRect.width = remainingSpace;
}
visibleCount++;
} else {
boolean rightDone = false;
boolean leftDone = false;
while ((visibleCount < tabCount) && !(rightDone && leftDone)) {
if (!rightDone && right >= 0 && right < tabCount) {
final Rectangle rightRect = rects[right];
if ((verticalTabRuns ? rightRect.height : rightRect.width) > remainingSpace) {
rightDone = true;
} else {
addToEnd(right, visibleCount);
visibleCount++;
remainingSpace -= (verticalTabRuns ? rightRect.height : rightRect.width);
right++;
continue;
}
} else {
rightDone = true;
}
if (!leftDone && left >= 0 && left < tabCount) {
final Rectangle leftRect = rects[left];
if ((verticalTabRuns ? leftRect.height : leftRect.width) > remainingSpace) {
leftDone = true;
} else {
addToBeginning(left, visibleCount);
visibleCount++;
remainingSpace -= (verticalTabRuns ? leftRect.height : leftRect.width);
left--;
}
} else {
leftDone = true;
}
}
}
if (visibleCount > visibleTabList.length) visibleCount = visibleTabList.length;
hasMoreLeftTabs = visibleTabList[0] > 0;
hasMoreRightTabs = visibleTabList[visibleCount - 1] < visibleTabList.length - 1;
numberOfVisibleTabs = visibleCount;
lastLeftmostTab = getIndex(0);
lastReturnAt = returnAt;
final int firstTabIndex = getIndex(0);
final int lastTabIndex = getIndex(visibleCount - 1);
for (int i = 0; i < tabCount; i++) {
if (i < firstTabIndex || i > lastTabIndex) {
final Rectangle rect = rects[i];
rect.x = Short.MAX_VALUE;
rect.y = Short.MAX_VALUE;
}
}
}
protected void alignRectsRunFor(final Rectangle[] rects, final Dimension tabPaneSize, final int tabPlacement, final boolean isRightToLeft) {
final boolean isVertical = tabPlacement == SwingConstants.LEFT || tabPlacement == SwingConstants.RIGHT;
if (isVertical) {
if (needsScrollers) {
stretchScrollingVerticalRun(rects, tabPaneSize);
} else {
centerVerticalRun(rects, tabPaneSize);
}
} else {
if (needsScrollers) {
stretchScrollingHorizontalRun(rects, tabPaneSize, isRightToLeft);
} else {
centerHorizontalRun(rects, tabPaneSize, isRightToLeft);
}
}
}
private void centerHorizontalRun(final Rectangle[] rects, final Dimension size, final boolean isRightToLeft) {
int totalLength = 0;
for (final Rectangle element : rects) {
totalLength += element.width;
}
int x = size.width / 2 - totalLength / 2;
if (isRightToLeft) {
for (final Rectangle rect : rects) {
rect.x = x;
x += rect.width;
}
} else {
for (int i = rects.length - 1; i >= 0; i--) {
final Rectangle rect = rects[i];
rect.x = x;
x += rect.width;
}
}
}
private void centerVerticalRun(final Rectangle[] rects, final Dimension size) {
int totalLength = 0;
for (final Rectangle element : rects) {
totalLength += element.height;
}
int y = size.height / 2 - totalLength / 2;
if (true) {
for (final Rectangle rect : rects) {
rect.y = y;
y += rect.height;
}
} else {
for (int i = rects.length - 1; i >= 0; i--) {
final Rectangle rect = rects[i];
rect.y = y;
y += rect.height;
}
}
}
private void stretchScrollingHorizontalRun(final Rectangle[] rects, final Dimension size, final boolean isRightToLeft) {
final int totalTabs = getTotal();
final int firstTabIndex = getIndex(0);
final int lastTabIndex = getIndex(totalTabs - 1);
int totalRunLength = 0;
for (int i = firstTabIndex; i <= lastTabIndex; i++) {
totalRunLength += rects[i].width;
}
int slack = size.width - totalRunLength - pane.tabAreaInsets.left - pane.tabAreaInsets.right;
if (needsLeftScrollTab()) {
slack -= FIXED_SCROLL_TAB_LENGTH;
}
if (needsRightScrollTab()) {
slack -= FIXED_SCROLL_TAB_LENGTH;
}
final int minSlack = (int)((float)(slack) / (float)(totalTabs));
int extraSlack = slack - (minSlack * totalTabs);
int runningLength = 0;
final int xOffset = pane.tabAreaInsets.left + (needsLeftScrollTab() ? FIXED_SCROLL_TAB_LENGTH : 0);
if (isRightToLeft) {
for (int i = firstTabIndex; i <= lastTabIndex; i++) {
final Rectangle rect = rects[i];
int slackToAdd = minSlack;
if (extraSlack > 0) {
slackToAdd++;
extraSlack--;
}
rect.x = runningLength + xOffset;
rect.width += slackToAdd;
runningLength += rect.width;
}
} else {
for (int i = lastTabIndex; i >= firstTabIndex; i--) {
final Rectangle rect = rects[i];
int slackToAdd = minSlack;
if (extraSlack > 0) {
slackToAdd++;
extraSlack--;
}
rect.x = runningLength + xOffset;
rect.width += slackToAdd;
runningLength += rect.width;
}
}
if (isRightToLeft) {
leftScrollTabRect.x = pane.tabAreaInsets.left;
leftScrollTabRect.y = rects[firstTabIndex].y;
leftScrollTabRect.height = rects[firstTabIndex].height;
rightScrollTabRect.x = size.width - pane.tabAreaInsets.right - rightScrollTabRect.width;
rightScrollTabRect.y = rects[lastTabIndex].y;
rightScrollTabRect.height = rects[lastTabIndex].height;
} else {
rightScrollTabRect.x = pane.tabAreaInsets.left;
rightScrollTabRect.y = rects[firstTabIndex].y;
rightScrollTabRect.height = rects[firstTabIndex].height;
leftScrollTabRect.x = size.width - pane.tabAreaInsets.right - rightScrollTabRect.width;
leftScrollTabRect.y = rects[lastTabIndex].y;
leftScrollTabRect.height = rects[lastTabIndex].height;
if (needsLeftScrollTab()) {
for (int i = lastTabIndex; i >= firstTabIndex; i--) {
final Rectangle rect = rects[i];
rect.x -= FIXED_SCROLL_TAB_LENGTH;
}
}
if (needsRightScrollTab()) {
for (int i = lastTabIndex; i >= firstTabIndex; i--) {
final Rectangle rect = rects[i];
rect.x += FIXED_SCROLL_TAB_LENGTH;
}
}
}
}
private void stretchScrollingVerticalRun(final Rectangle[] rects, final Dimension size) {
final int totalTabs = getTotal();
final int firstTabIndex = getIndex(0);
final int lastTabIndex = getIndex(totalTabs - 1);
int totalRunLength = 0;
for (int i = firstTabIndex; i <= lastTabIndex; i++) {
totalRunLength += rects[i].height;
}
int slack = size.height - totalRunLength - pane.tabAreaInsets.top - pane.tabAreaInsets.bottom;
if (needsLeftScrollTab()) {
slack -= FIXED_SCROLL_TAB_LENGTH;
}
if (needsRightScrollTab()) {
slack -= FIXED_SCROLL_TAB_LENGTH;
}
final int minSlack = (int)((float)(slack) / (float)(totalTabs));
int extraSlack = slack - (minSlack * totalTabs);
int runningLength = 0;
final int yOffset = pane.tabAreaInsets.top + (needsLeftScrollTab() ? FIXED_SCROLL_TAB_LENGTH : 0);
for (int i = firstTabIndex; i <= lastTabIndex; i++) {
final Rectangle rect = rects[i];
int slackToAdd = minSlack;
if (extraSlack > 0) {
slackToAdd++;
extraSlack--;
}
rect.y = runningLength + yOffset;
rect.height += slackToAdd;
runningLength += rect.height;
}
leftScrollTabRect.x = rects[firstTabIndex].x;
leftScrollTabRect.y = pane.tabAreaInsets.top;
leftScrollTabRect.width = rects[firstTabIndex].width;
rightScrollTabRect.x = rects[lastTabIndex].x;
rightScrollTabRect.y = size.height - pane.tabAreaInsets.bottom - rightScrollTabRect.height;
rightScrollTabRect.width = rects[lastTabIndex].width;
}
}