1 /*
   2  * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @key headful
  27  * @bug 8150724 8151303
  28  * @author a.stepanov
  29  * @summary Check that correct resolution variants are chosen for icons
  30  *          when multiresolution image is used for their construction.
  31  *
  32  * @library ../../../../lib/testlibrary/
  33  * @build ExtendedRobot
  34  * @run main/othervm/timeout=240 -Dsun.java2d.uiScale=1 MultiresolutionIconTest
  35  * @run main/othervm/timeout=240 -Dsun.java2d.uiScale=2 MultiresolutionIconTest
  36  */
  37 
  38 
  39 // TODO: please remove the "@requires" tag after 8151303 fix
  40 
  41 
  42 import java.awt.*;
  43 import java.awt.event.InputEvent;
  44 import java.awt.image.BaseMultiResolutionImage;
  45 import java.awt.image.BufferedImage;
  46 import javax.swing.*;
  47 
  48 public class MultiresolutionIconTest extends JFrame {
  49 
  50     private final static int SZ = 100;
  51     private final static int N = 5; // number of components
  52 
  53     private final static String SCALE = "sun.java2d.uiScale";
  54     private final static Color C1X = Color.RED;
  55     private final static Color C2X = Color.BLUE;
  56 
  57     private JLabel lbl;
  58     private JTabbedPane tabbedPane;
  59 
  60     private final ExtendedRobot r;
  61 
  62     private static BufferedImage generateImage(int sz, Color c) {
  63 
  64         BufferedImage img = new BufferedImage(sz, sz, BufferedImage.TYPE_INT_RGB);
  65         Graphics g = img.getGraphics();
  66         g.setColor(c);
  67         g.fillRect(0, 0, sz, sz);
  68         return img;
  69     }
  70 
  71     public MultiresolutionIconTest(UIManager.LookAndFeelInfo lf) throws Exception {
  72 
  73         UIManager.setLookAndFeel(lf.getClassName());
  74         r = new ExtendedRobot();
  75         SwingUtilities.invokeAndWait(this::UI);
  76     }
  77 
  78     private void UI() {
  79 
  80         setUndecorated(true);
  81 
  82         BufferedImage img1x = generateImage(SZ / 2, C1X);
  83         BufferedImage img2x = generateImage(SZ, C2X);
  84         BaseMultiResolutionImage mri = new BaseMultiResolutionImage(
  85             new BufferedImage[]{img1x, img2x});
  86         Icon icon = new ImageIcon(mri);
  87 
  88         // hardcoded icon size for OS X (Mac OS X L&F) - see JDK-8151060
  89         BufferedImage tab1x = generateImage(16, C1X);
  90         BufferedImage tab2x = generateImage(32, C2X);
  91         BaseMultiResolutionImage tabMRI = new BaseMultiResolutionImage(
  92             new BufferedImage[]{tab1x, tab2x});
  93         Icon tabIcon = new ImageIcon(tabMRI);
  94 
  95         setSize((N + 1) * SZ, SZ);
  96         setLocation(50, 50);
  97 
  98         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  99         getContentPane().setLayout(new GridLayout(1, 1));
 100 
 101         JPanel p = new JPanel();
 102         p.setLayout(new GridLayout(1, N));
 103 
 104         JButton btn = new JButton(icon);
 105         p.add(btn);
 106 
 107         JToggleButton tbn = new JToggleButton(icon);
 108         p.add(tbn);
 109 
 110         JRadioButton rbn = new JRadioButton(icon);
 111         rbn.setHorizontalAlignment(SwingConstants.CENTER);
 112         p.add(rbn);
 113 
 114         JCheckBox cbx = new JCheckBox(icon);
 115         cbx.setHorizontalAlignment(SwingConstants.CENTER);
 116         p.add(cbx);
 117 
 118         lbl = new JLabel(icon);
 119         p.add(lbl);
 120 
 121         tabbedPane = new JTabbedPane(JTabbedPane.LEFT);
 122         tabbedPane.addTab("", tabIcon, p);
 123         getContentPane().add(tabbedPane);
 124 
 125         setResizable(false);
 126         setVisible(true);
 127     }
 128 
 129     private boolean checkPressedColor(int x, int y, Color ok) {
 130 
 131         r.mouseMove(x, y);
 132         r.waitForIdle();
 133         r.mousePress(InputEvent.BUTTON1_DOWN_MASK);
 134         r.waitForIdle(100);
 135         Color c = r.getPixelColor(x, y);
 136         r.waitForIdle(100);
 137         r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
 138         r.waitForIdle(100);
 139         if (!c.equals(ok)) { return false; }
 140         // check the icon's color hasn't changed
 141         // after the mouse was released
 142         c = r.getPixelColor(x, y);
 143         return c.equals(ok);
 144     }
 145 
 146     private boolean checkTabIcon(
 147         int xStart, int xEnd, int yStart, int yEnd, Color ok, Color nok) {
 148 
 149         for (int y = yStart; y < yEnd; y += 2) {
 150             for (int x = xStart; x < xEnd; x += 2) {
 151                 Color c = r.getPixelColor(x, y);
 152                 if (c.equals(nok)) { return false; }
 153                 else if (c.equals(ok)) {
 154                     // shift a bit to avoid the selection effects
 155                     return checkPressedColor(x + 5, y + 5, ok);
 156                 }
 157             }
 158         }
 159 
 160         return false; // didn't find the icon
 161     }
 162 
 163 
 164     private void doTest() {
 165 
 166         r.waitForIdle(2000);
 167         String scale = System.getProperty(SCALE);
 168         boolean is2x = "2".equals(scale);
 169         Color expected = is2x ? C2X : C1X;
 170         Color unexpected = is2x ? C1X : C2X;
 171 
 172         Point p = lbl.getLocationOnScreen();
 173         int x = p.x + lbl.getWidth() / 2;
 174         int y = p.y + lbl.getHeight() / 2;
 175         int w = lbl.getWidth();
 176 
 177         boolean ok = true, curr;
 178         Color c;
 179         String components[] = new String[]{
 180             "JLabel", "JCheckBox", "JRadioButton", "JToggleButton", "JButton"};
 181         for (int i = 0; i < N; i++) {
 182 
 183             curr = true;
 184             int t = x - i * w;
 185 
 186             // check icon color
 187             c = r.getPixelColor(t, y);
 188             System.out.print(components[i] + " icon: ");
 189             if (!c.equals(expected)) {
 190                 curr = false;
 191             } else {
 192                 // check icon color when mouse button pressed - see JDK-8151303
 193                 curr = checkPressedColor(t, y, expected);
 194             }
 195 
 196             System.out.println(curr ? "ok" : "nok");
 197             ok = ok && curr;
 198 
 199             r.waitForIdle();
 200         }
 201 
 202         int x0 = tabbedPane.getLocationOnScreen().x;
 203         int x1 = x - ((N - 1) * w + w / 2);
 204         int y0 = getLocationOnScreen().y;
 205         int y1 = y0 + getHeight();
 206         curr = checkTabIcon(x0, x1, y0, y1, expected, unexpected);
 207 
 208         System.out.println("JTabbedPane icon: " + (curr ? "ok" : "nok"));
 209         ok = ok && curr;
 210 
 211         if (!ok) { throw new RuntimeException("test failed"); }
 212 
 213         r.waitForIdle();
 214         dispose();
 215     }
 216 
 217     public static void main(String[] args) throws Exception {
 218 
 219         for (UIManager.LookAndFeelInfo LF: UIManager.getInstalledLookAndFeels()) {
 220             System.out.println("\nL&F: " + LF.getName());
 221             (new MultiresolutionIconTest(LF)).doTest();
 222         }
 223     }
 224 }