/* * 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) return; int offset = -myScrollOffset; for (TabInfo info : myLastSingRowLayout.myVisibleInfos) { final int length = getRequiredLength(info); if (info == myTabs.getSelectedInfo()) { int maxLength = myLastSingRowLayout.toFitLength - getStrategy().getMoreRectAxisSize(); if (offset < 0 && length < maxLength) { myScrollOffset += offset; } else 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 && label.getInfo() != myTabs.getSelectedInfo()) { 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; } }