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