/******************************************************************************* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 ); } } }