/*******************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tiny Look and Feel * * (C) Copyright 2003 - 2007 Hans Bickel * * For
* licensing information and credits, please refer to the * comment in file
* de.muntjak.tinylookandfeel.TinyLookAndFeel * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
package de.muntjak.tinylookandfeel;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Locale;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.UIResource;
import de.muntjak.tinylookandfeel.controlpanel.ControlPanel;
/*
* @(#)TinyTitlePane.java 1.10 01/12/03 Copyright 2002 Sun Microsystems, Inc.
* All rights reserved. SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license
* terms.
*/
/*
* 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.
*
* @version 1.10 12/03/01 @author Terry Kellerman
* @since 1.4
*/
/**
* TinyTitlePane
*
* @version 1.0
* @author Hans Bickel
*/
@SuppressWarnings (
{ "all" } )
public class TinyTitlePane extends JComponent
{
private static final int IMAGE_HEIGHT = 16;
private static final int IMAGE_WIDTH = 16;
private static TinyWindowButtonUI iconButtonUI;
private static TinyWindowButtonUI maxButtonUI;
private static TinyWindowButtonUI closeButtonUI;
/**
* 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;
/**
* Listens for changes in the state of the Window listener to update the state
* of the widgets.
*/
private WindowListener windowListener;
private ComponentListener windowMoveListener;
/**
* 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;
/**
* RootPaneUI that created us.
*/
private TinyRootPaneUI rootPaneUI;
public TinyTitlePane ( JRootPane root, TinyRootPaneUI ui )
{
rootPane = root;
rootPaneUI = ui;
state = -1;
installSubcomponents ();
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 );
windowMoveListener = new WindowMoveListener ();
window.addComponentListener ( windowMoveListener );
}
}
/**
* Uninstalls the necessary listeners.
*/
private void uninstallListeners ()
{
if ( window != null )
{
window.removeWindowListener ( windowListener );
window.removePropertyChangeListener ( propertyChangeListener );
window.removeComponentListener ( windowMoveListener );
}
}
/**
* 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 ();
}
}
public void removeNotify ()
{
super.removeNotify ();
uninstallListeners ();
window = null;
}
/**
* Adds any sub-Components contained in the <code>TinyTitlePane</code>.
*/
private void installSubcomponents ()
{
if ( getWindowDecorationStyle () == JRootPane.FRAME )
{
createActions ();
menuBar = createMenuBar ();
add ( menuBar );
createButtons ();
add ( iconifyButton );
add ( toggleButton );
add ( closeButton );
iconifyButton.putClientProperty ( "externalFrameButton", Boolean.TRUE );
toggleButton.putClientProperty ( "externalFrameButton", Boolean.TRUE );
closeButton.putClientProperty ( "externalFrameButton", Boolean.TRUE );
}
else if ( getWindowDecorationStyle () != JRootPane.NONE )
{
createActions ();
createButtons ();
add ( closeButton );
closeButton.putClientProperty ( "externalFrameButton", Boolean.FALSE );
}
}
/**
* Installs the fonts and necessary properties on the TinyTitlePane.
*/
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 ( frame.getExtendedState () | Frame.ICONIFIED );
}
}
/**
* Maximizes the Frame.
*/
private void maximize ()
{
Frame frame = getFrame ();
if ( frame != null )
{
setMaximizeBounds ( frame );
frame
.setExtendedState ( frame.getExtendedState () | Frame.MAXIMIZED_BOTH );
}
}
protected void setMaximizeBounds ( Frame frame )
{
if ( frame.getMaximizedBounds () != null )
return;
Insets screenInsets = Toolkit.getDefaultToolkit ().getScreenInsets (
frame.getGraphicsConfiguration () );
Dimension screenSize = Toolkit.getDefaultToolkit ().getScreenSize ();
// spare any Systemmenus or Taskbars or ??...
int x = screenInsets.top;
int y = screenInsets.left;
int w = screenSize.width - x - screenInsets.right;
int h = screenSize.height - y - screenInsets.bottom;
Rectangle maxBounds = new Rectangle ( x, y, w, h );
frame.setMaximizedBounds ( maxBounds );
}
/**
* Restores the Frame size.
*/
private void restore ()
{
Frame frame = getFrame ();
if ( frame == null )
{
return;
}
if ( ( frame.getExtendedState () & Frame.ICONIFIED ) == Frame.ICONIFIED )
{
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 ();
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 );
// we use this property to prevent the Menu from drawing rollovers
menu.putClientProperty ( "isSystemMenu", Boolean.TRUE );
}
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 = getInt ( "MetalTitlePane.restoreMnemonic", -1 );
if ( mnemonic != -1 )
{
mi.setMnemonic ( mnemonic );
}
mi = menu.add ( iconifyAction );
mnemonic = getInt ( "MetalTitlePane.iconifyMnemonic", -1 );
if ( mnemonic != -1 )
{
mi.setMnemonic ( mnemonic );
}
if ( Toolkit.getDefaultToolkit ().isFrameStateSupported (
Frame.MAXIMIZED_BOTH ) )
{
mi = menu.add ( maximizeAction );
mnemonic = getInt ( "MetalTitlePane.maximizeMnemonic", -1 );
if ( mnemonic != -1 )
{
mi.setMnemonic ( mnemonic );
}
}
menu.addSeparator ();
mi = menu.add ( closeAction );
mnemonic = getInt ( "MetalTitlePane.closeMnemonic", -1 );
if ( mnemonic != -1 )
{
mi.setMnemonic ( mnemonic );
}
}
/**
* Creates the buttons of the title pane and initializes their actions.
*/
protected void createButtons ()
{
if ( iconButtonUI == null )
{
iconButtonUI = TinyWindowButtonUI
.createButtonUIForType ( TinyWindowButtonUI.MINIMIZE );
maxButtonUI = TinyWindowButtonUI
.createButtonUIForType ( TinyWindowButtonUI.MAXIMIZE );
closeButtonUI = TinyWindowButtonUI
.createButtonUIForType ( TinyWindowButtonUI.CLOSE );
}
iconifyButton = new SpecialUIButton ( iconButtonUI );
iconifyButton.setAction ( iconifyAction );
iconifyButton.setRolloverEnabled ( true );
toggleButton = new SpecialUIButton ( maxButtonUI );
toggleButton.setAction ( maximizeAction );
toggleButton.setRolloverEnabled ( true );
closeButton = new SpecialUIButton ( closeButtonUI );
closeButton.setAction ( closeAction );
closeButton.setRolloverEnabled ( true );
closeButton.getAccessibleContext ().setAccessibleName ( "Close" );
iconifyButton.getAccessibleContext ().setAccessibleName ( "Iconify" );
toggleButton.getAccessibleContext ().setAccessibleName ( "Maximize" );
if ( TinyLookAndFeel.controlPanelInstantiated )
{
ControlPanel.setWindowButtons ( new JButton []
{ iconifyButton, toggleButton, closeButton } );
}
}
/**
* Returns the <code>LayoutManager</code> that should be installed on the
* <code>TinyTitlePane</code>.
*/
private LayoutManager createLayout ()
{
return new TitlePaneLayout ();
}
/**
* Updates state dependant upon the Window's active state.
*/
private void setActive ( boolean isActive )
{
if ( getWindowDecorationStyle () == JRootPane.FRAME )
{
Boolean activeB = isActive ? Boolean.TRUE : Boolean.FALSE;
iconifyButton.putClientProperty ( "paintActive", activeB );
closeButton.putClientProperty ( "paintActive", activeB );
toggleButton.putClientProperty ( "paintActive", activeB );
iconifyButton.setEnabled ( isActive );
closeButton.setEnabled ( isActive );
toggleButton.setEnabled ( isActive );
}
// 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 ) == Frame.MAXIMIZED_BOTH
&& ( rootPane.getBorder () == null || ( rootPane.getBorder () instanceof UIResource ) )
&& frame.isShowing () )
{
// rootPane.setBorder(null);
}
else if ( ( state & Frame.MAXIMIZED_BOTH ) != Frame.MAXIMIZED_BOTH )
{
// This is a croak, if state becomes bound, this can
// be nuked.
// rootPaneUI.installBorder(rootPane);
}
if ( frame.isResizable () )
{
if ( ( state & Frame.MAXIMIZED_VERT ) == Frame.MAXIMIZED_VERT
|| ( state & Frame.MAXIMIZED_HORIZ ) == Frame.MAXIMIZED_HORIZ )
{
updateToggleButton ( restoreAction );
maximizeAction.setEnabled ( false );
restoreAction.setEnabled ( true );
}
else
{
updateToggleButton ( maximizeAction );
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 )
{
toggleButton.setAction ( action );
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;
}
public boolean isSelected ()
{
Window window = getWindow ();
return ( window == null ) ? true : window.isActive ();
}
public boolean isFrameMaximized ()
{
Frame frame = getFrame ();
if ( frame != null )
{
return ( ( frame.getExtendedState () & Frame.MAXIMIZED_BOTH ) == Frame.MAXIMIZED_BOTH );
}
return false;
}
/**
* Renders the TitlePane ( => paints the title).
*/
public void paintComponent ( Graphics g )
{
// As state isn't bound, we need a convenience place to check
// if it has changed.
if ( getFrame () != null )
{
setState ( getFrame ().getExtendedState () );
}
Window window = getWindow ();
boolean leftToRight = ( window == null ) ? getRootPane ()
.getComponentOrientation ().isLeftToRight () : window
.getComponentOrientation ().isLeftToRight ();
boolean isSelected = ( window == null ) ? true : window.isActive ();
int width = getWidth ();
int height = getHeight ();
int xOffset = leftToRight ? 5 : width - 5;
if ( getWindowDecorationStyle () == JRootPane.FRAME )
{
xOffset += leftToRight ? IMAGE_WIDTH + 5 : -IMAGE_WIDTH - 5;
}
String theTitle = getTitle ();
if ( theTitle != null )
{
Font f = UIManager.getFont ( "InternalFrame.normalTitleFont" );
FontMetrics fm = g.getFontMetrics ();
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 = clippedText ( theTitle, fm, titleW );
}
else
{
titleW = xOffset - rect.x - rect.width - 4;
theTitle = clippedText ( theTitle, fm, titleW );
xOffset -= SwingUtilities.computeStringWidth ( fm, theTitle );
}
int titleLength = SwingUtilities.computeStringWidth ( fm, theTitle );
if ( isSelected )
{
g.setColor ( Theme.frameTitleColor [ Theme.style ].getColor () );
g.drawString ( theTitle, xOffset, yOffset );
}
else
{
// for an inactive window
g.setColor ( Theme.frameTitleDisabledColor [ Theme.style ].getColor () );
g.drawString ( theTitle, xOffset, yOffset );
}
xOffset += leftToRight ? titleLength + 5 : -5;
}
}
/**
* Convenience method to clip the passed in text to the specified size.
*/
private String clippedText ( String text, FontMetrics fm, int availTextWidth )
{
if ( ( text == null ) || ( text.equals ( "" ) ) )
{
return "";
}
int textWidth = SwingUtilities.computeStringWidth ( fm, text );
String clipString = "...";
if ( textWidth > availTextWidth )
{
int totalWidth = SwingUtilities.computeStringWidth ( fm, clipString );
int nChars;
for ( nChars = 0 ; nChars < text.length () ; nChars++ )
{
totalWidth += fm.charWidth ( text.charAt ( nChars ) );
if ( totalWidth > availTextWidth )
{
break;
}
}
text = text.substring ( 0, nChars ) + clipString;
}
return text;
}
private int getInt ( Object key, int defaultValue )
{
Object value = UIManager.get ( key );
if ( value instanceof Integer )
{
return ( ( Integer ) value ).intValue ();
}
if ( value instanceof String )
{
try
{
return Integer.parseInt ( ( String ) value );
}
catch ( NumberFormatException nfe )
{
}
}
return defaultValue;
}
/**
* 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 )
{
Frame frame = getFrame ();
Image image = ( frame != null ) ? frame.getIconImage () : null;
if ( image != null )
{
g.drawImage ( image, 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 ()
{
Icon icon = UIManager.getIcon ( "InternalFrame.icon" );
if ( icon != null )
{
return new Dimension ( icon.getIconWidth (), icon.getIconHeight () );
}
Dimension size = super.getPreferredSize ();
return new Dimension ( Math.max ( IMAGE_WIDTH, size.width ), Math.max (
size.height, IMAGE_HEIGHT ) );
}
}
/**
* This inner class is marked "public" due to a compiler bug. This
* class should be treated as a "protected" inner class. Instantiate
* it only within subclasses of <Foo>.
*/
private class TitlePaneLayout implements LayoutManager
{
public void addLayoutComponent ( String name, Component c )
{
}
public void removeLayoutComponent ( Component c )
{
}
public Dimension preferredLayoutSize ( Container c )
{
return new Dimension ( TinyLookAndFeel.MINIMUM_FRAME_WIDTH,
computeHeight () );
}
public Dimension minimumLayoutSize ( Container c )
{
return preferredLayoutSize ( c );
}
private int computeHeight ()
{
if ( getFrame () instanceof JFrame )
{
setMaximizeBounds ( getFrame () );
return Theme.frameTitleHeight [ Theme.derivedStyle [ Theme.style ] ];
}
else
{
return Theme.frameInternalTitleHeight [ Theme.derivedStyle [ Theme.style ] ];
}
}
public void layoutContainer ( Container c )
{
if ( getWindowDecorationStyle () == JRootPane.NONE )
{
buttonsWidth = 0;
return;
}
boolean leftToRight = ( window == null ) ? getRootPane ()
.getComponentOrientation ().isLeftToRight () : window
.getComponentOrientation ().isLeftToRight ();
int w = getWidth ();
int x;
int spacing;
int buttonHeight;
int buttonWidth;
if ( closeButton != null )
{
buttonHeight = closeButton.getPreferredSize ().height;
buttonWidth = closeButton.getPreferredSize ().width;
}
else
{
buttonHeight = IMAGE_HEIGHT;
buttonWidth = IMAGE_WIDTH;
}
int y = ( getHeight () - buttonHeight ) / 2 + 1;
if ( Theme.derivedStyle [ Theme.style ] == Theme.W99_STYLE )
{
y += 1;
}
// 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 )
{
// this is a JFrame
menuBar.setBounds ( x, y, buttonWidth, buttonHeight );
}
x = leftToRight ? w : 0;
spacing = 2;
x += leftToRight ? -spacing - buttonWidth : spacing;
if ( closeButton != null )
{
closeButton.setBounds ( x, y, buttonWidth, buttonHeight );
}
if ( !leftToRight )
x += buttonWidth;
if ( Toolkit.getDefaultToolkit ().isFrameStateSupported (
Frame.MAXIMIZED_BOTH ) )
{
if ( toggleButton.getParent () != null )
{
x += leftToRight ? -spacing - buttonWidth : spacing;
toggleButton.setBounds ( x, y, buttonWidth, buttonHeight );
if ( !leftToRight )
{
x += buttonWidth;
}
}
}
if ( iconifyButton != null && iconifyButton.getParent () != null )
{
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".equals ( name ) )
{
revalidate ();
repaint ();
}
}
}
/**
* 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 );
}
}
class WindowMoveListener extends ComponentAdapter
{
public void componentMoved ( ComponentEvent e )
{
if ( getWindowDecorationStyle () == JRootPane.NONE )
return;
// paint the non-opaque upper edges
Window w = getWindow ();
if ( !w.isShowing () )
return;
w.repaint ( 0, 0, w.getWidth (), 5 );
}
public void componentResized ( ComponentEvent e )
{
if ( getWindowDecorationStyle () == JRootPane.NONE )
return;
// paint the non-opaque upper edges
Window w = getWindow ();
if ( !w.isShowing () )
return;
w.repaint ( 0, 0, w.getWidth (), 5 );
}
}
}