/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import javax.swing.AbstractButton;
import de.muntjak.tinylookandfeel.controlpanel.ColorRoutines;
import de.muntjak.tinylookandfeel.controlpanel.DrawRoutines;
/**
* TinyRadioButtonIcon
*
* @version 1.0
* @author Hans Bickel
*/
class TinyRadioButtonIcon extends TinyCheckBoxIcon {
// cache for already drawn icons - speeds up drawing by a factor
// of 80 or more if there are several radio buttons or one radio button
// is painted several times
static HashMap cache = new HashMap();
static final int[][] a = {
{255, 255, 255, 242, 228, 209, 187, 165, 142, 255, 255},
{255, 255, 242, 228, 209, 187, 165, 142, 120, 104, 255},
{255, 242, 228, 209, 187, 165, 142, 120, 104, 86, 72},
{242, 228, 209, 187, 165, 142, 120, 104, 86, 72, 56},
{228, 209, 187, 165, 142, 120, 104, 86, 72, 56, 42},
{209, 187, 165, 142, 120, 104, 86, 72, 56, 42, 28},
{187, 165, 142, 120, 104, 86, 72, 56, 42, 28, 17},
{165, 142, 120, 104, 86, 72, 56, 42, 28, 17, 9},
{142, 120, 104, 86, 72, 56, 42, 28, 17, 9, 0},
{255, 104, 86, 72, 56, 42, 28, 17, 9, 0, 255},
{255, 255, 72, 56, 42, 28, 17, 9, 0, 255, 255}
};
/**
* Draws the check box icon at the specified location.
*
* @param c The component to draw on.
* @param g The graphics context.
* @param x The x coordinate of the top left corner.
* @param y The y coordinate of the top left corner.
*/
public void paintIcon(Component c, Graphics g, int x, int y) {
AbstractButton button = (AbstractButton) c;
// inner space
Color col = null;
if(!button.isEnabled()) {
col = Theme.buttonDisabledColor[Theme.style].getColor();
}
else if(button.getModel().isPressed()) {
if(button.getModel().isRollover() || button.getModel().isArmed()) {
col = Theme.buttonPressedColor[Theme.style].getColor();
}
else {
col = Theme.buttonNormalColor[Theme.style].getColor();
}
}
else if(button.getModel().isRollover() && Theme.buttonRollover[Theme.style]) {
col = Theme.buttonRolloverBgColor[Theme.style].getColor();
}
else {
col = Theme.buttonNormalColor[Theme.style].getColor();
}
g.setColor(col);
switch(Theme.derivedStyle[Theme.style]) {
case Theme.TINY_STYLE:
drawTinyRadio(g, button, col, x, y, getIconWidth(), getIconHeight());
break;
case Theme.W99_STYLE:
drawWinRadio(g, button, col, x, y, getIconWidth(), getIconHeight());
break;
case Theme.YQ_STYLE:
if(TinyLookAndFeel.controlPanelInstantiated) {
drawXpRadioNoCache(g, button, col, x, y, getIconWidth(), getIconHeight());
}
else {
drawXpRadio(g, button, col, x, y, getIconWidth(), getIconHeight());
}
break;
}
// checkmark
if(!button.isSelected()) return;
if(!button.isEnabled()) {
col = Theme.buttonCheckDisabledColor[Theme.style].getColor();
}
else {
col = Theme.buttonCheckColor[Theme.style].getColor();
}
g.setColor(col);
switch(Theme.derivedStyle[Theme.style]) {
case Theme.TINY_STYLE:
drawTinyCheckMark(g, col, x, y);
break;
case Theme.W99_STYLE:
drawWinCheckMark(g, col, x, y);
break;
case Theme.YQ_STYLE:
drawXpCheckMark(g, col, x, y);
break;
}
}
private void drawTinyRadio(Graphics g, AbstractButton b, Color c,
int x, int y, int w, int h)
{
}
private void drawWinRadio(Graphics g, AbstractButton b, Color c,
int x, int y, int w, int h)
{
if(b.getModel().isPressed() && b.getModel().isRollover()) {
g.setColor(Theme.backColor[Theme.style].getColor());
}
else {
if(!b.isEnabled()) {
g.setColor(Theme.buttonLightDisabledColor[Theme.style].getColor());
}
else {
g.setColor(Theme.buttonLightColor[Theme.style].getColor());
}
}
g.fillRect(x + 2, y + 2, 8, 8);
g.setColor(Theme.backColor[Theme.style].getColor());
g.drawLine(x + 9, y + 3, x + 9, y + 3);
g.drawLine(x + 10, y + 4, x + 10, y + 7);
g.drawLine(x + 9, y + 8, x + 9, y + 8);
g.drawLine(x + 8, y + 9, x + 9, y + 9);
g.drawLine(x + 2, y + 9, x + 3, y + 9);
g.drawLine(x + 4, y + 10, x + 7, y + 10);
if(!b.isEnabled()) {
g.setColor(Theme.buttonLightDisabledColor[Theme.style].getColor());
}
else {
g.setColor(Theme.buttonLightColor[Theme.style].getColor());
}
g.drawLine(x + 10, y + 2, x + 10, y + 3);
g.drawLine(x + 11, y + 4, x + 11, y + 7);
g.drawLine(x + 10, y + 8, x + 10, y + 9);
g.drawLine(x + 8, y + 10, x + 9, y + 10);
g.drawLine(x + 4, y + 11, x + 7, y + 11);
g.drawLine(x + 2, y + 10, x + 3, y + 10);
if(!b.isEnabled()) {
g.setColor(Theme.buttonBorderDisabledColor[Theme.style].getColor());
}
else {
g.setColor(Theme.buttonBorderColor[Theme.style].getColor());
}
g.drawLine(x + 4, y + 1, x + 7, y + 1);
g.drawLine(x + 2, y + 2, x + 3, y + 2);
g.drawLine(x + 8, y + 2, x + 9, y + 2);
g.drawLine(x + 2, y + 3, x + 2, y + 3);
g.drawLine(x + 1, y + 4, x + 1, y + 7);
g.drawLine(x + 2, y + 8, x + 2, y + 8);
if(!b.isEnabled()) {
g.setColor(Theme.buttonDarkDisabledColor[Theme.style].getColor());
}
else {
g.setColor(Theme.buttonDarkColor[Theme.style].getColor());
}
g.drawLine(x + 4, y + 0, x + 7, y + 0);
g.drawLine(x + 2, y + 1, x + 3, y + 1);
g.drawLine(x + 8, y + 1, x + 9, y + 1);
g.drawLine(x + 1, y + 2, x + 1, y + 3);
g.drawLine(x + 0, y + 4, x + 0, y + 7);
g.drawLine(x + 1, y + 8, x + 1, y + 9);
}
private void drawXpRadio(Graphics g, AbstractButton b, Color c,
int x, int y, int w, int h)
{
boolean pressed = b.getModel().isPressed();
boolean armed = b.getModel().isArmed();
boolean enabled = b.isEnabled();
boolean rollover = b.getModel().isRollover();
boolean focused = (Theme.buttonFocusBorder[Theme.style] &&
!rollover && b.isFocusOwner());
Color bg = b.getBackground();
if(!b.isOpaque()) {
Container parent = b.getParent();
bg = parent.getBackground();
while(parent != null && !parent.isOpaque()) {
parent = parent.getParent();
bg = parent.getBackground();
}
}
RadioKey key = new RadioKey(c, bg, pressed, enabled, (rollover || armed), focused);
Object value = cache.get(key);
if(value != null) {
// image already cached - paint image and return
g.drawImage((Image)value, x, y, b);
return;
}
Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics imgGraphics = img.getGraphics();
imgGraphics.setColor(bg);
imgGraphics.fillRect(0, 0, w, h);
// spread light is between 0 and 20
int spread1 = Theme.buttonSpreadLight[Theme.style];
int spread2 = Theme.buttonSpreadDark[Theme.style];
if(!enabled) {
spread1 = Theme.buttonSpreadLightDisabled[Theme.style];
spread2 = Theme.buttonSpreadDarkDisabled[Theme.style];
}
int spreadStep1 = spread1 * 5; // 20 -> 100
// this means, we can never fully darken background,
// but we also want it bright enough
int spreadStep2 = spread2 * 4; // 20 -> 80
if(pressed && (rollover || armed)) {
spreadStep2 *= 2;
}
c = ColorRoutines.lighten(c, spreadStep1);
imgGraphics.setColor(ColorRoutines.darken(c, spreadStep2));
imgGraphics.fillRect(2, 2, w - 4, h - 4);
imgGraphics.fillRect(1, 5, 1, 3);
imgGraphics.fillRect(11, 5, 1, 3);
imgGraphics.fillRect(5, 1, 3, 1);
imgGraphics.fillRect(5, 11, 3, 1);
Color color;
for (int row = 0; row < 11; row++) {
for (int col = 0; col < 11; col++) {
color = new Color(c.getRed(), c.getGreen(), c.getBlue(), 255 - a[col][row]);
imgGraphics.setColor(color);
imgGraphics.drawLine(col + 1, row + 1, col + 1, row + 1);
}
}
// border
if(!enabled) {
DrawRoutines.drawXpRadioBorder(imgGraphics,
Theme.buttonBorderDisabledColor[Theme.style].getColor(), 0, 0, w, h);
}
else {
if(rollover && Theme.buttonRollover[Theme.style] && !pressed) {
DrawRoutines.drawXpRadioRolloverBorder(imgGraphics,
Theme.buttonRolloverColor[Theme.style].getColor(), 0, 0, w, h);
}
else if(focused && !pressed) {
DrawRoutines.drawXpRadioRolloverBorder(imgGraphics,
Theme.buttonDefaultColor[Theme.style].getColor(), 0, 0, w, h);
}
DrawRoutines.drawXpRadioBorder(imgGraphics,
Theme.buttonBorderColor[Theme.style].getColor(), 0, 0, w, h);
}
// dispose of image graphics
imgGraphics.dispose();
// draw the image
g.drawImage(img, x, y, b);
// add the image to the cache
cache.put(key, img);
}
// the old routine - execute this, if we are in the control panel
// (else border colors not updated)
private void drawXpRadioNoCache(Graphics g, AbstractButton b, Color c,
int x, int y, int w, int h)
{
boolean pressed = b.getModel().isPressed();
boolean armed = b.getModel().isArmed();
boolean enabled = b.isEnabled();
boolean rollover = b.getModel().isRollover();
boolean focused = (Theme.buttonFocusBorder[Theme.style] &&
!rollover && b.isFocusOwner());
boolean useCachedImage = !pressed && !armed && !rollover && !focused;
Image img = null;
Object key = null;
if(useCachedImage) {
if(enabled) {
key = new EnabledRadioKey(c,
Theme.buttonBorderColor[Theme.style].getColor());
}
else {
key = new DisabledRadioKey(c,
Theme.buttonBorderDisabledColor[Theme.style].getColor());
}
Object value = cache.get(key);
if(value != null) {
// image already cached - paint image and return
g.drawImage((Image)value, x, y, b);
return;
}
img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
}
// spread light is between 0 and 20
int spread1 = Theme.buttonSpreadLight[Theme.style];
int spread2 = Theme.buttonSpreadDark[Theme.style];
if(!enabled) {
spread1 = Theme.buttonSpreadLightDisabled[Theme.style];
spread2 = Theme.buttonSpreadDarkDisabled[Theme.style];
}
int spreadStep1 = spread1 * 5; // 20 -> 100
// this means, we can never fully darken background,
// but we also want it bright enough
int spreadStep2 = spread2 * 4; // 20 -> 80
if(pressed && (rollover || armed)) {
spreadStep2 *= 2;
}
c = ColorRoutines.lighten(c, spreadStep1);
Graphics graphics = null;
int bx = x, by = y;
if(img != null) {
graphics = img.getGraphics();
Color bg = b.getBackground();
if(!b.isOpaque()) {
Container parent = b.getParent();
bg = parent.getBackground();
while(parent != null && !parent.isOpaque()) {
parent = parent.getParent();
bg = parent.getBackground();
}
}
graphics.setColor(bg);
graphics.fillRect(0, 0, w - 1, h - 1);
bx = 0; by = 0;
}
else {
graphics = g;
graphics.translate(x, y);
}
graphics.setColor(ColorRoutines.darken(c, spreadStep2));
graphics.fillRect(2, 2, w - 4, h - 4);
graphics.fillRect(1, 5, 1, 3);
graphics.fillRect(11, 5, 1, 3);
graphics.fillRect(6, 1, 1, 1);
graphics.fillRect(6, 11, 1, 1);
Color color;
for (int row = 0; row < 11; row++) {
for (int col = 0; col < 11; col++) {
color = new Color(c.getRed(), c.getGreen(), c.getBlue(), 255 - a[col][row]);
graphics.setColor(color);
graphics.drawLine(col + 1, row + 1, col + 1, row + 1);
}
}
if(img == null) {
graphics.translate(-x, -y);
}
// border
if (!enabled) {
DrawRoutines.drawXpRadioBorder(
graphics, Theme.buttonBorderDisabledColor[Theme.style].getColor(), bx, by, w, h);
}
else {
if(rollover && Theme.buttonRollover[Theme.style] && !pressed) {
DrawRoutines.drawXpRadioRolloverBorder(
graphics, Theme.buttonRolloverColor[Theme.style].getColor(), bx, by, w, h);
}
else if(focused && !pressed) {
DrawRoutines.drawXpRadioRolloverBorder(graphics,
Theme.buttonDefaultColor[Theme.style].getColor(), bx, by, w, h);
}
DrawRoutines.drawXpRadioBorder(
graphics, Theme.buttonBorderColor[Theme.style].getColor(), bx, by, w, h);
}
if(img != null) {
// dispose of image graphics
graphics.dispose();
// draw the image
g.drawImage(img, x, y, b);
// cache image
cache.put(key, img);
}
}
private void drawTinyCheckMark(Graphics g, Color c, int x, int y) {
}
private void drawWinCheckMark(Graphics g, Color c, int x, int y) {
g.fillRect(x + 4, y + 5, 4, 2);
g.drawLine(x + 5, y + 4, x + 6, y + 4);
g.drawLine(x + 5, y + 7, x + 6, y + 7);
}
private void drawXpCheckMark(Graphics g, Color c, int x, int y) {
g.translate(x, y);
g.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), 224));
g.fillRect(5, 5, 3, 3);
g.setColor(c);
g.drawLine(6, 6, 6, 6);
g.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), 192));
g.drawLine(6, 4, 6, 4);
g.drawLine(4, 6, 4, 6);
g.drawLine(8, 6, 8, 6);
g.drawLine(6, 8, 6, 8);
g.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), 128));
g.drawLine(5, 4, 5, 4);
g.drawLine(7, 4, 7, 4);
g.drawLine(4, 5, 4, 5);
g.drawLine(8, 5, 8, 5);
g.drawLine(4, 7, 4, 7);
g.drawLine(8, 7, 8, 7);
g.drawLine(5, 8, 5, 8);
g.drawLine(7, 8, 7, 8);
g.translate(-x, -y);
}
/*
* EnabledRadioKey is used as key in the cache HashMap.
* Overrides equals() and hashCode().
* Used only if we are run from ControlPanel.
*/
static class EnabledRadioKey {
int spread1;
int spread2;
Color c, back;
EnabledRadioKey(Color c, Color back) {
spread1 = Theme.buttonSpreadLight[Theme.style];
spread2 = Theme.buttonSpreadDark[Theme.style];
this.c = c;
this.back = back;
}
public boolean equals(Object o) {
if(o == null) return false;
if(!(o instanceof EnabledCheckKey)) return false;
EnabledCheckKey other = (EnabledCheckKey)o;
return (c.equals(other.c) &&
back.equals(other.back) &&
spread1 == other.spread1 &&
spread2 == other.spread2);
}
public int hashCode() {
return c.hashCode() * back.hashCode() * spread1 * spread2;
}
}
/*
* DisabledRadioKey is used as key in the cache HashMap.
* Overrides equals() and hashCode().
* Used only if we are run from ControlPanel.
*/
static class DisabledRadioKey {
int spread1;
int spread2;
Color c, back;
DisabledRadioKey(Color c, Color back) {
spread1 = Theme.buttonSpreadLightDisabled[Theme.style];
spread2 = Theme.buttonSpreadDarkDisabled[Theme.style];
this.c = c;
this.back = back;
}
public boolean equals(Object o) {
if(o == null) return false;
if(!(o instanceof DisabledCheckKey)) return false;
DisabledCheckKey other = (DisabledCheckKey)o;
return (c.equals(other.c) &&
back.equals(other.back) &&
spread1 == other.spread1 &&
spread2 == other.spread2);
}
public int hashCode() {
return c.hashCode() * back.hashCode() * spread1 * spread2;
}
}
/*
* RadioKey is used as key in the cache HashMap.
* Overrides equals() and hashCode().
*/
static class RadioKey {
private Color c, background;
private boolean pressed;
private boolean enabled;
private boolean rollover;
private boolean focused;
RadioKey(Color c, Color background,
boolean pressed, boolean enabled, boolean rollover, boolean focused)
{
this.c = c;
this.background = background;
this.pressed = pressed;
this.enabled = enabled;
this.rollover = rollover;
this.focused = focused;
}
public boolean equals(Object o) {
if(o == null) return false;
if(!(o instanceof RadioKey)) return false;
RadioKey other = (RadioKey)o;
return pressed == other.pressed &&
enabled == other.enabled &&
rollover == other.rollover &&
focused == other.focused &&
c.equals(other.c) &&
background.equals(other.background);
}
public int hashCode() {
return c.hashCode() *
background.hashCode() *
(pressed ? 1 : 2) *
(enabled ? 4 : 8) *
(rollover ? 16 : 32);
}
}
}