/******************************************************************************* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 */ @SuppressWarnings ( { "all" } ) 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 ); } } }