--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/visual-panels/core/src/java/util/com/oracle/solaris/vp/util/swing/SleekTabbedPaneUI.java Thu May 24 04:16:47 2012 -0400
@@ -0,0 +1,420 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ */
+
+package com.oracle.solaris.vp.util.swing;
+
+import java.awt.*;
+import java.awt.geom.Area;
+import javax.swing.*;
+import javax.swing.plaf.*;
+import javax.swing.plaf.basic.BasicTabbedPaneUI;
+
+public class SleekTabbedPaneUI extends BasicTabbedPaneUI {
+ //
+ // Static data
+ //
+
+ // Default color of the border
+ static final Color _COLOR = new Color(163, 184, 203);
+
+ // Default color of the selected tab
+ static final Color _BORDER_COLOR = Color.DARK_GRAY;
+
+ // Default color of the inactive tabs
+ private static final Color _INACTIVE_COLOR =
+ UIManager.getColor("TabbedPane.background");
+
+ // Gap between tabs
+ private static final int TAB_GAP = 2;
+
+ // Arc of the tab corners
+ private static final int TAB_ARC = 8;
+
+ // Space around the contents of each tab, within the tab
+ private static final Insets TAB_INSETS = new Insets(2, 10, 0, 10);
+
+ // Additional space around selected tab
+ private static final Insets SELECTED_TAB_INSETS = new Insets(0, 0, 0, 0);
+
+ // Space around tab group
+ private static final int TAB_AREA_GAP = TAB_GAP;
+ private static final Insets TAB_AREA_INSETS_NO_BORDER =
+ new Insets(0, TAB_AREA_GAP, 0, TAB_AREA_GAP);
+ private static final Insets TAB_AREA_INSETS_BORDER =
+ new Insets(0, 0, 0, 0);
+
+ // Height of the solid bar running underneath tabs, above the content area
+ private static final int CONTENT_TOP_HEIGHT = 5;
+ private static final Insets CONTENT_INSETS_NO_BORDER =
+ new Insets(CONTENT_TOP_HEIGHT, 0, 0, 0);
+ private static final Insets CONTENT_INSETS_BORDER =
+ new Insets(CONTENT_TOP_HEIGHT, 1, 1, 1);
+
+ //
+ // Instance data
+ //
+
+ private Color color = _COLOR;
+ private Color borderColor = _BORDER_COLOR;
+ private Color contentBorderColor = _BORDER_COLOR;
+ private Color inactiveColor = _INACTIVE_COLOR;
+
+ private boolean drawContentBorder = false;
+
+ //
+ // BasicTabbedPaneUI methods
+ //
+
+ @Override
+ protected int calculateTabWidth(
+ int tabPlacement, int tabIndex, FontMetrics metrics) {
+
+ // Uniform tab widths
+ int width = 0;
+ for (int i = 0, n = tabPane.getTabCount(); i < n; i++) {
+ width = Math.max(width,
+ super.calculateTabWidth(tabPlacement, i, metrics));
+ }
+
+ return width + TAB_GAP + 1;
+ }
+
+ @Override
+ protected Insets getContentBorderInsets(int tabPlacement) {
+ return getDrawContentBorder() ?
+ CONTENT_INSETS_BORDER : CONTENT_INSETS_NO_BORDER;
+ }
+
+ @Override
+ protected int getTabLabelShiftY(
+ int tabPlacement, int tabIndex, boolean isSelected) {
+
+ // Don't offset the label of the selected tab
+ return 0;
+ }
+
+ @Override
+ protected void installDefaults() {
+ super.installDefaults();
+
+ // Let the JTabbedPane determine it's own opacity
+ UIManager.put("TabbedPane.contentOpaque", false);
+
+ tabAreaInsets = getDrawContentBorder() ?
+ TAB_AREA_INSETS_BORDER : TAB_AREA_INSETS_NO_BORDER;
+
+ tabInsets = TAB_INSETS;
+ selectedTabPadInsets = SELECTED_TAB_INSETS;
+
+ // Embolden font
+ tabPane.setFont(tabPane.getFont().deriveFont(Font.BOLD));
+ }
+
+ @Override
+ protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement,
+ int selectedIndex, int x, int y, int w, int h) {
+
+ if (getDrawContentBorder()) {
+ Graphics2D g2 = (Graphics2D)g;
+ g2.setPaint(getContentBorderColor());
+ g2.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ }
+ }
+
+ @Override
+ protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement,
+ int selectedIndex, int x, int y, int w, int h) {
+
+ if (getDrawContentBorder()) {
+ Graphics2D g2 = (Graphics2D)g;
+ g2.setPaint(getContentBorderColor());
+ g2.drawLine(x, y, x, y + h - 1);
+ }
+ }
+
+ @Override
+ protected void paintContentBorderRightEdge(Graphics g, int tabPlacement,
+ int selectedIndex, int x, int y, int w, int h) {
+
+ if (getDrawContentBorder()) {
+ Graphics2D g2 = (Graphics2D)g;
+ g2.setPaint(getContentBorderColor());
+ g2.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+ }
+ }
+
+ @Override
+ protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
+ int selectedIndex, int x, int y, int w, int h) {
+
+ Graphics2D g2 = (Graphics2D)g;
+
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ h = CONTENT_TOP_HEIGHT;
+
+ if (h > 0) {
+ Color color = getColor();
+
+ // Paint the background
+ g2.setPaint(color);
+ g2.fillRect(x, y, w, h - 1);
+
+ if (h > 2) {
+ // Paint a light gradient
+ g2.setComposite(AlphaComposite.getInstance(
+ AlphaComposite.SRC_OVER, .25f));
+ Paint paint = new GradientPaint(
+ x, y, color, x, y + h - 1, Color.white, false);
+ g2.setPaint(paint);
+ g2.fillRect(x, y, w, h - 1);
+
+ // Reset alpha
+ g2.setPaintMode();
+ }
+
+ g2.setColor(getBorderColor());
+
+ // Draw top line
+ if (selectedIndex >= 0) {
+ Rectangle selectedRect = getTabBounds(selectedIndex, calcRect);
+ int sWidth = selectedRect.width - TAB_GAP - 1;
+
+ g2.drawLine(x, y, selectedRect.x, y);
+ g2.drawLine(selectedRect.x + sWidth, y, x + w - 1, y);
+ } else {
+ g2.drawLine(x, y, x + w - 1, y);
+ }
+
+ if (h > 1) {
+ // Draw bottom line
+ g2.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ }
+ }
+ }
+
+ @Override
+ protected void paintFocusIndicator(Graphics g, int tabPlacement,
+ Rectangle[] rects, int tabIndex, Rectangle iconRect, Rectangle textRect,
+ boolean isSelected) {
+
+ Rectangle tabRect = rects[tabIndex];
+ Rectangle tmp = (Rectangle)tabRect.clone();
+
+ tmp.width -= TAB_GAP;
+ rects[tabIndex] = tmp;
+
+ super.paintFocusIndicator(
+ g, tabPlacement, rects, tabIndex, iconRect, textRect, isSelected);
+
+ rects[tabIndex] = tabRect;
+ }
+
+ @Override
+ protected void paintIcon(Graphics g, int tabPlacement,
+ int tabIndex, Icon icon, Rectangle iconRect, boolean isSelected) {
+ if (icon != null) {
+ Rectangle tmp = (Rectangle)iconRect.clone();
+
+ // The superclass centers the icon, so restore insets
+ tmp.x -= (tabInsets.right - tabInsets.left) / 2;
+ tmp.y -= (tabInsets.bottom - tabInsets.top) / 2;
+
+ // The superclass centers the icon, so account for gap
+ tmp.x -= (TAB_GAP + 1) / 2;
+
+ super.paintIcon(g, tabPlacement, tabIndex, icon, tmp, isSelected);
+ }
+ }
+
+ @Override
+ protected void paintTabBackground(Graphics g, int tabPlacement,
+ int tabIndex, int x, int y, int w, int h, boolean isSelected) {
+
+ Graphics2D g2 = (Graphics2D)g;
+
+ Color color = isSelected ? getColor() : getInactiveColor();
+
+ Shape clip = g2.getClip();
+ Area aClip = new Area(clip);
+ aClip.intersect(new Area(new Rectangle(x, y, w, h)));
+ g2.setClip(aClip);
+
+ // Paint the background of the tab
+ g2.setColor(color);
+ g2.fillRoundRect(x, y, w - TAB_GAP - 1, (3 * h) / 2, TAB_ARC, TAB_ARC);
+
+ // Paint the light (top) gradient of the tab
+ g2.setComposite(AlphaComposite.getInstance(
+ AlphaComposite.SRC_OVER, .8f));
+ Paint paint = new GradientPaint(
+ x, y, Color.WHITE, x, y + ((float)h / 2f), color, false);
+ g2.setPaint(paint);
+ g2.fillRoundRect(x, y, w - TAB_GAP - 1, (3 * h) / 2, TAB_ARC, TAB_ARC);
+
+ g2.setClip(clip);
+ }
+
+ @Override
+ protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
+ int x, int y, int w, int h, boolean isSelected) {
+
+ Graphics2D g2 = (Graphics2D)g;
+
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ Shape clip = g2.getClip();
+ Area aClip = new Area(clip);
+ aClip.intersect(new Area(new Rectangle(x, y, w, h)));
+ g2.setClip(aClip);
+
+ g2.setColor(getBorderColor());
+ g2.drawRoundRect(x, y, w - TAB_GAP - 1, (3 * h) / 2, TAB_ARC, TAB_ARC);
+
+ // Paint a shadow on the sides
+ g2.setComposite(AlphaComposite.getInstance(
+ AlphaComposite.SRC_OVER, .25f));
+ g2.setColor(Color.BLACK);
+ g2.drawRoundRect(
+ x + 1, y, w - TAB_GAP - 3, (3 * h) / 2, TAB_ARC, TAB_ARC);
+
+ // Reset alpha
+ g2.setPaintMode();
+ g2.setClip(clip);
+ }
+
+ @Override
+ protected void paintText(Graphics g, int tabPlacement, Font font,
+ FontMetrics metrics, int tabIndex, String title, Rectangle textRect,
+ boolean isSelected) {
+
+ Rectangle tmp = (Rectangle)textRect.clone();
+
+ // The superclass centers the text, so restore insets
+ tmp.x -= (tabInsets.right - tabInsets.left) / 2;
+ tmp.y -= (tabInsets.bottom - tabInsets.top) / 2;
+
+ // The superclass centers the text, so account for gap
+ tmp.x -= (TAB_GAP + 1) / 2;
+
+ super.paintText(g, tabPlacement, font, metrics,
+ tabIndex, title, tmp, isSelected);
+ }
+
+ //
+ // SleekTabbedPaneUI methods
+ //
+
+ public Color getBorderColor() {
+ return borderColor;
+ }
+
+ public Color getContentBorderColor() {
+ return contentBorderColor;
+ }
+
+ public Color getColor() {
+ return color;
+ }
+
+ public boolean getDrawContentBorder() {
+ return drawContentBorder;
+ }
+
+ public Color getInactiveColor() {
+ return inactiveColor;
+ }
+
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ public void setContentBorderColor(Color contentBorderColor) {
+ this.contentBorderColor = contentBorderColor;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ public void setDrawContentBorder(boolean drawContentBorder) {
+ this.drawContentBorder = drawContentBorder;
+ }
+
+ public void setInactiveColor(Color inactiveColor) {
+ this.inactiveColor = inactiveColor;
+ }
+
+ //
+ // Static methods
+ //
+
+ public static ComponentUI createUI(JComponent c) {
+ return new SleekTabbedPaneUI();
+ }
+
+ public static void main(String[] args) {
+ Class[] uis = {
+ null, SleekTabbedPaneUI.class
+ };
+
+ int[] placements = {
+ JTabbedPane.TOP,
+ JTabbedPane.LEFT,
+ };
+
+ for (int k = 0; k < uis.length; k++) {
+ for (int i = 0; i < placements.length; i++) {
+ JTabbedPane tabs = new JTabbedPane();
+
+ if (uis[k] != null) {
+ try {
+ tabs.setUI((TabbedPaneUI)uis[k].newInstance());
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ tabs.setTabPlacement(placements[i]);
+
+ for (int j = 0; j < 5; j++) {
+ tabs.addTab("Tab " + j, new JLabel("Label " + j));
+ }
+
+ JFrame frame = new JFrame();
+ Container c = frame.getContentPane();
+ c.setLayout(new BorderLayout());
+ c.add(tabs, BorderLayout.CENTER);
+ frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+ frame.pack();
+ frame.setVisible(true);
+
+ frame.setSize(new Dimension(300, 300));
+ }
+ }
+ }
+}