blob: f411713201edcf97fd5238c47bac21c0dd0af213 [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.icons.AllIcons;
import com.intellij.ui.tabs.impl.JBTabsImpl;
import com.intellij.ui.tabs.impl.ShapeTransform;
import com.intellij.ui.tabs.impl.TabLabel;
import com.intellij.ui.tabs.impl.TabLayout;
import java.awt.*;
public abstract class SingleRowLayoutStrategy {
private static final int MIN_TAB_WIDTH = 50;
final SingleRowLayout myLayout;
final JBTabsImpl myTabs;
protected SingleRowLayoutStrategy(final SingleRowLayout layout) {
myLayout = layout;
myTabs = myLayout.myTabs;
}
abstract int getMoreRectAxisSize();
public abstract int getStartPosition(final SingleRowPassInfo data);
public abstract int getToFitLength(final SingleRowPassInfo data);
public abstract int getLengthIncrement(final Dimension dimension);
public abstract int getMinPosition(final Rectangle bounds);
public abstract int getMaxPosition(final Rectangle bounds);
protected abstract int getFixedFitLength(final SingleRowPassInfo data);
public Rectangle getLayoutRect(final SingleRowPassInfo data, final int position, final int length) {
return getLayoutRec(position, getFixedPosition(data), length, getFixedFitLength(data));
}
protected abstract Rectangle getLayoutRec(final int position, final int fixedPos, final int length, final int fixedFitLength);
protected abstract int getFixedPosition(final SingleRowPassInfo data);
public abstract Rectangle getMoreRect(final SingleRowPassInfo data);
public abstract boolean isToCenterTextWhenStretched();
public abstract ShapeTransform createShapeTransform(Rectangle rectangle);
public abstract boolean canBeStretched();
public abstract void layoutComp(SingleRowPassInfo data);
public boolean isSideComponentOnTabs() {
return false;
}
public abstract boolean isDragOut(TabLabel tabLabel, int deltaX, int deltaY);
/**
* Whether a tab that didn't fit completely on the right/bottom side in scrollable layout should be clipped or hidden altogether.
*
* @return true if the tab should be clipped, false if hidden.
*/
public abstract boolean drawPartialOverflowTabs();
/**
* Return the change of scroll offset for every unit of mouse wheel scrolling.
*
* @param label the first visible tab label
* @return the scroll amount
*/
public abstract int getScrollUnitIncrement(TabLabel label);
abstract static class Horizontal extends SingleRowLayoutStrategy {
protected Horizontal(final SingleRowLayout layout) {
super(layout);
}
public boolean isToCenterTextWhenStretched() {
return true;
}
@Override
public boolean canBeStretched() {
return true;
}
@Override
public boolean isDragOut(TabLabel tabLabel, int deltaX, int deltaY) {
return Math.abs(deltaY) > tabLabel.getHeight() * TabLayout.getDragOutMultiplier();
}
public int getMoreRectAxisSize() {
return AllIcons.General.MoreTabs.getIconWidth() + 15;
}
public int getToFitLength(final SingleRowPassInfo data) {
if (data.hToolbar != null) {
return myTabs.getWidth() - data.insets.left - data.insets.right - data.hToolbar.getMinimumSize().width;
} else {
return myTabs.getWidth() - data.insets.left - data.insets.right;
}
}
public int getLengthIncrement(final Dimension labelPrefSize) {
return myTabs.isEditorTabs() ? labelPrefSize.width < MIN_TAB_WIDTH ? MIN_TAB_WIDTH : labelPrefSize.width : labelPrefSize.width;
}
@Override
public int getMinPosition(Rectangle bounds) {
return (int)bounds.getX();
}
public int getMaxPosition(final Rectangle bounds) {
return (int)bounds.getMaxX();
}
public int getFixedFitLength(final SingleRowPassInfo data) {
return myTabs.myHeaderFitSize.height;
}
public Rectangle getLayoutRec(final int position, final int fixedPos, final int length, final int fixedFitLength) {
return new Rectangle(position, fixedPos, length, fixedFitLength);
}
public int getStartPosition(final SingleRowPassInfo data) {
return data.insets.left;
}
@Override
public boolean drawPartialOverflowTabs() {
return false;
}
@Override
public int getScrollUnitIncrement(TabLabel label) {
return 10;
}
}
static class Top extends Horizontal {
Top(final SingleRowLayout layout) {
super(layout);
}
@Override
public boolean isSideComponentOnTabs() {
return !myTabs.isSideComponentVertical() && myTabs.isSideComponentOnTabs();
}
public ShapeTransform createShapeTransform(Rectangle labelRec) {
return new ShapeTransform.Top(labelRec);
}
public int getFixedPosition(final SingleRowPassInfo data) {
return data.insets.top;
}
public Rectangle getMoreRect(final SingleRowPassInfo data) {
int x;
if (myTabs.isEditorTabs()) {
x = data.layoutSize.width - data.moreRectAxisSize - 1;
}
else {
x = data.position + (data.lastGhostVisible ? data.lastGhost.width : 0);
}
return new Rectangle(x, data.insets.top + JBTabsImpl.getSelectionTabVShift(),
data.moreRectAxisSize - 1, myTabs.myHeaderFitSize.height - 1);
}
@Override
public void layoutComp(SingleRowPassInfo data) {
if (myTabs.isHideTabs()) {
myTabs.layoutComp(data, 0, 0, 0, 0);
} else {
final int vToolbarWidth = data.vToolbar != null ? data.vToolbar.getPreferredSize().width : 0;
final int x = vToolbarWidth > 0 ? vToolbarWidth + 1 : 0;
final int hToolbarHeight = !myTabs.isSideComponentOnTabs() && data.hToolbar != null ? data.hToolbar.getPreferredSize().height : 0;
final int y = myTabs.myHeaderFitSize.height + (myTabs.isEditorTabs() ? 0 : 1) +
(hToolbarHeight > 0 ? hToolbarHeight - 2 : 0);
if (data.hToolbar != null) {
final Rectangle compBounds = myTabs.layoutComp(x, y, data.comp, 0, 0);
if (myTabs.isSideComponentOnTabs()) {
int toolbarX = data.moreRect != null ? (int)data.moreRect.getMaxX() + myTabs.getToolbarInset() : (data.position + myTabs.getToolbarInset());
final Rectangle rec =
new Rectangle(toolbarX, data.insets.top + 1, myTabs.getSize().width - data.insets.left - toolbarX, myTabs.myHeaderFitSize.height);
myTabs.layout(data.hToolbar, rec);
} else {
final int toolbarHeight = data.hToolbar.getPreferredSize().height - 2;
myTabs.layout(data.hToolbar, compBounds.x, compBounds.y - toolbarHeight - 1, compBounds.width, toolbarHeight);
}
} else if (data.vToolbar != null) {
final Rectangle compBounds = myTabs.layoutComp(x, y, data.comp, 0, 0);
final int toolbarWidth = data.vToolbar.getPreferredSize().width;
myTabs.layout(data.vToolbar, compBounds.x - toolbarWidth - 1, compBounds.y, toolbarWidth, compBounds.height);
} else {
myTabs.layoutComp(x, y, data.comp, 0, 0);
}
}
}
}
static class Bottom extends Horizontal {
Bottom(final SingleRowLayout layout) {
super(layout);
}
@Override
public void layoutComp(SingleRowPassInfo data) {
if (myTabs.isHideTabs()) {
myTabs.layoutComp(data, 0, 0, 0, 0);
} else {
myTabs.layoutComp(data, 0, 0, 0, -(myTabs.myHeaderFitSize.height + 1));
}
}
public int getFixedPosition(final SingleRowPassInfo data) {
return myTabs.getSize().height - data.insets.bottom - myTabs.myHeaderFitSize.height - 1;
}
public Rectangle getMoreRect(final SingleRowPassInfo data) {
return new Rectangle(myTabs.getWidth() - data.insets.right - data.moreRectAxisSize + 2, getFixedPosition(data),
data.moreRectAxisSize - 1, myTabs.myHeaderFitSize.height - 1);
}
@Override
public ShapeTransform createShapeTransform(Rectangle labelRec) {
return new ShapeTransform.Bottom(labelRec);
}
}
abstract static class Vertical extends SingleRowLayoutStrategy {
protected Vertical(SingleRowLayout layout) {
super(layout);
}
@Override
public boolean isDragOut(TabLabel tabLabel, int deltaX, int deltaY) {
return Math.abs(deltaX) > tabLabel.getHeight() * TabLayout.getDragOutMultiplier();
}
public boolean isToCenterTextWhenStretched() {
return false;
}
int getMoreRectAxisSize() {
return AllIcons.General.MoreTabs.getIconHeight() + 4;
}
@Override
public boolean canBeStretched() {
return false;
}
public int getStartPosition(final SingleRowPassInfo data) {
return data.insets.top;
}
public int getToFitLength(final SingleRowPassInfo data) {
return myTabs.getHeight() - data.insets.top - data.insets.bottom;
}
public int getLengthIncrement(final Dimension labelPrefSize) {
return labelPrefSize.height;
}
@Override
public int getMinPosition(Rectangle bounds) {
return (int) bounds.getMinY();
}
public int getMaxPosition(final Rectangle bounds) {
int maxY = (int)bounds.getMaxY();
return myTabs.isEditorTabs() ? maxY - 1 : maxY;
}
public int getFixedFitLength(final SingleRowPassInfo data) {
return myTabs.myHeaderFitSize.width;
}
@Override
public boolean drawPartialOverflowTabs() {
return false;
}
@Override
public int getScrollUnitIncrement(TabLabel label) {
return label.getPreferredSize().height;
}
}
static class Left extends Vertical {
Left(final SingleRowLayout layout) {
super(layout);
}
@Override
public void layoutComp(SingleRowPassInfo data) {
if (myTabs.isHideTabs()) {
myTabs.layoutComp(data, 0, 0, 0, 0);
} else {
myTabs.layoutComp(data, myTabs.myHeaderFitSize.width + 1, 0, 0, 0);
}
}
@Override
public ShapeTransform createShapeTransform(Rectangle labelRec) {
return new ShapeTransform.Left(labelRec);
}
public Rectangle getLayoutRec(final int position, final int fixedPos, final int length, final int fixedFitLength) {
return new Rectangle(fixedPos, position, fixedFitLength, length);
}
public int getFixedPosition(final SingleRowPassInfo data) {
return data.insets.left;
}
public Rectangle getMoreRect(final SingleRowPassInfo data) {
return new Rectangle(data.insets.left + JBTabsImpl.getSelectionTabVShift(),
myTabs.getHeight() - data.insets.bottom - data.moreRectAxisSize - 1,
myTabs.myHeaderFitSize.width - 1,
data.moreRectAxisSize - 1);
}
}
static class Right extends Vertical {
Right(SingleRowLayout layout) {
super(layout);
}
@Override
public void layoutComp(SingleRowPassInfo data) {
if (myTabs.isHideTabs()) {
myTabs.layoutComp(data, 0, 0, 0, 0);
} else {
myTabs.layoutComp(data, 0, 0, -(myTabs.myHeaderFitSize.width), 0);
}
}
public ShapeTransform createShapeTransform(Rectangle labelRec) {
return new ShapeTransform.Right(labelRec);
}
public Rectangle getLayoutRec(int position, int fixedPos, int length, int fixedFitLength) {
return new Rectangle(fixedPos, position, fixedFitLength - 1, length);
}
public int getFixedPosition(SingleRowPassInfo data) {
return data.layoutSize.width - myTabs.myHeaderFitSize.width - data.insets.right;
}
public Rectangle getMoreRect(SingleRowPassInfo data) {
return new Rectangle(data.layoutSize.width - myTabs.myHeaderFitSize.width,
myTabs.getHeight() - data.insets.bottom - data.moreRectAxisSize - 1,
myTabs.myHeaderFitSize.width - 1,
data.moreRectAxisSize - 1);
}
}
}