1 /* 2 * Copyright (c) 2013, 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 /* @test 24 @bug 4927934 25 @summary JTree traversal is unlike Native windows tree traversal 26 @author Andrey Pikalev 27 @run main bug4927934 28 */ 29 30 import javax.swing.*; 31 import javax.swing.event.*; 32 import javax.swing.tree.*; 33 import java.awt.*; 34 import java.awt.event.*; 35 import java.lang.reflect.InvocationTargetException; 36 import sun.awt.*; 37 38 public class bug4927934 implements TreeSelectionListener, TreeExpansionListener, FocusListener { 39 40 final static Object listener = new bug4927934(); 41 42 static boolean focusGained = false; 43 public static boolean selectionChanged = false; 44 public static boolean treeExpanded = false; 45 public static boolean treeCollapsed = false; 46 47 static JFrame frame; 48 static JTree tree; 49 static Robot robot; 50 51 public static void main(String args[]) throws Exception { 52 UIManager.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel()); 53 54 robot = new Robot(); 55 robot.setAutoDelay(50); 56 57 SwingUtilities.invokeAndWait(new Runnable() { 58 public void run() { 59 frame = new JFrame(); 60 61 DefaultMutableTreeNode root = new DefaultMutableTreeNode("root"); 62 createNodes(root); 63 tree = new JTree(root); 64 JScrollPane scrollPane = new JScrollPane(tree); 65 frame.getContentPane().add(scrollPane); 66 67 tree.addFocusListener((FocusListener)listener); 68 tree.addTreeSelectionListener((TreeSelectionListener)listener); 69 tree.addTreeExpansionListener((TreeExpansionListener)listener); 70 71 frame.setSize(300, 300); 72 frame.setVisible(true); 73 } 74 }); 75 76 SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); 77 toolkit.realSync(); 78 Thread.sleep(1000); 79 80 SwingUtilities.invokeLater(new Runnable() { 81 public void run() { 82 tree.requestFocus(); 83 } 84 }); 85 86 synchronized(listener) { 87 if (!focusGained) { 88 System.out.println("waiting focusGained..."); 89 try { 90 listener.wait(10000); 91 } catch (InterruptedException e) { 92 e.printStackTrace(); 93 } 94 } 95 } 96 97 // GO TO RIGHT 98 selectionChanged = false; 99 hitKey(KeyEvent.VK_RIGHT); 100 toolkit.realSync(); 101 if (!checkSelectionChanged(tree, 0)) { 102 throw new RuntimeException("Root should be selected"); 103 } 104 105 selectionChanged = false; 106 hitKey(KeyEvent.VK_RIGHT); 107 toolkit.realSync(); 108 if (!checkSelectionChanged(tree, 1)) { 109 throw new RuntimeException("Node should be selected"); 110 } 111 112 treeExpanded = false; 113 hitKey(KeyEvent.VK_RIGHT); 114 toolkit.realSync(); 115 if (!isTreeExpanded()) { 116 throw new RuntimeException("Node should be expanded"); 117 } 118 119 selectionChanged = false; 120 hitKey(KeyEvent.VK_RIGHT); 121 toolkit.realSync(); 122 if (!checkSelectionChanged(tree, 2)) { 123 throw new RuntimeException("Leaf1 should be selected"); 124 } 125 126 selectionChanged = false; 127 hitKey(KeyEvent.VK_RIGHT); 128 toolkit.realSync(); 129 if (!checkSelectionChanged(tree, 2)) { 130 throw new RuntimeException("Leaf1 should be selected"); 131 } 132 133 // GO TO LEFT 134 selectionChanged = false; 135 hitKey(KeyEvent.VK_LEFT); 136 toolkit.realSync(); 137 if (!checkSelectionChanged(tree, 1)) { 138 throw new RuntimeException("Node should be selected"); 139 } 140 141 treeCollapsed = false; 142 hitKey(KeyEvent.VK_LEFT); 143 if (!isTreeCollapsed()) { 144 throw new RuntimeException("Node should be collapsed"); 145 } 146 147 selectionChanged = false; 148 hitKey(KeyEvent.VK_LEFT); 149 toolkit.realSync(); 150 if (!checkSelectionChanged(tree, 0)) { 151 throw new RuntimeException("Root should be selected"); 152 } 153 154 treeCollapsed = false; 155 hitKey(KeyEvent.VK_LEFT); 156 toolkit.realSync(); 157 if (!isTreeCollapsed()) { 158 throw new RuntimeException("Root should be collapsed"); 159 } 160 } 161 162 163 synchronized public void focusLost(FocusEvent e) { 164 } 165 166 synchronized public void focusGained(FocusEvent e) { 167 focusGained = true; 168 System.out.println("focusGained"); 169 listener.notifyAll(); 170 } 171 172 private static void createNodes(DefaultMutableTreeNode root) { 173 DefaultMutableTreeNode node = new DefaultMutableTreeNode("Node"); 174 node.add(new DefaultMutableTreeNode("Leaf1")); 175 node.add(new DefaultMutableTreeNode("Leaf2")); 176 root.add(node); 177 root.add(new DefaultMutableTreeNode("Leaf3")); 178 } 179 180 synchronized public void valueChanged(TreeSelectionEvent e) { 181 selectionChanged = true; 182 System.out.println("selectionChanged"); 183 notifyAll(); 184 } 185 186 synchronized public void treeCollapsed(TreeExpansionEvent e) { 187 System.out.println("treeCollapsed"); 188 treeCollapsed = true; 189 notifyAll(); 190 } 191 192 synchronized public void treeExpanded(TreeExpansionEvent e) { 193 System.out.println("treeExpanded"); 194 treeExpanded = true; 195 notifyAll(); 196 } 197 198 private static void hitKey(int key) { 199 System.out.println("key " + key + " pressed"); 200 robot.keyPress(key); 201 robot.keyRelease(key); 202 } 203 204 private static boolean checkSelectionChanged(JTree tree, int shouldBeSel) { 205 synchronized(listener) { 206 if (!selectionChanged) { 207 System.out.println("waiting for selectionChanged..."); 208 try { 209 listener.wait(5000); 210 } catch (InterruptedException e) { 211 e.printStackTrace(); 212 } 213 } 214 } 215 int selRow = tree.getLeadSelectionRow(); 216 System.out.println("Selected row: " + selRow); 217 return selRow == shouldBeSel; 218 } 219 220 private static boolean isTreeExpanded() { 221 synchronized(listener) { 222 if (!treeExpanded) { 223 System.out.println("waiting for treeExpanded..."); 224 try { 225 listener.wait(5000); 226 } catch (InterruptedException e) { 227 e.printStackTrace(); 228 } 229 } 230 } 231 return treeExpanded; 232 } 233 234 private static boolean isTreeCollapsed() { 235 synchronized(listener) { 236 if (!treeCollapsed) { 237 System.out.println("waiting for treeCollapsed..."); 238 try { 239 listener.wait(5000); 240 } catch (InterruptedException e) { 241 e.printStackTrace(); 242 } 243 } 244 } 245 return treeCollapsed; 246 } 247 }