1 /*
   2  * Copyright (c) 2014, 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  * @library ../../regtesthelpers
  28  * @build Util
  29  * @bug 8033699
  30  * @summary  Incorrect radio button behavior when pressing tab key
  31  * @author Vivi An
  32  * @run main bug8033699
  33  */
  34 
  35 import javax.swing.*;
  36 import javax.swing.event.*;
  37 import java.awt.event.*;
  38 import java.awt.*;
  39 
  40 public class bug8033699 {
  41     private static Robot robot;
  42 
  43     private static JButton btnStart;
  44     private static ButtonGroup btnGrp;
  45     private static JButton btnEnd;
  46     private static JButton btnMiddle;
  47     private static JRadioButton radioBtn1;
  48     private static JRadioButton radioBtn2;
  49     private static JRadioButton radioBtn3;
  50     private static JRadioButton radioBtnSingle;
  51 
  52     public static void main(String args[]) throws Throwable {
  53         SwingUtilities.invokeAndWait(new Runnable() {
  54             public void run() {
  55                 createAndShowGUI();
  56             }
  57         });
  58 
  59         robot = new Robot();
  60         Thread.sleep(100);
  61 
  62         robot.setAutoDelay(100);
  63 
  64         // tab key test grouped radio button
  65         runTest1();
  66 
  67         // tab key test non-grouped radio button
  68         runTest2();
  69 
  70         // shift tab key test grouped and non grouped radio button
  71         runTest3();
  72 
  73         // left/up key test in grouped radio button
  74         runTest4();
  75 
  76         // down/right key test in grouped radio button
  77         runTest5();
  78 
  79         // tab from radio button in group to next component in the middle of button group layout
  80         runTest6();
  81 
  82         // tab to radio button in group from component in the middle of button group layout
  83         runTest7();
  84 
  85         // down key circle back to first button in grouped radio button
  86         runTest8();
  87     }
  88 
  89     private static void createAndShowGUI() {
  90         JFrame mainFrame = new JFrame("Bug 8033699 - 8 Tests for Grouped/Non Group Radio Buttons");
  91 
  92         btnStart = new JButton("Start");
  93         btnEnd = new JButton("End");
  94         btnMiddle = new JButton("Middle");
  95 
  96         JPanel box = new JPanel();
  97         box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
  98         box.setBorder(BorderFactory.createTitledBorder("Grouped Radio Buttons"));
  99         radioBtn1 = new JRadioButton("A");
 100         radioBtn2 = new JRadioButton("B");
 101         radioBtn3 = new JRadioButton("C");
 102 
 103         ButtonGroup btnGrp = new ButtonGroup();
 104         btnGrp.add(radioBtn1);
 105         btnGrp.add(radioBtn2);
 106         btnGrp.add(radioBtn3);
 107         radioBtn1.setSelected(true);
 108 
 109         box.add(radioBtn1);
 110         box.add(radioBtn2);
 111         box.add(btnMiddle);
 112         box.add(radioBtn3);
 113 
 114         radioBtnSingle = new JRadioButton("Not Grouped");
 115         radioBtnSingle.setSelected(true);
 116 
 117         mainFrame.getContentPane().add(btnStart);
 118         mainFrame.getContentPane().add(box);
 119         mainFrame.getContentPane().add(radioBtnSingle);
 120         mainFrame.getContentPane().add(btnEnd);
 121 
 122         mainFrame.getRootPane().setDefaultButton(btnStart);
 123         btnStart.requestFocus();
 124 
 125         mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 126         mainFrame.setLayout(new BoxLayout(mainFrame.getContentPane(), BoxLayout.Y_AXIS));
 127 
 128         mainFrame.setSize(300, 300);
 129         mainFrame.setLocation(200, 200);
 130         mainFrame.setVisible(true);
 131         mainFrame.toFront();
 132     }
 133 
 134     // Radio button Group as a single component when traversing through tab key
 135     private static void runTest1() throws Exception{
 136         hitKey(robot, KeyEvent.VK_TAB);
 137         hitKey(robot, KeyEvent.VK_TAB);
 138 
 139         SwingUtilities.invokeAndWait(new Runnable() {
 140             public void run() {
 141                 if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtnSingle) {
 142                     System.out.println("Radio Button Group Go To Next Component through Tab Key failed");
 143                     throw new RuntimeException("Focus is not on Radio Button Single as Expected");
 144                 }
 145             }
 146         });
 147     }
 148 
 149     // Non-Grouped Radio button as a single component when traversing through tab key
 150     private static void runTest2() throws Exception{
 151         hitKey(robot, KeyEvent.VK_TAB);
 152         SwingUtilities.invokeAndWait(new Runnable() {
 153             public void run() {
 154                 if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != btnEnd) {
 155                     System.out.println("Non Grouped Radio Button Go To Next Component through Tab Key failed");
 156                     throw new RuntimeException("Focus is not on Button End as Expected");
 157                 }
 158             }
 159         });
 160     }
 161 
 162     // Non-Grouped Radio button and Group Radio button as a single component when traversing through shift-tab key
 163     private static void runTest3() throws Exception{
 164         hitKey(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB);
 165         hitKey(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB);
 166         SwingUtilities.invokeAndWait(new Runnable() {
 167             public void run() {
 168                 if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn3) {
 169                     System.out.println("Radio button Group/Non Grouped Radio Button SHIFT-Tab Key Test failed");
 170                     throw new RuntimeException("Focus is not on Radio Button C as Expected");
 171                 }
 172             }
 173         });
 174     }
 175 
 176     // Using arrow key to move focus in radio button group
 177     private static void runTest4() throws Exception{
 178         hitKey(robot, KeyEvent.VK_UP);
 179         hitKey(robot, KeyEvent.VK_LEFT);
 180         SwingUtilities.invokeAndWait(new Runnable() {
 181             public void run() {
 182                 if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn1) {
 183                     System.out.println("Radio button Group UP/LEFT Arrow Key Move Focus Failed");
 184                     throw new RuntimeException("Focus is not on Radio Button A as Expected");
 185                 }
 186             }
 187         });
 188     }
 189 
 190     private static void runTest5() throws Exception{
 191         hitKey(robot, KeyEvent.VK_DOWN);
 192         hitKey(robot, KeyEvent.VK_RIGHT);
 193         SwingUtilities.invokeAndWait(new Runnable() {
 194             public void run() {
 195                 if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn3) {
 196                     System.out.println("Radio button Group Left/Up Arrow Key Move Focus Failed");
 197                     throw new RuntimeException("Focus is not on Radio Button C as Expected");
 198                 }
 199             }
 200         });
 201     }
 202 
 203     private static void runTest6() throws Exception{
 204         hitKey(robot, KeyEvent.VK_DOWN);
 205         hitKey(robot, KeyEvent.VK_DOWN);
 206         SwingUtilities.invokeAndWait(new Runnable() {
 207             public void run() {
 208                 if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn2) {
 209                     System.out.println("Radio button Group Circle Back To First Button Test");
 210                     throw new RuntimeException("Focus is not on Radio Button A as Expected");
 211                 }
 212             }
 213         });
 214     }
 215 
 216     private static void runTest7() throws Exception{
 217         hitKey(robot, KeyEvent.VK_TAB);
 218         SwingUtilities.invokeAndWait(new Runnable() {
 219             public void run() {
 220                 if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != btnMiddle) {
 221                     System.out.println("Separate Component added in button group layout");
 222                     throw new RuntimeException("Focus is not on Middle Button as Expected");
 223                 }
 224             }
 225         });
 226     }
 227 
 228     private static void runTest8() throws Exception{
 229         hitKey(robot, KeyEvent.VK_TAB);
 230         SwingUtilities.invokeAndWait(new Runnable() {
 231             public void run() {
 232                 if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != radioBtn3) {
 233                     System.out.println("Separate Component added in button group layout");
 234                     throw new RuntimeException("Focus is not on Radio Button C as Expected");
 235                 }
 236             }
 237         });
 238     }
 239 
 240     private static void hitKey(Robot robot, int keycode) {
 241         robot.keyPress(keycode);
 242         robot.keyRelease(keycode);
 243         robot.waitForIdle();
 244     }
 245 
 246     private static void hitKey(Robot robot, int mode, int keycode) {
 247         robot.keyPress(mode);
 248         robot.keyPress(keycode);
 249         robot.keyRelease(mode);
 250         robot.keyRelease(keycode);
 251         robot.waitForIdle();
 252     }
 253 }