Path: blob/master/test/jdk/java/awt/Focus/FocusTraversalPolicy/ButtonGroupLayoutTraversal/ButtonGroupLayoutTraversalTest.java
66646 views
/*1* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @key headful26* @bug 8154043 817250927* @summary Fields not reachable anymore by tab-key, because of new tabbing28* behaviour of radio button groups.29* @run main ButtonGroupLayoutTraversalTest30*/3132import java.awt.BorderLayout;33import java.awt.Color;34import java.awt.GridLayout;35import java.awt.Robot;36import java.awt.event.FocusAdapter;37import java.awt.event.FocusEvent;38import java.awt.event.KeyEvent;39import java.util.Arrays;40import javax.swing.JFrame;41import javax.swing.SwingUtilities;42import javax.swing.UIManager;43import javax.swing.JPanel;44import javax.swing.ButtonGroup;45import javax.swing.JComponent;46import javax.swing.JRadioButton;47import javax.swing.JToggleButton;48import javax.swing.LayoutFocusTraversalPolicy;49import javax.swing.UnsupportedLookAndFeelException;5051public class ButtonGroupLayoutTraversalTest {5253private static final int NX = 3;54private static final int NY = 3;5556private static final int[] focusCnt = new int[NX * NY];5758private static JFrame window;59private static Robot robot;6061public static void main(String[] args) throws Exception {62robot = new Robot();63robot.setAutoDelay(100);6465for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {66try {67SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf));68SwingUtilities.invokeAndWait(() -> initLayout(NX, NY));69test();70} finally {71SwingUtilities.invokeAndWait(() -> {72if (window != null) {73window.dispose();74}75window = null;76synchronized (focusCnt) {77Arrays.fill(focusCnt, 0);78}79});80}81}82}838485private static void test() {86robot.waitForIdle();87robot.delay(1000);8889for (int i = 0; i < NX * NY - NX * NY / 2 - 1; i++) {90robot.keyPress(KeyEvent.VK_RIGHT);91robot.keyRelease(KeyEvent.VK_RIGHT);92robot.waitForIdle();93}9495for (int i = 0; i < NX * NY / 2; i++) {96robot.keyPress(KeyEvent.VK_TAB);97robot.keyRelease(KeyEvent.VK_TAB);98robot.waitForIdle();99}100101robot.delay(200);102103synchronized (focusCnt) {104for (int i = 0; i < NX * NY; i++) {105if (focusCnt[i] < 1) {106throw new RuntimeException("Component " + i107+ " is not reachable in the forward focus cycle");108} else if (focusCnt[i] > 1) {109throw new RuntimeException("Component " + i110+ " got focus more than once in the forward focus cycle");111}112}113}114115for (int i = 0; i < NX * NY / 2; i++) {116robot.keyPress(KeyEvent.VK_SHIFT);117robot.keyPress(KeyEvent.VK_TAB);118robot.keyRelease(KeyEvent.VK_TAB);119robot.keyRelease(KeyEvent.VK_SHIFT);120robot.waitForIdle();121}122123for (int i = 0; i < NX * NY - NX * NY / 2 - 1; i++) {124robot.keyPress(KeyEvent.VK_LEFT);125robot.keyRelease(KeyEvent.VK_LEFT);126robot.waitForIdle();127}128129robot.keyPress(KeyEvent.VK_SHIFT);130robot.keyPress(KeyEvent.VK_TAB);131robot.keyRelease(KeyEvent.VK_TAB);132robot.keyRelease(KeyEvent.VK_SHIFT);133robot.waitForIdle();134135robot.delay(200);136137synchronized (focusCnt) {138for (int i = 0; i < NX * NY; i++) {139if (focusCnt[i] < 2) {140throw new RuntimeException("Component " + i141+ " is not reachable in the backward focus cycle");142} else if (focusCnt[i] > 2) {143throw new RuntimeException("Component " + i144+ " got focus more than once in the backward focus cycle");145}146}147}148149}150151private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) {152try {153UIManager.setLookAndFeel(laf.getClassName());154System.out.println(laf.getName());155} catch (UnsupportedLookAndFeelException ignored){156System.out.println("Unsupported LookAndFeel: " + laf.getClassName());157} catch (ClassNotFoundException | InstantiationException |158IllegalAccessException e) {159throw new RuntimeException(e);160}161}162163public static void initLayout(int nx, int ny) {164window = new JFrame("Test");165window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);166JPanel rootPanel = new JPanel();167rootPanel.setLayout(new BorderLayout());168JPanel formPanel = new JPanel(new GridLayout(nx, ny));169formPanel.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy());170formPanel.setFocusCycleRoot(true);171ButtonGroup radioButtonGroup = new ButtonGroup();172for (int i = 0; i < nx * ny; i++) {173JToggleButton comp;174if (i % 2 == 0) {175comp = new JRadioButton("Grouped component");176radioButtonGroup.add(comp);177} else {178comp = new JRadioButton("Single component");179}180formPanel.add(comp);181int fi = i;182comp.setBackground(Color.red);183comp.addFocusListener(new FocusAdapter() {184@Override185public void focusGained(FocusEvent e) {186synchronized (focusCnt) {187focusCnt[fi]++;188JComponent btn = (JComponent) e.getSource();189if (focusCnt[fi] == 1) {190btn.setBackground(Color.yellow);191} else if (focusCnt[fi] == 2) {192btn.setBackground(Color.green);193} else {194btn.setBackground(Color.red);195}196}197}198});199}200rootPanel.add(formPanel, BorderLayout.CENTER);201window.add(rootPanel);202window.setLocationRelativeTo(null);203window.pack();204window.setVisible(true);205}206}207208209