/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import javax.swing.*;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.plaf.metal.MetalScrollButton;
import de.muntjak.tinylookandfeel.controlpanel.*;
/**
* TinyScrollButton
*
* @version 1.0
* @author Hans Bickel
*/
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);
}
}
}