/*
 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.swing.plaf.basic;

import sun.swing.SwingUtilities2;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.io.Serializable;
import sun.swing.DefaultLookup;

/**
 * A Basic L&F implementation of ProgressBarUI.
 *
 * @author Michael C. Albers
 * @author Kathy Walrath
 */
public class BasicProgressBarUI extends ProgressBarUI {
    private int cachedPercent;
    private int cellLength, cellSpacing;
    // The "selectionForeground" is the color of the text when it is painted
    // over a filled area of the progress bar. The "selectionBackground"
    // is for the text over the unfilled progress bar area.
    private Color selectionForeground, selectionBackground;

    private Animator animator;

    protected JProgressBar progressBar;
    protected ChangeListener changeListener;
    private Handler handler;

    /**
     * The current state of the indeterminate animation's cycle.
     * 0, the initial value, means paint the first frame.
     * When the progress bar is indeterminate and showing,
     * the default animation thread updates this variable
     * by invoking incrementAnimationIndex()
     * every repaintInterval milliseconds.
     */
    private int animationIndex = 0;

    /**
     * The number of frames per cycle. Under the default implementation,
     * this depends on the cycleTime and repaintInterval.  It
     * must be an even number for the default painting algorithm.  This
     * value is set in the initIndeterminateValues method.
     */
    private int numFrames;   //0 1|numFrames-1 ... numFrames/2

    /**
     * Interval (in ms) between repaints of the indeterminate progress bar.
     * The value of this method is set
     * (every time the progress bar changes to indeterminate mode)
     * using the
     * "ProgressBar.repaintInterval" key in the defaults table.
     */
    private int repaintInterval;

    /**
     * The number of milliseconds until the animation cycle repeats.
     * The value of this method is set
     * (every time the progress bar changes to indeterminate mode)
     * using the
     * "ProgressBar.cycleTime" key in the defaults table.
     */
    private int cycleTime;  //must be repaintInterval*2*aPositiveInteger

    //performance stuff
    private static boolean ADJUSTTIMER = true; //makes a BIG difference;
                                               //make this false for
                                               //performance tests

    /**
     * Used to hold the location and size of the bouncing box (returned
     * by getBox) to be painted.
     *
     * @since 1.5
     */
    protected Rectangle boxRect;

    /**
     * The rectangle to be updated the next time the
     * animation thread calls repaint.  For bouncing-box
     * animation this rect should include the union of
     * the currently displayed box (which needs to be erased)
     * and the box to be displayed next.
     * This rectangle's values are set in
     * the setAnimationIndex method.
     */
    private Rectangle nextPaintRect;

    //cache
    /** The component's painting area, not including the border. */
    private Rectangle componentInnards;    //the current painting area
    private Rectangle oldComponentInnards; //used to see if the size changed

    /** For bouncing-box animation, the change in position per frame. */
    private double delta = 0.0;

    private int maxPosition = 0; //maximum X (horiz) or Y box location


    public static ComponentUI createUI(JComponent x) {
        return new BasicProgressBarUI();
    }

    public void installUI(JComponent c) {
        progressBar = (JProgressBar)c;
        installDefaults();
        installListeners();
        if (progressBar.isIndeterminate()) {
            initIndeterminateValues();
        }
    }

    public void uninstallUI(JComponent c) {
        if (progressBar.isIndeterminate()) {
            cleanUpIndeterminateValues();
        }
        uninstallDefaults();
        uninstallListeners();
        progressBar = null;
    }

    protected void installDefaults() {
        LookAndFeel.installProperty(progressBar, "opaque", Boolean.TRUE);
        LookAndFeel.installBorder(progressBar,"ProgressBar.border");
        LookAndFeel.installColorsAndFont(progressBar,
                                         "ProgressBar.background",
                                         "ProgressBar.foreground",
                                         "ProgressBar.font");
        cellLength = UIManager.getInt("ProgressBar.cellLength");
        if (cellLength == 0) cellLength = 1;
        cellSpacing = UIManager.getInt("ProgressBar.cellSpacing");
        selectionForeground = UIManager.getColor("ProgressBar.selectionForeground");
        selectionBackground = UIManager.getColor("ProgressBar.selectionBackground");
    }

    protected void uninstallDefaults() {
        LookAndFeel.uninstallBorder(progressBar);
    }

    protected void installListeners() {
        //Listen for changes in the progress bar's data.
        changeListener = getHandler();
        progressBar.addChangeListener(changeListener);

        //Listen for changes between determinate and indeterminate state.
        progressBar.addPropertyChangeListener(getHandler());
    }

    private Handler getHandler() {
        if (handler == null) {
            handler = new Handler();
        }
        return handler;
    }

    /**
     * Starts the animation thread, creating and initializing
     * it if necessary. This method is invoked when an
     * indeterminate progress bar should start animating.
     * Reasons for this may include:
     * <ul>
     *    <li>The progress bar is determinate and becomes displayable
     *    <li>The progress bar is displayable and becomes determinate
     *    <li>The progress bar is displayable and determinate and this
     *        UI is installed
     * </ul>
     * If you implement your own animation thread,
     * you must override this method.
     *
     * @since 1.4
     * @see #stopAnimationTimer
     */
    protected void startAnimationTimer() {
        if (animator == null) {
            animator = new Animator();
        }

        animator.start(getRepaintInterval());
    }

    /**
     * Stops the animation thread.
     * This method is invoked when the indeterminate
     * animation should be stopped. Reasons for this may include:
     * <ul>
     *    <li>The progress bar changes to determinate
     *    <li>The progress bar is no longer part of a displayable hierarchy
     *    <li>This UI in uninstalled
     * </ul>
     * If you implement your own animation thread,
     * you must override this method.
     *
     * @since 1.4
     * @see #startAnimationTimer
     */
    protected void stopAnimationTimer() {
        if (animator != null) {
            animator.stop();
        }
    }

    /**
     * Removes all listeners installed by this object.
     */
    protected void uninstallListeners() {
        progressBar.removeChangeListener(changeListener);
        progressBar.removePropertyChangeListener(getHandler());
        handler = null;
    }


    /**
     * Returns the baseline.
     *
     * @throws NullPointerException {@inheritDoc}
     * @throws IllegalArgumentException {@inheritDoc}
     * @see javax.swing.JComponent#getBaseline(int, int)
     * @since 1.6
     */
    public int getBaseline(JComponent c, int width, int height) {
        super.getBaseline(c, width, height);
        if (progressBar.isStringPainted() &&
                progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            FontMetrics metrics = progressBar.
                    getFontMetrics(progressBar.getFont());
            Insets insets = progressBar.getInsets();
            int y = insets.top;
            height = height - insets.top - insets.bottom;
            return y + (height + metrics.getAscent() -
                        metrics.getLeading() -
                        metrics.getDescent()) / 2;
        }
        return -1;
    }

    /**
     * Returns an enum indicating how the baseline of the component
     * changes as the size changes.
     *
     * @throws NullPointerException {@inheritDoc}
     * @see javax.swing.JComponent#getBaseline(int, int)
     * @since 1.6
     */
    public Component.BaselineResizeBehavior getBaselineResizeBehavior(
            JComponent c) {
        super.getBaselineResizeBehavior(c);
        if (progressBar.isStringPainted() &&
                progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            return Component.BaselineResizeBehavior.CENTER_OFFSET;
        }
        return Component.BaselineResizeBehavior.OTHER;
    }

    // Many of the Basic*UI components have the following methods.
    // This component does not have these methods because *ProgressBarUI
    //  is not a compound component and does not accept input.
    //
    // protected void installComponents()
    // protected void uninstallComponents()
    // protected void installKeyboardActions()
    // protected void uninstallKeyboardActions()

    protected Dimension getPreferredInnerHorizontal() {
        Dimension horizDim = (Dimension)DefaultLookup.get(progressBar, this,
            "ProgressBar.horizontalSize");
        if (horizDim == null) {
            horizDim = new Dimension(146, 12);
        }
        return horizDim;
    }

    protected Dimension getPreferredInnerVertical() {
        Dimension vertDim = (Dimension)DefaultLookup.get(progressBar, this,
            "ProgressBar.verticalSize");
        if (vertDim == null) {
            vertDim = new Dimension(12, 146);
        }
        return vertDim;
    }

    /**
     * The "selectionForeground" is the color of the text when it is painted
     * over a filled area of the progress bar.
     */
    protected Color getSelectionForeground() {
        return selectionForeground;
    }

    /**
     * The "selectionBackground" is the color of the text when it is painted
     * over an unfilled area of the progress bar.
     */
    protected Color getSelectionBackground() {
        return selectionBackground;
    }

    private int getCachedPercent() {
        return cachedPercent;
    }

    private void setCachedPercent(int cachedPercent) {
        this.cachedPercent = cachedPercent;
    }

    /**
     * Returns the width (if HORIZONTAL) or height (if VERTICAL)
     * of each of the indivdual cells/units to be rendered in the
     * progress bar. However, for text rendering simplification and
     * aesthetic considerations, this function will return 1 when
     * the progress string is being rendered.
     *
     * @return the value representing the spacing between cells
     * @see    #setCellLength
     * @see    JProgressBar#isStringPainted
     */
    protected int getCellLength() {
        if (progressBar.isStringPainted()) {
            return 1;
        } else {
            return cellLength;
        }
    }

    protected void setCellLength(int cellLen) {
        this.cellLength = cellLen;
    }

    /**
     * Returns the spacing between each of the cells/units in the
     * progress bar. However, for text rendering simplification and
     * aesthetic considerations, this function will return 0 when
     * the progress string is being rendered.
     *
     * @return the value representing the spacing between cells
     * @see    #setCellSpacing
     * @see    JProgressBar#isStringPainted
     */
    protected int getCellSpacing() {
        if (progressBar.isStringPainted()) {
            return 0;
        } else {
            return cellSpacing;
        }
    }

    protected void setCellSpacing(int cellSpace) {
        this.cellSpacing = cellSpace;
    }

    /**
     * This determines the amount of the progress bar that should be filled
     * based on the percent done gathered from the model. This is a common
     * operation so it was abstracted out. It assumes that your progress bar
     * is linear. That is, if you are making a circular progress indicator,
     * you will want to override this method.
     */
    protected int getAmountFull(Insets b, int width, int height) {
        int amountFull = 0;
        BoundedRangeModel model = progressBar.getModel();

        if ( (model.getMaximum() - model.getMinimum()) != 0) {
            if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
                amountFull = (int)Math.round(width *
                                             progressBar.getPercentComplete());
            } else {
                amountFull = (int)Math.round(height *
                                             progressBar.getPercentComplete());
            }
        }
        return amountFull;
    }

    /**
     * Delegates painting to one of two methods:
     * paintDeterminate or paintIndeterminate.
     */
    public void paint(Graphics g, JComponent c) {
        if (progressBar.isIndeterminate()) {
            paintIndeterminate(g, c);
        } else {
            paintDeterminate(g, c);
        }
    }

    /**
     * Stores the position and size of
     * the bouncing box that would be painted for the current animation index
     * in <code>r</code> and returns <code>r</code>.
     * Subclasses that add to the painting performed
     * in this class's implementation of <code>paintIndeterminate</code> --
     * to draw an outline around the bouncing box, for example --
     * can use this method to get the location of the bouncing
     * box that was just painted.
     * By overriding this method,
     * you have complete control over the size and position
     * of the bouncing box,
     * without having to reimplement <code>paintIndeterminate</code>.
     *
     * @param r  the Rectangle instance to be modified;
     *           may be <code>null</code>
     * @return   <code>null</code> if no box should be drawn;
     *           otherwise, returns the passed-in rectangle
     *           (if non-null)
     *           or a new rectangle
     *
     * @see #setAnimationIndex
     * @since 1.4
     */
    protected Rectangle getBox(Rectangle r) {
        int currentFrame = getAnimationIndex();
        int middleFrame = numFrames/2;

        if (sizeChanged() || delta == 0.0 || maxPosition == 0.0) {
            updateSizes();
        }

        r = getGenericBox(r);

        if (r == null) {
            return null;
        }
        if (middleFrame <= 0) {
            return null;
        }

        //assert currentFrame >= 0 && currentFrame < numFrames
        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            if (currentFrame < middleFrame) {
                r.x = componentInnards.x
                      + (int)Math.round(delta * (double)currentFrame);
            } else {
                r.x = maxPosition
                      - (int)Math.round(delta *
                                        (currentFrame - middleFrame));
            }
        } else { //VERTICAL indeterminate progress bar
            if (currentFrame < middleFrame) {
                r.y = componentInnards.y
                      + (int)Math.round(delta * currentFrame);
            } else {
                r.y = maxPosition
                      - (int)Math.round(delta *
                                        (currentFrame - middleFrame));
            }
        }
        return r;
    }

    /**
     * Updates delta, max position.
     * Assumes componentInnards is correct (e.g. call after sizeChanged()).
     */
    private void updateSizes() {
        int length = 0;

        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            length = getBoxLength(componentInnards.width,
                                  componentInnards.height);
            maxPosition = componentInnards.x + componentInnards.width
                          - length;

        } else { //VERTICAL progress bar
            length = getBoxLength(componentInnards.height,
                                  componentInnards.width);
            maxPosition = componentInnards.y + componentInnards.height
                          - length;
        }

        //If we're doing bouncing-box animation, update delta.
        delta = 2.0 * (double)maxPosition/(double)numFrames;
    }

    /**
     * Assumes that the component innards, max position, etc. are up-to-date.
     */
    private Rectangle getGenericBox(Rectangle r) {
        if (r == null) {
            r = new Rectangle();
        }

        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            r.width = getBoxLength(componentInnards.width,
                                   componentInnards.height);
            if (r.width < 0) {
                r = null;
            } else {
                r.height = componentInnards.height;
                r.y = componentInnards.y;
            }
          // end of HORIZONTAL

        } else { //VERTICAL progress bar
            r.height = getBoxLength(componentInnards.height,
                                    componentInnards.width);
            if (r.height < 0) {
                r = null;
            } else {
                r.width = componentInnards.width;
                r.x = componentInnards.x;
            }
        } // end of VERTICAL

        return r;
    }

    /**
     * Returns the length
     * of the "bouncing box" to be painted.
     * This method is invoked by the
     * default implementation of <code>paintIndeterminate</code>
     * to get the width (if the progress bar is horizontal)
     * or height (if vertical) of the box.
     * For example:
     * <blockquote>
     * <pre>
     *boxRect.width = getBoxLength(componentInnards.width,
     *                             componentInnards.height);
     * </pre>
     * </blockquote>
     *
     * @param availableLength  the amount of space available
     *                         for the bouncing box to move in;
     *                         for a horizontal progress bar,
     *                         for example,
     *                         this should be
     *                         the inside width of the progress bar
     *                         (the component width minus borders)
     * @param otherDimension   for a horizontal progress bar, this should be
     *                         the inside height of the progress bar; this
     *                         value might be used to constrain or determine
     *                         the return value
     *
     * @return the size of the box dimension being determined;
     *         must be no larger than <code>availableLength</code>
     *
     * @see javax.swing.SwingUtilities#calculateInnerArea
     * @since 1.5
     */
    protected int getBoxLength(int availableLength, int otherDimension) {
        return (int)Math.round(availableLength/6.0);
    }

    /**
     * All purpose paint method that should do the right thing for all
     * linear bouncing-box progress bars.
     * Override this if you are making another kind of
     * progress bar.
     *
     * @see #paintDeterminate
     *
     * @since 1.4
     */
    protected void paintIndeterminate(Graphics g, JComponent c) {
        if (!(g instanceof Graphics2D)) {
            return;
        }

        Insets b = progressBar.getInsets(); // area for border
        int barRectWidth = progressBar.getWidth() - (b.right + b.left);
        int barRectHeight = progressBar.getHeight() - (b.top + b.bottom);

        if (barRectWidth <= 0 || barRectHeight <= 0) {
            return;
        }

        Graphics2D g2 = (Graphics2D)g;

        // Paint the bouncing box.
        boxRect = getBox(boxRect);
        if (boxRect != null) {
            g2.setColor(progressBar.getForeground());
            g2.fillRect(boxRect.x, boxRect.y,
                       boxRect.width, boxRect.height);
        }

        // Deal with possible text painting
        if (progressBar.isStringPainted()) {
            if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
                paintString(g2, b.left, b.top,
                            barRectWidth, barRectHeight,
                            boxRect.x, boxRect.width, b);
            }
            else {
                paintString(g2, b.left, b.top,
                            barRectWidth, barRectHeight,
                            boxRect.y, boxRect.height, b);
            }
        }
    }


    /**
     * All purpose paint method that should do the right thing for almost
     * all linear, determinate progress bars. By setting a few values in
     * the defaults
     * table, things should work just fine to paint your progress bar.
     * Naturally, override this if you are making a circular or
     * semi-circular progress bar.
     *
     * @see #paintIndeterminate
     *
     * @since 1.4
     */
    protected void paintDeterminate(Graphics g, JComponent c) {
        if (!(g instanceof Graphics2D)) {
            return;
        }

        Insets b = progressBar.getInsets(); // area for border
        int barRectWidth = progressBar.getWidth() - (b.right + b.left);
        int barRectHeight = progressBar.getHeight() - (b.top + b.bottom);

        if (barRectWidth <= 0 || barRectHeight <= 0) {
            return;
        }

        int cellLength = getCellLength();
        int cellSpacing = getCellSpacing();
        // amount of progress to draw
        int amountFull = getAmountFull(b, barRectWidth, barRectHeight);

        Graphics2D g2 = (Graphics2D)g;
        g2.setColor(progressBar.getForeground());

        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            // draw the cells
            if (cellSpacing == 0 && amountFull > 0) {
                // draw one big Rect because there is no space between cells
                g2.setStroke(new BasicStroke((float)barRectHeight,
                        BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
            } else {
                // draw each individual cell
                g2.setStroke(new BasicStroke((float)barRectHeight,
                        BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL,
                        0.f, new float[] { cellLength, cellSpacing }, 0.f));
            }

            if (BasicGraphicsUtils.isLeftToRight(c)) {
                g2.drawLine(b.left, (barRectHeight/2) + b.top,
                        amountFull + b.left, (barRectHeight/2) + b.top);
            } else {
                g2.drawLine((barRectWidth + b.left),
                        (barRectHeight/2) + b.top,
                        barRectWidth + b.left - amountFull,
                        (barRectHeight/2) + b.top);
            }

        } else { // VERTICAL
            // draw the cells
            if (cellSpacing == 0 && amountFull > 0) {
                // draw one big Rect because there is no space between cells
                g2.setStroke(new BasicStroke((float)barRectWidth,
                        BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
            } else {
                // draw each individual cell
                g2.setStroke(new BasicStroke((float)barRectWidth,
                        BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL,
                        0f, new float[] { cellLength, cellSpacing }, 0f));
            }

            g2.drawLine(barRectWidth/2 + b.left,
                    b.top + barRectHeight,
                    barRectWidth/2 + b.left,
                    b.top + barRectHeight - amountFull);
        }

        // Deal with possible text painting
        if (progressBar.isStringPainted()) {
            paintString(g, b.left, b.top,
                        barRectWidth, barRectHeight,
                        amountFull, b);
        }
    }


    protected void paintString(Graphics g, int x, int y,
                               int width, int height,
                               int amountFull, Insets b) {
        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            if (BasicGraphicsUtils.isLeftToRight(progressBar)) {
                if (progressBar.isIndeterminate()) {
                    boxRect = getBox(boxRect);
                    paintString(g, x, y, width, height,
                            boxRect.x, boxRect.width, b);
                } else {
                    paintString(g, x, y, width, height, x, amountFull, b);
                }
            }
            else {
                paintString(g, x, y, width, height, x + width - amountFull,
                            amountFull, b);
            }
        }
        else {
            if (progressBar.isIndeterminate()) {
                boxRect = getBox(boxRect);
                paintString(g, x, y, width, height,
                        boxRect.y, boxRect.height, b);
            } else {
                paintString(g, x, y, width, height, y + height - amountFull,
                        amountFull, b);
            }
        }
    }

    /**
     * Paints the progress string.
     *
     * @param g Graphics used for drawing.
     * @param x x location of bounding box
     * @param y y location of bounding box
     * @param width width of bounding box
     * @param height height of bounding box
     * @param fillStart start location, in x or y depending on orientation,
     *        of the filled portion of the progress bar.
     * @param amountFull size of the fill region, either width or height
     *        depending upon orientation.
     * @param b Insets of the progress bar.
     */
    private void paintString(Graphics g, int x, int y, int width, int height,
                             int fillStart, int amountFull, Insets b) {
        if (!(g instanceof Graphics2D)) {
            return;
        }

        Graphics2D g2 = (Graphics2D)g;
        String progressString = progressBar.getString();
        g2.setFont(progressBar.getFont());
        Point renderLocation = getStringPlacement(g2, progressString,
                                                  x, y, width, height);
        Rectangle oldClip = g2.getClipBounds();

        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            g2.setColor(getSelectionBackground());
            SwingUtilities2.drawString(progressBar, g2, progressString,
                                       renderLocation.x, renderLocation.y);
            g2.setColor(getSelectionForeground());
            g2.clipRect(fillStart, y, amountFull, height);
            SwingUtilities2.drawString(progressBar, g2, progressString,
                                       renderLocation.x, renderLocation.y);
        } else { // VERTICAL
            g2.setColor(getSelectionBackground());
            AffineTransform rotate =
                    AffineTransform.getRotateInstance(Math.PI/2);
            g2.setFont(progressBar.getFont().deriveFont(rotate));
            renderLocation = getStringPlacement(g2, progressString,
                                                  x, y, width, height);
            SwingUtilities2.drawString(progressBar, g2, progressString,
                                       renderLocation.x, renderLocation.y);
            g2.setColor(getSelectionForeground());
            g2.clipRect(x, fillStart, width, amountFull);
            SwingUtilities2.drawString(progressBar, g2, progressString,
                                       renderLocation.x, renderLocation.y);
        }
        g2.setClip(oldClip);
    }


    /**
     * Designate the place where the progress string will be painted.
     * This implementation places it at the center of the progress
     * bar (in both x and y). Override this if you want to right,
     * left, top, or bottom align the progress string or if you need
     * to nudge it around for any reason.
     */
    protected Point getStringPlacement(Graphics g, String progressString,
                                       int x,int y,int width,int height) {
        FontMetrics fontSizer = SwingUtilities2.getFontMetrics(progressBar, g,
                                            progressBar.getFont());
        int stringWidth = SwingUtilities2.stringWidth(progressBar, fontSizer,
                                                      progressString);

        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            return new Point(x + Math.round(width/2 - stringWidth/2),
                             y + ((height +
                                 fontSizer.getAscent() -
                                 fontSizer.getLeading() -
                                 fontSizer.getDescent()) / 2));
        } else { // VERTICAL
            return new Point(x + ((width - fontSizer.getAscent() +
                    fontSizer.getLeading() + fontSizer.getDescent()) / 2),
                    y + Math.round(height/2 - stringWidth/2));
        }
    }


    public Dimension getPreferredSize(JComponent c) {
        Dimension       size;
        Insets          border = progressBar.getInsets();
        FontMetrics     fontSizer = progressBar.getFontMetrics(
                                                  progressBar.getFont());

        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            size = new Dimension(getPreferredInnerHorizontal());
            // Ensure that the progress string will fit
            if (progressBar.isStringPainted()) {
                // I'm doing this for completeness.
                String progString = progressBar.getString();
                int stringWidth = SwingUtilities2.stringWidth(
                          progressBar, fontSizer, progString);
                if (stringWidth > size.width) {
                    size.width = stringWidth;
                }
                // This uses both Height and Descent to be sure that
                // there is more than enough room in the progress bar
                // for everything.
                // This does have a strange dependency on
                // getStringPlacememnt() in a funny way.
                int stringHeight = fontSizer.getHeight() +
                                   fontSizer.getDescent();
                if (stringHeight > size.height) {
                    size.height = stringHeight;
                }
            }
        } else {
            size = new Dimension(getPreferredInnerVertical());
            // Ensure that the progress string will fit.
            if (progressBar.isStringPainted()) {
                String progString = progressBar.getString();
                int stringHeight = fontSizer.getHeight() +
                        fontSizer.getDescent();
                if (stringHeight > size.width) {
                    size.width = stringHeight;
                }
                // This is also for completeness.
                int stringWidth = SwingUtilities2.stringWidth(
                                       progressBar, fontSizer, progString);
                if (stringWidth > size.height) {
                    size.height = stringWidth;
                }
            }
        }

        size.width += border.left + border.right;
        size.height += border.top + border.bottom;
        return size;
    }

    /**
     * The Minimum size for this component is 10. The rationale here
     * is that there should be at least one pixel per 10 percent.
     */
    public Dimension getMinimumSize(JComponent c) {
        Dimension pref = getPreferredSize(progressBar);
        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            pref.width = 10;
        } else {
            pref.height = 10;
        }
        return pref;
    }

    public Dimension getMaximumSize(JComponent c) {
        Dimension pref = getPreferredSize(progressBar);
        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            pref.width = Short.MAX_VALUE;
        } else {
            pref.height = Short.MAX_VALUE;
        }
        return pref;
    }

    /**
     * Gets the index of the current animation frame.
     *
     * @since 1.4
     */
    protected int getAnimationIndex() {
        return animationIndex;
    }

    /**
     * Returns the number of frames for the complete animation loop
     * used by an indeterminate JProgessBar. The progress chunk will go
     * from one end to the other and back during the entire loop. This
     * visual behavior may be changed by subclasses in other Look and Feels.
     *
     * @return the number of frames
     * @since 1.6
     */
    protected final int getFrameCount() {
        return numFrames;
    }

    /**
     * Sets the index of the current animation frame
     * to the specified value and requests that the
     * progress bar be repainted.
     * Subclasses that don't use the default painting code
     * might need to override this method
     * to change the way that the <code>repaint</code> method
     * is invoked.
     *
     * @param newValue the new animation index; no checking
     *                 is performed on its value
     * @see #incrementAnimationIndex
     *
     * @since 1.4
     */
    protected void setAnimationIndex(int newValue) {
        if (animationIndex != newValue) {
            if (sizeChanged()) {
                animationIndex = newValue;
                maxPosition = 0;  //needs to be recalculated
                delta = 0.0;      //needs to be recalculated
                progressBar.repaint();
                return;
            }

            //Get the previous box drawn.
            nextPaintRect = getBox(nextPaintRect);

            //Update the frame number.
            animationIndex = newValue;

            //Get the next box to draw.
            if (nextPaintRect != null) {
                boxRect = getBox(boxRect);
                if (boxRect != null) {
                    nextPaintRect.add(boxRect);
                }
            }
        } else { //animationIndex == newValue
            return;
        }

        if (nextPaintRect != null) {
            progressBar.repaint(nextPaintRect);
        } else {
            progressBar.repaint();
        }
    }

    private boolean sizeChanged() {
        if ((oldComponentInnards == null) || (componentInnards == null)) {
            return true;
        }

        oldComponentInnards.setRect(componentInnards);
        componentInnards = SwingUtilities.calculateInnerArea(progressBar,
                                                             componentInnards);
        return !oldComponentInnards.equals(componentInnards);
    }

    /**
     * Sets the index of the current animation frame,
     * to the next valid value,
     * which results in the progress bar being repainted.
     * The next valid value is, by default,
     * the current animation index plus one.
     * If the new value would be too large,
     * this method sets the index to 0.
     * Subclasses might need to override this method
     * to ensure that the index does not go over
     * the number of frames needed for the particular
     * progress bar instance.
     * This method is invoked by the default animation thread
     * every <em>X</em> milliseconds,
     * where <em>X</em> is specified by the "ProgressBar.repaintInterval"
     * UI default.
     *
     * @see #setAnimationIndex
     * @since 1.4
     */
    protected void incrementAnimationIndex() {
        int newValue = getAnimationIndex() + 1;

        if (newValue < numFrames) {
            setAnimationIndex(newValue);
        } else {
            setAnimationIndex(0);
        }
    }

    /**
     * Returns the desired number of milliseconds between repaints.
     * This value is meaningful
     * only if the progress bar is in indeterminate mode.
     * The repaint interval determines how often the
     * default animation thread's timer is fired.
     * It's also used by the default indeterminate progress bar
     * painting code when determining
     * how far to move the bouncing box per frame.
     * The repaint interval is specified by
     * the "ProgressBar.repaintInterval" UI default.
     *
     * @return  the repaint interval, in milliseconds
     */
    private int getRepaintInterval() {
        return repaintInterval;
    }

    private int initRepaintInterval() {
        repaintInterval = DefaultLookup.getInt(progressBar,
                this, "ProgressBar.repaintInterval", 50);
        return repaintInterval;
    }

    /**
     * Returns the number of milliseconds per animation cycle.
     * This value is meaningful
     * only if the progress bar is in indeterminate mode.
     * The cycle time is used by the default indeterminate progress bar
     * painting code when determining
     * how far to move the bouncing box per frame.
     * The cycle time is specified by
     * the "ProgressBar.cycleTime" UI default
     * and adjusted, if necessary,
     * by the initIndeterminateDefaults method.
     *
     * @return  the cycle time, in milliseconds
     */
    private int getCycleTime() {
        return cycleTime;
    }

    private int initCycleTime() {
        cycleTime = DefaultLookup.getInt(progressBar, this,
                "ProgressBar.cycleTime", 3000);
        return cycleTime;
    }


    /** Initialize cycleTime, repaintInterval, numFrames, animationIndex. */
    private void initIndeterminateDefaults() {
        initRepaintInterval(); //initialize repaint interval
        initCycleTime();       //initialize cycle length

        // Make sure repaintInterval is reasonable.
        if (repaintInterval <= 0) {
            repaintInterval = 100;
        }

        // Make sure cycleTime is reasonable.
        if (repaintInterval > cycleTime) {
            cycleTime = repaintInterval * 20;
        } else {
            // Force cycleTime to be a even multiple of repaintInterval.
            int factor = (int)Math.ceil(
                                 ((double)cycleTime)
                               / ((double)repaintInterval*2));
            cycleTime = repaintInterval*factor*2;
        }
    }

    /**
     * Invoked by PropertyChangeHandler.
     *
     *  NOTE: This might not be invoked until after the first
     *  paintIndeterminate call.
     */
    private void initIndeterminateValues() {
        initIndeterminateDefaults();
        //assert cycleTime/repaintInterval is a whole multiple of 2.
        numFrames = cycleTime/repaintInterval;
        initAnimationIndex();

        boxRect = new Rectangle();
        nextPaintRect = new Rectangle();
        componentInnards = new Rectangle();
        oldComponentInnards = new Rectangle();

        // we only bother installing the HierarchyChangeListener if we
        // are indeterminate
        progressBar.addHierarchyListener(getHandler());

        // start the animation thread if necessary
        if (progressBar.isDisplayable()) {
            startAnimationTimer();
        }
    }

    /** Invoked by PropertyChangeHandler. */
    private void cleanUpIndeterminateValues() {
        // stop the animation thread if necessary
        if (progressBar.isDisplayable()) {
            stopAnimationTimer();
        }

        cycleTime = repaintInterval = 0;
        numFrames = animationIndex = 0;
        maxPosition = 0;
        delta = 0.0;

        boxRect = nextPaintRect = null;
        componentInnards = oldComponentInnards = null;

        progressBar.removeHierarchyListener(getHandler());
    }

    // Called from initIndeterminateValues to initialize the animation index.
    // This assumes that numFrames is set to a correct value.
    private void initAnimationIndex() {
        if ((progressBar.getOrientation() == JProgressBar.HORIZONTAL) &&
            (BasicGraphicsUtils.isLeftToRight(progressBar))) {
            // If this is a left-to-right progress bar,
            // start at the first frame.
            setAnimationIndex(0);
        } else {
            // If we go right-to-left or vertically, start at the right/bottom.
            setAnimationIndex(numFrames/2);
        }
    }

    //
    // Animation Thread
    //
    /**
     * Implements an animation thread that invokes repaint
     * at a fixed rate.  If ADJUSTTIMER is true, this thread
     * will continuously adjust the repaint interval to
     * try to make the actual time between repaints match
     * the requested rate.
     */
    private class Animator implements ActionListener {
        private Timer timer;
        private long previousDelay; //used to tune the repaint interval
        private int interval; //the fixed repaint interval
        private long lastCall; //the last time actionPerformed was called
        private int MINIMUM_DELAY = 5;

        /**
         * Creates a timer if one doesn't already exist,
         * then starts the timer thread.
         */
        private void start(int interval) {
            previousDelay = interval;
            lastCall = 0;

            if (timer == null) {
                timer = new Timer(interval, this);
            } else {
                timer.setDelay(interval);
            }

            if (ADJUSTTIMER) {
                timer.setRepeats(false);
                timer.setCoalesce(false);
            }

            timer.start();
        }

        /**
         * Stops the timer thread.
         */
        private void stop() {
            timer.stop();
        }

        /**
         * Reacts to the timer's action events.
         */
        public void actionPerformed(ActionEvent e) {
            if (ADJUSTTIMER) {
                long time = System.currentTimeMillis();

                if (lastCall > 0) { //adjust nextDelay
                //XXX maybe should cache this after a while
                    //actual = time - lastCall
                    //difference = actual - interval
                    //nextDelay = previousDelay - difference
                    //          = previousDelay - (time - lastCall - interval)
                   int nextDelay = (int)(previousDelay
                                          - time + lastCall
                                          + getRepaintInterval());
                    if (nextDelay < MINIMUM_DELAY) {
                        nextDelay = MINIMUM_DELAY;
                    }
                    timer.setInitialDelay(nextDelay);
                    previousDelay = nextDelay;
                }
                timer.start();
                lastCall = time;
            }

            incrementAnimationIndex(); //paint next frame
        }
    }


    /**
     * This inner class is marked &quot;public&quot; due to a compiler bug.
     * This class should be treated as a &quot;protected&quot; inner class.
     * Instantiate it only within subclasses of BasicProgressBarUI.
     */
    public class ChangeHandler implements ChangeListener {
        // NOTE: This class exists only for backward compatability. All
        // its functionality has been moved into Handler. If you need to add
        // new functionality add it to the Handler, but make sure this
        // class calls into the Handler.
        public void stateChanged(ChangeEvent e) {
            getHandler().stateChanged(e);
        }
    }


    private class Handler implements ChangeListener, PropertyChangeListener, HierarchyListener {
        // ChangeListener
        public void stateChanged(ChangeEvent e) {
            BoundedRangeModel model = progressBar.getModel();
            int newRange = model.getMaximum() - model.getMinimum();
            int newPercent;
            int oldPercent = getCachedPercent();

            if (newRange > 0) {
                newPercent = (int)((100 * (long)model.getValue()) / newRange);
            } else {
                newPercent = 0;
            }

            if (newPercent != oldPercent) {
                setCachedPercent(newPercent);
                progressBar.repaint();
            }
        }

        // PropertyChangeListener
        public void propertyChange(PropertyChangeEvent e) {
            String prop = e.getPropertyName();
            if ("indeterminate" == prop) {
                if (progressBar.isIndeterminate()) {
                    initIndeterminateValues();
                } else {
                    //clean up
                    cleanUpIndeterminateValues();
                }
                progressBar.repaint();
            }
        }

        // we don't want the animation to keep running if we're not displayable
        public void hierarchyChanged(HierarchyEvent he) {
            if ((he.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
                if (progressBar.isIndeterminate()) {
                    if (progressBar.isDisplayable()) {
                        startAnimationTimer();
                    } else {
                        stopAnimationTimer();
                    }
                }
            }
        }
    }
}
