1/* 2 * Copyright (c) 2011, 2012, 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/* 25 * @test 26 * @key headful 27 * @bug 6263446 28 * @summary Tests that double-clicking to edit a cell doesn't select the content. 29 * @author Shannon Hickey 30 * @modules java.desktop/javax.swing.tree:open 31 * @run main bug6263446 32 */ 33import java.awt.*; 34import java.awt.event.InputEvent; 35import java.lang.reflect.Field; 36import javax.swing.*; 37import javax.swing.tree.*; 38 39public class bug6263446 { 40 41 private static final String FIRST = "AAAAAAAAAAA"; 42 private static final String SECOND = "BB"; 43 private static final String ALL = FIRST + " " + SECOND; 44 private static JTree tree; 45 private static Robot robot; 46 47 public static void main(String[] args) throws Exception { 48 robot = new Robot(); 49 robot.setAutoDelay(50); 50 51 SwingUtilities.invokeAndWait(new Runnable() { 52 53 public void run() { 54 createAndShowGUI(); 55 } 56 }); 57 58 robot.waitForIdle(); 59 60 Point point = getClickPoint(); 61 robot.mouseMove(point.x, point.y); 62 63 // click count 3 64 click(1); 65 assertNotEditing(); 66 67 click(2); 68 assertNotEditing(); 69 70 click(3); 71 assertEditing(); 72 cancelCellEditing(); 73 assertNotEditing(); 74 75 click(4); 76 checkSelectedText(FIRST); 77 78 click(5); 79 checkSelectedText(ALL); 80 81 // click count 4 82 setClickCountToStart(4); 83 84 click(1); 85 assertNotEditing(); 86 87 click(2); 88 assertNotEditing(); 89 90 click(3); 91 assertNotEditing(); 92 93 click(4); 94 assertEditing(); 95 cancelCellEditing(); 96 assertNotEditing(); 97 98 click(5); 99 checkSelectedText(FIRST); 100 101 click(6); 102 checkSelectedText(ALL); 103 104 // start path editing 105 startPathEditing(); 106 assertEditing(); 107 108 click(1); 109 checkSelection(null); 110 111 click(2); 112 checkSelection(FIRST); 113 114 click(3); 115 checkSelection(ALL); 116 } 117 118 private static void click(int times) { 119 robot.delay(500); 120 for (int i = 0; i < times; i++) { 121 robot.mousePress(InputEvent.BUTTON1_MASK); 122 robot.mouseRelease(InputEvent.BUTTON1_MASK); 123 } 124 } 125 126 private static Point getClickPoint() throws Exception { 127 final Point[] result = new Point[1]; 128 129 SwingUtilities.invokeAndWait(new Runnable() { 130 131 @Override 132 public void run() { 133 Rectangle rect = tree.getRowBounds(0); 134 // UPDATE !!! 135 Point p = new Point(rect.x + rect.width / 2, rect.y + 2); 136 SwingUtilities.convertPointToScreen(p, tree); 137 result[0] = p; 138 139 } 140 }); 141 142 return result[0]; 143 } 144 145 private static TreeModel createTreeModel() { 146 return new DefaultTreeModel(new DefaultMutableTreeNode(ALL)); 147 } 148 149 private static void createAndShowGUI() { 150 151 JFrame frame = new JFrame(); 152 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 153 154 tree = new JTree(createTreeModel()); 155 tree.setRootVisible(true); 156 tree.setEditable(true); 157 158 159 frame.getContentPane().add(tree); 160 frame.pack(); 161 frame.setVisible(true); 162 } 163 164 private static void setClickCountToStart(final int clicks) throws Exception { 165 SwingUtilities.invokeAndWait(new Runnable() { 166 167 @Override 168 public void run() { 169 try { 170 DefaultTreeCellEditor editor = 171 (DefaultTreeCellEditor) tree.getCellEditor(); 172 Field field = DefaultTreeCellEditor.class.getDeclaredField("realEditor"); 173 field.setAccessible(true); 174 DefaultCellEditor ce = (DefaultCellEditor) field.get(editor); 175 ce.setClickCountToStart(clicks); 176 } catch (IllegalAccessException e) { 177 throw new RuntimeException(e); 178 } catch (NoSuchFieldException e) { 179 throw new RuntimeException(e); 180 } 181 } 182 }); 183 184 robot.waitForIdle(); 185 186 } 187 188 private static void startPathEditing() throws Exception { 189 SwingUtilities.invokeAndWait(new Runnable() { 190 191 @Override 192 public void run() { 193 tree.startEditingAtPath(tree.getPathForRow(0)); 194 } 195 }); 196 } 197 198 private static void cancelCellEditing() throws Exception { 199 SwingUtilities.invokeAndWait(new Runnable() { 200 201 @Override 202 public void run() { 203 tree.getCellEditor().cancelCellEditing(); 204 } 205 }); 206 } 207 208 private static void checkSelection(final String sel) throws Exception { 209 SwingUtilities.invokeAndWait(new Runnable() { 210 211 @Override 212 public void run() { 213 try { 214 DefaultTreeCellEditor editor = 215 (DefaultTreeCellEditor) tree.getCellEditor(); 216 Field field = DefaultTreeCellEditor.class.getDeclaredField("realEditor"); 217 field.setAccessible(true); 218 DefaultCellEditor ce = (DefaultCellEditor) field.get(editor); 219 JTextField tf = (JTextField) ce.getComponent(); 220 String text = tf.getSelectedText(); 221 222 if (sel == null) { 223 if (text != null && text.length() != 0) { 224 throw new RuntimeException("Nothing should be selected, but \"" + text + "\" is selected."); 225 } 226 } else if (!sel.equals(text)) { 227 throw new RuntimeException("\"" + sel + "\" should be selected, but \"" + text + "\" is selected."); 228 } 229 } catch (IllegalAccessException e) { 230 throw new RuntimeException(e); 231 } catch (NoSuchFieldException e) { 232 throw new RuntimeException(e); 233 } 234 } 235 }); 236 } 237 238 private static void checkSelectedText(String sel) throws Exception { 239 assertEditing(); 240 checkSelection(sel); 241 cancelCellEditing(); 242 assertNotEditing(); 243 } 244 245 private static void assertEditing() throws Exception { 246 assertEditingNoTreeLock(true); 247 } 248 249 private static void assertNotEditing() throws Exception { 250 assertEditingNoTreeLock(false); 251 } 252 253 private static void assertEditingNoTreeLock(final boolean editing) throws Exception { 254 robot.waitForIdle(); 255 256 SwingUtilities.invokeAndWait(new Runnable() { 257 258 @Override 259 public void run() { 260 if (editing && !tree.isEditing()) { 261 throw new RuntimeException("Tree should be editing"); 262 } 263 if (!editing && tree.isEditing()) { 264 throw new RuntimeException("Tree should not be editing"); 265 } 266 } 267 }); 268 269 } 270 271} 272