--- old/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java 2013-08-22 13:59:24.176193600 +0400 +++ new/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java 2013-08-22 13:59:23.640625600 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import javax.swing.*; import javax.swing.event.*; +import java.applet.Applet; import java.awt.*; import java.awt.event.*; import java.awt.datatransfer.*; @@ -42,6 +43,7 @@ import javax.swing.tree.*; import javax.swing.text.Position; import javax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag; +import sun.awt.AWTAccessor; import sun.swing.SwingUtilities2; import sun.swing.DefaultLookup; @@ -2165,8 +2167,14 @@ nodeBounds.width, nodeBounds.height); editingPath = path; + + Container validateRoot = null; if (editingComponent instanceof JComponent) { - ((JComponent)editingComponent).revalidate(); + validateRoot = getValidateRoot((Container)editingComponent, true); + } + + if (validateRoot != null) { + AWTAccessor.getContainerAccessor().validateUnconditionally(validateRoot); } else { editingComponent.validate(); } @@ -2219,6 +2227,37 @@ return false; } + // The implementation of the method is copied from SwingUtilities + private Container getValidateRoot(Container c, boolean visibleOnly) { + Container root = null; + + for (; c != null; c = c.getParent()) + { + if (!c.isDisplayable() || c instanceof CellRendererPane) { + return null; + } + if (c.isValidateRoot()) { + root = c; + break; + } + } + + if (root == null) { + return null; + } + + for (; c != null; c = c.getParent()) { + if (!c.isDisplayable() || (visibleOnly && !c.isVisible())) { + return null; + } + if (c instanceof Window || c instanceof Applet) { + return root; + } + } + + return null; + } + // // Following are primarily for handling mouse events. // --- /dev/null 2013-08-22 13:59:28.000000000 +0400 +++ new/test/javax/swing/plaf/basic/BasicTreeUI/8023474/bug8023474.java 2013-08-22 13:59:27.914668300 +0400 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8023474 + * @summary Tests that the first mouse press starts editing in JTree + * @author Dmitry Markov + * @run main bug8023474 + */ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.event.CellEditorListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeCellRenderer; +import java.awt.*; +import java.awt.event.InputEvent; +import java.util.EventObject; + +public class bug8023474 { + private static JTree tree; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + Point point = getRowPointToClick(1); + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + toolkit.realSync(); + + Boolean result = (Boolean)tree.getCellEditor().getCellEditorValue(); + if (!result) { + throw new RuntimeException("Test Failed!"); + } + } + + private static void createAndShowGUI() { + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + + DefaultMutableTreeNode root = new DefaultMutableTreeNode("root"); + DefaultMutableTreeNode item = new DefaultMutableTreeNode("item"); + DefaultMutableTreeNode subItem = new DefaultMutableTreeNode("subItem"); + + root.add(item); + item.add(subItem); + + DefaultTreeModel model = new DefaultTreeModel(root); + tree = new JTree(model); + + tree.setCellEditor(new Editor()); + tree.setEditable(true); + tree.setRowHeight(30); + tree.setCellRenderer(new CheckboxCellRenderer()); + + JFrame frame = new JFrame("bug8023474"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.add(new JScrollPane(tree)); + frame.setSize(400, 300); + frame.setVisible(true); + } + + private static Point getRowPointToClick(final int row) throws Exception { + final Point[] result = new Point[1]; + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Rectangle rect = tree.getRowBounds(row); + Point point = new Point(rect.x + 10, rect.y + rect.height / 2); + SwingUtilities.convertPointToScreen(point, tree); + result[0] = point; + } + }); + return result[0]; + } + + private static class Editor extends JPanel implements TreeCellEditor { + private JCheckBox checkbox; + + public Editor() { + setOpaque(false); + checkbox = new JCheckBox(); + add(checkbox); + } + + public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, + boolean expanded, boolean leaf, int row) { + checkbox.setText(value.toString()); + checkbox.setSelected(false); + return this; + } + + public Object getCellEditorValue() { + return checkbox.isSelected(); + } + + public boolean isCellEditable(EventObject anEvent) { + return true; + } + + public boolean shouldSelectCell(EventObject anEvent) { + return true; + } + + public boolean stopCellEditing() { + return true; + } + + public void cancelCellEditing() { + } + + public void addCellEditorListener(CellEditorListener l) { + } + + public void removeCellEditorListener(CellEditorListener l) { + } + } + + private static class CheckboxCellRenderer extends JPanel implements TreeCellRenderer { + private JCheckBox checkbox; + + public CheckboxCellRenderer() { + setOpaque(false); + checkbox = new JCheckBox(); + add(checkbox); + } + + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, + boolean leaf, int row, boolean hasFocus) { + checkbox.setText(value.toString()); + checkbox.setSelected(false); + return this; + } + } +}