1/*
2 * Copyright (c) 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/* @test
25 * @bug 8074883
26 * @summary Tab key should move to focused button in a button group
27 * @run main ButtonGroupFocusTest
28 */
29
30import javax.swing.*;
31import java.awt.*;
32import java.awt.event.KeyEvent;
33
34public class ButtonGroupFocusTest {
35
36    private static JRadioButton button1;
37    private static JRadioButton button2;
38    private static JRadioButton button3;
39    private static JRadioButton button4;
40    private static JRadioButton button5;
41    private static Robot robot;
42    private static JFrame frame;
43
44    public static void main(String[] args) throws Exception {
45        robot = new Robot();
46        robot.setAutoDelay(100);
47
48        SwingUtilities.invokeAndWait(() -> {
49            frame = new JFrame();
50            Container contentPane = frame.getContentPane();
51            contentPane.setLayout(new FlowLayout());
52            button1 = new JRadioButton("Button 1");
53            contentPane.add(button1);
54            button2 = new JRadioButton("Button 2");
55            contentPane.add(button2);
56            button3 = new JRadioButton("Button 3");
57            contentPane.add(button3);
58            button4 = new JRadioButton("Button 4");
59            contentPane.add(button4);
60            button5 = new JRadioButton("Button 5");
61            contentPane.add(button5);
62            ButtonGroup group = new ButtonGroup();
63            group.add(button1);
64            group.add(button2);
65            group.add(button3);
66
67            group = new ButtonGroup();
68            group.add(button4);
69            group.add(button5);
70
71            button2.setSelected(true);
72
73            frame.pack();
74            frame.setVisible(true);
75        });
76
77        robot.waitForIdle();
78        robot.delay(200);
79
80        SwingUtilities.invokeAndWait(() -> {
81            if( !button2.hasFocus() ) {
82                frame.dispose();
83                throw new RuntimeException(
84                        "Button 2 should get focus after activation");
85            }
86        });
87
88        robot.keyPress(KeyEvent.VK_TAB);
89        robot.keyRelease(KeyEvent.VK_TAB);
90
91        robot.waitForIdle();
92        robot.delay(200);
93
94        SwingUtilities.invokeAndWait(() -> {
95            if( !button4.hasFocus() ) {
96                frame.dispose();
97                throw new RuntimeException(
98                        "Button 4 should get focus");
99            }
100            button3.setSelected(true);
101        });
102
103        robot.keyPress(KeyEvent.VK_TAB);
104        robot.keyRelease(KeyEvent.VK_TAB);
105
106        robot.waitForIdle();
107        robot.delay(200);
108
109        SwingUtilities.invokeAndWait(() -> {
110            if( !button3.hasFocus() ) {
111                frame.dispose();
112                throw new RuntimeException(
113                        "selected Button 3 should get focus");
114            }
115        });
116
117        SwingUtilities.invokeLater(frame::dispose);
118    }
119}
120