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