SelfDrawingIcon.java :  » IDE » Schmortopf » Schmortopf » FileComponents » View » Java Open Source

Java Open Source » IDE » Schmortopf 
Schmortopf » Schmortopf » FileComponents » View » SelfDrawingIcon.java
package Schmortopf.FileComponents.View;

                   
 /**
  *  An Icon, which draws its content using awt/swing
  *  without connection to a file on disk.
  *
  *  Used for tree's.
  */

import java.util.Vector;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;

import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.metal.*;





public class SelfDrawingIcon implements Icon
{

  public static final byte ColorBlack   = (byte)0; // Black -> black or white, depends on background
  public static final byte ColorOrange  = (byte)1;
  public static final byte ColorRed     = (byte)2;
  public static final byte ColorYellow  = (byte)3;
  public static final byte ColorGreen   = (byte)4;
  public static final byte ColorBlue    = (byte)5;
  public static final byte ColorGray    = (byte)6;


  private String iconText;
  private int textColorKey;

  private Color  textColor = Color.black;

  private Shape[] textShapes;
  private Stroke stroke;

  private GradientPaint gradientPaint;
  private GradientPaint gradientPaintSelected;
  
  private int height;
  private int width;

  private boolean isSelected = false;
  private Color selectionColor = new Color(122,122,122);


  private Color startColor = Color.white;


 /**
  *  Creates an icon with the passed text on it.
  *  The textColorKey is must be one of the static keys of this class.
  *  The actual textcolor is adjusted, so that the contrast to
  *  the current background is big enough.
  */
  public SelfDrawingIcon( final String iconText,
                          final int textColorKey )
  {
    this.iconText = iconText;
    this.textColorKey = textColorKey;
    this.textColor = this.createColorWithContrastToBackground( textColorKey );

    // Make the glyphvector :
    final  Font rawFont = UIManager.getFont("Tree.font");

    int textPixelSize = rawFont.getSize(); // unit is pixel, not points here.
    final Font font = new Font( rawFont.getName(), Font.BOLD, textPixelSize );
    final FontRenderContext frc = new FontRenderContext( new AffineTransform(),true,true );
    final GlyphVector glyphVector = font.createGlyphVector(frc,this.iconText);

    double hShift = 0.0;
    double vShift = 0.0;

    this.textShapes = new Shape[glyphVector.getNumGlyphs()];

    // The font metrics has changed a bit since jdk 1.4, so adjust the sizes :
    String version = System.getProperty("java.version");
    if( version.compareTo("1.4") < 0 )
     {
       // jdk 1.3 or less :
       this.height = textPixelSize + 4;
       hShift = font.getSize()/4.0;
       vShift = font.getSize(); // in pixels, not dots
       // In jdk1.3 getGlyphOutline() returned the glyph at
       // the origin of the system, so it has to be translated for each :
       for( int k=0; k < glyphVector.getNumGlyphs(); k++ )
        {
          final Shape glyph = glyphVector.getGlyphOutline(k);
          Point2D pos = glyphVector.getGlyphPosition(k);
          AffineTransform trans =             
             AffineTransform.getTranslateInstance( pos.getX() + hShift,
                                                   pos.getY() + vShift );
          final Shape translatedGlyph = trans.createTransformedShape(glyph);
          this.textShapes[k] = translatedGlyph;
        }
     }
    else   
     {
       // jdk 1.4 or later :
       this.height = textPixelSize + 4;
       hShift = font.getSize()/4; // offset for all
       vShift = font.getSize(); // in pixels, not dots
       // In jdk1.4+, getGlyphOutline() returns the glyph at the correct
       // position inside the glyph vector, so we don't have to shift each : 
       for( int k=0; k < glyphVector.getNumGlyphs(); k++ )
        {
          final Shape glyph = glyphVector.getGlyphOutline(k);
          Point2D pos = glyphVector.getGlyphPosition(k);
          AffineTransform trans =
             AffineTransform.getTranslateInstance( hShift,
                                                   pos.getY() + vShift );
          final Shape translatedGlyph = trans.createTransformedShape(glyph);
          this.textShapes[k] = translatedGlyph;
        }
     }


    this.width = 16;
    if( this.textShapes.length > 0 )
     {
       final Shape lastShape = this.textShapes[ this.textShapes.length-1 ];
       this.width = lastShape.getBounds().x + lastShape.getBounds().width + 4;
     }
     
    // We rasterize the width, so that the icons produce a few
    // different widths, but not too much, so it looks properly :
    final int sizeStep = 2 * font.getSize();
    int min,max;
    for( int i=1; i < 4; i++ )
     {
       min = (i-1) * sizeStep;
       max = i * sizeStep;
       if( ( this.width > min ) && ( this.width <= max ) )
        {
          this.width = max;
        }
     }

   this.stroke = new BasicStroke( 2, // 2 point stroke for shadowing
                                  BasicStroke.CAP_BUTT,
                                  BasicStroke.JOIN_BEVEL );

   // Create a gradient from a startcolor to the backgroundcolor :
   final Color endColor = UIManager.getColor("TextField.background");
   final int endColorAverage = (endColor.getRed()+endColor.getGreen()+endColor.getBlue())/3;
   this.startColor = null;
   if( endColorAverage > 122 )
    {
      this.startColor = new Color(200,200,200);
    } 
   else
    {
      this.startColor = new Color(80,80,80);
    }
   this.gradientPaint = new GradientPaint( 0f,0f,
                                           startColor,
                                           (float)this.width,
                                           0.0f,
                                           endColor );
   this.gradientPaintSelected = new GradientPaint( 0f,0f,
                                           startColor,
                                           (float)this.width,
                                           0.0f,
                                           endColor );

  } // Constructor



  

 /**
  *  Switch for the attribute isSelected, which
  *  changes some drawing properties.
  */
  public void setSelected( final boolean state )
  {
    this.isSelected = state;
  } // setSelected



  public void setSelectionColor( final Color selectionColor )
  {
    this.selectionColor = selectionColor;
    // change the gradient to an uniform filled paint
    // with the selectioncolor :
    this.gradientPaintSelected = new GradientPaint( 0f,0f,
                                            this.selectionColor,
                                            (float)this.width,
                                            0.0f,
                                            this.selectionColor );
  }



  /**
   * Draw the icon at the specified location.  Icon implementations
   * may use the Component argument to get properties useful for
   * painting, e.g. the foreground or background color.
   */
  public void paintIcon( Component c, Graphics g, int x, int y )
  {
    final Graphics2D graphics2D = (Graphics2D)g;
    // Backup:
    final Color saveColor = graphics2D.getColor();
    final AffineTransform backupTransform = graphics2D.getTransform();
    final Stroke backupStroke = graphics2D.getStroke();
    final Paint savePaint = graphics2D.getPaint();
    
    final Object backupAntiAliasRendering = graphics2D.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
    final Object backupQualityRendering = graphics2D.getRenderingHint( RenderingHints.KEY_RENDERING );
    
    // Reconfigure / draw:
    g.translate(x,y);

    graphics2D.setRenderingHint( RenderingHints.KEY_ANTIALIASING,
                                 RenderingHints.VALUE_ANTIALIAS_ON );
    graphics2D.setRenderingHint( RenderingHints.KEY_RENDERING,
                                 RenderingHints.VALUE_RENDER_QUALITY );
    
    // paint the gradient background :

    GradientPaint currentGradient = null;
    if( this.isSelected )
     {
        currentGradient = this.gradientPaintSelected;
     }
    else
     {
        currentGradient = this.gradientPaint;
     }

    graphics2D.setPaint( currentGradient );
    graphics2D.fill( new Rectangle(0,0,this.getIconWidth(),this.getIconHeight() ) );

    graphics2D.setPaint(this.textColor);
    for( int k=0; k < this.textShapes.length; k++ )
     {
       graphics2D.fill( this.textShapes[k] );
     }

    // Restore :    
    graphics2D.setTransform( backupTransform );
    graphics2D.setColor(saveColor);
    graphics2D.setStroke(backupStroke);
    
    graphics2D.setRenderingHint( RenderingHints.KEY_ANTIALIASING,backupAntiAliasRendering );
    graphics2D.setRenderingHint( RenderingHints.KEY_RENDERING,backupQualityRendering );

    graphics2D.setPaint(savePaint);
  } // paintIcon



  /**
   * Returns the icon's width.
   *
   * @return an int specifying the fixed width of the icon.
   */
  public int getIconWidth()
  {
    return this.width;
  }



  /**
   * Returns the icon's height.
   *
   * @return an int specifying the fixed height of the icon.
   */
  public int getIconHeight()
  {
    return this.height;
  }



  private Color createColorWithContrastToBackground( final int textColorKey )
  {
    final Color background = UIManager.getColor("TextField.background");
    final int average = (background.getRed()+background.getGreen()+background.getBlue())/3;
    int contrast = 255-average;
    if( contrast < 50  ) contrast =  50; // dont saturate all
    if( contrast > 200 ) contrast = 200; // dont saturate all
    Color c = null;
    switch( textColorKey )
     {
       case ColorBlack :
            if( average > 122 )
             {
               c = new Color(0,0,0);
             } else
             {
               c = new Color(255,255,255);
             }
            break;
       case ColorRed :
               c = this.createColorFromFractions(0.850,0.075,0.075,contrast);
            break;
       case ColorOrange :
               c = this.createColorFromFractions(0.500,0.350,0.150,contrast);
            break;
       case ColorYellow :
               c = this.createColorFromFractions(0.450,0.450,0.100,contrast);
            break;
       case ColorGreen :
               c = this.createColorFromFractions(0.075,0.850,0.075,contrast);
            break;
       case ColorBlue :
               c = this.createColorFromFractions(0.075,0.075,0.850,contrast);
            break;
       case ColorGray :
               c = new Color( contrast,contrast,contrast );
            break;
       default :
            c = new Color(30,30,30); // should not happen
     } // case
    return c;
  }



 /**
  *  Creates a color with the passed color fractions, which
  *  has the passed average value.
  *  The sum of the fractions should equal one.
  */
  private Color createColorFromFractions(  final double rFraction,
                                           final double gFraction,
                                           final double bFraction,
                                           final int grayScaleAverage )
  {
    final double avInitial = ( rFraction + gFraction + bFraction ) / 3.0;
    double scalingFactor = 1.0;
    if( avInitial > 1e-10 )
     {
       scalingFactor = 1.0 * grayScaleAverage / avInitial;
     }
    double r = rFraction * scalingFactor;
    double g = gFraction * scalingFactor;
    double b = bFraction * scalingFactor;
    // If we can't reach the fractions, try to hold the average
    // by transferring from the biggest value. Its only
    // an approximative correction somehow, not more :
    if(  (rFraction > gFraction) && (rFraction > bFraction) )
     {
       if( r > 255.0 )
        {
          final double halfOver = (r-255.0)/2.0;
          r = 255.0;
          g += halfOver;
          b += halfOver;
        }
     }
    else
    if(  (gFraction > rFraction) && (gFraction > bFraction) )
     {
       if( g > 255.0 )
        {
          final double halfOver = (g-255.0)/2.0;
          g = 255.0;
          r += halfOver;
          b += halfOver;
        }
     }
    else
    if(  (bFraction > rFraction) && (bFraction > gFraction) )
     {
       if( b > 255.0 )
        {
          final double halfOver = (b-255.0)/2.0;
          b = 255.0;
          r += halfOver;
          g += halfOver;
        }
     }
    // chop:
    if( r > 255.0 ) r = 255;
    if( g > 255.0 ) g = 255;
    if( b > 255.0 ) b = 255;
    return new Color( (int)r, (int)g, (int)b );
  }




} // SelfDrawingIcon





java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.