You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1041 lines
32 KiB
1041 lines
32 KiB
/*
|
|
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
package javax.swing.plaf.metal;
|
|
|
|
import sun.swing.SwingUtilities2;
|
|
import sun.awt.SunToolkit;
|
|
import java.awt.*;
|
|
import java.awt.event.*;
|
|
import java.beans.*;
|
|
import javax.swing.*;
|
|
import javax.swing.border.*;
|
|
import javax.swing.event.InternalFrameEvent;
|
|
import javax.swing.plaf.*;
|
|
import javax.swing.plaf.basic.*;
|
|
import java.util.Locale;
|
|
import javax.accessibility.*;
|
|
|
|
|
|
/**
|
|
* Class that manages a JLF awt.Window-descendant class's title bar.
|
|
* <p>
|
|
* This class assumes it will be created with a particular window
|
|
* decoration style, and that if the style changes, a new one will
|
|
* be created.
|
|
*
|
|
* @author Terry Kellerman
|
|
* @since 1.4
|
|
*/
|
|
class MetalTitlePane extends JComponent {
|
|
private static final Border handyEmptyBorder = new EmptyBorder(0,0,0,0);
|
|
private static final int IMAGE_HEIGHT = 16;
|
|
private static final int IMAGE_WIDTH = 16;
|
|
|
|
/**
|
|
* PropertyChangeListener added to the JRootPane.
|
|
*/
|
|
private PropertyChangeListener propertyChangeListener;
|
|
|
|
/**
|
|
* JMenuBar, typically renders the system menu items.
|
|
*/
|
|
private JMenuBar menuBar;
|
|
/**
|
|
* Action used to close the Window.
|
|
*/
|
|
private Action closeAction;
|
|
|
|
/**
|
|
* Action used to iconify the Frame.
|
|
*/
|
|
private Action iconifyAction;
|
|
|
|
/**
|
|
* Action to restore the Frame size.
|
|
*/
|
|
private Action restoreAction;
|
|
|
|
/**
|
|
* Action to restore the Frame size.
|
|
*/
|
|
private Action maximizeAction;
|
|
|
|
/**
|
|
* Button used to maximize or restore the Frame.
|
|
*/
|
|
private JButton toggleButton;
|
|
|
|
/**
|
|
* Button used to maximize or restore the Frame.
|
|
*/
|
|
private JButton iconifyButton;
|
|
|
|
/**
|
|
* Button used to maximize or restore the Frame.
|
|
*/
|
|
private JButton closeButton;
|
|
|
|
/**
|
|
* Icon used for toggleButton when window is normal size.
|
|
*/
|
|
private Icon maximizeIcon;
|
|
|
|
/**
|
|
* Icon used for toggleButton when window is maximized.
|
|
*/
|
|
private Icon minimizeIcon;
|
|
|
|
/**
|
|
* Image used for the system menu icon
|
|
*/
|
|
private Image systemIcon;
|
|
|
|
/**
|
|
* Listens for changes in the state of the Window listener to update
|
|
* the state of the widgets.
|
|
*/
|
|
private WindowListener windowListener;
|
|
|
|
/**
|
|
* Window we're currently in.
|
|
*/
|
|
private Window window;
|
|
|
|
/**
|
|
* JRootPane rendering for.
|
|
*/
|
|
private JRootPane rootPane;
|
|
|
|
/**
|
|
* Room remaining in title for bumps.
|
|
*/
|
|
private int buttonsWidth;
|
|
|
|
/**
|
|
* Buffered Frame.state property. As state isn't bound, this is kept
|
|
* to determine when to avoid updating widgets.
|
|
*/
|
|
private int state;
|
|
|
|
/**
|
|
* MetalRootPaneUI that created us.
|
|
*/
|
|
private MetalRootPaneUI rootPaneUI;
|
|
|
|
|
|
// Colors
|
|
private Color inactiveBackground = UIManager.getColor("inactiveCaption");
|
|
private Color inactiveForeground = UIManager.getColor("inactiveCaptionText");
|
|
private Color inactiveShadow = UIManager.getColor("inactiveCaptionBorder");
|
|
private Color activeBumpsHighlight = MetalLookAndFeel.getPrimaryControlHighlight();
|
|
private Color activeBumpsShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
|
|
private Color activeBackground = null;
|
|
private Color activeForeground = null;
|
|
private Color activeShadow = null;
|
|
|
|
// Bumps
|
|
private MetalBumps activeBumps
|
|
= new MetalBumps( 0, 0,
|
|
activeBumpsHighlight,
|
|
activeBumpsShadow,
|
|
MetalLookAndFeel.getPrimaryControl() );
|
|
private MetalBumps inactiveBumps
|
|
= new MetalBumps( 0, 0,
|
|
MetalLookAndFeel.getControlHighlight(),
|
|
MetalLookAndFeel.getControlDarkShadow(),
|
|
MetalLookAndFeel.getControl() );
|
|
|
|
|
|
public MetalTitlePane(JRootPane root, MetalRootPaneUI ui) {
|
|
this.rootPane = root;
|
|
rootPaneUI = ui;
|
|
|
|
state = -1;
|
|
|
|
installSubcomponents();
|
|
determineColors();
|
|
installDefaults();
|
|
|
|
setLayout(createLayout());
|
|
}
|
|
|
|
/**
|
|
* Uninstalls the necessary state.
|
|
*/
|
|
private void uninstall() {
|
|
uninstallListeners();
|
|
window = null;
|
|
removeAll();
|
|
}
|
|
|
|
/**
|
|
* Installs the necessary listeners.
|
|
*/
|
|
private void installListeners() {
|
|
if (window != null) {
|
|
windowListener = createWindowListener();
|
|
window.addWindowListener(windowListener);
|
|
propertyChangeListener = createWindowPropertyChangeListener();
|
|
window.addPropertyChangeListener(propertyChangeListener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Uninstalls the necessary listeners.
|
|
*/
|
|
private void uninstallListeners() {
|
|
if (window != null) {
|
|
window.removeWindowListener(windowListener);
|
|
window.removePropertyChangeListener(propertyChangeListener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the <code>WindowListener</code> to add to the
|
|
* <code>Window</code>.
|
|
*/
|
|
private WindowListener createWindowListener() {
|
|
return new WindowHandler();
|
|
}
|
|
|
|
/**
|
|
* Returns the <code>PropertyChangeListener</code> to install on
|
|
* the <code>Window</code>.
|
|
*/
|
|
private PropertyChangeListener createWindowPropertyChangeListener() {
|
|
return new PropertyChangeHandler();
|
|
}
|
|
|
|
/**
|
|
* Returns the <code>JRootPane</code> this was created for.
|
|
*/
|
|
public JRootPane getRootPane() {
|
|
return rootPane;
|
|
}
|
|
|
|
/**
|
|
* Returns the decoration style of the <code>JRootPane</code>.
|
|
*/
|
|
private int getWindowDecorationStyle() {
|
|
return getRootPane().getWindowDecorationStyle();
|
|
}
|
|
|
|
public void addNotify() {
|
|
super.addNotify();
|
|
|
|
uninstallListeners();
|
|
|
|
window = SwingUtilities.getWindowAncestor(this);
|
|
if (window != null) {
|
|
if (window instanceof Frame) {
|
|
setState(((Frame)window).getExtendedState());
|
|
}
|
|
else {
|
|
setState(0);
|
|
}
|
|
setActive(window.isActive());
|
|
installListeners();
|
|
updateSystemIcon();
|
|
}
|
|
}
|
|
|
|
public void removeNotify() {
|
|
super.removeNotify();
|
|
|
|
uninstallListeners();
|
|
window = null;
|
|
}
|
|
|
|
/**
|
|
* Adds any sub-Components contained in the <code>MetalTitlePane</code>.
|
|
*/
|
|
private void installSubcomponents() {
|
|
int decorationStyle = getWindowDecorationStyle();
|
|
if (decorationStyle == JRootPane.FRAME) {
|
|
createActions();
|
|
menuBar = createMenuBar();
|
|
add(menuBar);
|
|
createButtons();
|
|
add(iconifyButton);
|
|
add(toggleButton);
|
|
add(closeButton);
|
|
} else if (decorationStyle == JRootPane.PLAIN_DIALOG ||
|
|
decorationStyle == JRootPane.INFORMATION_DIALOG ||
|
|
decorationStyle == JRootPane.ERROR_DIALOG ||
|
|
decorationStyle == JRootPane.COLOR_CHOOSER_DIALOG ||
|
|
decorationStyle == JRootPane.FILE_CHOOSER_DIALOG ||
|
|
decorationStyle == JRootPane.QUESTION_DIALOG ||
|
|
decorationStyle == JRootPane.WARNING_DIALOG) {
|
|
createActions();
|
|
createButtons();
|
|
add(closeButton);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determines the Colors to draw with.
|
|
*/
|
|
private void determineColors() {
|
|
switch (getWindowDecorationStyle()) {
|
|
case JRootPane.FRAME:
|
|
activeBackground = UIManager.getColor("activeCaption");
|
|
activeForeground = UIManager.getColor("activeCaptionText");
|
|
activeShadow = UIManager.getColor("activeCaptionBorder");
|
|
break;
|
|
case JRootPane.ERROR_DIALOG:
|
|
activeBackground = UIManager.getColor(
|
|
"OptionPane.errorDialog.titlePane.background");
|
|
activeForeground = UIManager.getColor(
|
|
"OptionPane.errorDialog.titlePane.foreground");
|
|
activeShadow = UIManager.getColor(
|
|
"OptionPane.errorDialog.titlePane.shadow");
|
|
break;
|
|
case JRootPane.QUESTION_DIALOG:
|
|
case JRootPane.COLOR_CHOOSER_DIALOG:
|
|
case JRootPane.FILE_CHOOSER_DIALOG:
|
|
activeBackground = UIManager.getColor(
|
|
"OptionPane.questionDialog.titlePane.background");
|
|
activeForeground = UIManager.getColor(
|
|
"OptionPane.questionDialog.titlePane.foreground");
|
|
activeShadow = UIManager.getColor(
|
|
"OptionPane.questionDialog.titlePane.shadow");
|
|
break;
|
|
case JRootPane.WARNING_DIALOG:
|
|
activeBackground = UIManager.getColor(
|
|
"OptionPane.warningDialog.titlePane.background");
|
|
activeForeground = UIManager.getColor(
|
|
"OptionPane.warningDialog.titlePane.foreground");
|
|
activeShadow = UIManager.getColor(
|
|
"OptionPane.warningDialog.titlePane.shadow");
|
|
break;
|
|
case JRootPane.PLAIN_DIALOG:
|
|
case JRootPane.INFORMATION_DIALOG:
|
|
default:
|
|
activeBackground = UIManager.getColor("activeCaption");
|
|
activeForeground = UIManager.getColor("activeCaptionText");
|
|
activeShadow = UIManager.getColor("activeCaptionBorder");
|
|
break;
|
|
}
|
|
activeBumps.setBumpColors(activeBumpsHighlight, activeBumpsShadow,
|
|
activeBackground);
|
|
}
|
|
|
|
/**
|
|
* Installs the fonts and necessary properties on the MetalTitlePane.
|
|
*/
|
|
private void installDefaults() {
|
|
setFont(UIManager.getFont("InternalFrame.titleFont", getLocale()));
|
|
}
|
|
|
|
/**
|
|
* Uninstalls any previously installed UI values.
|
|
*/
|
|
private void uninstallDefaults() {
|
|
}
|
|
|
|
/**
|
|
* Returns the <code>JMenuBar</code> displaying the appropriate
|
|
* system menu items.
|
|
*/
|
|
protected JMenuBar createMenuBar() {
|
|
menuBar = new SystemMenuBar();
|
|
menuBar.setFocusable(false);
|
|
menuBar.setBorderPainted(true);
|
|
menuBar.add(createMenu());
|
|
return menuBar;
|
|
}
|
|
|
|
/**
|
|
* Closes the Window.
|
|
*/
|
|
private void close() {
|
|
Window window = getWindow();
|
|
|
|
if (window != null) {
|
|
window.dispatchEvent(new WindowEvent(
|
|
window, WindowEvent.WINDOW_CLOSING));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Iconifies the Frame.
|
|
*/
|
|
private void iconify() {
|
|
Frame frame = getFrame();
|
|
if (frame != null) {
|
|
frame.setExtendedState(state | Frame.ICONIFIED);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Maximizes the Frame.
|
|
*/
|
|
private void maximize() {
|
|
Frame frame = getFrame();
|
|
if (frame != null) {
|
|
frame.setExtendedState(state | Frame.MAXIMIZED_BOTH);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Restores the Frame size.
|
|
*/
|
|
private void restore() {
|
|
Frame frame = getFrame();
|
|
|
|
if (frame == null) {
|
|
return;
|
|
}
|
|
|
|
if ((state & Frame.ICONIFIED) != 0) {
|
|
frame.setExtendedState(state & ~Frame.ICONIFIED);
|
|
} else {
|
|
frame.setExtendedState(state & ~Frame.MAXIMIZED_BOTH);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create the <code>Action</code>s that get associated with the
|
|
* buttons and menu items.
|
|
*/
|
|
private void createActions() {
|
|
closeAction = new CloseAction();
|
|
if (getWindowDecorationStyle() == JRootPane.FRAME) {
|
|
iconifyAction = new IconifyAction();
|
|
restoreAction = new RestoreAction();
|
|
maximizeAction = new MaximizeAction();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the <code>JMenu</code> displaying the appropriate menu items
|
|
* for manipulating the Frame.
|
|
*/
|
|
private JMenu createMenu() {
|
|
JMenu menu = new JMenu("");
|
|
if (getWindowDecorationStyle() == JRootPane.FRAME) {
|
|
addMenuItems(menu);
|
|
}
|
|
return menu;
|
|
}
|
|
|
|
/**
|
|
* Adds the necessary <code>JMenuItem</code>s to the passed in menu.
|
|
*/
|
|
private void addMenuItems(JMenu menu) {
|
|
Locale locale = getRootPane().getLocale();
|
|
JMenuItem mi = menu.add(restoreAction);
|
|
int mnemonic = MetalUtils.getInt("MetalTitlePane.restoreMnemonic", -1);
|
|
|
|
if (mnemonic != -1) {
|
|
mi.setMnemonic(mnemonic);
|
|
}
|
|
|
|
mi = menu.add(iconifyAction);
|
|
mnemonic = MetalUtils.getInt("MetalTitlePane.iconifyMnemonic", -1);
|
|
if (mnemonic != -1) {
|
|
mi.setMnemonic(mnemonic);
|
|
}
|
|
|
|
if (Toolkit.getDefaultToolkit().isFrameStateSupported(
|
|
Frame.MAXIMIZED_BOTH)) {
|
|
mi = menu.add(maximizeAction);
|
|
mnemonic =
|
|
MetalUtils.getInt("MetalTitlePane.maximizeMnemonic", -1);
|
|
if (mnemonic != -1) {
|
|
mi.setMnemonic(mnemonic);
|
|
}
|
|
}
|
|
|
|
menu.add(new JSeparator());
|
|
|
|
mi = menu.add(closeAction);
|
|
mnemonic = MetalUtils.getInt("MetalTitlePane.closeMnemonic", -1);
|
|
if (mnemonic != -1) {
|
|
mi.setMnemonic(mnemonic);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a <code>JButton</code> appropriate for placement on the
|
|
* TitlePane.
|
|
*/
|
|
private JButton createTitleButton() {
|
|
JButton button = new JButton();
|
|
|
|
button.setFocusPainted(false);
|
|
button.setFocusable(false);
|
|
button.setOpaque(true);
|
|
return button;
|
|
}
|
|
|
|
/**
|
|
* Creates the Buttons that will be placed on the TitlePane.
|
|
*/
|
|
private void createButtons() {
|
|
closeButton = createTitleButton();
|
|
closeButton.setAction(closeAction);
|
|
closeButton.setText(null);
|
|
closeButton.putClientProperty("paintActive", Boolean.TRUE);
|
|
closeButton.setBorder(handyEmptyBorder);
|
|
closeButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY,
|
|
"Close");
|
|
closeButton.setIcon(UIManager.getIcon("InternalFrame.closeIcon"));
|
|
|
|
if (getWindowDecorationStyle() == JRootPane.FRAME) {
|
|
maximizeIcon = UIManager.getIcon("InternalFrame.maximizeIcon");
|
|
minimizeIcon = UIManager.getIcon("InternalFrame.minimizeIcon");
|
|
|
|
iconifyButton = createTitleButton();
|
|
iconifyButton.setAction(iconifyAction);
|
|
iconifyButton.setText(null);
|
|
iconifyButton.putClientProperty("paintActive", Boolean.TRUE);
|
|
iconifyButton.setBorder(handyEmptyBorder);
|
|
iconifyButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY,
|
|
"Iconify");
|
|
iconifyButton.setIcon(UIManager.getIcon("InternalFrame.iconifyIcon"));
|
|
|
|
toggleButton = createTitleButton();
|
|
toggleButton.setAction(restoreAction);
|
|
toggleButton.putClientProperty("paintActive", Boolean.TRUE);
|
|
toggleButton.setBorder(handyEmptyBorder);
|
|
toggleButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY,
|
|
"Maximize");
|
|
toggleButton.setIcon(maximizeIcon);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the <code>LayoutManager</code> that should be installed on
|
|
* the <code>MetalTitlePane</code>.
|
|
*/
|
|
private LayoutManager createLayout() {
|
|
return new TitlePaneLayout();
|
|
}
|
|
|
|
/**
|
|
* Updates state dependant upon the Window's active state.
|
|
*/
|
|
private void setActive(boolean isActive) {
|
|
Boolean activeB = isActive ? Boolean.TRUE : Boolean.FALSE;
|
|
|
|
closeButton.putClientProperty("paintActive", activeB);
|
|
if (getWindowDecorationStyle() == JRootPane.FRAME) {
|
|
iconifyButton.putClientProperty("paintActive", activeB);
|
|
toggleButton.putClientProperty("paintActive", activeB);
|
|
}
|
|
// Repaint the whole thing as the Borders that are used have
|
|
// different colors for active vs inactive
|
|
getRootPane().repaint();
|
|
}
|
|
|
|
/**
|
|
* Sets the state of the Window.
|
|
*/
|
|
private void setState(int state) {
|
|
setState(state, false);
|
|
}
|
|
|
|
/**
|
|
* Sets the state of the window. If <code>updateRegardless</code> is
|
|
* true and the state has not changed, this will update anyway.
|
|
*/
|
|
private void setState(int state, boolean updateRegardless) {
|
|
Window w = getWindow();
|
|
|
|
if (w != null && getWindowDecorationStyle() == JRootPane.FRAME) {
|
|
if (this.state == state && !updateRegardless) {
|
|
return;
|
|
}
|
|
Frame frame = getFrame();
|
|
|
|
if (frame != null) {
|
|
JRootPane rootPane = getRootPane();
|
|
|
|
if (((state & Frame.MAXIMIZED_BOTH) != 0) &&
|
|
(rootPane.getBorder() == null ||
|
|
(rootPane.getBorder() instanceof UIResource)) &&
|
|
frame.isShowing()) {
|
|
rootPane.setBorder(null);
|
|
}
|
|
else if ((state & Frame.MAXIMIZED_BOTH) == 0) {
|
|
// This is a croak, if state becomes bound, this can
|
|
// be nuked.
|
|
rootPaneUI.installBorder(rootPane);
|
|
}
|
|
if (frame.isResizable()) {
|
|
if ((state & Frame.MAXIMIZED_BOTH) != 0) {
|
|
updateToggleButton(restoreAction, minimizeIcon);
|
|
maximizeAction.setEnabled(false);
|
|
restoreAction.setEnabled(true);
|
|
}
|
|
else {
|
|
updateToggleButton(maximizeAction, maximizeIcon);
|
|
maximizeAction.setEnabled(true);
|
|
restoreAction.setEnabled(false);
|
|
}
|
|
if (toggleButton.getParent() == null ||
|
|
iconifyButton.getParent() == null) {
|
|
add(toggleButton);
|
|
add(iconifyButton);
|
|
revalidate();
|
|
repaint();
|
|
}
|
|
toggleButton.setText(null);
|
|
}
|
|
else {
|
|
maximizeAction.setEnabled(false);
|
|
restoreAction.setEnabled(false);
|
|
if (toggleButton.getParent() != null) {
|
|
remove(toggleButton);
|
|
revalidate();
|
|
repaint();
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// Not contained in a Frame
|
|
maximizeAction.setEnabled(false);
|
|
restoreAction.setEnabled(false);
|
|
iconifyAction.setEnabled(false);
|
|
remove(toggleButton);
|
|
remove(iconifyButton);
|
|
revalidate();
|
|
repaint();
|
|
}
|
|
closeAction.setEnabled(true);
|
|
this.state = state;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the toggle button to contain the Icon <code>icon</code>, and
|
|
* Action <code>action</code>.
|
|
*/
|
|
private void updateToggleButton(Action action, Icon icon) {
|
|
toggleButton.setAction(action);
|
|
toggleButton.setIcon(icon);
|
|
toggleButton.setText(null);
|
|
}
|
|
|
|
/**
|
|
* Returns the Frame rendering in. This will return null if the
|
|
* <code>JRootPane</code> is not contained in a <code>Frame</code>.
|
|
*/
|
|
private Frame getFrame() {
|
|
Window window = getWindow();
|
|
|
|
if (window instanceof Frame) {
|
|
return (Frame)window;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns the <code>Window</code> the <code>JRootPane</code> is
|
|
* contained in. This will return null if there is no parent ancestor
|
|
* of the <code>JRootPane</code>.
|
|
*/
|
|
private Window getWindow() {
|
|
return window;
|
|
}
|
|
|
|
/**
|
|
* Returns the String to display as the title.
|
|
*/
|
|
private String getTitle() {
|
|
Window w = getWindow();
|
|
|
|
if (w instanceof Frame) {
|
|
return ((Frame)w).getTitle();
|
|
}
|
|
else if (w instanceof Dialog) {
|
|
return ((Dialog)w).getTitle();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Renders the TitlePane.
|
|
*/
|
|
public void paintComponent(Graphics g) {
|
|
// As state isn't bound, we need a convenience place to check
|
|
// if it has changed. Changing the state typically changes the
|
|
if (getFrame() != null) {
|
|
setState(getFrame().getExtendedState());
|
|
}
|
|
JRootPane rootPane = getRootPane();
|
|
Window window = getWindow();
|
|
boolean leftToRight = (window == null) ?
|
|
rootPane.getComponentOrientation().isLeftToRight() :
|
|
window.getComponentOrientation().isLeftToRight();
|
|
boolean isSelected = (window == null) ? true : window.isActive();
|
|
int width = getWidth();
|
|
int height = getHeight();
|
|
|
|
Color background;
|
|
Color foreground;
|
|
Color darkShadow;
|
|
|
|
MetalBumps bumps;
|
|
|
|
if (isSelected) {
|
|
background = activeBackground;
|
|
foreground = activeForeground;
|
|
darkShadow = activeShadow;
|
|
bumps = activeBumps;
|
|
} else {
|
|
background = inactiveBackground;
|
|
foreground = inactiveForeground;
|
|
darkShadow = inactiveShadow;
|
|
bumps = inactiveBumps;
|
|
}
|
|
|
|
g.setColor(background);
|
|
g.fillRect(0, 0, width, height);
|
|
|
|
g.setColor( darkShadow );
|
|
g.drawLine ( 0, height - 1, width, height -1);
|
|
g.drawLine ( 0, 0, 0 ,0);
|
|
g.drawLine ( width - 1, 0 , width -1, 0);
|
|
|
|
int xOffset = leftToRight ? 5 : width - 5;
|
|
|
|
if (getWindowDecorationStyle() == JRootPane.FRAME) {
|
|
xOffset += leftToRight ? IMAGE_WIDTH + 5 : - IMAGE_WIDTH - 5;
|
|
}
|
|
|
|
String theTitle = getTitle();
|
|
if (theTitle != null) {
|
|
FontMetrics fm = SwingUtilities2.getFontMetrics(rootPane, g);
|
|
|
|
g.setColor(foreground);
|
|
|
|
int yOffset = ( (height - fm.getHeight() ) / 2 ) + fm.getAscent();
|
|
|
|
Rectangle rect = new Rectangle(0, 0, 0, 0);
|
|
if (iconifyButton != null && iconifyButton.getParent() != null) {
|
|
rect = iconifyButton.getBounds();
|
|
}
|
|
int titleW;
|
|
|
|
if( leftToRight ) {
|
|
if (rect.x == 0) {
|
|
rect.x = window.getWidth() - window.getInsets().right-2;
|
|
}
|
|
titleW = rect.x - xOffset - 4;
|
|
theTitle = SwingUtilities2.clipStringIfNecessary(
|
|
rootPane, fm, theTitle, titleW);
|
|
} else {
|
|
titleW = xOffset - rect.x - rect.width - 4;
|
|
theTitle = SwingUtilities2.clipStringIfNecessary(
|
|
rootPane, fm, theTitle, titleW);
|
|
xOffset -= SwingUtilities2.stringWidth(rootPane, fm,
|
|
theTitle);
|
|
}
|
|
int titleLength = SwingUtilities2.stringWidth(rootPane, fm,
|
|
theTitle);
|
|
SwingUtilities2.drawString(rootPane, g, theTitle, xOffset,
|
|
yOffset );
|
|
xOffset += leftToRight ? titleLength + 5 : -5;
|
|
}
|
|
|
|
int bumpXOffset;
|
|
int bumpLength;
|
|
if( leftToRight ) {
|
|
bumpLength = width - buttonsWidth - xOffset - 5;
|
|
bumpXOffset = xOffset;
|
|
} else {
|
|
bumpLength = xOffset - buttonsWidth - 5;
|
|
bumpXOffset = buttonsWidth + 5;
|
|
}
|
|
int bumpYOffset = 3;
|
|
int bumpHeight = getHeight() - (2 * bumpYOffset);
|
|
bumps.setBumpArea( bumpLength, bumpHeight );
|
|
bumps.paintIcon(this, g, bumpXOffset, bumpYOffset);
|
|
}
|
|
|
|
/**
|
|
* Actions used to <code>close</code> the <code>Window</code>.
|
|
*/
|
|
private class CloseAction extends AbstractAction {
|
|
public CloseAction() {
|
|
super(UIManager.getString("MetalTitlePane.closeTitle",
|
|
getLocale()));
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
close();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Actions used to <code>iconfiy</code> the <code>Frame</code>.
|
|
*/
|
|
private class IconifyAction extends AbstractAction {
|
|
public IconifyAction() {
|
|
super(UIManager.getString("MetalTitlePane.iconifyTitle",
|
|
getLocale()));
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
iconify();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Actions used to <code>restore</code> the <code>Frame</code>.
|
|
*/
|
|
private class RestoreAction extends AbstractAction {
|
|
public RestoreAction() {
|
|
super(UIManager.getString
|
|
("MetalTitlePane.restoreTitle", getLocale()));
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
restore();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Actions used to <code>restore</code> the <code>Frame</code>.
|
|
*/
|
|
private class MaximizeAction extends AbstractAction {
|
|
public MaximizeAction() {
|
|
super(UIManager.getString("MetalTitlePane.maximizeTitle",
|
|
getLocale()));
|
|
}
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
maximize();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Class responsible for drawing the system menu. Looks up the
|
|
* image to draw from the Frame associated with the
|
|
* <code>JRootPane</code>.
|
|
*/
|
|
private class SystemMenuBar extends JMenuBar {
|
|
public void paint(Graphics g) {
|
|
if (isOpaque()) {
|
|
g.setColor(getBackground());
|
|
g.fillRect(0, 0, getWidth(), getHeight());
|
|
}
|
|
|
|
if (systemIcon != null) {
|
|
g.drawImage(systemIcon, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null);
|
|
} else {
|
|
Icon icon = UIManager.getIcon("InternalFrame.icon");
|
|
|
|
if (icon != null) {
|
|
icon.paintIcon(this, g, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
public Dimension getMinimumSize() {
|
|
return getPreferredSize();
|
|
}
|
|
public Dimension getPreferredSize() {
|
|
Dimension size = super.getPreferredSize();
|
|
|
|
return new Dimension(Math.max(IMAGE_WIDTH, size.width),
|
|
Math.max(size.height, IMAGE_HEIGHT));
|
|
}
|
|
}
|
|
|
|
private class TitlePaneLayout implements LayoutManager {
|
|
public void addLayoutComponent(String name, Component c) {}
|
|
public void removeLayoutComponent(Component c) {}
|
|
public Dimension preferredLayoutSize(Container c) {
|
|
int height = computeHeight();
|
|
return new Dimension(height, height);
|
|
}
|
|
|
|
public Dimension minimumLayoutSize(Container c) {
|
|
return preferredLayoutSize(c);
|
|
}
|
|
|
|
private int computeHeight() {
|
|
FontMetrics fm = rootPane.getFontMetrics(getFont());
|
|
int fontHeight = fm.getHeight();
|
|
fontHeight += 7;
|
|
int iconHeight = 0;
|
|
if (getWindowDecorationStyle() == JRootPane.FRAME) {
|
|
iconHeight = IMAGE_HEIGHT;
|
|
}
|
|
|
|
int finalHeight = Math.max( fontHeight, iconHeight );
|
|
return finalHeight;
|
|
}
|
|
|
|
public void layoutContainer(Container c) {
|
|
boolean leftToRight = (window == null) ?
|
|
getRootPane().getComponentOrientation().isLeftToRight() :
|
|
window.getComponentOrientation().isLeftToRight();
|
|
|
|
int w = getWidth();
|
|
int x;
|
|
int y = 3;
|
|
int spacing;
|
|
int buttonHeight;
|
|
int buttonWidth;
|
|
|
|
if (closeButton != null && closeButton.getIcon() != null) {
|
|
buttonHeight = closeButton.getIcon().getIconHeight();
|
|
buttonWidth = closeButton.getIcon().getIconWidth();
|
|
}
|
|
else {
|
|
buttonHeight = IMAGE_HEIGHT;
|
|
buttonWidth = IMAGE_WIDTH;
|
|
}
|
|
|
|
// assumes all buttons have the same dimensions
|
|
// these dimensions include the borders
|
|
|
|
x = leftToRight ? w : 0;
|
|
|
|
spacing = 5;
|
|
x = leftToRight ? spacing : w - buttonWidth - spacing;
|
|
if (menuBar != null) {
|
|
menuBar.setBounds(x, y, buttonWidth, buttonHeight);
|
|
}
|
|
|
|
x = leftToRight ? w : 0;
|
|
spacing = 4;
|
|
x += leftToRight ? -spacing -buttonWidth : spacing;
|
|
if (closeButton != null) {
|
|
closeButton.setBounds(x, y, buttonWidth, buttonHeight);
|
|
}
|
|
|
|
if( !leftToRight ) x += buttonWidth;
|
|
|
|
if (getWindowDecorationStyle() == JRootPane.FRAME) {
|
|
if (Toolkit.getDefaultToolkit().isFrameStateSupported(
|
|
Frame.MAXIMIZED_BOTH)) {
|
|
if (toggleButton.getParent() != null) {
|
|
spacing = 10;
|
|
x += leftToRight ? -spacing -buttonWidth : spacing;
|
|
toggleButton.setBounds(x, y, buttonWidth, buttonHeight);
|
|
if (!leftToRight) {
|
|
x += buttonWidth;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (iconifyButton != null && iconifyButton.getParent() != null) {
|
|
spacing = 2;
|
|
x += leftToRight ? -spacing -buttonWidth : spacing;
|
|
iconifyButton.setBounds(x, y, buttonWidth, buttonHeight);
|
|
if (!leftToRight) {
|
|
x += buttonWidth;
|
|
}
|
|
}
|
|
}
|
|
buttonsWidth = leftToRight ? w - x : x;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* PropertyChangeListener installed on the Window. Updates the necessary
|
|
* state as the state of the Window changes.
|
|
*/
|
|
private class PropertyChangeHandler implements PropertyChangeListener {
|
|
public void propertyChange(PropertyChangeEvent pce) {
|
|
String name = pce.getPropertyName();
|
|
|
|
// Frame.state isn't currently bound.
|
|
if ("resizable".equals(name) || "state".equals(name)) {
|
|
Frame frame = getFrame();
|
|
|
|
if (frame != null) {
|
|
setState(frame.getExtendedState(), true);
|
|
}
|
|
if ("resizable".equals(name)) {
|
|
getRootPane().repaint();
|
|
}
|
|
}
|
|
else if ("title".equals(name)) {
|
|
repaint();
|
|
}
|
|
else if ("componentOrientation" == name) {
|
|
revalidate();
|
|
repaint();
|
|
}
|
|
else if ("iconImage" == name) {
|
|
updateSystemIcon();
|
|
revalidate();
|
|
repaint();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update the image used for the system icon
|
|
*/
|
|
private void updateSystemIcon() {
|
|
Window window = getWindow();
|
|
if (window == null) {
|
|
systemIcon = null;
|
|
return;
|
|
}
|
|
java.util.List<Image> icons = window.getIconImages();
|
|
assert icons != null;
|
|
|
|
if (icons.size() == 0) {
|
|
systemIcon = null;
|
|
}
|
|
else if (icons.size() == 1) {
|
|
systemIcon = icons.get(0);
|
|
}
|
|
else {
|
|
systemIcon = SunToolkit.getScaledIconImage(icons,
|
|
IMAGE_WIDTH,
|
|
IMAGE_HEIGHT);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* WindowListener installed on the Window, updates the state as necessary.
|
|
*/
|
|
private class WindowHandler extends WindowAdapter {
|
|
public void windowActivated(WindowEvent ev) {
|
|
setActive(true);
|
|
}
|
|
|
|
public void windowDeactivated(WindowEvent ev) {
|
|
setActive(false);
|
|
}
|
|
}
|
|
}
|