/* BasicProgressBarUI.java --
   Copyright (C) 2004, 2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.plaf.basic;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JComponent;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ProgressBarUI;

/**
 * The Basic Look and Feel UI delegate for the 
 * JProgressBar.
 */
public class BasicProgressBarUI extends ProgressBarUI
{
  /**
   * A helper class that listens for ChangeEvents 
   * from the progressBar's model.
   */
  protected class ChangeHandler implements ChangeListener
  {
    /**
     * Called every time the state of the model changes.
     *
     * @param e The ChangeEvent given by the model.
     */
    public void stateChanged(ChangeEvent e)
    {
      // Nothing to do but repaint.
      progressBar.repaint();
    }
  }

  /**
   * This helper class is used to listen for 
   * PropertyChangeEvents from the progressBar.
   */
  private class PropertyChangeHandler implements PropertyChangeListener
  {
    /**
     * Called every time the properties of the 
     * progressBar change.
     *
     * @param e The PropertyChangeEvent given by the progressBar.
     */
    public void propertyChange(PropertyChangeEvent e)
    {
      // Only need to listen for indeterminate changes.
      // All other things are done on a repaint.
      if (e.getPropertyName().equals("inderterminate"))
	if (((Boolean) e.getNewValue()).booleanValue())
	  startAnimationTimer();
	else
	  stopAnimationTimer();
      else
        progressBar.repaint();
    }
  }

  /**
   * This helper class is used to listen for 
   * the animationTimer's intervals. On every interval,
   * the bouncing box should move.
   */
  private class Animator implements ActionListener
  {
    /**
     * Called every time the animationTimer reaches
     * its interval.
     *
     * @param e The ActionEvent given by the timer.
     */
    public void actionPerformed(ActionEvent e)
    {
      // Incrementing the animation index will cause
      // a repaint.
      incrementAnimationIndex();
    }
  }

  /** The timer used to move the bouncing box. */
  private transient Timer animationTimer;

  // The total number of frames must be an even number.
  // The total number of frames is calculated from
  // the cycleTime and repaintInterval given by
  // the basic Look and Feel defaults.
  //
  // +-----------------------------------------------+
  // | frame0 | frame1 | frame2 | frame 3 | frame 4  |
  // |        | frame7 | frame6 | frame 5 |          |
  // +-----------------------------------------------+
  
  /** The current animation index. */
  private transient int animationIndex;

  /** The total number of frames.*/
  private transient int numFrames;

  /** The helper that moves the bouncing box. */
  private transient Animator animation;

  /** The helper that listens for property change events. */
  private transient PropertyChangeHandler propertyListener;

  /** The Listener for the model. */
  protected ChangeListener changeListener;

  /** The progressBar for this UI. */
  protected JProgressBar progressBar;

  /** The length of the cell. The cell is the painted part. */
  private transient int cellLength;

  /** The gap between cells. */
  private transient int cellSpacing;

  /** The color of the text when the bar is not over it.*/
  private transient Color selectionBackground;

  /** The color of the text when the bar is over it. */
  private transient Color selectionForeground;

  /**
   * Creates a new BasicProgressBarUI object.
   */
  public BasicProgressBarUI()
  {
    super();
  }

  /**
   * Creates a new BasicProgressBarUI for the component.
   *
   * @param x The JComponent to create the UI for.
   *
   * @return A new BasicProgressBarUI.
   */
  public static ComponentUI createUI(JComponent x)
  {
    return new BasicProgressBarUI();
  }

  /**
   * This method returns the length of the bar (from the minimum)
   * in pixels (or units that the Graphics object draws in) based
   * on the progressBar's getPercentComplete() value.
   *
   * @param b The insets of the progressBar.
   * @param width The width of the progressBar.
   * @param height The height of the progressBar.
   *
   * @return The length of the bar that should be painted in pixels.
   */
  protected int getAmountFull(Insets b, int width, int height)
  {
    double percentDone = progressBar.getPercentComplete();
    if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
      return (int) (percentDone * (width - b.left - b.right));
    else
      return (int) (percentDone * (height - b.top - b.bottom));
  }

  /**
   * The current animation index.
   *
   * @return The current animation index.
   */
  protected int getAnimationIndex()
  {
    return animationIndex;
  }

  /**
   * This method returns the size and position of the bouncing box
   * for the current animation index. It stores the values in the 
   * given rectangle and returns it. It returns null if no box should
   * be drawn.
   *
   * @param r The bouncing box rectangle.
   *
   * @return The bouncing box rectangle.
   */
  protected Rectangle getBox(Rectangle r)
  {
    if (!progressBar.isIndeterminate())
      return null;
    //numFrames has to be an even number as defined by spec.
    int iterations = numFrames / 2 + 1;

    double boxDependent;
    double boxIndependent;

    if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
      {
	Dimension dims = getPreferredInnerHorizontal();
	boxDependent = (double) dims.width / iterations;
	boxIndependent = dims.height;
      }
    else
      {
	Dimension dims = getPreferredInnerVertical();
	boxDependent = (double) dims.height / iterations;
	boxIndependent = dims.width;
      }

    Rectangle vr = new Rectangle();
    SwingUtilities.calculateInnerArea(progressBar, vr);

    int index = getAnimationIndex();
    if (animationIndex > (numFrames + 1) / 2)
      index = numFrames - getAnimationIndex();

    if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
      {
	r.x = vr.x + (int) (index * boxDependent);
	r.y = vr.y;
	r.width = (int) boxDependent;
	r.height = (int) boxIndependent;
      }
    else
      {
	index++;
	r.x = vr.x;
	r.y = vr.height - (int) (index * boxDependent) + vr.y;
	r.width = (int) boxIndependent;
	r.height = (int) boxDependent;
      }

    return r;
  }

  /**
   * This method returns the length of the cells.
   *
   * @return The cell length.
   */
  protected int getCellLength()
  {
    return cellLength;
  }

  /**
   * This method returns the spacing between cells.
   *
   * @return The cell gap.
   */
  protected int getCellSpacing()
  {
    return cellSpacing;
  }

  /**
   * This method returns the maximum size of the JComponent.
   * If it returns null, it is up to the LayoutManager
   * to give it a size.
   *
   * @param c The component to find a maximum size for.
   *
   * @return The maximum size.
   */
  public Dimension getMaximumSize(JComponent c)
  {
    return getPreferredSize(c);
  }

  /**
   * This method returns the minimum size of the JComponent.
   * If it returns null, it is up to the LayoutManager to
   * give it a size.
   *
   * @param c The component to find a minimum size for.
   *
   * @return The minimum size.
   */
  public Dimension getMinimumSize(JComponent c)
  {
    return getPreferredSize(c);
  }

  /**
   * This method returns the preferred size of the inner
   * rectangle (the bounds without the insets) if the
   * progressBar is horizontal.
   *
   * @return The preferred size of the progressBar minus 
   *         insets if it's horizontal.
   */
  protected Dimension getPreferredInnerHorizontal()
  {
    Rectangle vr = new Rectangle();

    SwingUtilities.calculateInnerArea(progressBar, vr);

    return new Dimension(vr.width, vr.height);
  }

  /**
   * This method returns the preferred size of the inner
   * rectangle (the bounds without insets) if the 
   * progressBar is vertical.
   *
   * @return The preferred size of the progressBar minus
   *         insets if it's vertical.
   */
  protected Dimension getPreferredInnerVertical()
  {
    Rectangle vr = new Rectangle();

    SwingUtilities.calculateInnerArea(progressBar, vr);

    return new Dimension(vr.width, vr.height);
  }

  /**
   * This method returns the preferred size of the 
   * given JComponent. If it returns null, then it
   * is up to the LayoutManager to give it a size.
   *
   * @param c The component to find the preferred size for.
   *
   * @return The preferred size of the component.
   */
  public Dimension getPreferredSize(JComponent c)
  {
    // The only thing we need to worry about is
    // the text size.
    Graphics g = progressBar.getGraphics();

    Insets insets = c.getInsets();

    FontMetrics fm = g.getFontMetrics(c.getFont());

    int textW = fm.stringWidth(progressBar.getString());
    int textH = fm.getHeight();

    g.dispose();

    if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
      {
	if (textH < 20)
	  textH = 20;
	if (textW < 200)
	  textW = 200;
      }
    else
      {
	if (textH < 200)
	  textH = 200;
	if (textW < 20)
	  textW = 20;
      }
    textW += insets.left + insets.right;
    textH += insets.top + insets.bottom;
    return new Dimension(textW, textH);
  }

  /**
   * This method returns the Color that the text is shown in when the bar is
   * not over the text.
   *
   * @return The color of the text when the bar is not over it.
   */
  protected Color getSelectionBackground()
  {
    return selectionBackground;
  }

  /**
   * This method returns the Color that the text is shown in  when the bar is
   * over the text.
   *
   * @return The color of the text when the bar is over it.
   */
  protected Color getSelectionForeground()
  {
    return selectionForeground;
  }

  /**
   * This method returns the point (the top left of the bounding box)
   * where the text should be painted. 
   *
   * @param g The Graphics object to measure FontMetrics with.
   * @param progressString The string to paint.
   * @param x The x coordinate of the overall bounds box.
   * @param y The y coordinate of the overall bounds box.
   * @param width The width of the overall bounds box.
   * @param height The height of the overall bounds box.
   *
   * @return The top left of the bounding box where text should be painted.
   */
  protected Point getStringPlacement(Graphics g, String progressString, int x,
                                     int y, int width, int height)
  {
    Rectangle tr = new Rectangle();
    Rectangle vr = new Rectangle(x, y, width, height);
    Rectangle ir = new Rectangle();

    Font f = g.getFont();
    FontMetrics fm = g.getFontMetrics(f);

    SwingUtilities.layoutCompoundLabel(progressBar, fm, progressString, null,
                                       SwingConstants.CENTER,
                                       SwingConstants.CENTER,
                                       SwingConstants.CENTER,
                                       SwingConstants.CENTER, vr, ir, tr, 0);
    return new Point(tr.x, tr.y);
  }

  /**
   * This method increments the animation index.
   */
  protected void incrementAnimationIndex()
  {
    animationIndex++;
    //numFrames is like string length, it should be named numFrames or something
    if (animationIndex >= numFrames)
      animationIndex = 0;
    progressBar.repaint();
  }

  /**
   * This method paints the progressBar. It delegates its responsibilities
   * to paintDeterminate and paintIndeterminate.
   *
   * @param g The Graphics object to paint with.
   * @param c The JComponent to paint.
   */
  public void paint(Graphics g, JComponent c)
  {
    if (! progressBar.isIndeterminate())
      paintDeterminate(g, c);
    else
      paintIndeterminate(g, c);
      
    if (progressBar.isBorderPainted())
      progressBar.getBorder().paintBorder(progressBar, g, 0, 0,
                                          progressBar.getWidth(),
					  progressBar.getHeight());
  }

  /**
   * This method is called if the painting to be done is 
   * for a determinate progressBar.
   *
   * @param g The Graphics object to paint with.
   * @param c The JComponent to paint.
   */
  protected void paintDeterminate(Graphics g, JComponent c)
  {
    Color saved = g.getColor();
    int space = getCellSpacing();
    int len = getCellLength();
    int max = progressBar.getMaximum();
    int min = progressBar.getMinimum();
    int value = progressBar.getValue();

    Rectangle vr = new Rectangle();
    SwingUtilities.calculateInnerArea(c, vr);

    Rectangle or = c.getBounds();

    Insets insets = c.getInsets();

    int amountFull = getAmountFull(insets, or.width, or.height);

    g.setColor(c.getBackground());
    g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false);

    if (max != min && len != 0 && value > min)
      {
	int iterations = value / (space + len);

	if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
	  {
	    double spaceInUnits = space * (double) vr.width / (max - min);
	    double lenInUnits = len * (double) vr.width / (max - min);
	    double currX = vr.x;

	    g.setColor(c.getForeground());
	    g.fill3DRect(vr.x, vr.y, amountFull, vr.height, true);

	    g.setColor(c.getBackground());
	    if (spaceInUnits != 0)
	      {
		for (int i = 0; i < iterations; i++)
		  {
		    currX += lenInUnits;
		    g.fill3DRect((int) currX, vr.y, (int) spaceInUnits,
		                 vr.height, true);
		    currX += spaceInUnits;
		  }
	      }
	  }
	else
	  {
	    double currY = vr.y;
	    double spaceInUnits = space * (double) vr.height / (max - min);
	    double lenInUnits = len * (double) vr.height / (max - min);

	    g.setColor(c.getForeground());
	    g.fill3DRect(vr.x, vr.y + vr.height - amountFull, vr.width,
	                 amountFull, true);

	    g.setColor(c.getBackground());

	    if (spaceInUnits != 0)
	      {
		for (int i = 0; i < iterations; i++)
		  {
		    currY -= lenInUnits + spaceInUnits;
		    g.fill3DRect(vr.x, (int) currY, vr.width,
		                 (int) spaceInUnits, true);
		  }
	      }
	  }
      }

    if (progressBar.isStringPainted() && !progressBar.getString().equals(""))
      paintString(g, 0, 0, or.width, or.height, amountFull, insets);
    g.setColor(saved);
  }

  /**
   * This method is called if the painting to be done is for
   * an indeterminate progressBar.
   *
   * @param g The Graphics object to paint with.
   * @param c The JComponent to paint.
   */
  protected void paintIndeterminate(Graphics g, JComponent c)
  {
    //need to paint the box at it's current position. no text is painted since
    //all we're doing is bouncing back and forth
    Color saved = g.getColor();
    Insets insets = c.getInsets();

    Rectangle or = c.getBounds();
    Rectangle vr = new Rectangle();
    SwingUtilities.calculateInnerArea(c, vr);

    g.setColor(c.getBackground());
    g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false);

    Rectangle box = new Rectangle();
    getBox(box);

    g.setColor(c.getForeground());
    g.fill3DRect(box.x, box.y, box.width, box.height, true);

    if (progressBar.isStringPainted() && !progressBar.getString().equals(""))
      paintString(g, 0, 0, or.width, or.height,
                  getAmountFull(insets, or.width, or.height), insets);

    g.setColor(saved);
  }

  /**
   * This method paints the string for the progressBar.
   *
   * @param g The Graphics object to paint with.
   * @param x The x coordinate of the progressBar.
   * @param y The y coordinate of the progressBar.
   * @param width The width of the progressBar.
   * @param height The height of the progressBar.
   * @param amountFull The amount of the progressBar that has its bar filled.
   * @param b The insets of the progressBar.
   */
  protected void paintString(Graphics g, int x, int y, int width, int height,
                             int amountFull, Insets b)
  {
    // We want to place in the exact center of the bar.
    Point placement = getStringPlacement(g, progressBar.getString(),
                                         x + b.left, y + b.top,
                                         width - b.left - b.right,
                                         height - b.top - b.bottom);
    Color saved = g.getColor();

    // FIXME: The Color of the text should use selectionForeground and selectionBackground
    // but that can't be done right now, so we'll use white in the mean time.
    g.setColor(Color.WHITE);

    FontMetrics fm = g.getFontMetrics(progressBar.getFont());

    g.drawString(progressBar.getString(), placement.x,
                 placement.y + fm.getAscent());

    g.setColor(saved);
  }

  /**
   * This method sets the current animation index. If the index
   * is greater than the number of frames, it resets to 0.
   *
   * @param newValue The new animation index.
   */
  protected void setAnimationIndex(int newValue)
  {
    animationIndex = (newValue <= numFrames) ? newValue : 0;
    progressBar.repaint();
  }

  /**
   * This method sets the cell length.
   *
   * @param cellLen The cell length.
   */
  protected void setCellLength(int cellLen)
  {
    cellLength = cellLen;
  }

  /**
   * This method sets the cell spacing.
   *
   * @param cellSpace The cell spacing.
   */
  protected void setCellSpacing(int cellSpace)
  {
    cellSpacing = cellSpace;
  }

  /**
   * This method starts the animation timer. It is called
   * when the propertyChangeListener detects that the progressBar
   * has changed to indeterminate mode.
   *
   * @since 1.4
   */
  protected void startAnimationTimer()
  {
    if (animationTimer != null)
      animationTimer.start();
  }

  /**
   * This method stops the animation timer. It is called when
   * the propertyChangeListener detects that the progressBar
   * has changed to determinate mode.
   *
   * @since 1.4
   */
  protected void stopAnimationTimer()
  {
    if (animationTimer != null)
      animationTimer.stop();
    setAnimationIndex(0);
  }

  /**
   * This method changes the settings for the progressBar to
   * the defaults provided by the current Look and Feel.
   */
  protected void installDefaults()
  {
    UIDefaults defaults = UIManager.getLookAndFeelDefaults();

    progressBar.setFont(defaults.getFont("ProgressBar.font"));
    progressBar.setForeground(defaults.getColor("ProgressBar.foreground"));
    progressBar.setBackground(defaults.getColor("ProgressBar.background"));
    progressBar.setBorder(defaults.getBorder("ProgressBar.border"));
    progressBar.setOpaque(true);

    selectionForeground = defaults.getColor("ProgressBar.selectionForeground");
    selectionBackground = defaults.getColor("ProgressBar.selectionBackground");
    cellLength = defaults.getInt("ProgressBar.cellLength");
    cellSpacing = defaults.getInt("ProgressBar.cellSpacing");

    int repaintInterval = defaults.getInt("ProgressBar.repaintInterval");
    int cycleTime = defaults.getInt("ProgressBar.cycleTime");

    if (cycleTime % repaintInterval != 0
        && (cycleTime / repaintInterval) % 2 != 0)
      {
	int div = (cycleTime / repaintInterval) + 2;
	div /= 2;
	div *= 2;
	cycleTime = div * repaintInterval;
      }
    setAnimationIndex(0);
    numFrames = cycleTime / repaintInterval;
    animationTimer.setDelay(repaintInterval);
  }

  /**
   * The method uninstalls any defaults that were
   * set by the current Look and Feel.
   */
  protected void uninstallDefaults()
  {
    progressBar.setFont(null);
    progressBar.setForeground(null);
    progressBar.setBackground(null);

    selectionForeground = null;
    selectionBackground = null;
  }

  /**
   * This method registers listeners to all the 
   * components that this UI delegate needs to listen to.
   */
  protected void installListeners()
  {
    changeListener = new ChangeHandler();
    propertyListener = new PropertyChangeHandler();
    animation = new Animator();

    progressBar.addChangeListener(changeListener);
    progressBar.addPropertyChangeListener(propertyListener);
    animationTimer.addActionListener(animation);
  }

  /**
   * This method unregisters listeners to all the 
   * components that were listened to.
   */
  protected void uninstallListeners()
  {
    progressBar.removeChangeListener(changeListener);
    progressBar.removePropertyChangeListener(propertyListener);
    animationTimer.removeActionListener(animation);

    changeListener = null;
    propertyListener = null;
    animation = null;
  }

  /**
   * This method installs the UI for the given JComponent.
   * This includes setting up defaults and listeners as
   * well as initializing any values or objects that
   * the UI may need.
   *
   * @param c The JComponent that is having this UI installed.
   */
  public void installUI(JComponent c)
  {
    super.installUI(c);
    if (c instanceof JProgressBar)
      {
	progressBar = (JProgressBar) c;

	animationTimer = new Timer(200, null);
	animationTimer.setRepeats(true);

	installDefaults();
	installListeners();
      }
  }

  /**
   * This method removes the UI for the given JComponent.
   * This includes removing any listeners or defaults
   * that the installUI may have set up.
   *
   * @param c The JComponent that is having this UI uninstalled.
   */
  public void uninstallUI(JComponent c)
  {
    super.uninstallUI(c);
    uninstallListeners();
    uninstallDefaults();

    animationTimer = null;
    progressBar = null;
  }
}
