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