/*
 * Copyright (c) 1997, 2008, 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 com.sun.java.swing.plaf.windows;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.lang.ref.*;
import java.util.*;
import javax.swing.plaf.basic.*;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;

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.
 */
public class WindowsScrollBarUI extends BasicScrollBarUI {
    private Grid thumbGrid;
    private Grid highlightGrid;

    /**
     * Creates a UI for a JScrollBar.
     *
     * @param c the text field
     * @return the UI
     */
    public static ComponentUI createUI(JComponent c) {
        return new WindowsScrollBarUI();
    }

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

        if (XPStyle.getXP() != null) {
            scrollbar.setBorder(null);
        }
    }

    public void uninstallUI(JComponent c) {
        super.uninstallUI(c);
        thumbGrid = highlightGrid = null;
    }

    protected void configureScrollBarColors() {
        super.configureScrollBarColors();
        Color color = UIManager.getColor("ScrollBar.trackForeground");
        if (color != null && trackColor != null) {
            thumbGrid = Grid.getGrid(color, trackColor);
        }

        color = UIManager.getColor("ScrollBar.trackHighlightForeground");
        if (color != null && trackHighlightColor != null) {
            highlightGrid = Grid.getGrid(color, trackHighlightColor);
        }
    }

    protected JButton createDecreaseButton(int orientation)  {
        return new WindowsArrowButton(orientation,
                                    UIManager.getColor("ScrollBar.thumb"),
                                    UIManager.getColor("ScrollBar.thumbShadow"),
                                    UIManager.getColor("ScrollBar.thumbDarkShadow"),
                                    UIManager.getColor("ScrollBar.thumbHighlight"));
    }

    protected JButton createIncreaseButton(int orientation)  {
        return new WindowsArrowButton(orientation,
                                    UIManager.getColor("ScrollBar.thumb"),
                                    UIManager.getColor("ScrollBar.thumbShadow"),
                                    UIManager.getColor("ScrollBar.thumbDarkShadow"),
                                    UIManager.getColor("ScrollBar.thumbHighlight"));
    }

    /**
     * {@inheritDoc}
     * @since 1.6
     */
    @Override
    protected ArrowButtonListener createArrowButtonListener(){
        // we need to repaint the entire scrollbar because state change for each
        // button causes a state change for the thumb and other button on Vista
        if(XPStyle.isVista()) {
            return new ArrowButtonListener() {
                public void mouseEntered(MouseEvent evt) {
                    repaint();
                    super.mouseEntered(evt);
                }
                public void mouseExited(MouseEvent evt) {
                    repaint();
                    super.mouseExited(evt);
                }
                private void repaint() {
                    scrollbar.repaint();
                }
            };
        } else {
            return super.createArrowButtonListener();
        }
    }

    protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds){
        boolean v = (scrollbar.getOrientation() == JScrollBar.VERTICAL);

        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
            JScrollBar sb = (JScrollBar)c;
            State state = State.NORMAL;
            // Pending: Implement rollover (hot) and pressed
            if (!sb.isEnabled()) {
                state = State.DISABLED;
            }
            Part part = v ? Part.SBP_LOWERTRACKVERT : Part.SBP_LOWERTRACKHORZ;
            xp.getSkin(sb, part).paintSkin(g, trackBounds, state);
        } else if (thumbGrid == null) {
            super.paintTrack(g, c, trackBounds);
        }
        else {
            thumbGrid.paint(g, trackBounds.x, trackBounds.y, trackBounds.width,
                            trackBounds.height);
            if (trackHighlight == DECREASE_HIGHLIGHT) {
                paintDecreaseHighlight(g);
            }
            else if (trackHighlight == INCREASE_HIGHLIGHT) {
                paintIncreaseHighlight(g);
            }
        }
    }

    protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
        boolean v = (scrollbar.getOrientation() == JScrollBar.VERTICAL);

        XPStyle xp = XPStyle.getXP();
        if (xp != null) {
            JScrollBar sb = (JScrollBar)c;
            State state = State.NORMAL;
            if (!sb.isEnabled()) {
                state = State.DISABLED;
            } else if (isDragging) {
                state = State.PRESSED;
            } else if (isThumbRollover()) {
                state = State.HOT;
            } else if (XPStyle.isVista()) {
                if ((incrButton != null && incrButton.getModel().isRollover()) ||
                    (decrButton != null && decrButton.getModel().isRollover())) {
                    state = State.HOVER;
                }
            }
            // Paint thumb
            Part thumbPart = v ? Part.SBP_THUMBBTNVERT : Part.SBP_THUMBBTNHORZ;
            xp.getSkin(sb, thumbPart).paintSkin(g, thumbBounds, state);
            // Paint gripper
            Part gripperPart = v ? Part.SBP_GRIPPERVERT : Part.SBP_GRIPPERHORZ;
            Skin skin = xp.getSkin(sb, gripperPart);
            Insets gripperInsets = xp.getMargin(c, thumbPart, null, Prop.CONTENTMARGINS);
            if (gripperInsets == null ||
                (v && (thumbBounds.height - gripperInsets.top -
                       gripperInsets.bottom >= skin.getHeight())) ||
                (!v && (thumbBounds.width - gripperInsets.left -
                        gripperInsets.right >= skin.getWidth()))) {
                skin.paintSkin(g,
                               thumbBounds.x + (thumbBounds.width  - skin.getWidth()) / 2,
                               thumbBounds.y + (thumbBounds.height - skin.getHeight()) / 2,
                               skin.getWidth(), skin.getHeight(), state);
            }
        } else {
            super.paintThumb(g, c, thumbBounds);
        }
    }


    protected void paintDecreaseHighlight(Graphics g) {
        if (highlightGrid == null) {
            super.paintDecreaseHighlight(g);
        }
        else {
            Insets insets = scrollbar.getInsets();
            Rectangle thumbR = getThumbBounds();
            int x, y, w, h;

            if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
                x = insets.left;
                y = decrButton.getY() + decrButton.getHeight();
                w = scrollbar.getWidth() - (insets.left + insets.right);
                h = thumbR.y - y;
            }
            else {
                x = decrButton.getX() + decrButton.getHeight();
                y = insets.top;
                w = thumbR.x - x;
                h = scrollbar.getHeight() - (insets.top + insets.bottom);
            }
            highlightGrid.paint(g, x, y, w, h);
        }
    }


    protected void paintIncreaseHighlight(Graphics g) {
        if (highlightGrid == null) {
            super.paintDecreaseHighlight(g);
        }
        else {
            Insets insets = scrollbar.getInsets();
            Rectangle thumbR = getThumbBounds();
            int x, y, w, h;

            if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
                x = insets.left;
                y = thumbR.y + thumbR.height;
                w = scrollbar.getWidth() - (insets.left + insets.right);
                h = incrButton.getY() - y;
            }
            else {
                x = thumbR.x + thumbR.width;
                y = insets.top;
                w = incrButton.getX() - x;
                h = scrollbar.getHeight() - (insets.top + insets.bottom);
            }
            highlightGrid.paint(g, x, y, w, h);
        }
    }


    /**
     * {@inheritDoc}
     * @since 1.6
     */
    @Override
    protected void setThumbRollover(boolean active) {
        boolean old = isThumbRollover();
        super.setThumbRollover(active);
        // we need to repaint the entire scrollbar because state change for thumb
        // causes state change for incr and decr buttons on Vista
        if(XPStyle.isVista() && active != old) {
            scrollbar.repaint();
        }
    }

    /**
     * WindowsArrowButton is used for the buttons to position the
     * document up/down. It differs from BasicArrowButton in that the
     * preferred size is always a square.
     */
    private class WindowsArrowButton extends BasicArrowButton {

        public WindowsArrowButton(int direction, Color background, Color shadow,
                         Color darkShadow, Color highlight) {
            super(direction, background, shadow, darkShadow, highlight);
        }

        public WindowsArrowButton(int direction) {
            super(direction);
        }

        public void paint(Graphics g) {
            XPStyle xp = XPStyle.getXP();
            if (xp != null) {
                ButtonModel model = getModel();
                Skin skin = xp.getSkin(this, Part.SBP_ARROWBTN);
                State state = null;

                boolean jointRollover = XPStyle.isVista() && (isThumbRollover() ||
                    (this == incrButton && decrButton.getModel().isRollover()) ||
                    (this == decrButton && incrButton.getModel().isRollover()));

                // normal, rollover, pressed, disabled
                if (model.isArmed() && model.isPressed()) {
                    switch (direction) {
                        case NORTH: state = State.UPPRESSED;    break;
                        case SOUTH: state = State.DOWNPRESSED;  break;
                        case WEST:  state = State.LEFTPRESSED;  break;
                        case EAST:  state = State.RIGHTPRESSED; break;
                    }
                } else if (!model.isEnabled()) {
                    switch (direction) {
                        case NORTH: state = State.UPDISABLED;    break;
                        case SOUTH: state = State.DOWNDISABLED;  break;
                        case WEST:  state = State.LEFTDISABLED;  break;
                        case EAST:  state = State.RIGHTDISABLED; break;
                    }
                } else if (model.isRollover() || model.isPressed()) {
                    switch (direction) {
                        case NORTH: state = State.UPHOT;    break;
                        case SOUTH: state = State.DOWNHOT;  break;
                        case WEST:  state = State.LEFTHOT;  break;
                        case EAST:  state = State.RIGHTHOT; break;
                    }
                } else if (jointRollover) {
                    switch (direction) {
                        case NORTH: state = State.UPHOVER;    break;
                        case SOUTH: state = State.DOWNHOVER;  break;
                        case WEST:  state = State.LEFTHOVER;  break;
                        case EAST:  state = State.RIGHTHOVER; break;
                    }
                } else {
                    switch (direction) {
                        case NORTH: state = State.UPNORMAL;    break;
                        case SOUTH: state = State.DOWNNORMAL;  break;
                        case WEST:  state = State.LEFTNORMAL;  break;
                        case EAST:  state = State.RIGHTNORMAL; break;
                    }
                }

                skin.paintSkin(g, 0, 0, getWidth(), getHeight(), state);
            } else {
                super.paint(g);
            }
        }

        public Dimension getPreferredSize() {
            int size = 16;
            if (scrollbar != null) {
                switch (scrollbar.getOrientation()) {
                case JScrollBar.VERTICAL:
                    size = scrollbar.getWidth();
                    break;
                case JScrollBar.HORIZONTAL:
                    size = scrollbar.getHeight();
                    break;
                }
                size = Math.max(size, 5);
            }
            return new Dimension(size, size);
        }
    }


    /**
     * This should be pulled out into its own class if more classes need to
     * use it.
     * <p>
     * Grid is used to draw the track for windows scrollbars. Grids
     * are cached in a HashMap, with the key being the rgb components
     * of the foreground/background colors. Further the Grid is held through
     * a WeakRef so that it can be freed when no longer needed. As the
     * Grid is rather expensive to draw, it is drawn in a BufferedImage.
     */
    private static class Grid {
        private static final int BUFFER_SIZE = 64;
        private static HashMap<String, WeakReference<Grid>> map;

        private BufferedImage image;

        static {
            map = new HashMap<String, WeakReference<Grid>>();
        }

        public static Grid getGrid(Color fg, Color bg) {
            String key = fg.getRGB() + " " + bg.getRGB();
            WeakReference<Grid> ref = map.get(key);
            Grid grid = (ref == null) ? null : ref.get();
            if (grid == null) {
                grid = new Grid(fg, bg);
                map.put(key, new WeakReference<Grid>(grid));
            }
            return grid;
        }

        public Grid(Color fg, Color bg) {
            int cmap[] = { fg.getRGB(), bg.getRGB() };
            IndexColorModel icm = new IndexColorModel(8, 2, cmap, 0, false, -1,
                                                      DataBuffer.TYPE_BYTE);
            image = new BufferedImage(BUFFER_SIZE, BUFFER_SIZE,
                                      BufferedImage.TYPE_BYTE_INDEXED, icm);
            Graphics g = image.getGraphics();
            try {
                g.setClip(0, 0, BUFFER_SIZE, BUFFER_SIZE);
                paintGrid(g, fg, bg);
            }
            finally {
                g.dispose();
            }
        }

        /**
         * Paints the grid into the specified Graphics at the specified
         * location.
         */
        public void paint(Graphics g, int x, int y, int w, int h) {
            Rectangle clipRect = g.getClipBounds();
            int minX = Math.max(x, clipRect.x);
            int minY = Math.max(y, clipRect.y);
            int maxX = Math.min(clipRect.x + clipRect.width, x + w);
            int maxY = Math.min(clipRect.y + clipRect.height, y + h);

            if (maxX <= minX || maxY <= minY) {
                return;
            }
            int xOffset = (minX - x) % 2;
            for (int xCounter = minX; xCounter < maxX;
                 xCounter += BUFFER_SIZE) {
                int yOffset = (minY - y) % 2;
                int width = Math.min(BUFFER_SIZE - xOffset,
                                     maxX - xCounter);

                for (int yCounter = minY; yCounter < maxY;
                     yCounter += BUFFER_SIZE) {
                    int height = Math.min(BUFFER_SIZE - yOffset,
                                          maxY - yCounter);

                    g.drawImage(image, xCounter, yCounter,
                                xCounter + width, yCounter + height,
                                xOffset, yOffset,
                                xOffset + width, yOffset + height, null);
                    if (yOffset != 0) {
                        yCounter -= yOffset;
                        yOffset = 0;
                    }
                }
                if (xOffset != 0) {
                    xCounter -= xOffset;
                    xOffset = 0;
                }
            }
        }

        /**
         * Actually renders the grid into the Graphics <code>g</code>.
         */
        private void paintGrid(Graphics g, Color fg, Color bg) {
            Rectangle clipRect = g.getClipBounds();
            g.setColor(bg);
            g.fillRect(clipRect.x, clipRect.y, clipRect.width,
                       clipRect.height);
            g.setColor(fg);
            g.translate(clipRect.x, clipRect.y);
            int width = clipRect.width;
            int height = clipRect.height;
            int xCounter = clipRect.x % 2;
            for (int end = width - height; xCounter < end; xCounter += 2) {
                g.drawLine(xCounter, 0, xCounter + height, height);
            }
            for (int end = width; xCounter < end; xCounter += 2) {
                g.drawLine(xCounter, 0, width, width - xCounter);
            }

            int yCounter = ((clipRect.x % 2) == 0) ? 2 : 1;
            for (int end = height - width; yCounter < end; yCounter += 2) {
                g.drawLine(0, yCounter, width, yCounter + width);
            }
            for (int end = height; yCounter < end; yCounter += 2) {
                g.drawLine(0, yCounter, height - yCounter, height);
            }
            g.translate(-clipRect.x, -clipRect.y);
        }
    }
}
