blob: eb4989d4bacdee941dc77d42b658b197547ca504 [file] [log] [blame]
/*
* Copyright 2000-2009 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.plaf.beg;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.text.View;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.metal.MetalTabbedPaneUI;
import java.awt.*;
public class BegTabbedPaneUI extends MetalTabbedPaneUI {
private static final Color LIGHT = new Color(247, 243, 239);
private static final Color DARK = new Color(189, 187, 182);
private boolean myNoIconSpace = false;
private boolean myPaintContentBorder = true;
public void installUI(JComponent c) {
super.installUI(c);
Object clientProperty = UIUtil.getTabbedPanePaintContentBorder(c);
if (clientProperty instanceof Boolean) {
Boolean aBoolean = (Boolean)clientProperty;
myPaintContentBorder = aBoolean.booleanValue();
}
}
protected Insets getContentBorderInsets(int tabPlacement) {
if (tabPlacement == TOP && !myPaintContentBorder) {
return new Insets(1, 0, 0, 0);
}
if (tabPlacement == BOTTOM && !myPaintContentBorder) {
return new Insets(0, 0, 1, 0);
}
if (tabPlacement == LEFT && !myPaintContentBorder) {
return new Insets(0, 1, 0, 0);
}
if (tabPlacement == RIGHT && !myPaintContentBorder) {
return new Insets(0, 0, 0, 1);
}
return new Insets(1, 1, 1, 1);
}
protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
g.setColor(darkShadow);
switch (tabPlacement) {
case TOP:
{
if (isSelected) {
// left
UIUtil.drawLine(g, x, y + 1, x, y + h - 1);
// top
UIUtil.drawLine(g, x + 1, y, x + w - 3, y);
// right
UIUtil.drawLine(g, x + w - 2, y + 1, x + w - 2, y + h - 1);
}
else {
// left
UIUtil.drawLine(g, x, y + 1, x, y + h - 1);
// top
UIUtil.drawLine(g, x + 1, y, x + w - 3, y);
// right
UIUtil.drawLine(g, x + w - 2, y + 1, x + w - 2, y + h - 1);
}
break;
}
case LEFT:
{
// top
UIUtil.drawLine(g, x + 1, y + 1, x + w - 1, y + 1);
// left
UIUtil.drawLine(g, x, y + 2, x, y + h - 2);
//bottom
UIUtil.drawLine(g, x + 1, y + h - 1, x + w - 1, y + h - 1);
break;
}
case BOTTOM:
{
if (isSelected) {
// left
UIUtil.drawLine(g, x, y, x, y + h - 2);
// bottom
UIUtil.drawLine(g, x + 1, y + h - 1, x + w - 2, y + h - 1);
// right
UIUtil.drawLine(g, x + w - 1, y, x + w - 1, y + h - 2);
}
else {
// left
UIUtil.drawLine(g, x, y, x, y + h - 1);
// bottom
UIUtil.drawLine(g, x + 1, y + h - 1, x + w - 3, y + h - 1);
// right
UIUtil.drawLine(g, x + w - 2, y, x + w - 2, y + h - 1);
}
break;
}
case RIGHT:
{
// top
UIUtil.drawLine(g, x, y + 1, x + w - 2, y + 1);
// right
UIUtil.drawLine(g, x + w - 1, y + 2, x + w - 1, y + h - 2);
//bottom
UIUtil.drawLine(g, x, y + h - 1, x + w - 2, y + h - 1);
break;
}
default:
{
throw new IllegalArgumentException("unknown tabPlacement: " + tabPlacement);
}
}
}
protected void paintText(Graphics g, int tabPlacement,
Font font, FontMetrics metrics, int tabIndex,
String title, Rectangle textRect,
boolean isSelected) {
if (isSelected) {
font = font.isBold()? font : font.deriveFont(Font.BOLD);
metrics = metrics.getFont().isBold()? metrics : g.getFontMetrics(font);
}
else {
font = font.isPlain()? font : font.deriveFont(Font.PLAIN);
metrics = metrics.getFont().isPlain()? metrics : g.getFontMetrics(font);
}
g.setFont(font);
if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
g.setColor(tabPane.getForegroundAt(tabIndex));
g.drawString(title, textRect.x - (myNoIconSpace ? 5 : 0), textRect.y + metrics.getAscent());
}
else {
// tab disabled
g.setColor(tabPane.getBackgroundAt(tabIndex).brighter());
g.drawString(title, textRect.x, textRect.y + metrics.getAscent());
g.setColor(tabPane.getBackgroundAt(tabIndex).darker());
g.drawString(title, textRect.x - (myNoIconSpace ? 6 : 1), textRect.y + metrics.getAscent() - 1);
}
}
protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
if (isSelected) {
g.setColor(LIGHT);
}
else {
g.setColor(DARK);
}
switch (tabPlacement) {
case LEFT:
g.fillRect(x + 1, y + 2, w - 2, h - 3);
break;
case RIGHT:
g.fillRect(x, y + 2, w - 1, h - 3);
break;
case BOTTOM:
g.fillRect(x + 1, y, w - 3, h - 1);
break;
case TOP:
default:
g.fillRect(x + 1, y + 1, w - 2, h);
}
}
protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
if (tabPlacement == TOP || myPaintContentBorder) {
boolean leftToRight = isLeftToRight(tabPane);
int right = x + w - 1;
Rectangle selRect = selectedIndex < 0 ? null :
getTabBounds(selectedIndex, calcRect);
g.setColor(darkShadow);
// Draw unbroken line if tabs are not on TOP, OR
// selected tab is not in run adjacent to content, OR
// selected tab is not visible (SCROLL_TAB_LAYOUT)
//
if (tabPlacement != TOP || selectedIndex < 0 ||
(selRect.y + selRect.height + 1 < y) ||
(selRect.x < x || selRect.x > x + w)) {
UIUtil.drawLine(g, x, y, x + w - 1, y);
}
else {
// Break line to show visual connection to selected tab
boolean lastInRun = isLastInRun(selectedIndex);
UIUtil.drawLine(g, x, y, selRect.x, y);
if (selRect.x + selRect.width < right - 1) {
if (leftToRight && !lastInRun) {
UIUtil.drawLine(g, selRect.x + selRect.width - 2, y, right, y);
}
else {
UIUtil.drawLine(g, selRect.x + selRect.width - 2, y, right, y);
}
}
else {
UIUtil.drawLine(g, x + w - 2, y, x + w - 2, y);
}
}
}
}
protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
if (tabPlacement == BOTTOM || myPaintContentBorder) {
boolean leftToRight = isLeftToRight(tabPane);
int bottom = y + h - 1;
int right = x + w - 1;
Rectangle selRect = selectedIndex < 0 ? null :
getTabBounds(selectedIndex, calcRect);
g.setColor(darkShadow);
// Draw unbroken line if tabs are not on BOTTOM, OR
// selected tab is not in run adjacent to content, OR
// selected tab is not visible (SCROLL_TAB_LAYOUT)
//
if (tabPlacement != BOTTOM || selectedIndex < 0 ||
(selRect.y - 1 > h) ||
(selRect.x < x || selRect.x > x + w)) {
UIUtil.drawLine(g, x, y + h - 1, x + w - 1, y + h - 1);
}
else {
// Break line to show visual connection to selected tab
boolean lastInRun = isLastInRun(selectedIndex);
if (leftToRight || lastInRun) {
UIUtil.drawLine(g, x, bottom, selRect.x, bottom);
}
else {
UIUtil.drawLine(g, x, bottom, selRect.x - 1, bottom);
}
if (selRect.x + selRect.width < x + w - 2) {
if (leftToRight && !lastInRun) {
UIUtil.drawLine(g, selRect.x + selRect.width, bottom, right, bottom);
}
else {
UIUtil.drawLine(g, selRect.x + selRect.width - 1, bottom, right, bottom);
}
}
}
}
}
protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
if (tabPlacement == LEFT || myPaintContentBorder) {
Rectangle selRect = selectedIndex < 0 ? null :
getTabBounds(selectedIndex, calcRect);
g.setColor(darkShadow);
// Draw unbroken line if tabs are not on LEFT, OR
// selected tab is not in run adjacent to content, OR
// selected tab is not visible (SCROLL_TAB_LAYOUT)
//
if (tabPlacement != LEFT || selectedIndex < 0 ||
(selRect.x + selRect.width + 1 < x) ||
(selRect.y < y || selRect.y > y + h)) {
UIUtil.drawLine(g, x, y, x, y + h - 2);
}
else {
// Break line to show visual connection to selected tab
UIUtil.drawLine(g, x, y, x, selRect.y + 1);
if (selRect.y + selRect.height < y + h - 2) {
UIUtil.drawLine(g, x, selRect.y + selRect.height + 1, x, y + h + 2);
}
}
}
}
protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
if (tabPlacement == RIGHT || myPaintContentBorder) {
Rectangle selRect = selectedIndex < 0 ? null :
getTabBounds(selectedIndex, calcRect);
g.setColor(darkShadow);
// Draw unbroken line if tabs are not on RIGHT, OR
// selected tab is not in run adjacent to content, OR
// selected tab is not visible (SCROLL_TAB_LAYOUT)
//
if (tabPlacement != RIGHT || selectedIndex < 0 ||
(selRect.x - 1 > w) ||
(selRect.y < y || selRect.y > y + h)) {
UIUtil.drawLine(g, x + w - 1, y, x + w - 1, y + h - 1);
}
else {
// Break line to show visual connection to selected tab
UIUtil.drawLine(g, x + w - 1, y, x + w - 1, selRect.y);
if (selRect.y + selRect.height < y + h - 2) {
UIUtil.drawLine(g, x + w - 1, selRect.y + selRect.height, x + w - 1, y + h - 2);
}
}
}
}
private boolean isLastInRun(int tabIndex) {
int run = getRunForTab(tabPane.getTabCount(), tabIndex);
int lastIndex = lastTabInRun(tabPane.getTabCount(), run);
return tabIndex == lastIndex;
}
static boolean isLeftToRight(Component c) {
return c.getComponentOrientation().isLeftToRight();
}
protected int calculateTabHeight(int tabPlacement, int tabIndex, int fontHeight) {
return (int)(super.calculateTabHeight(tabPlacement, tabIndex, fontHeight) * 1.0);
}
protected int calculateMaxTabHeight(int tabPlacement) {
FontMetrics metrics = getFontMetrics();
int tabCount = tabPane.getTabCount();
int result = 0;
int fontHeight = metrics.getHeight();
for (int i = 0; i < tabCount; i++) {
result = Math.max(calculateTabHeight(tabPlacement, i, fontHeight), result);
}
return result;
}
/**
* invoked by reflection
*/
public static ComponentUI createUI(JComponent c) {
return new BegTabbedPaneUI();
}
/**
* IdeaTabbedPaneUI uses bold font for selected tab. Bold width of some fonts is
* less then width of plain font. To handle correctly this "anomaly" we have to
* determine maximum of these two widths.
*/
protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) {
final Font font = metrics.getFont();
final FontMetrics plainMetrics = font.isPlain()? metrics : tabPane.getFontMetrics(font.deriveFont(Font.PLAIN));
final int widthPlain = super.calculateTabWidth(tabPlacement, tabIndex, plainMetrics);
final FontMetrics boldMetrics = font.isBold()? metrics : tabPane.getFontMetrics(font.deriveFont(Font.BOLD));
final int widthBold = super.calculateTabWidth(tabPlacement, tabIndex, boldMetrics);
final int width = Math.max(widthPlain, widthBold);
myLayoutMetrics = (width == widthPlain)? plainMetrics : boldMetrics;
return width;
}
private FontMetrics myLayoutMetrics = null;
protected void layoutLabel(int tabPlacement, FontMetrics metrics, int tabIndex, String title, Icon icon, Rectangle tabRect,
Rectangle iconRect, Rectangle textRect, boolean isSelected) {
metrics = (myLayoutMetrics != null)? myLayoutMetrics : metrics;
textRect.x = textRect.y = iconRect.x = iconRect.y = 0;
View v = getTextViewForTab(tabIndex);
if (v != null) {
tabPane.putClientProperty("html", v);
}
SwingUtilities.layoutCompoundLabel(tabPane,
metrics, title, icon,
SwingUtilities.CENTER,
// left align title on LEFT/RIGHT placed tab
tabPlacement == RIGHT || tabPlacement == LEFT ? SwingUtilities.LEFT : SwingUtilities.CENTER,
SwingUtilities.CENTER,
SwingUtilities.TRAILING,
tabRect,
iconRect,
textRect,
textIconGap);
tabPane.putClientProperty("html", null);
int xNudge = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
int yNudge = getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
iconRect.x += xNudge;
iconRect.y += yNudge;
textRect.x += xNudge;
textRect.y += yNudge;
//super.layoutLabel(tabPlacement, _metrics, tabIndex, title, icon, tabRect, iconRect, textRect, isSelected);
}
public void setNoIconSpace(boolean noIconSpace) {
myNoIconSpace = noIconSpace;
}
public void setPaintContentBorder(boolean paintContentBorder) {
myPaintContentBorder = paintContentBorder;
}
protected int calculateTabAreaHeight(int tabPlacement, int horizRunCount, int maxTabHeight) {
for (int i = 0; i < tabPane.getTabCount(); i++) {
Component component = tabPane.getComponentAt(i);
if (component != null) {
return super.calculateTabAreaHeight(tabPlacement, horizRunCount, maxTabHeight);
}
}
return maxTabHeight + tabRunOverlay;
}
}