/*
 * Copyright (c) 2016, 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.
 *
 * 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.
 */

/* @test
 * @bug 7172750
 * @summary Test to check Synth ScrollBar:ScrollBarThumb[].backgroundPainter is invoked
 * @run main SynthScrollbarThumbPainterTest
 */

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.Painter;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

public class SynthScrollbarThumbPainterTest {

    private static Robot testRobot;
    private static Point pos = new Point();
    private static MyFrame testFrame;

    public static void main(String[] args) throws Exception {
        // Create Robot
        testRobot = new Robot();

        // Create test UI
        String lookAndFeelString = "javax.swing.plaf.nimbus.NimbusLookAndFeel";
        SwingUtilities.invokeAndWait(new Runnable() {
            @Override
            public void run() {
                try {
                    constructTestUI(lookAndFeelString);
                } catch (Exception ex) {
                    throw new RuntimeException("Exception creating test UI");
                }
            }
        });

        testRobot.waitForIdle();
        testRobot.delay(200);

        // Run test method
        testScrollBarThumbPainter();

        // Dispose test UI
        disposeTestUI();
    }

    private static void disposeTestUI() throws Exception {
        SwingUtilities.invokeAndWait(() -> {
            testFrame.dispose();
        });
    }


    private static void constructTestUI(String lookAndFeelString) throws Exception {
        // Set look and feel
        UIManager.setLookAndFeel(lookAndFeelString);

        // Set ScrollBarThumb background painters
        UIManager.getLookAndFeelDefaults().put("ScrollBar:ScrollBarThumb[Enabled].backgroundPainter", new FillPainter(Color.RED));
        UIManager.getLookAndFeelDefaults().put("ScrollBar:ScrollBarThumb[MouseOver].backgroundPainter", new FillPainter(Color.GREEN));
        UIManager.getLookAndFeelDefaults().put("ScrollBar:ScrollBarThumb[Pressed].backgroundPainter", new FillPainter(Color.BLUE));

        // Create UI
        testFrame = new MyFrame();
    }

   private static void testScrollBarThumbPainter() throws Exception {
        Point p = testFrame.getLocation();
        pos.setLocation(p.x + 185, p.y + 80); // offset where scrollbar exists

        testRobot.delay(200);

        // Get the scrollbar color
        Color ScrollbarColor = testFrame.getPixelColor(pos.x - p.x, pos.y - p.y);

        // Assert ScrollbarThumb 'Enable' state color
        if (!ScrollbarColor.equals(Color.RED)) {
            disposeTestUI();
            throw new RuntimeException("ScrollbarThumb 'Enable' state color does not match expected color");
        }

        // Move the mouse over scrollbar
        testRobot.mouseMove(pos.x, pos.y);
        testRobot.delay(200);

        ScrollbarColor = testFrame.getPixelColor(pos.x - p.x, pos.y - p.y);

        //Assert ScrollbarThumb 'MouseOver' state color
        if (!ScrollbarColor.equals(Color.GREEN)) {
            disposeTestUI();
            throw new RuntimeException("ScrollbarThumb 'MouseOver' state color does not match expected color");
        }

        // Mouse Press on scrollbar
        testRobot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
        testRobot.delay(200);

        ScrollbarColor = testFrame.getPixelColor(pos.x - p.x, pos.y - p.y);

        testRobot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
        testRobot.delay(200);

        //Assert ScrollbarThumb 'Pressed' state color
        if (!ScrollbarColor.equals(Color.BLUE)) {
            disposeTestUI();
            throw new RuntimeException("ScrollbarThumb 'Pressed' state color does not match expected color");
        }
    }

}


class FillPainter implements Painter<JComponent> {

    private final Color color;

    FillPainter(Color c) {
        color = c;
    }

    @Override
    public void paint(Graphics2D g, JComponent object, int width, int height) {
        g.setColor(color);
        g.fillRect(0, 0, width - 1, height - 1);
    }
}

class MyFrame extends JFrame {

    private BufferedImage bi;
    private final String content = "A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM\nN\nO";

    public MyFrame() {
        JEditorPane editpane = new JEditorPane();
        editpane.setEditable(false);
        editpane.setText(content);
        editpane.setCaretPosition(0);

        JScrollPane scrollpane = new JScrollPane(editpane);

        add(scrollpane);

        setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        setSize(new Dimension(200, 200));
        bi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
        setResizable(false);
        setVisible(true);
    }


    public Color getPixelColor(int x, int y) {

        paintFrameToBufferedImage(this);

        int pixel = bi.getRGB(x, y);

        int alpha = (pixel >> 24) & 0xff;
        int red = (pixel >> 16) & 0xff;
        int green = (pixel >> 8) & 0xff;
        int blue = (pixel) & 0xff;

        Color pixelColor = new Color(red, green, blue, alpha);
        return pixelColor;
    }

    private void paintFrameToBufferedImage(Component component) {
       component.paint(bi.getGraphics());
    }
} //MyFrame

