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