/******************************************************************************* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.Insets; import java.awt.image.BufferedImage; import java.util.HashMap; import javax.swing.SwingConstants; import javax.swing.plaf.basic.BasicArrowButton; import de.muntjak.tinylookandfeel.controlpanel.ColorRoutines; /** * TinyScrollButton * * @version 1.0 * @author Hans Bickel */ @SuppressWarnings ( { "all" } ) public class TinyScrollButton extends BasicArrowButton { // cache for already drawn icons - speeds up drawing by a factor // of 2.2 if there are several scroll buttons or one scroll button // is painted several times static HashMap cache = new HashMap (); private boolean isRollover; private TinyScrollBarUI scrollbarUI; protected static Dimension [] size = new Dimension [ 3 ]; static { size [ 0 ] = new Dimension ( 15, 15 ); size [ 1 ] = new Dimension ( 16, 16 ); size [ 2 ] = new Dimension ( 17, 17 ); } /** * Create a new ScrollButton. * * @see javax.swing.plaf.metal.MetalScrollButton#MetalScrollButton(int, int, * boolean) */ public TinyScrollButton ( int direction, TinyScrollBarUI scrollbarUI ) { super ( direction ); this.scrollbarUI = scrollbarUI; setBorder ( null ); setRolloverEnabled ( true ); setMargin ( new Insets ( 0, 0, 0, 0 ) ); setSize ( size [ Theme.derivedStyle [ Theme.style ] ] ); } /** * Paints the button * * @see java.awt.Component#paint(Graphics) */ public void paint ( Graphics g ) { isRollover = false; Color c = null; if ( !scrollbarUI.isThumbVisible () ) { c = Theme.scrollButtDisabledColor [ Theme.style ].getColor (); } else if ( getModel ().isPressed () ) { c = Theme.scrollButtPressedColor [ Theme.style ].getColor (); } else if ( getModel ().isRollover () && Theme.scrollRollover [ Theme.style ] ) { c = Theme.scrollButtRolloverColor [ Theme.style ].getColor (); isRollover = true; } else { c = Theme.scrollButtColor [ Theme.style ].getColor (); } g.setColor ( c ); switch ( Theme.derivedStyle [ Theme.style ] ) { case Theme.TINY_STYLE : drawTinyButton ( g, getSize () ); break; case Theme.W99_STYLE : drawWinButton ( g, getSize () ); break; case Theme.YQ_STYLE : if ( TinyLookAndFeel.controlPanelInstantiated ) { drawXpButtonNoCache ( g, getSize (), c ); } else { drawXpButton ( g, getSize (), c ); } break; } // arrows depend on scrollbar's style if ( !scrollbarUI.isThumbVisible () ) { g.setColor ( Theme.scrollArrowDisabledColor [ Theme.style ].getColor () ); } else { g.setColor ( Theme.scrollArrowColor [ Theme.style ].getColor () ); } switch ( Theme.derivedStyle [ Theme.style ] ) { case Theme.TINY_STYLE : drawTinyArrow ( g, getSize () ); break; case Theme.W99_STYLE : drawWinArrow ( g, getSize () ); break; case Theme.YQ_STYLE : drawXpArrow ( g, getSize () ); break; } } private void drawTinyButton ( Graphics g, Dimension size ) { } private void drawWinButton ( Graphics g, Dimension size ) { g.fillRect ( 1, 1, size.width - 2, size.height - 2 ); g.drawLine ( 0, 0, size.width - 1, 0 ); g.drawLine ( 0, 0, 0, size.height - 1 ); if ( getModel ().isPressed () && scrollbarUI.isThumbVisible () ) { g.setColor ( Theme.scrollBorderColor [ Theme.style ].getColor () ); g.drawRect ( 0, 0, size.width - 1, size.height - 1 ); } else { g.setColor ( Theme.scrollLightColor [ Theme.style ].getColor () ); g.drawLine ( 1, 1, size.width - 3, 1 ); g.drawLine ( 1, 1, 1, size.height - 3 ); g.setColor ( Theme.scrollDarkColor [ Theme.style ].getColor () ); g.drawLine ( size.width - 2, 1, size.width - 2, size.height - 3 ); g.drawLine ( 1, size.height - 2, size.width - 2, size.height - 2 ); g.setColor ( Theme.scrollBorderColor [ Theme.style ].getColor () ); g.drawLine ( size.width - 1, 0, size.width - 1, size.height - 2 ); g.drawLine ( 0, size.height - 1, size.width - 1, size.height - 1 ); } } private void drawXpButton ( Graphics g, Dimension size, Color c ) { boolean enabled = scrollbarUI.isThumbVisible (); boolean pressed = getModel ().isPressed (); boolean rollover = getModel ().isRollover () && Theme.scrollRollover [ Theme.style ]; ScrollButtonKey key = new ScrollButtonKey ( ( direction == NORTH || direction == SOUTH ), c, pressed, enabled, rollover ); Object value = cache.get ( key ); if ( value != null ) { // image was cached - paint image and return g.drawImage ( ( Image ) value, 0, 0, this ); return; } Image img = new BufferedImage ( 17, 17, BufferedImage.TYPE_INT_ARGB ); Graphics imgGraphics = img.getGraphics (); // size is 17x17, independent of orientation int spread1 = Theme.scrollSpreadLight [ Theme.style ]; int spread2 = Theme.scrollSpreadDark [ Theme.style ]; if ( !scrollbarUI.isThumbVisible () ) { spread1 = Theme.scrollSpreadLightDisabled [ Theme.style ]; spread2 = Theme.scrollSpreadDarkDisabled [ Theme.style ]; } switch ( direction ) { case NORTH : case SOUTH : int h = 17; float spreadStep1 = 10.0f * spread1 / 11; float spreadStep2 = 10.0f * spread2 / 11; int halfY = 6; int yd; for ( int y = 1 ; y < h - 1 ; y++ ) { if ( y < halfY ) { yd = halfY - y; imgGraphics.setColor ( ColorRoutines.lighten ( c, ( int ) ( yd * spreadStep1 ) ) ); } else if ( y == halfY ) { imgGraphics.setColor ( c ); } else { yd = y - halfY; imgGraphics.setColor ( ColorRoutines.darken ( c, ( int ) ( yd * spreadStep2 ) ) ); } imgGraphics.drawLine ( 3, y, 14, y ); } imgGraphics.setColor ( Theme.scrollTrackBorderColor [ Theme.style ] .getColor () ); imgGraphics.drawLine ( 0, 0, 0, 16 ); if ( !scrollbarUI.isThumbVisible () ) { c = Theme.scrollLightDisabledColor [ Theme.style ].getColor (); } else { c = Theme.scrollLightColor [ Theme.style ].getColor (); } imgGraphics.setColor ( c ); imgGraphics.drawLine ( 2, 1, 2, 15 ); imgGraphics.drawLine ( 15, 1, 15, 15 ); Color lightAlpha = new Color ( c.getRed (), c.getGreen (), c.getBlue (), TinyScrollBarUI.alpha ); if ( !scrollbarUI.isThumbVisible () ) { c = Theme.scrollBorderDisabledColor [ Theme.style ].getColor (); } else { c = Theme.scrollBorderColor [ Theme.style ].getColor (); } imgGraphics.setColor ( c ); imgGraphics.drawRect ( 1, 0, 15, 16 ); // edges - blend borderColor with lightColor imgGraphics.setColor ( new Color ( c.getRed (), c.getGreen (), c .getBlue (), TinyScrollBarUI.alpha ) ); imgGraphics.drawLine ( 2, 1, 2, 1 ); imgGraphics.drawLine ( 15, 1, 15, 1 ); imgGraphics.drawLine ( 2, 15, 2, 15 ); imgGraphics.drawLine ( 15, 15, 15, 15 ); // blend lightColor with borderColor imgGraphics.setColor ( lightAlpha ); imgGraphics.drawLine ( 1, 0, 1, 0 ); imgGraphics.drawLine ( 1, 16, 1, 16 ); imgGraphics.drawLine ( 16, 0, 16, 0 ); imgGraphics.drawLine ( 16, 16, 16, 16 ); break; case EAST : case WEST : spreadStep1 = 10.0f * spread1 / 10; spreadStep2 = 10.0f * spread2 / 10; halfY = 6; for ( int y = 1 ; y < 15 ; y++ ) { if ( y < halfY ) { yd = halfY - y; imgGraphics.setColor ( ColorRoutines.lighten ( c, ( int ) ( yd * spreadStep1 ) ) ); } else if ( y == halfY ) { imgGraphics.setColor ( c ); } else { yd = y - halfY; imgGraphics.setColor ( ColorRoutines.darken ( c, ( int ) ( yd * spreadStep2 ) ) ); } imgGraphics.drawLine ( 2, y + 1, 14, y + 1 ); } imgGraphics.setColor ( Theme.scrollTrackBorderColor [ Theme.style ] .getColor () ); imgGraphics.drawLine ( 0, 0, 16, 0 ); if ( !scrollbarUI.isThumbVisible () ) { c = Theme.scrollLightDisabledColor [ Theme.style ].getColor (); } else { c = Theme.scrollLightColor [ Theme.style ].getColor (); } imgGraphics.setColor ( c ); imgGraphics.drawLine ( 1, 2, 1, 15 ); imgGraphics.drawLine ( 15, 2, 15, 15 ); lightAlpha = new Color ( c.getRed (), c.getGreen (), c.getBlue (), TinyScrollBarUI.alpha ); if ( !scrollbarUI.isThumbVisible () ) { c = Theme.scrollBorderDisabledColor [ Theme.style ].getColor (); } else { c = Theme.scrollBorderColor [ Theme.style ].getColor (); } imgGraphics.setColor ( c ); imgGraphics.drawRect ( 0, 1, 16, 15 ); // edges - blend borderColor with lightColor imgGraphics.setColor ( new Color ( c.getRed (), c.getGreen (), c .getBlue (), TinyScrollBarUI.alpha ) ); imgGraphics.drawLine ( 1, 2, 1, 2 ); imgGraphics.drawLine ( 15, 2, 15, 2 ); imgGraphics.drawLine ( 1, 15, 1, 15 ); imgGraphics.drawLine ( 15, 15, 15, 15 ); // blend lightColor with borderColor imgGraphics.setColor ( lightAlpha ); imgGraphics.drawLine ( 0, 1, 0, 1 ); imgGraphics.drawLine ( 16, 1, 16, 1 ); imgGraphics.drawLine ( 0, 16, 0, 16 ); imgGraphics.drawLine ( 16, 16, 16, 16 ); break; } // dispose of image graphics imgGraphics.dispose (); // draw the image g.drawImage ( img, 0, 0, this ); // add the image to the cache cache.put ( key, img ); } private void drawXpButtonNoCache ( Graphics g, Dimension size, Color c ) { // size is 17x17, independent of orientation int spread1 = Theme.scrollSpreadLight [ Theme.style ]; int spread2 = Theme.scrollSpreadDark [ Theme.style ]; if ( !scrollbarUI.isThumbVisible () ) { spread1 = Theme.scrollSpreadLightDisabled [ Theme.style ]; spread2 = Theme.scrollSpreadDarkDisabled [ Theme.style ]; } switch ( direction ) { case SwingConstants.NORTH : case SwingConstants.SOUTH : int h = 17; float spreadStep1 = 10.0f * spread1 / 11; float spreadStep2 = 10.0f * spread2 / 11; int halfY = 6; 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 ( 3, y, 14, y ); } g.setColor ( Theme.scrollTrackBorderColor [ Theme.style ].getColor () ); g.drawLine ( 0, 0, 0, 16 ); if ( !scrollbarUI.isThumbVisible () ) { c = Theme.scrollLightDisabledColor [ Theme.style ].getColor (); } else { c = Theme.scrollLightColor [ Theme.style ].getColor (); } g.setColor ( c ); g.drawLine ( 2, 1, 2, 15 ); g.drawLine ( 15, 1, 15, 15 ); Color lightAlpha = new Color ( c.getRed (), c.getGreen (), c.getBlue (), TinyScrollBarUI.alpha ); if ( !scrollbarUI.isThumbVisible () ) { c = Theme.scrollBorderDisabledColor [ Theme.style ].getColor (); } else { c = Theme.scrollBorderColor [ Theme.style ].getColor (); } g.setColor ( c ); g.drawRect ( 1, 0, 15, 16 ); // edges - blend borderColor with lightColor g.setColor ( new Color ( c.getRed (), c.getGreen (), c.getBlue (), TinyScrollBarUI.alpha ) ); g.drawLine ( 2, 1, 2, 1 ); g.drawLine ( 15, 1, 15, 1 ); g.drawLine ( 2, 15, 2, 15 ); g.drawLine ( 15, 15, 15, 15 ); // blend lightColor with borderColor g.setColor ( lightAlpha ); g.drawLine ( 1, 0, 1, 0 ); g.drawLine ( 1, 16, 1, 16 ); g.drawLine ( 16, 0, 16, 0 ); g.drawLine ( 16, 16, 16, 16 ); break; case SwingConstants.EAST : case SwingConstants.WEST : spreadStep1 = 10.0f * spread1 / 10; spreadStep2 = 10.0f * spread2 / 10; halfY = 6; for ( int y = 1 ; y < 15 ; 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 + 1, 14, y + 1 ); } g.setColor ( Theme.scrollTrackBorderColor [ Theme.style ].getColor () ); g.drawLine ( 0, 0, 16, 0 ); if ( !scrollbarUI.isThumbVisible () ) { c = Theme.scrollLightDisabledColor [ Theme.style ].getColor (); } else { c = Theme.scrollLightColor [ Theme.style ].getColor (); } g.setColor ( c ); g.drawLine ( 1, 2, 1, 15 ); g.drawLine ( 15, 2, 15, 15 ); lightAlpha = new Color ( c.getRed (), c.getGreen (), c.getBlue (), TinyScrollBarUI.alpha ); if ( !scrollbarUI.isThumbVisible () ) { c = Theme.scrollBorderDisabledColor [ Theme.style ].getColor (); } else { c = Theme.scrollBorderColor [ Theme.style ].getColor (); } g.setColor ( c ); g.drawRect ( 0, 1, 16, 15 ); // edges - blend borderColor with lightColor g.setColor ( new Color ( c.getRed (), c.getGreen (), c.getBlue (), TinyScrollBarUI.alpha ) ); g.drawLine ( 1, 2, 1, 2 ); g.drawLine ( 15, 2, 15, 2 ); g.drawLine ( 1, 15, 1, 15 ); g.drawLine ( 15, 15, 15, 15 ); // blend lightColor with borderColor g.setColor ( lightAlpha ); g.drawLine ( 0, 1, 0, 1 ); g.drawLine ( 16, 1, 16, 1 ); g.drawLine ( 0, 16, 0, 16 ); g.drawLine ( 16, 16, 16, 16 ); break; } } private void drawTinyArrow ( Graphics g, Dimension size ) { } private void drawWinArrow ( Graphics g, Dimension size ) { int x = 4; if ( getModel ().isPressed () && scrollbarUI.isThumbVisible () ) { x = 5; } switch ( direction ) { case SwingConstants.NORTH : g.drawLine ( x + 3, x + 2, x + 3, x + 2 ); g.drawLine ( x + 2, x + 3, x + 4, x + 3 ); g.drawLine ( x + 1, x + 4, x + 5, x + 4 ); g.drawLine ( x, x + 5, x + 6, x + 5 ); if ( !scrollbarUI.isThumbVisible () ) { g.setColor ( Color.WHITE ); g.drawLine ( x + 1, x + 6, x + 7, x + 6 ); } break; case SwingConstants.SOUTH : g.drawLine ( x, x + 2, x + 6, x + 2 ); g.drawLine ( x + 1, x + 3, x + 5, x + 3 ); g.drawLine ( x + 2, x + 4, x + 4, x + 4 ); g.drawLine ( x + 3, x + 5, x + 3, x + 5 ); if ( !scrollbarUI.isThumbVisible () ) { g.setColor ( Color.WHITE ); g.drawLine ( x + 4, x + 6, x + 4, x + 6 ); g.drawLine ( x + 4, x + 5, x + 5, x + 5 ); g.drawLine ( x + 5, x + 4, x + 6, x + 4 ); g.drawLine ( x + 6, x + 3, x + 7, x + 3 ); } break; case SwingConstants.EAST : g.drawLine ( x + 5, x + 3, x + 5, x + 3 ); g.drawLine ( x + 4, x + 2, x + 4, x + 4 ); g.drawLine ( x + 3, x + 1, x + 3, x + 5 ); g.drawLine ( x + 2, x, x + 2, x + 6 ); if ( !scrollbarUI.isThumbVisible () ) { g.setColor ( Color.WHITE ); g.drawLine ( x + 3, x + 7, x + 3, x + 7 ); g.drawLine ( x + 3, x + 6, x + 4, x + 6 ); g.drawLine ( x + 4, x + 5, x + 5, x + 5 ); g.drawLine ( x + 5, x + 4, x + 6, x + 4 ); } break; case SwingConstants.WEST : g.drawLine ( x + 1, x + 3, x + 1, x + 3 ); g.drawLine ( x + 2, x + 2, x + 2, x + 4 ); g.drawLine ( x + 3, x + 1, x + 3, x + 5 ); g.drawLine ( x + 4, x, x + 4, x + 6 ); if ( !scrollbarUI.isThumbVisible () ) { g.setColor ( Color.WHITE ); g.drawLine ( x + 5, x + 1, x + 5, x + 7 ); } break; } } private void drawXpArrow ( Graphics g, Dimension size ) { switch ( direction ) { case SwingConstants.NORTH : g.drawLine ( 8, 5, 8, 5 ); g.drawLine ( 7, 6, 9, 6 ); g.drawLine ( 6, 7, 10, 7 ); g.drawLine ( 5, 8, 7, 8 ); g.drawLine ( 9, 8, 11, 8 ); g.drawLine ( 4, 9, 6, 9 ); g.drawLine ( 10, 9, 12, 9 ); g.drawLine ( 5, 10, 5, 10 ); g.drawLine ( 11, 10, 11, 10 ); break; case SwingConstants.SOUTH : g.drawLine ( 5, 6, 5, 6 ); g.drawLine ( 11, 6, 11, 6 ); g.drawLine ( 4, 7, 6, 7 ); g.drawLine ( 10, 7, 12, 7 ); g.drawLine ( 5, 8, 7, 8 ); g.drawLine ( 9, 8, 11, 8 ); g.drawLine ( 6, 9, 10, 9 ); g.drawLine ( 7, 10, 9, 10 ); g.drawLine ( 8, 11, 8, 11 ); break; case SwingConstants.EAST : g.drawLine ( 6, 5, 6, 5 ); g.drawLine ( 6, 11, 6, 11 ); g.drawLine ( 7, 4, 7, 6 ); g.drawLine ( 7, 10, 7, 12 ); g.drawLine ( 8, 5, 8, 7 ); g.drawLine ( 8, 9, 8, 11 ); g.drawLine ( 9, 6, 9, 10 ); g.drawLine ( 10, 7, 10, 9 ); g.drawLine ( 11, 8, 11, 8 ); break; case SwingConstants.WEST : g.drawLine ( 4, 8, 4, 8 ); g.drawLine ( 5, 7, 5, 9 ); g.drawLine ( 6, 6, 6, 10 ); g.drawLine ( 7, 5, 7, 7 ); g.drawLine ( 7, 9, 7, 11 ); g.drawLine ( 8, 4, 8, 6 ); g.drawLine ( 8, 10, 8, 12 ); g.drawLine ( 9, 5, 9, 5 ); g.drawLine ( 9, 11, 9, 11 ); break; } } /** * Returns the preferred size of the component wich is the size of the skin * * @see java.awt.Component#getPreferredSize() */ public Dimension getPreferredSize () { return size [ Theme.derivedStyle [ Theme.style ] ]; } /* * ScrollButtonKey is used as key in the cache HashMap. Overrides equals() and * hashCode(). */ static class ScrollButtonKey { private boolean vertical; private Color c; private boolean pressed; private boolean enabled; private boolean rollover; ScrollButtonKey ( boolean vertical, Color c, boolean pressed, boolean enabled, boolean rollover ) { this.vertical = vertical; this.c = c; this.pressed = pressed; this.enabled = enabled; this.rollover = rollover; } public boolean equals ( Object o ) { if ( o == null ) return false; if ( ! ( o instanceof ScrollButtonKey ) ) return false; ScrollButtonKey other = ( ScrollButtonKey ) o; return vertical == other.vertical && pressed == other.pressed && enabled == other.enabled && rollover == other.rollover && c.equals ( other.c ); } public int hashCode () { return c.hashCode () * ( pressed ? 1 : 2 ) * ( enabled ? 4 : 8 ) * ( rollover ? 16 : 32 ) * ( vertical ? 64 : 128 ); } } }