blob: ce2408ff623a0ef29ff94f51b85d2e176a43f553 [file] [log] [blame]
/*
* Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.java.swing.plaf.motif;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import java.io.Serializable;
/**
* A Motif L&F implementation of TabbedPaneUI.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is appropriate
* for short term storage or RMI between applications running the same
* version of Swing. A future release of Swing will provide support for
* long term persistence.
*
* @author Amy Fowler
* @author Philip Milne
*/
public class MotifTabbedPaneUI extends BasicTabbedPaneUI
{
// Instance variables initialized at installation
protected Color unselectedTabBackground;
protected Color unselectedTabForeground;
protected Color unselectedTabShadow;
protected Color unselectedTabHighlight;
// UI creation
public static ComponentUI createUI(JComponent tabbedPane) {
return new MotifTabbedPaneUI();
}
// UI Installation/De-installation
protected void installDefaults() {
super.installDefaults();
unselectedTabBackground = UIManager.getColor("TabbedPane.unselectedTabBackground");
unselectedTabForeground = UIManager.getColor("TabbedPane.unselectedTabForeground");
unselectedTabShadow = UIManager.getColor("TabbedPane.unselectedTabShadow");
unselectedTabHighlight = UIManager.getColor("TabbedPane.unselectedTabHighlight");
}
protected void uninstallDefaults() {
super.uninstallDefaults();
unselectedTabBackground = null;
unselectedTabForeground = null;
unselectedTabShadow = null;
unselectedTabHighlight = null;
}
// UI Rendering
protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
int selectedIndex,
int x, int y, int w, int h) {
Rectangle selRect = selectedIndex < 0? null :
getTabBounds(selectedIndex, calcRect);
g.setColor(lightHighlight);
// Draw unbroken line if tabs are not on TOP, OR
// selected tab is not visible (SCROLL_TAB_LAYOUT)
//
if (tabPlacement != TOP || selectedIndex < 0 ||
(selRect.x < x || selRect.x > x + w)) {
g.drawLine(x, y, x+w-2, y);
} else {
// Break line to show visual connection to selected tab
g.drawLine(x, y, selRect.x - 1, y);
if (selRect.x + selRect.width < x + w - 2) {
g.drawLine(selRect.x + selRect.width, y,
x+w-2, y);
}
}
}
protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement,
int selectedIndex,
int x, int y, int w, int h) {
Rectangle selRect = selectedIndex < 0? null :
getTabBounds(selectedIndex, calcRect);
g.setColor(shadow);
// Draw unbroken line if tabs are not on BOTTOM, OR
// selected tab is not visible (SCROLL_TAB_LAYOUT)
//
if (tabPlacement != BOTTOM || selectedIndex < 0 ||
(selRect.x < x || selRect.x > x + w)) {
g.drawLine(x+1, y+h-1, x+w-1, y+h-1);
} else {
// Break line to show visual connection to selected tab
g.drawLine(x+1, y+h-1, selRect.x - 1, y+h-1);
if (selRect.x + selRect.width < x + w - 2) {
g.drawLine(selRect.x + selRect.width, y+h-1, x+w-2, y+h-1);
}
}
}
protected void paintContentBorderRightEdge(Graphics g, int tabPlacement,
int selectedIndex,
int x, int y, int w, int h) {
Rectangle selRect = selectedIndex < 0? null :
getTabBounds(selectedIndex, calcRect);
g.setColor(shadow);
// Draw unbroken line if tabs are not on RIGHT, OR
// selected tab is not visible (SCROLL_TAB_LAYOUT)
//
if (tabPlacement != RIGHT || selectedIndex < 0 ||
(selRect.y < y || selRect.y > y + h)) {
g.drawLine(x+w-1, y+1, x+w-1, y+h-1);
} else {
// Break line to show visual connection to selected tab
g.drawLine(x+w-1, y+1, x+w-1, selRect.y - 1);
if (selRect.y + selRect.height < y + h - 2 ) {
g.drawLine(x+w-1, selRect.y + selRect.height,
x+w-1, y+h-2);
}
}
}
protected void paintTabBackground(Graphics g,
int tabPlacement, int tabIndex,
int x, int y, int w, int h,
boolean isSelected ) {
g.setColor(isSelected? tabPane.getBackgroundAt(tabIndex) : unselectedTabBackground);
switch(tabPlacement) {
case LEFT:
g.fillRect(x+1, y+1, w-1, h-2);
break;
case RIGHT:
g.fillRect(x, y+1, w-1, h-2);
break;
case BOTTOM:
g.fillRect(x+1, y, w-2, h-3);
g.drawLine(x+2, y+h-3, x+w-3, y+h-3);
g.drawLine(x+3, y+h-2, x+w-4, y+h-2);
break;
case TOP:
default:
g.fillRect(x+1, y+3, w-2, h-3);
g.drawLine(x+2, y+2, x+w-3, y+2);
g.drawLine(x+3, y+1, x+w-4, y+1);
}
}
protected void paintTabBorder(Graphics g,
int tabPlacement, int tabIndex,
int x, int y, int w, int h,
boolean isSelected) {
g.setColor(isSelected? lightHighlight : unselectedTabHighlight);
switch(tabPlacement) {
case LEFT:
g.drawLine(x, y+2, x, y+h-3);
g.drawLine(x+1, y+1, x+1, y+2);
g.drawLine(x+2, y, x+2, y+1);
g.drawLine(x+3, y, x+w-1, y);
g.setColor(isSelected? shadow : unselectedTabShadow);
g.drawLine(x+1, y+h-3, x+1, y+h-2);
g.drawLine(x+2, y+h-2, x+2, y+h-1);
g.drawLine(x+3, y+h-1, x+w-1, y+h-1);
break;
case RIGHT:
g.drawLine(x, y, x+w-3, y);
g.setColor(isSelected? shadow : unselectedTabShadow);
g.drawLine(x+w-3, y, x+w-3, y+1);
g.drawLine(x+w-2, y+1, x+w-2, y+2);
g.drawLine(x+w-1, y+2, x+w-1, y+h-3);
g.drawLine(x+w-2, y+h-3, x+w-2, y+h-2);
g.drawLine(x+w-3, y+h-2, x+w-3, y+h-1);
g.drawLine(x, y+h-1, x+w-3, y+h-1);
break;
case BOTTOM:
g.drawLine(x, y, x, y+h-3);
g.drawLine(x+1, y+h-3, x+1, y+h-2);
g.drawLine(x+2, y+h-2, x+2, y+h-1);
g.setColor(isSelected? shadow : unselectedTabShadow);
g.drawLine(x+3, y+h-1, x+w-4, y+h-1);
g.drawLine(x+w-3, y+h-2, x+w-3, y+h-1);
g.drawLine(x+w-2, y+h-3, x+w-2, y+h-2);
g.drawLine(x+w-1, y, x+w-1, y+h-3);
break;
case TOP:
default:
g.drawLine(x, y+2, x, y+h-1);
g.drawLine(x+1, y+1, x+1, y+2);
g.drawLine(x+2, y, x+2, y+1);
g.drawLine(x+3, y, x+w-4, y);
g.setColor(isSelected? shadow : unselectedTabShadow);
g.drawLine(x+w-3, y, x+w-3, y+1);
g.drawLine(x+w-2, y+1, x+w-2, y+2);
g.drawLine(x+w-1, y+2, x+w-1, y+h-1);
}
}
protected void paintFocusIndicator(Graphics g, int tabPlacement,
Rectangle[] rects, int tabIndex,
Rectangle iconRect, Rectangle textRect,
boolean isSelected) {
Rectangle tabRect = rects[tabIndex];
if (tabPane.hasFocus() && isSelected) {
int x, y, w, h;
g.setColor(focus);
switch(tabPlacement) {
case LEFT:
x = tabRect.x + 3;
y = tabRect.y + 3;
w = tabRect.width - 6;
h = tabRect.height - 7;
break;
case RIGHT:
x = tabRect.x + 2;
y = tabRect.y + 3;
w = tabRect.width - 6;
h = tabRect.height - 7;
break;
case BOTTOM:
x = tabRect.x + 3;
y = tabRect.y + 2;
w = tabRect.width - 7;
h = tabRect.height - 6;
break;
case TOP:
default:
x = tabRect.x + 3;
y = tabRect.y + 3;
w = tabRect.width - 7;
h = tabRect.height - 6;
}
g.drawRect(x, y, w, h);
}
}
protected int getTabRunIndent(int tabPlacement, int run) {
return run*3;
}
protected int getTabRunOverlay(int tabPlacement) {
tabRunOverlay = (tabPlacement == LEFT || tabPlacement == RIGHT)?
(int)Math.round((float)maxTabWidth * .10) :
(int)Math.round((float)maxTabHeight * .22);
// Ensure that runover lay is not more than insets
// 2 pixel offset is set from insets to each run
switch(tabPlacement) {
case LEFT:
if( tabRunOverlay > tabInsets.right - 2 )
tabRunOverlay = tabInsets.right - 2 ;
break;
case RIGHT:
if( tabRunOverlay > tabInsets.left - 2 )
tabRunOverlay = tabInsets.left - 2 ;
break;
case TOP:
if( tabRunOverlay > tabInsets.bottom - 2 )
tabRunOverlay = tabInsets.bottom - 2 ;
break;
case BOTTOM:
if( tabRunOverlay > tabInsets.top - 2 )
tabRunOverlay = tabInsets.top - 2 ;
break;
}
return tabRunOverlay;
}
}