EFCNToolGradientPanel.java :  » IDE » Schmortopf » Schmortopf » Utility » gui » Java Open Source

Java Open Source » IDE » Schmortopf 
Schmortopf » Schmortopf » Utility » gui » EFCNToolGradientPanel.java
package Schmortopf.Utility.gui;



import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.awt.*;
import java.io.*;
import java.util.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.beans.*;
import javax.swing.plaf.metal.*;


import Schmortopf.Utility.themes.*;




public class EFCNToolGradientPanel extends JPanel
{

  // The gradient types :
  public static int ApplyUpperLeftCornerHighLight = 0;
  public static int ApplyVerticalHighLight = 1;

  // Some predefined color keystrings :
  public static String ActiveTitleBackground = "InternalFrame.activeTitleBackground";
  public static String PanelBackground       = "Panel.background";


  // The gradient strength :
  public static int LightGradientStrength  = 0;
  public static int MediumGradientStrength = 1;
  public static int StrongGradientStrength = 2;


  private Color lightColor = new Color(190,190,250);
  private Color mediumColor   = new Color(120,120,180);
  private Color darkColor   = new Color(80,80,120);
  float xGradient;

  private Color basisColor; // around this the gradient will be

  // gradient look : (defaults)
  private int gradientType     = ApplyUpperLeftCornerHighLight;
  private int gradientStrength = MediumGradientStrength;
  private String colorKey      = ActiveTitleBackground;

  float gradientLength;


  private int finalColorOffset;
  private int colorOffset;

  private boolean displayBackGroundPicture = true;
  // this can be turned off/on



  private boolean useParentBackGround = false; // when a background color has been assigned

  private ImageIcon backgroundImage = null;
  // This is set according to the current theme, and changes,
  // when the theme changes. It isnt used, if
  // displayBackGroundPicture is false.


  private ImageIcon customBackgroundImage = null;
  // This can be set by using one of the constructors.
  // If this is set, this backgroundimage is used always,
  // and not the one associated to the current theme.


  private boolean readyForSpecialUpdates = false;
  // Needed, as some updateUI() calls are too early
  // for the special UI updates, cause some components
  // could not be existing yet.


 /**
  *  Creates a panel where you can pass
  *  theGradientType = ApplyUpperLeftCornerHighLight
  *                 or ApplyVerticalHighLight
  *
  *  and
  *  theGradientStrength = LightGradientStrength
  *                     or MediumGradientStrength
  *                     or StrongGradientStrength
  *
  *  and
  *  theColorKey = null
  *             or ActiveTitleBackground
  *             or PanelBackground
  *             or any valid theme colorkey.
  *
  */
  public EFCNToolGradientPanel( final int    theGradientType,
                                final int    theGradientStrength,
                                final String theColorKey )
  {
    this( new BorderLayout(),true,theGradientType,theGradientStrength,theColorKey );
  }





 /**
  *  Creates a panel where you can pass
  *  theGradientType = ApplyUpperLeftCornerHighLight
  *                 or ApplyVerticalHighLight
  *
  *  and
  *  theGradientStrength = LightGradientStrength
  *                     or MediumGradientStrength
  *                     or StrongGradientStrength
  *
  *  and
  *  theColorKey = null
  *             or ActiveTitleBackground
  *             or PanelBackground
  *             or any valid theme colorkey.
  *
  */
  public EFCNToolGradientPanel( LayoutManager layout,
                                int    theGradientType,
                                int    theGradientStrength,
                                String theColorKey    )
  {
    this(layout,true,theGradientType,theGradientStrength,theColorKey);
  }




 /**
  *  Creates a panel where you can pass
  *  theGradientType = ApplyUpperLeftCornerHighLight
  *                 or ApplyVerticalHighLight
  *
  *  and
  *  theGradientStrength = LightGradientStrength
  *                     or MediumGradientStrength
  *                     or StrongGradientStrength
  *
  *  and
  *  theColorKey = null
  *             or ActiveTitleBackground
  *             or PanelBackground
  *             or any valid theme colorkey.
  *
  */
  public EFCNToolGradientPanel( LayoutManager layout,
                                boolean isDoubleBuffered,
                                int    theGradientType,
                                int    theGradientStrength,
                                String theColorKey   )
  {
    super(layout,isDoubleBuffered);
    this.gradientType = theGradientType;
    this.gradientStrength = theGradientStrength;
    if( colorKey != null )
     {
       this.colorKey = theColorKey;
     } // else use the default
    // scale the gradient along with the current font size :
    float unitSize = UIManager.getFont("TextField.font").getSize2D();
    this.xGradient = unitSize;

    this.updateSpecialUI(); // sets basisColor, startColor and endColor

    this.colorOffset = 0; // This will increased to the value of
                          // finalColorOffset in a few steps by the
                          // startupThread.

    this.finalColorOffset = 70; // medium gradient strength
    if( this.gradientStrength == LightGradientStrength )
     {
       this.finalColorOffset = 40;
     }
    if( this.gradientStrength == StrongGradientStrength )
     {
       this.finalColorOffset = 90;
     }

    // Launch the startupthread, which will increase the coloroffset :
    final StartupThread startupThread = new StartupThread(this);
    // but launch him after all swing work has been done -
    // so set it into the swing queue :
    EventQueue.invokeLater( new Runnable()
     {
       public void run()
       {
         startupThread.start();
       }
     });
    EventQueue.invokeLater( new Runnable()
     {
        public void run()
        {
          readyForSpecialUpdates = true;
        }
     });
  } // Constructor




 /**
  * Just calls <code>paint(g)</code>.  This method was overridden to
  * prevent an unnecessary call to clear the background.
  *
  * @param g the Graphics context in which to paint
  */
  public void update(Graphics g)
  {
    this.paint(g);
  }


  

 /**
  *  Overwritten method. Additionally updates special components.
  */
  public void updateUI()
  {
    super.updateUI();
    if( this.readyForSpecialUpdates )
     {
         if( !useParentBackGround ) // only if setBackground was never called
          {
            updateSpecialUI();
            // rescale the gradient along with the current font size :
            float unitSize = UIManager.getFont("TextField.font").getSize2D();
            xGradient = unitSize;
          }
     }
  }




 /**
  *  This last constructor additionally defines a custom background
  *  picture. If this constructor is used, the passed backround
  *  picture will be used for ever, instead of getting or changing
  *  the background picture with the theme.
  */
  public EFCNToolGradientPanel( LayoutManager layout,
                                int    theGradientType,
                                int    theGradientStrength,
                                String theColorKey,
                                ImageIcon customBackgroundImage   )
  {
    this( layout,theGradientType,theGradientStrength,theColorKey);
    this.customBackgroundImage = customBackgroundImage;
  }







 /**
  *  Set a a fixed background color, and with that : turns out the
  *  UIManager update mechanism.
  */
  public void setConstantBackground( Color bgColor )
  {
    super.setBackground(bgColor);
    this.useParentBackGround = true; // turns off UIManager special update
    this.basisColor = super.getBackground();
    this.calculateColors();
  }







 /**
  * Calculate the start and endcolor of the gradient
  * taking the basisColor as center color :
  */
  private void calculateColors()
  {
    int rBase = this.basisColor.getRed();
    int gBase = this.basisColor.getGreen();
    int bBase = this.basisColor.getBlue();
    // start color is lighter :
    int rStart = rBase + colorOffset;
    int gStart = gBase + colorOffset;
    int bStart = bBase + colorOffset;
    if(  (rStart <= 255) && (gStart <= 255) && (bStart <= 255) )
     {
       this.lightColor = new Color( rStart,gStart,bStart );
     } else
     {
       if( rStart > 255 ) rStart = 255;
       if( gStart > 255 ) gStart = 255;
       if( bStart > 255 ) bStart = 255;
       this.lightColor = new Color( rStart,gStart,bStart );
     }

    this.mediumColor = this.basisColor;

    rStart = rBase - colorOffset;
    gStart = gBase - colorOffset;
    bStart = bBase - colorOffset;
    if(  (rStart >= 0) && (gStart >= 0) && (bStart >= 0) )
     {
       this.darkColor = new Color( rStart,gStart,bStart );
     } else
     {
       if( rStart < 0 ) rStart = 0;
       if( gStart < 0 ) gStart = 0;
       if( bStart < 0 ) bStart = 0;
       this.darkColor = new Color( rStart,gStart,bStart );
     }

    // If the current panel has a background image, we use this one and
    // set the medium color slightly transparent :
    // The background image is valid, when there is a theme with background
    // image OR when a custom backgroundimage was set :



    // Intro scaling : During the startup thread loops,
    // the colorOffset goes from a fraction of finalColorOffset
    // in some steps upto this.finalColorOffset. We use this to
    // zoom in the transparency :
    double introShift = 50.0 * (this.finalColorOffset-this.colorOffset)/(1.0*this.finalColorOffset);
    int alphaColor = 170 + (int)introShift;
    if( alphaColor > 255 ) alphaColor = 255;
    if( alphaColor < 0   ) alphaColor = 0;
    if( this.displayBackGroundPicture )
     {
      if( this.customBackgroundImage != null )
       {
          // A custom image was set, so set the color a bit transparent :
          this.mediumColor = new Color(  mediumColor.getRed(),
                                         mediumColor.getGreen(),
                                         mediumColor.getBlue(),
                                         alphaColor );
          // and use this one :
          this.backgroundImage = this.customBackgroundImage;
       } else
       {
          // Check if we have a background image from the current theme:
          sun.awt.AppContext context =  sun.awt.AppContext.getAppContext();
          if( context != null)
           {
             MetalTheme currentTheme = (MetalTheme)context.get( "currentMetalTheme" );
             if( currentTheme != null )
              {
               if( currentTheme instanceof EFCNThemesBasis )
                {
                  EFCNThemesBasis efcnTheme = (EFCNThemesBasis)currentTheme;
                  this.backgroundImage = efcnTheme.getBackgroundImage();
                  if( this.backgroundImage != null )
                   {
                    this.mediumColor = new Color(  mediumColor.getRed(),
                                                   mediumColor.getGreen(),
                                                   mediumColor.getBlue(),
                                                   alphaColor );
                   }
                }
              }
           }
       }
     }
  } // calculateColors






 /**
  *  Must be called, when the lf theme changes.
  *  Called by the propertychange listener above.
  */
  public void updateSpecialUI()
  {
    // Derive the basisColor :
    Color color = UIManager.getColor( this.colorKey );
    // give more green and blue
    int r = color.getRed()   -  5;
    int g = color.getGreen() -  5;
    int b = color.getBlue()  + 10;
    // level out grayscale value a bit :
    if( r+g+b > 384 )
     {
       r -= 10;
       g -= 10;
       b -= 10;
     } else
     {
       r += 10;
       g += 10;
       b += 10;
     }
    // keep in range :
    if( r < 0 ) r = 0; if( r > 255 ) r = 255;
    if( g < 0 ) g = 0; if( g > 255 ) g = 255;
    if( b < 0 ) b = 0; if( b > 255 ) b = 255;
    // and set it as basis :
    this.basisColor = new Color(r,g,b);
    // Calculate the start and endColors from that :
    this.calculateColors();
  }













 /**
  *  Overwritten paint method to have a slight color gradient.
  */  
  public void paint( Graphics g )
  {
    Graphics2D graphics2D = (Graphics2D)g;
    final Paint savePaint = graphics2D.getPaint();

    // draw the background image, if we have one.
    // In this panel, we zoom the pic to fit horizontally,
    // and tile vertically :
    if( ( this.backgroundImage != null ) &&
        (this.displayBackGroundPicture )  )
     {
      int xMax = this.getWidth();
      int yMax = this.getHeight();
      int imageWidth  = this.backgroundImage.getIconWidth();
      int imageHeight = this.backgroundImage.getIconHeight();
      int x0 = this.getLocation().x;
      int y0 = this.getLocation().y;
      // Security [prevents endless loop, case an attribute is zero]
      if( (xMax > 1 ) &&
          (yMax > 1 ) &&
          (imageWidth > 1  ) &&
          (imageHeight > 1 )    )
       {
         AffineTransform backupTransform = graphics2D.getTransform();
         // zoom the background picture to fit the width, keep aspect ratio :
         AffineTransform xform = new AffineTransform();
         double scaleFactor = (1.0 * xMax) / (1.0 * imageWidth);
         xform.scale(scaleFactor,scaleFactor);
         // Tile vertically :
         int currentHeight = 0;
         int verticalOffset = (int)(scaleFactor*imageHeight);
         while( currentHeight < yMax )
          {
            graphics2D.drawImage( backgroundImage.getImage() ,xform,this );
            currentHeight += verticalOffset;
            xform.translate(0.0,imageHeight);
          }
         // Restore the previous graphics2D transformation :
         graphics2D.setTransform(backupTransform);
       } // if pic is ok
     } // if

    if( this.gradientType == ApplyUpperLeftCornerHighLight )
     {
      GradientPaint upperLeftGradientPaint =
                    new GradientPaint( 0f,0f,
                                       lightColor,
                                       xGradient,xGradient*5.0f,
                                       mediumColor );

      graphics2D.setPaint( upperLeftGradientPaint );
      graphics2D.fill( graphics2D.getClip() );
     }
    else if( this.gradientType == ApplyVerticalHighLight )
     {

      this.gradientLength = xGradient;
      if( gradientLength > this.getHeight()/2.5f )
       {
         gradientLength = this.getHeight()/2.5f;
       }
      GradientPaint upperVerticalGradientPaint =
                    new GradientPaint( 0f,0f,
                                       this.lightColor,
                                       0f, gradientLength,
                                       this.mediumColor );

      GradientPaint lowerVerticalGradientPaint =
                    new GradientPaint( 0f,getHeight(),
                                       this.darkColor,
                                       0f,getHeight() - gradientLength,
                                       this.mediumColor );

      Shape saveClip = graphics2D.getClip();

      Rectangle rLower = new Rectangle( 0,getHeight()/2,getWidth(),1+getHeight()/2 );
      graphics2D.setPaint( lowerVerticalGradientPaint );
      graphics2D.fill( rLower );

      Rectangle rUpper = new Rectangle( 0,0,getWidth(),1+getHeight()/2 );
      graphics2D.setPaint( upperVerticalGradientPaint );
      graphics2D.fill( rUpper );

      graphics2D.setClip(saveClip);
     }
    graphics2D.setPaint( savePaint );
    super.paintChildren(graphics2D);
  } // paint
  
  
  
    

  public boolean imageUpdate( Image img, int infoflags,
                              int x, int y, int width, int height)
  {
    return true;
  }




  public float getGradientLength()
  {
    return this.gradientLength;
  }





 /**
  *   Changes the color offset. Must be called inside
  *   the event dispatch thread.
  */
  public void setColorOffset( int newValue )
  {
    this.colorOffset = newValue;
    this.calculateColors();
    if( this.isShowing() )
     {
       this.updateUI();
     }
  }


  public void setDisplayBackgroundPicture( boolean use )
  {
    this.displayBackGroundPicture = use;
  }

  public int getFinalColorOffset()
  {
    return this.finalColorOffset;
  }





 /**
  * The startup thread, which makes this panel shape itself
  * in the first 3 seconds of its lifetime
  */
  private class StartupThread extends Thread
  {
     private EFCNToolGradientPanel bgPanel;
                 
     public StartupThread( EFCNToolGradientPanel bgPanel )
     {               
       this.bgPanel = bgPanel;
       this.setDaemon(true);
     }

     public void run()
     {
       int loops = 16;
       double offsetStep = (1.0*bgPanel.getFinalColorOffset())/(1.0*loops);
       for( int i=1; i <= loops; i++ )
        {
           final int colorOffset = (int)(i*offsetStep);
           SwingUtilities.invokeLater( new Runnable()
            {
              public void run()
              {
                bgPanel.setColorOffset(colorOffset);
              }
            });
           if( i==1 )
            {
              // Wait half a second initially - increases the effect :
              try{ Thread.sleep(660); } catch( Exception sdfkjh ){ }
            }
           else
            {
              try{ Thread.sleep(90); } catch(Exception wurscht ){}
            }
        }
     }

  } // class StartupThread





} // EFCNToolGradientPanel







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.