blob: ce8e47a4fa931ad572b90f17001a790fce3813a9 [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* 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.intellij.ui.tabs.impl.singleRow;
import com.intellij.ui.tabs.TabInfo;
import com.intellij.ui.tabs.impl.JBTabsImpl;
import com.intellij.ui.tabs.impl.TabLabel;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.List;
/**
* @author yole
*/
public class ScrollableSingleRowLayout extends SingleRowLayout {
private int myScrollOffset = 0;
private boolean myScrollSelectionInViewPending = false;
public ScrollableSingleRowLayout(final JBTabsImpl tabs) {
super(tabs);
}
@Override
int getScrollOffset() {
return myScrollOffset;
}
@Override
public void scroll(int units) {
myScrollOffset += units;
if (myLastSingRowLayout != null) {
int offset = -myScrollOffset;
for (TabInfo info : myLastSingRowLayout.myVisibleInfos) {
final int length = getRequiredLength(info);
if (info == myTabs.getSelectedInfo()) {
if (offset < 0) {
myScrollOffset+=offset;
}
else {
final int maxLength = myLastSingRowLayout.toFitLength - getStrategy().getMoreRectAxisSize();
if (offset + length > maxLength) {
myScrollOffset+=offset + length - maxLength;
}
}
break;
}
offset += length;
}
clampScrollOffsetToBounds(myLastSingRowLayout);
}
}
@Override
protected boolean checkLayoutLabels(SingleRowPassInfo data) {
if (myScrollSelectionInViewPending) {
return true;
}
return super.checkLayoutLabels(data);
}
private void clampScrollOffsetToBounds(SingleRowPassInfo data) {
if (data.requiredLength < data.toFitLength) {
myScrollOffset = 0;
}
else {
myScrollOffset = Math.max(0, Math.min(myScrollOffset, data.requiredLength - data.toFitLength + getStrategy().getMoreRectAxisSize()));
}
}
@Override
public void scrollSelectionInView() {
myScrollSelectionInViewPending = true;
}
public int getScrollUnitIncrement() {
if (myLastSingRowLayout != null) {
final List<TabInfo> visibleInfos = myLastSingRowLayout.myVisibleInfos;
if (visibleInfos.size() > 0) {
final TabInfo info = visibleInfos.get(0);
return getStrategy().getScrollUnitIncrement(myTabs.myInfo2Label.get(info));
}
}
return 0;
}
private void doScrollSelectionInView(SingleRowPassInfo passInfo) {
int offset = -myScrollOffset;
for (TabInfo info : passInfo.myVisibleInfos) {
final int length = getRequiredLength(info);
if (info == myTabs.getSelectedInfo()) {
if (offset < 0) {
scroll(offset);
}
else {
final int maxLength = passInfo.toFitLength - getStrategy().getMoreRectAxisSize();
if (offset + length > maxLength) {
scroll(offset + length - maxLength);
}
}
break;
}
offset += length;
}
}
@Override
protected void recomputeToLayout(SingleRowPassInfo data) {
calculateRequiredLength(data);
clampScrollOffsetToBounds(data);
if (myScrollSelectionInViewPending || myLastSingRowLayout == null || !data.layoutSize.equals(myLastSingRowLayout.layoutSize)) {
myScrollSelectionInViewPending = false;
doScrollSelectionInView(data);
}
}
protected void layoutMoreButton(SingleRowPassInfo data) {
if (data.requiredLength > data.toFitLength) {
data.moreRect = getStrategy().getMoreRect(data);
}
}
@Override
protected boolean applyTabLayout(SingleRowPassInfo data, TabLabel label, int length, int deltaToFit) {
if (data.requiredLength > data.toFitLength) {
length = getStrategy().getLengthIncrement(label.getPreferredSize());
final int moreRectSize = getStrategy().getMoreRectAxisSize();
if (data.position + length > data.toFitLength - moreRectSize) {
final int clippedLength = getStrategy().drawPartialOverflowTabs() ? data.toFitLength - data.position - moreRectSize - 4 : 0;
super.applyTabLayout(data, label, clippedLength, deltaToFit);
label.setAlignmentToCenter(false);
label.setActionPanelVisible(false);
return false;
}
}
label.setActionPanelVisible(true);
return super.applyTabLayout(data, label, length, deltaToFit);
}
@Override
public boolean isTabHidden(TabInfo tabInfo) {
final TabLabel label = myTabs.myInfo2Label.get(tabInfo);
final Rectangle bounds = label.getBounds();
return getStrategy().getMinPosition(bounds) < -10 || bounds.isEmpty();
}
@Nullable
@Override
protected TabLabel findLastVisibleLabel(SingleRowPassInfo data) {
int i = data.toLayout.size()-1;
while(i > 0) {
final TabInfo info = data.toLayout.get(i);
final TabLabel label = myTabs.myInfo2Label.get(info);
if (!label.getBounds().isEmpty()) {
return label;
}
i--;
}
return null;
}
}