/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.java.swing.plaf.windows;

import javax.swing.plaf.basic.*;
import javax.swing.plaf.*;
import javax.swing.*;
import java.awt.*;

import static com.sun.java.swing.plaf.windows.TMSchema.*;
import static com.sun.java.swing.plaf.windows.XPStyle.Skin;


/**
 * Windows rendition of the component.
 * <p>
 * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases.  The current serialization support is appropriate
 * for short term storage or RMI between applications running the same
 * version of Swing.  A future release of Swing will provide support for
 * long term persistence.
 *
 * @author Michael C. Albers
 */
public class WindowsProgressBarUI extends BasicProgressBarUI
{

    private Rectangle previousFullBox;
    private Insets indeterminateInsets;

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


    protected void installDefaults() {
        super.installDefaults();

        if (XPStyle.getXP() != null) {
            LookAndFeel.installProperty(progressBar, "opaque", Boolean.FALSE);
            progressBar.setBorder(null);
            indeterminateInsets = UIManager.getInsets("ProgressBar.indeterminateInsets");
        }
    }

    /**
     * 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) {
        int baseline = super.getBaseline(c, width, height);
        if (XPStyle.getXP() != null && progressBar.isStringPainted() &&
                progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
            FontMetrics metrics = progressBar.
                    getFontMetrics(progressBar.getFont());
            int y = progressBar.getInsets().top;
            if (progressBar.isIndeterminate()) {
                y = -1;
                height--;
            }
            else {
                y = 0;
                height -= 3;
            }
            baseline = y + (height + metrics.getAscent() -
                        metrics.getLeading() -
                        metrics.getDescent()) / 2;
        }
        return baseline;
    }

    protected Dimension getPreferredInnerHorizontal() {
        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
             Skin skin = xp.getSkin(progressBar, Part.PP_BAR);
             return new Dimension(
                     (int)super.getPreferredInnerHorizontal().getWidth(),
                     skin.getHeight());
         }
         return super.getPreferredInnerHorizontal();
    }

    protected Dimension getPreferredInnerVertical() {
         XPStyle xp = XPStyle.getXP();
         if (xp != null) {
             Skin skin = xp.getSkin(progressBar, Part.PP_BARVERT);
             return new Dimension(
                     skin.getWidth(),
                     (int)super.getPreferredInnerVertical().getHeight());
         }
         return super.getPreferredInnerVertical();
    }

    protected void paintDeterminate(Graphics g, JComponent c) {
        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
            boolean vertical = (progressBar.getOrientation() == JProgressBar.VERTICAL);
            boolean isLeftToRight = WindowsGraphicsUtils.isLeftToRight(c);
            int barRectWidth = progressBar.getWidth();
            int barRectHeight = progressBar.getHeight()-1;
            // amount of progress to draw
            int amountFull = getAmountFull(null, barRectWidth, barRectHeight);

            paintXPBackground(g, vertical, barRectWidth, barRectHeight);
            // Paint progress
            if (progressBar.isStringPainted()) {
                // Do not paint the standard stripes from the skin, because they obscure
                // the text
                g.setColor(progressBar.getForeground());
                barRectHeight -= 2;
                barRectWidth -= 2;
                Graphics2D g2 = (Graphics2D)g;
                g2.setStroke(new BasicStroke((float)(vertical ? barRectWidth : barRectHeight),
                                             BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
                if (!vertical) {
                    if (isLeftToRight) {
                        g2.drawLine(2,              barRectHeight / 2 + 1,
                                    amountFull - 2, barRectHeight / 2 + 1);
                    } else {
                        g2.drawLine(2 + barRectWidth,
                                    barRectHeight / 2 + 1,
                                    2 + barRectWidth - (amountFull - 2),
                                    barRectHeight / 2 + 1);
                    }
                    paintString(g, 0, 0, barRectWidth, barRectHeight, amountFull, null);
                } else {
                    g2.drawLine(barRectWidth/2 + 1, barRectHeight + 1,
                                barRectWidth/2 + 1, barRectHeight + 1 - amountFull + 2);
                    paintString(g, 2, 2, barRectWidth, barRectHeight, amountFull, null);
                }

            } else {
                Skin skin = xp.getSkin(progressBar, vertical ? Part.PP_CHUNKVERT : Part.PP_CHUNK);
                int thickness;
                if (vertical) {
                    thickness = barRectWidth - 5;
                } else {
                    thickness = barRectHeight - 5;
                }

                int chunkSize = xp.getInt(progressBar, Part.PP_PROGRESS, null, Prop.PROGRESSCHUNKSIZE, 2);
                int spaceSize = xp.getInt(progressBar, Part.PP_PROGRESS, null, Prop.PROGRESSSPACESIZE, 0);
                int nChunks = (amountFull-4) / (chunkSize + spaceSize);

                // See if we can squeeze in an extra chunk without spacing after
                if (spaceSize > 0 && (nChunks * (chunkSize + spaceSize) + chunkSize) < (amountFull-4)) {
                    nChunks++;
                }

                for (int i = 0; i < nChunks; i++) {
                    if (vertical) {
                        skin.paintSkin(g,
                                       3, barRectHeight - i * (chunkSize + spaceSize) - chunkSize - 2,
                                       thickness, chunkSize, null);
                    } else {
                        if (isLeftToRight) {
                            skin.paintSkin(g,
                                           4 + i * (chunkSize + spaceSize), 2,
                                           chunkSize, thickness, null);
                        } else {
                            skin.paintSkin(g,
                                           barRectWidth - (2 + (i+1) * (chunkSize + spaceSize)), 2,
                                           chunkSize, thickness, null);
                        }
                    }
                }
            }
        } else {
            super.paintDeterminate(g, c);
        }
    }


    /**
     * {@inheritDoc}
     * @since 1.6
     */
    protected void setAnimationIndex(int newValue) {
        super.setAnimationIndex(newValue);
        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
            if (boxRect != null) {
                // get the full repaint area and add it the
                // previous one so we can erase it
                Rectangle chunk = getFullChunkBounds(boxRect);
                if (previousFullBox != null) {
                    chunk.add(previousFullBox);
                }
                progressBar.repaint(chunk);
            } else {
                progressBar.repaint();
            }
        }
    }


    /**
     * {@inheritDoc}
     * @since 1.6
     */
    protected int getBoxLength(int availableLength, int otherDimension) {
        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
            return 6; // an apparently hard coded value in Windows
        }
        return super.getBoxLength(availableLength, otherDimension);
    }

    /**
     * {@inheritDoc}
     * @since 1.6
     */
    protected Rectangle getBox(Rectangle r) {
        Rectangle rect = super.getBox(r);

        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
            boolean vertical = (progressBar.getOrientation()
                                 == JProgressBar.VERTICAL);
            Part part = vertical ? Part.PP_BARVERT : Part.PP_BAR;
            Insets ins = indeterminateInsets;

            int currentFrame = getAnimationIndex();
            int framecount = getFrameCount()/2;

            int gap = xp.getInt(progressBar, Part.PP_PROGRESS, null,
                    Prop.PROGRESSSPACESIZE, 0);
            currentFrame = currentFrame % framecount;

            // this code adjusts the chunk size to properly account for the
            // size and gap specified in the XP style. It also does it's own
            // box placement for the chunk animation. This is required because
            // the inherited algorithm from BasicProgressBarUI goes back and
            // forth whereas XP only goes in one direction. XP also has ghosted
            // trailing chunks to create the illusion of speed. This code
            // adjusts the pixel length of the animation to account for the
            // trails.
            if (!vertical) {
                rect.y = rect.y + ins.top;
                rect.height = progressBar.getHeight() - ins.top - ins.bottom;
                int len = progressBar.getWidth() - ins.left - ins.right;
                len += (rect.width+gap)*2; // add 2x for the trails
                double delta = (double)(len) / (double)framecount;
                rect.x = (int)(delta * currentFrame) + ins.left;
            } else {
                rect.x = rect.x + ins.left;
                rect.width = progressBar.getWidth() - ins.left - ins.right;
                int len = progressBar.getHeight() - ins.top - ins.bottom;
                len += (rect.height+gap)*2; // add 2x for the trails
                double delta = (double)(len) / (double)framecount;
                rect.y = (int)(delta * currentFrame) + ins.top;
            }
        }
        return rect;
    }


    protected void paintIndeterminate(Graphics g, JComponent c) {
        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
            boolean vertical = (progressBar.getOrientation()
                                 == JProgressBar.VERTICAL);
            int barRectWidth = progressBar.getWidth();
            int barRectHeight = progressBar.getHeight();
            paintXPBackground(g, vertical, barRectWidth, barRectHeight);

            // Paint the bouncing box.
            boxRect = getBox(boxRect);
            if (boxRect != null) {
                g.setColor(progressBar.getForeground());
                if (!(g instanceof Graphics2D)) {
                    return;
                }
                paintIndeterminateFrame(boxRect, (Graphics2D)g, vertical,
                                        barRectWidth, barRectHeight);
                if (progressBar.isStringPainted()) {
                    if (!vertical) {
                        paintString(g, -1, -1, barRectWidth, barRectHeight, 0, null);
                    } else {
                        paintString(g, 1, 1, barRectWidth, barRectHeight, 0, null);
                    }
                }
            }
        } else {
            super.paintIndeterminate(g, c);
        }
    }

    private Rectangle getFullChunkBounds(Rectangle box) {
        boolean vertical = (progressBar.getOrientation() == JProgressBar.VERTICAL);
        XPStyle xp = XPStyle.getXP();
        int gap = xp.getInt(progressBar, Part.PP_PROGRESS, null,
                            Prop.PROGRESSSPACESIZE, 0);

        if (!vertical) {
            int chunksize = box.width+gap;
            return new Rectangle(box.x-chunksize*2, box.y, chunksize*3, box.height);
        } else {
            int chunksize = box.height+gap;
            return new Rectangle(box.x, box.y-chunksize*2, box.width, chunksize*3);
        }
    }

    private void paintIndeterminateFrame(Rectangle box, Graphics2D g,
                                          boolean vertical,
                                          int bgwidth, int bgheight) {
        XPStyle xp = XPStyle.getXP();

        // create a new graphics to keep drawing surface state
        Graphics2D gfx = (Graphics2D)g.create();

        Part part = vertical ? Part.PP_BARVERT : Part.PP_BAR;
        Part chunk = vertical ? Part.PP_CHUNKVERT : Part.PP_CHUNK;

        // calculate the chunk offsets
        int gap = xp.getInt(progressBar, Part.PP_PROGRESS, null,
                            Prop.PROGRESSSPACESIZE, 0);
        int deltax = 0;
        int deltay = 0;
        if (!vertical) {
            deltax = -box.width - gap;
            deltay = 0;
        } else {
            deltax = 0;
            deltay = -box.height - gap;
        }

        // Calculate the area of the chunks combined
        Rectangle fullBox = getFullChunkBounds(box);

        // save this box for the next time
        previousFullBox = fullBox;

        // this is the entire progress bar minus the track and borders
        Insets ins = indeterminateInsets;
        Rectangle progbarExtents = new Rectangle(ins.left, ins.top,
                                                 bgwidth  - ins.left - ins.right,
                                                 bgheight - ins.top  - ins.bottom);

        // only paint where the chunks overlap with the progress bar drawing area
        Rectangle repaintArea = progbarExtents.intersection(fullBox);

        // adjust the cliprect to chop the chunks when they go off the end
        gfx.clip(repaintArea);

        // get the skin
        XPStyle.Skin skin = xp.getSkin(progressBar, chunk);

        // do the drawing
        gfx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
        skin.paintSkin(gfx, box.x, box.y, box.width, box.height, null);
        box.translate(deltax, deltay);
        gfx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
        skin.paintSkin(gfx, box.x, box.y, box.width, box.height, null);
        box.translate(deltax, deltay);
        gfx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f));
        skin.paintSkin(gfx, box.x, box.y, box.width, box.height, null);

        // get rid of our clip and composite changes
        gfx.dispose();
    }

    private void paintXPBackground(Graphics g, boolean vertical,
                                   int barRectWidth, int barRectHeight) {
        XPStyle xp = XPStyle.getXP();
        Part part = vertical ? Part.PP_BARVERT : Part.PP_BAR;
        Skin skin = xp.getSkin(progressBar, part);

        // Paint background
        skin.paintSkin(g, 0, 0, barRectWidth, barRectHeight, null);
    }
}
