1 /*
   2  * Copyright (c) 2003, 2019, 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 import java.awt.GridBagConstraints;
  25 import java.awt.GridBagLayout;
  26 import java.awt.Point;
  27 import java.awt.Rectangle;
  28 import java.awt.Robot;
  29 import java.awt.event.InputEvent;
  30 
  31 import javax.swing.JFrame;
  32 import javax.swing.JSpinner;
  33 import javax.swing.SpinnerModel;
  34 import javax.swing.SpinnerNumberModel;
  35 import javax.swing.SwingUtilities;
  36 import javax.swing.UIManager;
  37 import javax.swing.UnsupportedLookAndFeelException;
  38 import javax.swing.event.ChangeEvent;
  39 import javax.swing.event.ChangeListener;
  40 
  41 import static javax.swing.UIManager.getInstalledLookAndFeels;
  42 
  43 /**
  44  * @test
  45  * @bug 4788637 7124307
  46  * @key headful
  47  * @summary JSpinner buttons don't conform to most platform conventions
  48  */
  49 public final class bug4788637 {
  50 
  51     private static JSpinner spinner;
  52     private static JFrame fr;
  53 
  54     private static Robot robot;
  55     private int step;
  56     private boolean spinnerValueChanged[] = {false, false, false};
  57 
  58     private static Point p;
  59     private static Rectangle rect;
  60 
  61     public static void main(final String[] args) throws Exception {
  62         robot = new Robot();
  63         robot.setAutoDelay(50);
  64         robot.setAutoWaitForIdle(true);
  65         for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) {
  66             SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf));
  67             bug4788637 app = new bug4788637();
  68             try {
  69                 SwingUtilities.invokeAndWait(app::createAndShowGUI);
  70                 robot.waitForIdle();
  71                 SwingUtilities.invokeAndWait(()-> {
  72                     spinner.requestFocus();
  73                     p = spinner.getLocationOnScreen();
  74                     rect = spinner.getBounds();
  75                 });
  76                 app.start();
  77             } finally {
  78                 SwingUtilities.invokeAndWait(app::destroy);
  79             }
  80         }
  81     }
  82 
  83     public void createAndShowGUI() {
  84         fr = new JFrame("Test");
  85         fr.setLayout( new GridBagLayout() );
  86 
  87         SpinnerModel model = new SpinnerNumberModel(50, 1, 100, 1);
  88         spinner = new JSpinner(model);
  89         fr.add(spinner,new GridBagConstraints());
  90 
  91         spinner.addChangeListener(new ChangeListener() {
  92             public void stateChanged(ChangeEvent e) {
  93                 synchronized (bug4788637.this) {
  94                     spinnerValueChanged[step] = true;
  95                     bug4788637.this.notifyAll();
  96                 }
  97             }
  98         });
  99 
 100         fr.setSize(200, 200);
 101         fr.setLocationRelativeTo(null);
 102         fr.setVisible(true);
 103         fr.toFront();
 104     }
 105 
 106     public void start() {
 107         try {
 108             Thread.sleep(1000);
 109             // Move mouse to the up arrow button
 110             robot.mouseMove(p.x+rect.width-3, p.y+3);
 111             robot.mousePress(InputEvent.BUTTON1_MASK);
 112             synchronized (bug4788637.this) {
 113                 if (!spinnerValueChanged[step]) {
 114                     bug4788637.this.wait(3000);
 115                 }
 116             }
 117 
 118             // Move mouse out of JSpinner
 119             robot.mouseMove(p.x+rect.width-3, p.y-3);
 120             synchronized (bug4788637.this) {
 121                 step++;
 122                 if (!spinnerValueChanged[step]) {
 123                     bug4788637.this.wait(3000);
 124                 }
 125             }
 126 
 127             // Move mouse to the up arrow button
 128             robot.mouseMove(p.x+rect.width-3, p.y+3);
 129             synchronized (bug4788637.this) {
 130                 step++;
 131                 if (!spinnerValueChanged[step]) {
 132                     bug4788637.this.wait(3000);
 133                 }
 134             }
 135 
 136             robot.mouseRelease(InputEvent.BUTTON1_MASK);
 137         } catch(Throwable t) {
 138             throw new RuntimeException(t);
 139         }
 140     }
 141 
 142     public void destroy() {
 143         fr.dispose();
 144         synchronized (bug4788637.this) {
 145             if (!spinnerValueChanged[0] ||
 146                     spinnerValueChanged[1] ||
 147                     !spinnerValueChanged[2]) {
 148                 throw new Error("JSpinner buttons don't conform to most platform conventions");
 149             }
 150         }
 151     }
 152 
 153     private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) {
 154         try {
 155             UIManager.setLookAndFeel(laf.getClassName());
 156             System.out.println("LookAndFeel: " + laf.getClassName());
 157         } catch (ClassNotFoundException | InstantiationException |
 158                 UnsupportedLookAndFeelException | IllegalAccessException e) {
 159             throw new RuntimeException(e);
 160         }
 161     }
 162 }