FocusTraversal.java revision 16310:2e5f7c4c78e5
1/*
2 * Copyright (c) 2015, 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 * @key headful
26 * @bug 8129940 8132770 8161470 8163169
27 * @summary JRadioButton should run custom FocusTraversalKeys for all LaFs
28 * @run main FocusTraversal
29 */
30import java.awt.BorderLayout;
31import java.awt.Component;
32import java.awt.KeyboardFocusManager;
33import java.awt.Robot;
34import java.awt.event.KeyEvent;
35import java.util.HashSet;
36import java.util.Set;
37import javax.swing.ButtonGroup;
38import javax.swing.FocusManager;
39import javax.swing.JButton;
40import javax.swing.JFrame;
41import javax.swing.JPanel;
42import javax.swing.JRadioButton;
43import javax.swing.JTextField;
44import javax.swing.KeyStroke;
45import javax.swing.SwingUtilities;
46import javax.swing.UIManager;
47import javax.swing.UnsupportedLookAndFeelException;
48
49public class FocusTraversal {
50
51    private static JFrame frame;
52    private static JRadioButton a;
53    private static JRadioButton b;
54    private static JRadioButton c;
55    private static JRadioButton d;
56    private static JTextField next;
57    private static JTextField prev;
58    private static Robot robot;
59
60    public static void main(String[] args) throws Exception {
61
62        robot = new Robot();
63        robot.setAutoDelay(100);
64        robot.waitForIdle();
65        UIManager.LookAndFeelInfo[] lookAndFeelArray
66                = UIManager.getInstalledLookAndFeels();
67        for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) {
68            executeCase(lookAndFeelItem.getClassName());
69        }
70    }
71
72    private static void executeCase(String lookAndFeelString)
73            throws Exception {
74        if (tryLookAndFeel(lookAndFeelString)) {
75            createUI(lookAndFeelString);
76            robot.waitForIdle();
77            runTestCase();
78            robot.waitForIdle();
79            cleanUp();
80            robot.waitForIdle();
81        }
82    }
83
84    private static void createUI(final String lookAndFeelString)
85            throws Exception {
86        SwingUtilities.invokeAndWait(new Runnable() {
87            @Override
88            public void run() {
89                Set<KeyStroke> keystrokes = new HashSet<KeyStroke>();
90                keystrokes.add(KeyStroke.getKeyStroke("TAB"));
91                keystrokes.add(KeyStroke.getKeyStroke("ENTER"));
92                frame = new JFrame("FocusTraversalTest " + lookAndFeelString);
93                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
94                frame.setUndecorated(true);
95                frame.setFocusTraversalKeys(
96                        KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
97                        keystrokes);
98
99                a = new JRadioButton("a");
100                b = new JRadioButton("b");
101                c = new JRadioButton("c");
102                d = new JRadioButton("d");
103
104                ButtonGroup radioButtonGroup = new ButtonGroup();
105                radioButtonGroup.add(a);
106                radioButtonGroup.add(b);
107                radioButtonGroup.add(c);
108                radioButtonGroup.add(d);
109
110                JPanel panel = new JPanel();
111                prev = new JTextField("text");
112                panel.add(prev);
113                panel.add(a);
114                panel.add(b);
115                panel.add(c);
116                panel.add(d);
117                next = new JTextField("text");
118                panel.add(next);
119
120                JPanel root = new JPanel();
121                root.setLayout(new BorderLayout());
122                root.add(panel, BorderLayout.CENTER);
123                root.add(new JButton("OK"), BorderLayout.SOUTH);
124
125                frame.add(root);
126                frame.pack();
127                frame.setLocationRelativeTo(null);
128                frame.setVisible(true);
129                frame.toFront();
130            }
131        });
132    }
133
134    private static void runTestCase() throws Exception {
135        focusOn(a);
136
137        robot.keyPress(KeyEvent.VK_ENTER);
138        robot.keyRelease(KeyEvent.VK_ENTER);
139        robot.waitForIdle();
140        isFocusOwner(next, "forward");
141        robot.keyPress(KeyEvent.VK_SHIFT);
142        robot.keyPress(KeyEvent.VK_TAB);
143        robot.keyRelease(KeyEvent.VK_TAB);
144        robot.keyRelease(KeyEvent.VK_SHIFT);
145        robot.waitForIdle();
146        isFocusOwner(a, "backward");
147
148    }
149
150    private static void focusOn(Component component)
151            throws Exception {
152        SwingUtilities.invokeAndWait(new Runnable() {
153            @Override
154            public void run() {
155                component.requestFocusInWindow();
156            }
157        });
158    }
159
160    private static void isFocusOwner(Component queriedFocusOwner,
161            String direction)
162            throws Exception {
163        SwingUtilities.invokeAndWait(new Runnable() {
164            @Override
165            public void run() {
166                Component actualFocusOwner
167                        = FocusManager.getCurrentManager().getFocusOwner();
168                if (actualFocusOwner != queriedFocusOwner) {
169                    frame.dispose();
170                    throw new RuntimeException(
171                            "Focus component is wrong after " + direction
172                            + " direction ");
173
174                }
175            }
176        });
177    }
178
179    private static boolean tryLookAndFeel(String lookAndFeelString)
180            throws Exception {
181
182        try {
183            UIManager.setLookAndFeel(
184                    lookAndFeelString);
185
186        } catch (UnsupportedLookAndFeelException
187                | ClassNotFoundException
188                | InstantiationException
189                | IllegalAccessException e) {
190            return false;
191        }
192        return true;
193    }
194
195    private static void cleanUp() throws Exception {
196        SwingUtilities.invokeAndWait(new Runnable() {
197            @Override
198            public void run() {
199                frame.dispose();
200            }
201        });
202    }
203}
204