/******************************************************************************* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.KeyEvent; import javax.swing.AbstractButton; import javax.swing.ButtonModel; import javax.swing.Icon; import javax.swing.InputMap; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JToggleButton; import javax.swing.KeyStroke; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.metal.MetalButtonUI; import de.muntjak.tinylookandfeel.controlpanel.ColorRoutines; /** * TinyButtonUI. The UI delegate for JButton, JToggleButton and ArrowButtons for * JSpinner. * * @version 1.3.04 * @author Hans Bickel */ @SuppressWarnings ( { "all" } ) public class TinyButtonUI extends MetalButtonUI { // if a button has not the defined background, it will // be darkened resp. lightened by BG_CHANGE amount if // pressed or rollover public static final int BG_CHANGE_AMOUNT = 10; /** * The Cached UI delegate. */ private static final TinyButtonUI buttonUI = new TinyButtonUI (); /* the only instance of the stroke for the focus */ private static final BasicStroke focusStroke = new BasicStroke ( 1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1.0f, new float [] { 1.0f, 1.0f }, 0.0f ); private boolean graphicsTranslated; private boolean isToolBarButton, isFileChooserButton; private boolean isDefault; public TinyButtonUI () { } public void installUI ( JComponent c ) { super.installUI ( c ); if ( !Theme.buttonEnter [ Theme.style ] ) return; if ( !c.isFocusable () ) return; InputMap km = ( InputMap ) UIManager.get ( getPropertyPrefix () + "focusInputMap" ); if ( km != null ) { // replace SPACE with ENTER (but SPACE will still work, don't know why) km.put ( KeyStroke.getKeyStroke ( KeyEvent.VK_ENTER, 0, false ), "pressed" ); km.put ( KeyStroke.getKeyStroke ( KeyEvent.VK_ENTER, 0, true ), "released" ); } } public void installDefaults ( AbstractButton button ) { super.installDefaults ( button ); button.setRolloverEnabled ( true ); } protected void paintFocus ( Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect ) { if ( isFileChooserButton || ( isToolBarButton && !Theme.toolFocus [ Theme.style ] ) || !Theme.buttonFocus [ Theme.style ] ) { return; } Graphics2D g2d = ( Graphics2D ) g; Rectangle focusRect = b.getBounds (); g.setColor ( Color.black ); g2d.setStroke ( focusStroke ); int x1 = 2; int y1 = 2; int x2 = x1 + focusRect.width - 5; int y2 = y1 + focusRect.height - 5; if ( !isToolBarButton ) { x1++ ; y1++ ; x2-- ; y2-- ; } if ( graphicsTranslated ) { g.translate ( -1, -1 ); } g2d.drawLine ( x1, y1, x2, y1 ); g2d.drawLine ( x1, y1, x1, y2 ); g2d.drawLine ( x1, y2, x2, y2 ); g2d.drawLine ( x2, y1, x2, y2 ); } /** * Creates the UI delegate for the given component. * * @param mainColor The component to create its UI delegate. * @return The UI delegate for the given component. */ public static ComponentUI createUI ( final JComponent c ) { return buttonUI; } protected void paintButtonPressed ( Graphics g, AbstractButton button ) { if ( isToolBarButton || isFileChooserButton ) return; Color col = null; if ( !button.getBackground ().equals ( Theme.buttonNormalColor [ Theme.style ].getColor () ) ) { col = ColorRoutines.darken ( button.getBackground (), BG_CHANGE_AMOUNT ); } else { col = Theme.buttonPressedColor [ Theme.style ].getColor (); } g.setColor ( col ); switch ( Theme.derivedStyle [ Theme.style ] ) { case Theme.TINY_STYLE : drawTinyButton ( g, button, col ); break; case Theme.W99_STYLE : drawWinButton ( g, button, col ); break; case Theme.YQ_STYLE : drawXpButton ( g, button, col, false ); break; } if ( ! ( button instanceof JToggleButton ) ) { // Changed in 1.3.04: If button is icon-only // then don't shift if ( Theme.shiftButtonText [ Theme.style ] && button.getText () != null && !"".equals ( button.getText () ) ) { g.translate ( 1, 1 ); graphicsTranslated = true; } } } public void paintToolBarButton ( Graphics g, AbstractButton b ) { Color col = null; // New in 1.3.7 boolean isRollover = b.getModel ().isRollover () || b.getModel ().isArmed (); Color toolButtColor = null; if ( isFileChooserButton ) { toolButtColor = b.getParent ().getBackground (); } else { toolButtColor = Theme.toolButtColor [ Theme.style ].getColor (); } if ( b.getModel ().isPressed () ) { if ( isRollover ) { col = Theme.toolButtPressedColor [ Theme.style ].getColor (); } else { if ( b.isSelected () ) { col = Theme.toolButtSelectedColor [ Theme.style ].getColor (); } else { col = toolButtColor; } } } else if ( isRollover && Theme.derivedStyle [ Theme.style ] == Theme.YQ_STYLE ) { if ( b.isSelected () ) { col = Theme.toolButtSelectedColor [ Theme.style ].getColor (); } else { col = Theme.toolButtRolloverColor [ Theme.style ].getColor (); } } else if ( b.isSelected () ) { col = Theme.toolButtSelectedColor [ Theme.style ].getColor (); } else { col = toolButtColor; } g.setColor ( col ); switch ( Theme.derivedStyle [ Theme.style ] ) { case Theme.TINY_STYLE : drawTinyToolBarButton ( g, b, col, false ); break; case Theme.W99_STYLE : drawWinToolBarButton ( g, b, col, false ); break; case Theme.YQ_STYLE : drawXpToolBarButton ( g, b, col, false ); break; } } public void paint ( Graphics g, JComponent c ) { AbstractButton button = ( AbstractButton ) c; if ( isToolBarButton || isFileChooserButton ) { paintToolBarButton ( g, button ); // the base class may paint text and/or icons super.paint ( g, c ); return; } if ( ( button instanceof JToggleButton ) && button.isSelected () ) { paintButtonPressed ( g, button ); // the base class may paint text and/or icons super.paint ( g, c ); return; } isDefault = ( c instanceof JButton ) && ( ( ( JButton ) c ).isDefaultButton () ); boolean isRollover = button.getModel ().isRollover () && Theme.buttonRollover [ Theme.derivedStyle [ Theme.style ] ]; boolean isDefinedBackground = c.getBackground ().equals ( Theme.buttonNormalColor [ Theme.style ].getColor () ); Color col = null; if ( !button.isEnabled () ) { col = Theme.buttonDisabledColor [ Theme.style ].getColor (); } else if ( button.getModel ().isPressed () ) { if ( isRollover ) { if ( isDefinedBackground ) { col = Theme.buttonPressedColor [ Theme.style ].getColor (); } else { col = ColorRoutines.darken ( c.getBackground (), BG_CHANGE_AMOUNT ); } } else { // button pressed but mouse exited col = c.getBackground (); } } else if ( isRollover ) { if ( isDefinedBackground ) { col = Theme.buttonRolloverBgColor [ Theme.style ].getColor (); } else { col = ColorRoutines.lighten ( c.getBackground (), BG_CHANGE_AMOUNT ); } } else { col = c.getBackground (); } g.setColor ( col ); switch ( Theme.derivedStyle [ Theme.style ] ) { case Theme.TINY_STYLE : drawTinyButton ( g, button, col ); break; case Theme.W99_STYLE : drawWinButton ( g, button, col ); break; case Theme.YQ_STYLE : drawXpButton ( g, button, col, isRollover ); break; } // the base class may paint text and/or icons super.paint ( g, c ); } // this overrides BasicButtonUI.paintIcon(...) protected void paintIcon ( Graphics g, JComponent c, Rectangle iconRect ) { if ( c instanceof JToggleButton ) { paintToggleButtonIcon ( g, c, iconRect ); } else { super.paintIcon ( g, c, iconRect ); } } protected void paintToggleButtonIcon ( Graphics g, JComponent c, Rectangle iconRect ) { AbstractButton b = ( AbstractButton ) c; ButtonModel model = b.getModel (); Icon icon = null; if ( !model.isEnabled () ) { if ( model.isSelected () ) { icon = ( Icon ) b.getDisabledSelectedIcon (); } else { icon = ( Icon ) b.getDisabledIcon (); } } else if ( model.isPressed () && model.isArmed () ) { icon = ( Icon ) b.getPressedIcon (); if ( icon == null ) { // Use selected icon icon = ( Icon ) b.getSelectedIcon (); } } else if ( model.isSelected () ) { if ( b.isRolloverEnabled () && model.isRollover () ) { icon = ( Icon ) b.getRolloverSelectedIcon (); if ( icon == null ) { icon = ( Icon ) b.getSelectedIcon (); } } else { icon = ( Icon ) b.getSelectedIcon (); } } else if ( model.isRollover () && Theme.derivedStyle [ Theme.style ] == Theme.YQ_STYLE ) { icon = ( Icon ) b.getRolloverIcon (); } if ( icon == null ) { icon = ( Icon ) b.getIcon (); } icon.paintIcon ( b, g, iconRect.x, iconRect.y ); } public void update ( Graphics g, JComponent c ) { isToolBarButton = Boolean.TRUE.equals ( c .getClientProperty ( TinyToolBarUI.IS_TOOL_BAR_BUTTON_KEY ) ); isFileChooserButton = Boolean.TRUE.equals ( c .getClientProperty ( TinyFileChooserUI.IS_FILE_CHOOSER_BUTTON_KEY ) ); paint ( g, c ); graphicsTranslated = false; } private void drawTinyButton ( Graphics g, AbstractButton b, Color c ) { } private void drawWinButton ( Graphics g, AbstractButton b, Color c ) { int w = b.getWidth (); int h = b.getHeight (); if ( b.isContentAreaFilled () && b.isOpaque () ) { g.fillRect ( 1, 1, w - 2, h - 2 ); } } private void drawXpButton ( Graphics g, AbstractButton b, Color c, boolean isRollover ) { if ( !b.isContentAreaFilled () ) return; if ( !b.isOpaque () ) return; int w = b.getWidth (); int h = b.getHeight (); // paint border background Color bg = b.getParent ().getBackground (); g.setColor ( bg ); g.drawRect ( 0, 0, w - 1, h - 1 ); int spread1 = Theme.buttonSpreadLight [ Theme.style ]; int spread2 = Theme.buttonSpreadDark [ Theme.style ]; if ( !b.isEnabled () ) { spread1 = Theme.buttonSpreadLightDisabled [ Theme.style ]; spread2 = Theme.buttonSpreadDarkDisabled [ Theme.style ]; } float spreadStep1 = 10.0f * spread1 / ( h - 3 ); float spreadStep2 = 10.0f * spread2 / ( h - 3 ); int halfY = h / 2; int yd; for ( int y = 1 ; y < h - 1 ; y++ ) { if ( y < halfY ) { yd = halfY - y; g.setColor ( ColorRoutines.lighten ( c, ( int ) ( yd * spreadStep1 ) ) ); } else if ( y == halfY ) { g.setColor ( c ); } else { yd = y - halfY; g.setColor ( ColorRoutines.darken ( c, ( int ) ( yd * spreadStep2 ) ) ); } g.drawLine ( 2, y, w - 3, y ); if ( y == 1 ) { // left vertical line g.drawLine ( 1, 1, 1, h - 2 ); if ( isRollover || isDefault ) { // right vertical line g.drawLine ( w - 2, 1, w - 2, h - 2 ); } } else if ( y == h - 2 && !isRollover && !isDefault ) { // right vertical line g.drawLine ( w - 2, 1, w - 2, h - 2 ); } } // 1 pixel away from each corner if ( isRollover ) { g.setColor ( Theme.buttonRolloverColor [ Theme.style ].getColor () ); g.drawLine ( 1, h - 2, 1, h - 2 ); g.drawLine ( w - 2, h - 2, w - 2, h - 2 ); } else if ( isDefault ) { g.setColor ( Theme.buttonDefaultColor [ Theme.style ].getColor () ); g.drawLine ( 1, h - 2, 1, h - 2 ); g.drawLine ( w - 2, h - 2, w - 2, h - 2 ); } } private void drawTinyToolBarButton ( Graphics g, AbstractButton b, Color c, boolean isPressed ) { } private void drawWinToolBarButton ( Graphics g, AbstractButton b, Color c, boolean isPressed ) { int w = b.getWidth (); int h = b.getHeight (); if ( b.isContentAreaFilled () ) { g.fillRect ( 1, 1, w - 2, h - 2 ); } } private void drawXpToolBarButton ( Graphics g, AbstractButton b, Color c, boolean isPressed ) { int w = b.getWidth (); int h = b.getHeight (); if ( b.isContentAreaFilled () ) { g.fillRect ( 1, 1, w - 2, h - 2 ); } // paint border background Color bg = b.getParent ().getBackground (); g.setColor ( bg ); g.drawRect ( 0, 0, w - 1, h - 1 ); } }