/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.gui.look.ui;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.QuadCurve2D;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JTabbedPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import com.rapidminer.gui.look.Colors;
import com.rapidminer.gui.look.GenericArrowButton;
import com.rapidminer.gui.look.RapidLookAndFeel;
import com.rapidminer.gui.look.RapidLookTools;
import com.vlsolutions.swing.docking.DockTabbedPane;
import com.vlsolutions.swing.docking.DockViewAsTab.TabHeader;
/**
* The UI for tabbed panes.
*
* @author Ingo Mierswa, Marco Boeck
*/
public class TabbedPaneUI extends BasicTabbedPaneUI {
private class TabbedPaneMouseListener implements MouseMotionListener, MouseListener {
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {
updateMouseOver(e.getPoint());
}
@Override
public void mouseExited(MouseEvent e) {
updateMouseOver(e.getPoint());
}
@Override
public void mousePressed(MouseEvent e) {
updateMouseOver(e.getPoint());
}
@Override
public void mouseReleased(MouseEvent e) {
updateMouseOver(e.getPoint());
}
@Override
public void mouseDragged(MouseEvent e) {}
@Override
public void mouseMoved(MouseEvent e) {
updateMouseOver(e.getPoint());
}
}
private TabbedPaneMouseListener mouseListener = new TabbedPaneMouseListener();
private ChangeListener tabSelListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// the content border is not repainted for the SettingsDialog unless this is
// done
TabbedPaneUI.this.tabPane.repaint();
}
});
}
};
private int rolloveredTabIndex = -1;
public static ComponentUI createUI(JComponent c) {
return new TabbedPaneUI();
}
@Override
protected JButton createScrollButton(int direction) {
if (direction != SOUTH && direction != NORTH && direction != EAST && direction != WEST) {
throw new IllegalArgumentException("Direction must be one of: " + "SOUTH, NORTH, EAST or WEST");
}
return new GenericArrowButton(direction, 17, 17);
}
@Override
protected void installListeners() {
super.installListeners();
this.tabPane.addMouseListener(this.mouseListener);
this.tabPane.addMouseMotionListener(this.mouseListener);
this.tabPane.addChangeListener(this.tabSelListener);
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
this.tabPane.removeMouseListener(this.mouseListener);
this.tabPane.removeMouseMotionListener(this.mouseListener);
}
@Override
protected void installDefaults() {
super.installDefaults();
}
@Override
protected FontMetrics getFontMetrics() {
Font font = tabPane.getFont();
// selected tab is bold, to avoid resizing always assume bold and make tabs bigger
font = font.deriveFont(Font.BOLD);
return tabPane.getFontMetrics(font);
}
@Override
protected MouseListener createMouseListener() {
return new MouseHandler();
}
@Override
protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) {
if (isDockingFrameworkTab()) {
return super.calculateTabWidth(tabPlacement, tabIndex, metrics) - 5;
}
return super.calculateTabWidth(tabPlacement, tabIndex, metrics) + 5;
}
@Override
protected LayoutManager createLayoutManager() {
if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) {
// can't override because private class..
return super.createLayoutManager();
} else {
// override for docking framework spacing fix!
return new BasicTabbedPaneUI.TabbedPaneLayout() {
@Override
protected void calculateTabRects(int tabPlacement, int tabCount) {
final int spacer = -5;
final int indent = 0;
super.calculateTabRects(tabPlacement, tabCount);
for (int i = 1; i < rects.length; i++) {
// hack to get the tabs closer together. Don't shift leftmost tab(s)
if (rects[i].x > 0) {
rects[i].x += i * spacer + indent;
}
}
}
};
}
}
@Override
protected Insets getTabInsets(int tabPlacement, int tabIndex) {
Insets t;
switch (tabPlacement) {
case SwingConstants.TOP:
if (isDockingFrameworkTab()) {
t = new Insets(6, 5, 6, -10);
} else {
t = new Insets(6, 8, 6, 8);
}
break;
case SwingConstants.LEFT:
t = new Insets(8, 8, 8, 8);
break;
case SwingConstants.RIGHT:
t = new Insets(8, 8, 8, 8);
break;
case SwingConstants.BOTTOM:
t = new Insets(8, 8, 8, 8);
break;
default:
t = new Insets(8, 8, 8, 8);
break;
}
return t;
}
@Override
protected Insets getSelectedTabPadInsets(int tabPlacement) {
Insets t;
switch (tabPlacement) {
case SwingConstants.TOP:
if (isDockingFrameworkTab()) {
t = new Insets(0, 5, 0, 0);
} else {
t = new Insets(0, 5, 0, 5);
}
break;
case SwingConstants.LEFT:
t = new Insets(1, 5, 0, 5);
break;
case SwingConstants.RIGHT:
t = new Insets(1, 5, 0, 5);
break;
case SwingConstants.BOTTOM:
t = new Insets(1, 5, 0, 5);
break;
default:
t = new Insets(1, 5, 0, 5);
break;
}
return t;
}
@Override
protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h,
boolean isSelected) {}
@Override
protected void paintFocusIndicator(Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex, Rectangle iconRect,
Rectangle textRect, boolean isSelected) {}
@Override
protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, int xp, int yp, int mw, int mh,
boolean isSelected) {
if (isSelected) {
paintTabBorderSelected(g, tabPlacement, tabIndex, xp, yp, mw, mh);
} else {
paintTabBorderFree(g, tabPlacement, tabIndex, xp, yp, mw, mh);
}
}
@Override
protected void paintContentBorder(Graphics g, int tabPlacement, int selectedIndex) {
int width = this.tabPane.getWidth();
int height = this.tabPane.getHeight();
Insets insets = this.tabPane.getInsets();
int x = insets.left;
int y = insets.top;
int w = width - insets.right - insets.left;
int h = height - insets.top - insets.bottom;
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Colors.TAB_CONTENT_BORDER);
int r = RapidLookAndFeel.CORNER_TAB_RADIUS;
Rectangle selTabBounds = new Rectangle();
switch (tabPlacement) {
case LEFT:
x += calculateTabAreaWidth(tabPlacement, this.runCount, this.maxTabWidth);
w -= x - insets.left;
// the goal is to draw a round border all around the content except for where the
// selected tab (if visible) is
getTabBounds(selectedIndex, selTabBounds);
// first we draw a round rect around everything
g2.drawRoundRect(x, y, w - 1, h - 1, r, r);
// now we remove the left line of the rect depending on whether the tab is in the
// top
// left corner, bottom left corner, or in the middle. Reason for that is that the
// top
// left or bottom left tab has no upper/lower left corner at all
g2.setColor(Colors.TAB_BACKGROUND_SELECTED);
if (selTabBounds.y < r) {
g2.fillRect(x - 1, y + 1, 5, selTabBounds.height - 1);
// now we draw the left border line again but not next to the selected tab
g2.setColor(Colors.TAB_CONTENT_BORDER);
g2.drawLine(x, y + selTabBounds.y + +selTabBounds.height, x, y + h - r);
// there are missing border pixels that needs fixing
g2.drawLine(x, y, x, y);
} else if (h - (y + selTabBounds.y + selTabBounds.height) < r) {
g2.fillRect(x, y + selTabBounds.y, 5, selTabBounds.height);
// now we draw the top border line again but not below the selected tab
g2.setColor(Colors.TAB_CONTENT_BORDER);
g2.drawLine(x, y, x, selTabBounds.y - y);
// there are missing border pixels that needs fixing
g2.drawLine(x, y + selTabBounds.y + selTabBounds.height, x + 1, y + selTabBounds.y + selTabBounds.height);
} else {
g2.fillRect(x, y + selTabBounds.y, 5, selTabBounds.height);
// now we draw the left border line again but not next to the selected tab
g2.setColor(Colors.TAB_CONTENT_BORDER);
g2.drawLine(x + r, y, x + selTabBounds.x, y);
g2.drawLine(x + selTabBounds.x + selTabBounds.width - 1, y, x + w - r, y);
// there are missing border pixels that needs fixing
g2.drawLine(x, y + selTabBounds.y, x, y + selTabBounds.y);
}
break;
case RIGHT:
w -= calculateTabAreaWidth(tabPlacement, this.runCount, this.maxTabWidth);
break;
case BOTTOM:
h -= calculateTabAreaHeight(tabPlacement, this.runCount, this.maxTabHeight);
break;
case TOP:
default:
y += calculateTabAreaHeight(tabPlacement, this.runCount, this.maxTabHeight);
h -= y - insets.top;
// the goal is to draw a round border all around the content except for where the
// selected tab (if visible) is
if (selectedIndex >= 0) {
getTabBounds(selectedIndex, selTabBounds);
}
// first we draw a round rect around everything
g2.drawRoundRect(x, y, w - 1, h - 1, r, r);
// now we remove the top line of the rect depending on whether the tab is in the top
// left corner, top right corner, or in the middle. Reason for that is that the top
// left or top right tab has no upper left/right corner at all
g2.setColor(Colors.TAB_BACKGROUND_SELECTED);
if (selTabBounds.x < r) {
g2.fillRect(x + 1, y - 1, selTabBounds.width - 1, 5);
// now we draw the top border line again but not below the selected tab
g2.setColor(Colors.TAB_CONTENT_BORDER);
g2.drawLine(x + selTabBounds.x + selTabBounds.width - 1, y, x + w - r, y);
// there are missing border pixels that needs fixing
g2.drawLine(x, y, x, y);
g2.drawLine(x + selTabBounds.x + selTabBounds.width - 1, y - 1, x + selTabBounds.x + selTabBounds.width
- 1, y - 1);
} else if (w - (x + selTabBounds.x + selTabBounds.width) < r) {
g2.fillRect(x + selTabBounds.x + 1, y - 1, selTabBounds.width - 2, 5);
// now we draw the top border line again but not below the selected tab
g2.setColor(Colors.TAB_CONTENT_BORDER);
g2.drawLine(x, y, selTabBounds.x - x, y);
// there are missing border pixels that needs fixing
g2.drawLine(x + w, y, x + w, y);
g2.drawLine(x + w - selTabBounds.width, y - 1, x + w - selTabBounds.width, y - 1);
} else {
g2.fillRect(x + selTabBounds.x, y - 1, selTabBounds.width - 1, 5);
// now we draw the top border line again but not below the selected tab
g2.setColor(Colors.TAB_CONTENT_BORDER);
g2.drawLine(x + r, y, x + selTabBounds.x, y);
g2.drawLine(x + selTabBounds.x + selTabBounds.width - 1, y, x + w - r, y);
// there are missing border pixels that needs fixing
g2.drawLine(x + selTabBounds.x, y - 1, x + selTabBounds.x, y - 1);
g2.drawLine(x + selTabBounds.x + selTabBounds.width - 1, y - 1, x + selTabBounds.x + selTabBounds.width
- 1, y - 1);
}
}
g2.dispose();
}
private void paintTabBorderSelected(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h) {
if (tabPlacement == SwingConstants.TOP) {
paintSelectedTop(g, x, y, w, h);
} else if (tabPlacement == SwingConstants.LEFT) {
paintSelectedLeft(g, x, y, w, h);
} else if (tabPlacement == SwingConstants.RIGHT) {
paintSelectedRight(g, x, y, w, h);
} else {
paintSelectedBottom(g, x, y, w, h);
}
}
private static void paintSelectedRight(Graphics g, int x, int y, int w, int h) {
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[2]);
g.drawLine(x, y + 1, x + w - 11, y + 1);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[3]);
g.drawLine(x, y, x + w - 15, y);
ColorUIResource c1 = RapidLookTools.getColors().getTabbedPaneColors()[4];
g.setColor(c1);
g.drawLine(w + x - 10, y + 1, w + x - 10, y + 2);
g.drawLine(w + x - 9, y + 2, w + x - 9, y + 2);
g.drawLine(w + x - 8, y + 2, w + x - 8, y + 3);
g.drawLine(w + x - 7, y + 3, w + x - 7, y + 4);
g.drawLine(w + x - 6, y + 4, w + x - 6, y + 5);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[5]);
g.drawLine(x, y + 2, x + w - 11, y + 2);
g.drawLine(x, y + 3, x + w - 9, y + 3);
g.drawLine(x, y + 4, x + w - 8, y + 4);
g.drawLine(x, y + 5, x + w - 7, y + 5);
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(new GradientPaint(1, y + 6, RapidLookTools.getColors().getTabbedPaneColors()[6], 1, y + h,
RapidLookTools.getColors().getTabbedPaneColors()[7]));
int[] xArr = new int[] { x + 4, w + x - 5, w + x - 5, x + 4 };
int[] yArr = new int[] { y + 6, y + 6, y + h, y + h };
Polygon p1 = new Polygon(xArr, yArr, 4);
g2.fillPolygon(p1);
g.setColor(c1);
g.drawLine(w + x - 5, y + 6, x + w - 5, y + h - 1);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[1]);
g.drawLine(x + w - 14, y, x + w - 12, y);
g.drawLine(w + x - 6, y + 6, x + w - 6, y + 6);
}
private static void paintSelectedLeft(Graphics g, int x, int y, int w, int h) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
drawLeftTab(x + 2, y, w - 2, h, g2, Colors.TAB_BACKGROUND_SELECTED);
g2.dispose();
}
private static void paintSelectedTop(Graphics g, int x, int y, int w, int h) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
drawTopTab(x, y, w, h, g2, Colors.TAB_BACKGROUND_SELECTED);
g2.dispose();
}
private static void paintSelectedBottom(Graphics g, int x, int y, int w, int h) {
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[1]);
g.drawLine(x + 11, y + h - 1, x + w - 12, y + h - 1);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[2]);
g.drawLine(x + 10, y + h - 2, x + w - 11, y + h - 2);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[3]);
g.drawLine(x + 13, y + h - 1, x + w - 14, y + h - 1);
ColorUIResource c1 = RapidLookTools.getColors().getTabbedPaneColors()[4];
g.setColor(c1);
// left
g.drawLine(x + 9, y + h - 2, x + 9, y + h - 3);
g.drawLine(x + 8, y + h - 3, x + 8, y + h - 3);
g.drawLine(x + 7, y + h - 3, x + 7, y + h - 4);
g.drawLine(x + 6, y + h - 4, x + 6, y + h - 5);
g.drawLine(x + 5, y + h - 5, x + 5, y + h - 6);
// right
g.drawLine(w + x - 10, y + h - 2, w + x - 10, y + h - 3);
g.drawLine(w + x - 9, y + h - 3, w + x - 9, y + h - 3);
g.drawLine(w + x - 8, y + h - 3, w + x - 8, y + h - 4);
g.drawLine(w + x - 7, y + h - 4, w + x - 7, y + h - 5);
g.drawLine(w + x - 6, y + h - 5, w + x - 6, y + h - 6);
// inner section
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[5]);
g.drawLine(x + 10, y + h - 3, x + w - 11, y + h - 3);
g.drawLine(x + 8, y + h - 4, x + w - 9, y + h - 4);
g.drawLine(x + 7, y + h - 5, x + w - 8, y + h - 5);
g.drawLine(x + 6, y + h - 6, x + w - 7, y + h - 6);
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(new GradientPaint(1, y, RapidLookTools.getColors().getTabbedPaneColors()[7], 1, y + h - 6,
RapidLookTools.getColors().getTabbedPaneColors()[6]));
int[] xArr = new int[] { x + 4, w + x - 5, x + w - 1, x };
int[] yArr = new int[] { y + h - 6, y + h - 6, y, y };
Polygon p1 = new Polygon(xArr, yArr, 4);
g2.fillPolygon(p1);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setColor(c1);
g2.drawLine(x, y, x + 4, y + h - 6);
g2.drawLine(w + x - 1, y, x + w - 5, y + h - 6);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT);
}
/**
* Draw a top tab at the given location and size with the given background color.
*
* @param x
* x location of the tab
* @param y
* y location of the tab
* @param w
* width of the tab
* @param h
* height of the tab
* @param g2
* graphics context
* @param color
* the background color of the tab
*/
private static void drawTopTab(int x, int y, int w, int h, Graphics2D g2, ColorUIResource color) {
double rTop = RapidLookAndFeel.CORNER_TAB_RADIUS * 0.67;
g2.setColor(color);
g2.fill(createTopTabShape(x + 1, y + 1, w - 1, h, rTop, true));
g2.setColor(Colors.TAB_BORDER);
g2.draw(createTopTabShape(x, y, w - 1, h, rTop, false));
}
/**
* Draw a left tab at the given location and size with the given background color.
*
* @param x
* x location of the tab
* @param y
* y location of the tab
* @param w
* width of the tab
* @param h
* height of the tab
* @param g2
* graphics context
* @param color
* the background color of the tab
*/
private static void drawLeftTab(int x, int y, int w, int h, Graphics2D g2, ColorUIResource color) {
double rTop = RapidLookAndFeel.CORNER_TAB_RADIUS * 0.67;
g2.setColor(color);
g2.fill(createLeftTabShape(x + 1, y + 1, w - 1, h, rTop, true));
g2.setColor(Colors.TAB_BORDER);
g2.draw(createLeftTabShape(x, y, w - 1, h, rTop, false));
}
/**
* Creates the shape for a top tab.
*
* @param x
* @param y
* @param w
* @param h
* @param rTop
* @param addBottom
* if {@code false}, the bottom line below the tab will not be added to the shape
* @return
*/
private static Path2D createTopTabShape(int x, int y, int w, int h, double rTop, boolean addBottom) {
Path2D path = new Path2D.Double();
path.append(new Line2D.Double(x, y + h - 1, x, y + rTop), true);
QuadCurve2D curve = new QuadCurve2D.Double(x, y + rTop, x, y, x + rTop, y);
path.append(curve, true);
path.append(new Line2D.Double(x + rTop, y, x + w - rTop, y), true);
curve = new QuadCurve2D.Double(x + w - rTop, y, x + w, y, x + w, y + rTop);
path.append(curve, true);
path.append(new Line2D.Double(x + w, y + rTop, x + w, y + h), true);
if (addBottom) {
path.append(new Line2D.Double(x + w, y + h - 1, x, y + h - 1), true);
}
return path;
}
/**
* Creates the shape for a left tab.
*
* @param x
* @param y
* @param w
* @param h
* @param rLeft
* @param addSide
* if {@code false}, the closing side line right of the tab will not be added to the
* shape
* @return
*/
private static Path2D createLeftTabShape(int x, int y, int w, int h, double rLeft, boolean addSide) {
Path2D path = new Path2D.Double();
path.append(new Line2D.Double(x + w, y + h, x + rLeft, y + h), true);
QuadCurve2D curve = new QuadCurve2D.Double(x + rLeft, y + h, x, y + h, x, y + h - rLeft);
path.append(curve, true);
path.append(new Line2D.Double(x, y + h - rLeft, x, y + rLeft), true);
curve = new QuadCurve2D.Double(x, y + rLeft, x, y, x + rLeft, y);
path.append(curve, true);
path.append(new Line2D.Double(x + rLeft, y, x + w, y), true);
if (addSide) {
path.append(new Line2D.Double(x + w, y, x + w, y + h - 1), true);
}
return path;
}
private void paintTabBorderFree(Graphics g, int tabPlacement, int tabIndex, int xp, int yp, int mw, int h) {
int x = xp + 2;
int y = yp;
int w = mw - 4;
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (tabPlacement == SwingConstants.BOTTOM) {
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[8]);
g.drawLine(x + 4, y + h - 1, x + w - 5, y + h - 1);
g.drawLine(x, y, x, y + h - 5);
g.drawLine(x + w - 1, y, x + w - 1, y + h - 4);
ColorUIResource c1 = RapidLookTools.getColors().getTabbedPaneColors()[9];
ColorUIResource c2 = RapidLookTools.getColors().getTabbedPaneColors()[20];
ColorUIResource c3 = RapidLookTools.getColors().getTabbedPaneColors()[10];
// left
g.setColor(c3);
g.drawLine(x + 2, y + h - 1, x, y + h - 3);
g.setColor(c1);
g.drawLine(x, y + h - 4, x + 3, y + h - 1);
g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
g.setColor(c2);
g.drawLine(x + 3, y + h - 2, x + 1, y + h - 4);
// right
g.setColor(c3);
g.drawLine(x + w - 1, y + h - 3, x + w - 3, y + h - 1);
g.setColor(c1);
g.drawLine(x + w - 4, y + h - 1, x + w - 1, y + h - 4);
g.drawLine(x + w - 2, y + h - 2, x + w - 2, y + h - 2);
g.setColor(c2);
g.drawLine(x + w - 4, y + h - 2, x + w - 2, y + h - 4);
if (tabIndex != this.rolloveredTabIndex) {
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[11]);
g.drawLine(x + 1, y, x + w - 2, y);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[12]);
g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[13]);
g.drawLine(x + 1, y + 2, x + w - 2, y + 2);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[14]);
g.drawLine(x + 1, y + 3, x + w - 2, y + 3);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[15]);
g.drawLine(x + 1, y + 4, x + w - 2, y + 4);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[16]);
g.drawLine(x + 1, y + 5, x + w - 2, y + 5);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[17]);
g.drawLine(x + 1, y + 6, x + w - 2, y + 6);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[18]);
g.fillRect(x + 1, y + 7, w - 2, h - 11);
g.drawLine(x + 2, y + h - 4, x + w - 3, y + h - 4);
g.drawLine(x + 3, y + h - 3, x + w - 4, y + h - 3);
g.drawLine(x + 4, y + h - 2, x + w - 5, y + h - 2);
} else {
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[18]);
g.drawLine(x + 1, y, x + w - 2, y);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[17]);
g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
g.drawLine(x + 1, y + 2, x + w - 2, y + 2);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[16]);
g.drawLine(x + 1, y + 3, x + w - 2, y + 3);
g.drawLine(x + 1, y + 4, x + w - 2, y + 4);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[15]);
g.drawLine(x + 1, y + 5, x + w - 2, y + 5);
g.drawLine(x + 1, y + 6, x + w - 2, y + 6);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[14]);
g.fillRect(x + 1, y + 7, w - 2, h - 11);
g.drawLine(x + 2, y + h - 4, x + w - 3, y + h - 4);
g.drawLine(x + 3, y + h - 3, x + w - 4, y + h - 3);
g.drawLine(x + 4, y + h - 2, x + w - 5, y + h - 2);
}
} else if (tabPlacement == SwingConstants.RIGHT) {
x -= 2;
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[8]);
g.drawLine(x, y, x + w - 5, y);
g.drawLine(x + w - 1, y + 4, x + w - 1, y + h - 1);
ColorUIResource c1 = RapidLookTools.getColors().getTabbedPaneColors()[9];
ColorUIResource c2 = RapidLookTools.getColors().getTabbedPaneColors()[19];
ColorUIResource c3 = RapidLookTools.getColors().getTabbedPaneColors()[10];
// right
g.setColor(c3);
g.drawLine(x + w - 1, y + 2, x + w - 3, y);
g.setColor(c1);
g.drawLine(x + w - 4, y, x + w - 1, y + 3);
g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
g.setColor(c2);
g.drawLine(x + w - 4, y + 1, x + w - 2, y + 3);
if (tabIndex != this.rolloveredTabIndex) {
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[11]);
g.drawLine(x, y + 1, x + w - 5, y + 1);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[12]);
g.drawLine(x, y + 2, x + w - 4, y + 2);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[13]);
g.drawLine(x, y + 3, x + w - 3, y + 3);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[14]);
g.drawLine(x, y + 4, x + w - 2, y + 4);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[15]);
g.drawLine(x, y + 5, x + w - 2, y + 5);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[16]);
g.drawLine(x, y + 6, x + w - 2, y + 6);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[17]);
g.drawLine(x, y + 7, x + w - 2, y + 7);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[18]);
g.fillRect(x, y + 8, w - 1, h - 8);
} else {
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[14]);
g.drawLine(x, y + 1, x + w - 5, y + 1);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[18]);
g.drawLine(x, y + 2, x + w - 4, y + 2);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[18]);
g.drawLine(x, y + 3, x + w - 3, y + 3);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[17]);
g.drawLine(x, y + 4, x + w - 2, y + 4);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[17]);
g.drawLine(x, y + 5, x + w - 2, y + 5);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[16]);
g.drawLine(x, y + 6, x + w - 2, y + 6);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[16]);
g.drawLine(x, y + 7, x + w - 2, y + 7);
g.setColor(RapidLookTools.getColors().getTabbedPaneColors()[15]);
g.fillRect(x, y + 8, w - 1, h - 8);
}
} else if (tabPlacement == SwingConstants.LEFT) {
w += 4;
if (tabIndex == rolloveredTabIndex) {
// highlight on hover
drawLeftTab(x, y, w, h, g2, Colors.TAB_BACKGROUND_HIGHLIGHT);
} else {
drawLeftTab(x, y, w, h, g2, Colors.TAB_BACKGROUND);
}
} else { // top
if (tabIndex == rolloveredTabIndex) {
// highlight on hover
drawTopTab(x, y, w, h, g2, Colors.TAB_BACKGROUND_HIGHLIGHT);
} else {
drawTopTab(x, y, w, h, g2, Colors.TAB_BACKGROUND);
}
}
g2.dispose();
}
@Override
protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) {
if (tabPane.getTabLayoutPolicy() != JTabbedPane.SCROLL_TAB_LAYOUT) {
if (isSelected) {
return -5;
}
}
return 0;
}
@Override
protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected) {
return 0;
}
protected void updateMouseOver(Point p) {
int roi = tabForCoordinate(this.tabPane, (int) p.getX(), (int) p.getY());
if (this.rolloveredTabIndex != roi) {
this.rolloveredTabIndex = roi;
this.tabPane.repaint();
}
}
@Override
public Insets getContentBorderInsets(int tabPlacement) {
return new Insets(1, 1, 2, 1);
}
@Override
protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title,
Rectangle textRect, boolean isSelected) {
// otherwise the tabs text would not have AA for some reason even though the rest of the
// components has AA without this
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
if (isSelected) {
font = font.deriveFont(Font.BOLD);
}
super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected);
}
/**
* Docking framework tabs use some weird dimensions so they get special treatment here
*
* @return {@code true} if it is a docking framework tab which should be reduced in size;
* {@code false} otherwise
*/
private boolean isDockingFrameworkTab() {
if (tabPane instanceof DockTabbedPane) {
return true;
}
if (tabPane instanceof TabHeader) {
TabHeader h = (TabHeader) tabPane;
if (h.getDockable() != null) {
return h.getDockable().getDockKey().isCloseEnabled();
}
}
return false;
}
}