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