/*
 * Copyright (c) 2000, 2006, 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 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.

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 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.
/** * PropertyChangeListener added to the JRootPane. */
private PropertyChangeListener propertyChangeListener;
JMenuBar, typically renders the system menu items.
/** * JMenuBar, typically renders the system menu items. */
private JMenuBar menuBar;
Action used to close the Window.
/** * Action used to close the Window. */
private Action closeAction;
Action used to iconify the Frame.
/** * Action used to iconify the Frame. */
private Action iconifyAction;
Action to restore the Frame size.
/** * Action to restore the Frame size. */
private Action restoreAction;
Action to restore the Frame size.
/** * Action to restore the Frame size. */
private Action maximizeAction;
Button used to maximize or restore the Frame.
/** * Button used to maximize or restore the Frame. */
private JButton toggleButton;
Button used to maximize or restore the Frame.
/** * Button used to maximize or restore the Frame. */
private JButton iconifyButton;
Button used to maximize or restore the Frame.
/** * Button used to maximize or restore the Frame. */
private JButton closeButton;
Icon used for toggleButton when window is normal size.
/** * Icon used for toggleButton when window is normal size. */
private Icon maximizeIcon;
Icon used for toggleButton when window is maximized.
/** * Icon used for toggleButton when window is maximized. */
private Icon minimizeIcon;
Image used for the system menu icon
/** * 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.
/** * 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.
/** * Window we're currently in. */
private Window window;
JRootPane rendering for.
/** * JRootPane rendering for. */
private JRootPane rootPane;
Room remaining in title for bumps.
/** * 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.
/** * 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.
/** * 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.
/** * Uninstalls the necessary state. */
private void uninstall() { uninstallListeners(); window = null; removeAll(); }
Installs the necessary listeners.
/** * Installs the necessary listeners. */
private void installListeners() { if (window != null) { windowListener = createWindowListener(); window.addWindowListener(windowListener); propertyChangeListener = createWindowPropertyChangeListener(); window.addPropertyChangeListener(propertyChangeListener); } }
Uninstalls the necessary listeners.
/** * Uninstalls the necessary listeners. */
private void uninstallListeners() { if (window != null) { window.removeWindowListener(windowListener); window.removePropertyChangeListener(propertyChangeListener); } }
Returns the WindowListener to add to the Window.
/** * Returns the <code>WindowListener</code> to add to the * <code>Window</code>. */
private WindowListener createWindowListener() { return new WindowHandler(); }
Returns the PropertyChangeListener to install on the Window.
/** * Returns the <code>PropertyChangeListener</code> to install on * the <code>Window</code>. */
private PropertyChangeListener createWindowPropertyChangeListener() { return new PropertyChangeHandler(); }
Returns the JRootPane this was created for.
/** * Returns the <code>JRootPane</code> this was created for. */
public JRootPane getRootPane() { return rootPane; }
Returns the decoration style of the JRootPane.
/** * 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 MetalTitlePane.
/** * 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.
/** * 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.
/** * Installs the fonts and necessary properties on the MetalTitlePane. */
private void installDefaults() { setFont(UIManager.getFont("InternalFrame.titleFont", getLocale())); }
Uninstalls any previously installed UI values.
/** * Uninstalls any previously installed UI values. */
private void uninstallDefaults() { }
Returns the JMenuBar displaying the appropriate system menu items.
/** * 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.
/** * Closes the Window. */
private void close() { Window window = getWindow(); if (window != null) { window.dispatchEvent(new WindowEvent( window, WindowEvent.WINDOW_CLOSING)); } }
Iconifies the Frame.
/** * Iconifies the Frame. */
private void iconify() { Frame frame = getFrame(); if (frame != null) { frame.setExtendedState(state | Frame.ICONIFIED); } }
Maximizes the Frame.
/** * Maximizes the Frame. */
private void maximize() { Frame frame = getFrame(); if (frame != null) { frame.setExtendedState(state | Frame.MAXIMIZED_BOTH); } }
Restores the Frame size.
/** * 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 Actions that get associated with the buttons and menu items.
/** * 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 JMenu displaying the appropriate menu items for manipulating the Frame.
/** * 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 JMenuItems to the passed in 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 JButton appropriate for placement on the TitlePane.
/** * 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.
/** * 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 LayoutManager that should be installed on the MetalTitlePane.
/** * 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.
/** * 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.
/** * Sets the state of the Window. */
private void setState(int state) { setState(state, false); }
Sets the state of the window. If updateRegardless is true and the state has not changed, this will update anyway.
/** * 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 icon, and Action action.
/** * 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 JRootPane is not contained in a Frame.
/** * 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 Window the JRootPane is contained in. This will return null if there is no parent ancestor of the JRootPane.
/** * 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.
/** * 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.
/** * 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 close the Window.
/** * 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 iconfiy the Frame.
/** * 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 restore the Frame.
/** * 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 restore the Frame.
/** * 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 JRootPane.
/** * 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.
/** * 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
/** * 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.
/** * 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); } } }