/*******************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JInternalFrame;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import javax.swing.plaf.metal.MetalLookAndFeel;
/**
* TinyInternalFrameTitlePane is not an UI-delegate but a JComponent.
*
* @version 1.0
* @author Hans Bickel
*/
@SuppressWarnings (
{ "all" } )
public class TinyInternalFrameTitlePane extends BasicInternalFrameTitlePane
implements LayoutManager
{
protected boolean isPalette = false;
/**
* The buttons width, calculated at runtime.
*/
private int buttonsWidth;
/**
* Installs some default values. Reads the internalframe title height from the
* ui defaults table.
*/
protected void installDefaults ()
{
super.installDefaults ();
frame.setFrameIcon ( UIManager.getDefaults ().getIcon (
"InternalFrame.icon" ) );
}
protected PropertyChangeListener createPropertyChangeListener ()
{
return new TinyPropertyChangeHandler ();
}
/**
* This constructor creates a title pane for the given internal frame
* instance.
*
* @param frame The internal frame that needs a title pane.
*/
public TinyInternalFrameTitlePane ( JInternalFrame frame )
{
super ( frame );
}
protected void paintTitleBackground ( Graphics g )
{
}
public boolean isFrameSelected ()
{
return frame.isSelected ();
}
public boolean isFrameMaximized ()
{
return frame.isMaximum ();
}
/**
* Paints this component.
*
* @param g The graphics context to use.
*/
public void paintComponent ( Graphics g )
{
if ( Theme.frameIsTransparent [ Theme.derivedStyle [ Theme.style ] ] )
{
frame.setOpaque ( false );
}
boolean leftToRight = frame.getComponentOrientation ().isLeftToRight ();
boolean isSelected = frame.isSelected ();
int width = getWidth ();
int height = getHeight ();
Color foreground = MetalLookAndFeel.getWindowTitleInactiveForeground ();
int titleLength = 0;
int xOffset = leftToRight ? 2 : width - 2;
String frameTitle = frame.getTitle ();
Icon icon = frame.getFrameIcon ();
if ( icon != null )
{
int iconY = Math.round ( ( height - icon.getIconHeight () ) / 2.0f );
if ( !leftToRight )
{
xOffset -= icon.getIconWidth ();
}
if ( Theme.derivedStyle [ Theme.style ] == Theme.W99_STYLE )
{
iconY += 1;
}
icon.paintIcon ( frame, g, xOffset, iconY );
xOffset += leftToRight ? icon.getIconWidth () + 2 : -2;
}
if ( frameTitle != null )
{
Font f = getFont ();
g.setFont ( f );
FontMetrics fm = g.getFontMetrics ();
titleLength = fm.stringWidth ( frameTitle );
int yOffset = ( ( height - fm.getHeight () ) / 2 ) + fm.getAscent () + 1;
if ( !leftToRight )
xOffset -= titleLength;
if ( isSelected )
{
g.setColor ( Theme.frameTitleColor [ Theme.style ].getColor () );
g.drawString ( frameTitle, xOffset, yOffset );
xOffset += leftToRight ? titleLength + 2 : -2;
}
else
{
// for an inactive window
g.setColor ( Theme.frameTitleDisabledColor [ Theme.style ].getColor () );
g.drawString ( frameTitle, xOffset, yOffset );
xOffset += leftToRight ? titleLength + 2 : -2;
}
}
}
/**
* Creates the layout manager for the title pane.
*
* @return The layout manager for the title pane.
*/
protected LayoutManager createLayout ()
{
return this;
}
protected void addSubComponents ()
{
super.addSubComponents ();
// if(menuBar != null) {
// menuBar.setOpaque(false);
// }
}
protected void setButtonIcons ()
{
}
/**
* This listener is added to the maximize, minimize and close button to manage
* the rollover status of the buttons
*/
class RolloverListener implements MouseListener
{
JButton button;
Action action;
public RolloverListener ( JButton b, Action a )
{
button = b;
action = a;
}
public void mouseClicked ( MouseEvent e )
{
action.actionPerformed ( new ActionEvent ( this, Event.ACTION_EVENT,
button.getText () ) );
}
public void mousePressed ( MouseEvent e )
{
}
public void mouseReleased ( MouseEvent e )
{
}
public void mouseEntered ( MouseEvent e )
{
button.getModel ().setRollover ( true );
if ( !button.isEnabled () )
{
button.setEnabled ( true );
}
button.repaint ();
}
public void mouseExited ( MouseEvent e )
{
button.getModel ().setRollover ( false );
if ( !frame.isSelected () )
{
button.setEnabled ( false );
}
button.repaint ();
}
}
static TinyWindowButtonUI iconButtonUI;
static TinyWindowButtonUI maxButtonUI;
static TinyWindowButtonUI closeButtonUI;
/**
* Creates the buttons of the title pane and initilizes their actions.
*/
protected void createButtons ()
{
if ( iconButtonUI == null )
{
iconButtonUI = TinyWindowButtonUI
.createButtonUIForType ( TinyWindowButtonUI.MINIMIZE );
maxButtonUI = TinyWindowButtonUI
.createButtonUIForType ( TinyWindowButtonUI.MAXIMIZE );
closeButtonUI = TinyWindowButtonUI
.createButtonUIForType ( TinyWindowButtonUI.CLOSE );
}
iconButton = new SpecialUIButton ( iconButtonUI );
iconButton.addActionListener ( iconifyAction );
iconButton.setRolloverEnabled ( true );
iconButton.addMouseListener ( new RolloverListener ( iconButton,
iconifyAction ) );
maxButton = new SpecialUIButton ( maxButtonUI );
maxButton.addActionListener ( maximizeAction );
maxButton.setRolloverEnabled ( true );
maxButton.addMouseListener ( new RolloverListener ( maxButton,
maximizeAction ) );
closeButton = new SpecialUIButton ( closeButtonUI );
closeButton.addActionListener ( closeAction );
closeButton.setRolloverEnabled ( true );
closeButton.addMouseListener ( new RolloverListener ( closeButton,
closeAction ) );
iconButton.putClientProperty ( "externalFrameButton", Boolean.FALSE );
maxButton.putClientProperty ( "externalFrameButton", Boolean.FALSE );
closeButton.putClientProperty ( "externalFrameButton", Boolean.FALSE );
iconButton
.getAccessibleContext ()
.setAccessibleName (
UIManager
.getString ( "InternalFrameTitlePane.iconifyButtonAccessibleName" ) );
maxButton
.getAccessibleContext ()
.setAccessibleName (
UIManager
.getString ( "InternalFrameTitlePane.maximizeButtonAccessibleName" ) );
closeButton.getAccessibleContext ().setAccessibleName (
UIManager
.getString ( "InternalFrameTitlePane.closeButtonAccessibleName" ) );
if ( frame.isSelected () )
{
activate ();
}
else
{
deactivate ();
}
}
/**
* Paints the title pane for a palette.
*
* @param g The graphics context to use.
*/
public void paintPalette ( Graphics g )
{
}
/**
* Adds the specified component with the specified name to the layout.
*
* @param name the component name
* @param mainColor the component to be added
*/
public void addLayoutComponent ( String name, Component c )
{
}
/**
* Removes the specified component from the layout.
*
* @param mainColor the component to be removed
*/
public void removeLayoutComponent ( Component c )
{
}
/**
* Calculates the preferred size dimensions for the specified panel given the
* components in the specified parent container.
*
* @param mainColor the component to be laid out
*/
public Dimension preferredLayoutSize ( Container c )
{
return getPreferredSize ( c );
}
/**
* Gets the preferred size of the given container.
*
* @return The preferred size of the given container.
*/
public Dimension getPreferredSize ( Container c )
{
isPalette = ( frame.getClientProperty ( "isPalette" ) == Boolean.TRUE );
// width.
int width = 22;
if ( frame.isClosable () )
{
width += 19;
}
if ( frame.isMaximizable () )
{
width += 19;
}
if ( frame.isIconifiable () )
{
width += 19;
}
FontMetrics fm = getFontMetrics ( getFont () );
String frameTitle = frame.getTitle ();
int title_w = frameTitle != null ? fm.stringWidth ( frameTitle ) : 0;
int title_length = frameTitle != null ? frameTitle.length () : 0;
// Leave room for three characters in the title.
if ( title_length > 3 )
{
int subtitle_w = fm.stringWidth ( frameTitle.substring ( 0, 3 ) + "..." );
width += ( title_w < subtitle_w ) ? title_w : subtitle_w;
}
else
{
width += title_w;
}
// height
int height = ( isPalette ? Theme.framePaletteTitleHeight [ Theme.derivedStyle [ Theme.style ] ]
: Theme.frameInternalTitleHeight [ Theme.derivedStyle [ Theme.style ] ] );
Dimension dim = new Dimension ( width, height );
// Take into account the border insets if any.
if ( getBorder () != null )
{
Insets insets = getBorder ().getBorderInsets ( c );
dim.height += insets.top + insets.bottom;
dim.width += insets.left + insets.right;
}
return dim;
}
/**
* The minimum size of the frame. This is used, for example, during resizing
* to find the minimum allowable size. Providing at least some minimum size
* fixes a bug which breaks horizontal resizing. <b>Note</b>: the Motif plaf
* allows for a 0,0 min size, but we provide a reasonable minimum here.
* <b>Future</b>: calculate min size based upon contents.
*/
public Dimension getMinimumSize ()
{
isPalette = ( frame.getClientProperty ( "isPalette" ) == Boolean.TRUE );
int height = ( isPalette ? Theme.framePaletteTitleHeight [ Theme.derivedStyle [ Theme.style ] ]
: Theme.frameInternalTitleHeight [ Theme.derivedStyle [ Theme.style ] ] );
return new Dimension ( TinyLookAndFeel.MINIMUM_INTERNAL_FRAME_WIDTH, height );
}
/**
* Calculates the minimum size dimensions for the specified panel given the
* components in the specified parent container.
*/
public Dimension minimumLayoutSize ( Container c )
{
return preferredLayoutSize ( c );
}
public void setPalette ( boolean b )
{
isPalette = b;
}
public boolean isPalette ()
{
return isPalette;
}
/**
* Lays out the container in the specified panel.
*
* @param c the component which needs to be laid out
*/
public void layoutContainer ( Container c )
{
isPalette = ( frame.getClientProperty ( "isPalette" ) == Boolean.TRUE );
boolean leftToRight = frame.getComponentOrientation ().isLeftToRight ();
int buttonHeight = closeButton.getPreferredSize ().height;
int w = getWidth ();
int x = leftToRight ? w : 0;
int y = ( getHeight () - buttonHeight ) / 2 + 1;
int spacing;
if ( Theme.derivedStyle [ Theme.style ] == Theme.W99_STYLE )
{
y += 1;
}
int buttonWidth = 0;
if ( isPalette )
{
buttonWidth = Theme.framePaletteButtonSize [ Theme.derivedStyle [ Theme.style ] ].width;
}
else
{
buttonWidth = Theme.frameInternalButtonSize [ Theme.derivedStyle [ Theme.style ] ].width;
}
if ( frame.isClosable () )
{
spacing = 2;
x += leftToRight ? -spacing - buttonWidth : spacing;
closeButton.setBounds ( x, y, buttonWidth, buttonHeight );
if ( !leftToRight )
x += ( buttonWidth );
}
if ( frame.isMaximizable () )
{
spacing = 2;
x += leftToRight ? -spacing - buttonWidth : spacing;
maxButton.setBounds ( x, y, buttonWidth, buttonHeight );
if ( !leftToRight )
x += buttonWidth;
}
if ( frame.isIconifiable () )
{
spacing = ( frame.isMaximizable () && Theme.style == Theme.W99_STYLE ) ? 0
: 2;
x += leftToRight ? -spacing - buttonWidth : spacing;
iconButton.setBounds ( x, y, buttonWidth, buttonHeight );
if ( !leftToRight )
x += buttonWidth;
}
buttonsWidth = leftToRight ? w - x : x;
}
public void activate ()
{
closeButton.setEnabled ( true );
iconButton.setEnabled ( true );
maxButton.setEnabled ( true );
}
public void deactivate ()
{
closeButton.setEnabled ( false );
iconButton.setEnabled ( false );
maxButton.setEnabled ( false );
}
/**
* @see java.awt.Component#getFont()
*/
public Font getFont ()
{
Font f = null;
if ( isPalette )
{
f = UIManager.getFont ( "InternalFrame.paletteTitleFont" );
}
else
{
f = UIManager.getFont ( "InternalFrame.normalTitleFont" );
}
if ( f == null )
{
f = new Font ( "SansSerife", Font.BOLD, 12 );
}
return f;
}
class TinyPropertyChangeHandler extends
BasicInternalFrameTitlePane.PropertyChangeHandler
{
public void propertyChange ( PropertyChangeEvent evt )
{
String prop = ( String ) evt.getPropertyName ();
if ( prop.equals ( JInternalFrame.IS_SELECTED_PROPERTY ) )
{
Boolean b = ( Boolean ) evt.getNewValue ();
iconButton.putClientProperty ( "paintActive", b );
closeButton.putClientProperty ( "paintActive", b );
maxButton.putClientProperty ( "paintActive", b );
}
// else if("JInternalFrame.messageType".equals(prop)) {
// updateOptionPaneState();
// frame.repaint();
// }
super.propertyChange ( evt );
}
}
}