package visual.dynamic.sampled;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/**
 * A fade-in or fade-out to the background color
 * (which may or may not be black))
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class Fade extends AbstractTransition
{
    private Composite    originalComposite;    
    private int          direction, frame;
    private Timer        timer;

    public static final int FADE_IN  = 0;
    public static final int FADE_OUT = 1;


    /**
     * Explicit Value Constructor
     *
     * @param direction FADE_IN or FADE_OUT
     * @param first     The first frame
     * @param duration  The duration (in frames)
     */
    public Fade(int direction, int first, int duration)
    {
       super(first, duration);
       
       if (direction == FADE_IN) this.direction = FADE_IN;
       else                      this.direction = FADE_OUT;
       
       //reset();
    }


    /**
     * Apply the post-rendering portion of
     * this Transition
     *
     * @param g      The rendering engine
     * @param frame  The current frame number
     */
    public void postRendering(Graphics g, int frame)
    {
       Graphics2D           g2;

       if (shouldApplyAt(frame))
       {
//[postRendering.

          g2 = (Graphics2D)g;
          if (originalComposite != null) g2.setComposite(originalComposite);
//]postRendering.
       }
    }
    


    /**
     * Apply the pre-rendering portion of
     * this Transition
     *
     * @param g      The rendering engine
     * @param frame  The current frame number
     */
    public void preRendering(Graphics g, int frame)
    {
       AlphaComposite       ac;
       float                alpha;        
       Graphics2D           g2;
        
       if (shouldApplyAt(frame))
       {
//[preRendering.           

          g2 = (Graphics2D)g;
          originalComposite = g2.getComposite();          

          alpha = ((float)(frame - first + 1))/(float)duration;
          if (direction == FADE_OUT) alpha = 1.0f - alpha;
           
          if      (alpha > 1.0f) alpha = 1.0f;
          else if (alpha < 0.0f) alpha = 0.0f;
           
           
          setDestinationPixels(g2);
           
          ac  = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                                           alpha);
          g2.setComposite(ac);
//]preRendering.
       }
    }
    

//[setDestinationPixels.

    /**
     * Set the destination (in the Porter-Duff sense) pixels
     * to be used in alpha blending
     *
     * @param g  The rendering engine
     */
    protected void setDestinationPixels(Graphics g)
    {
       Graphics2D       g2;
       Rectangle        r;

       g2 = (Graphics2D)g;

       r = g2.getClipBounds();

       g2.setComposite(AlphaComposite.Src);
       g2.setColor(g2.getBackground());
       g2.fill(r);
       g2.draw(r);
    }
//]setDestinationPixels.
}
