CVSROOT: /cvsroot/classpath Module name: classpath Changes by: Roman Kennke <rabbit78> 06/06/07 14:36:03
Modified files: javax/swing : JTree.java javax/swing/plaf/basic: BasicTreeUI.java javax/swing/tree: DefaultTreeCellEditor.java TreePath.java VariableHeightLayoutCache.java Log message: 2006-06-06 Roman Kennke <[EMAIL PROTECTED]> PR 27920 * javax/swing/JTree.java (JTree()): Initialize with default model. (JTree(TreeModel)): Clear expanded state hashtable. Added comment on the updateUI() / setModel() order. (setModel): Correctly (un-)setup the listeners. Clear the expanded paths. * javax/swing/plaf/basic/BasicTreeUI.java (BasicTreeUI()): Initialize listeners in installListeners(). (setModel): Complete editing on model change. Correctly resetup the listeners. Update the layout cache accordingly. (setShowRootHandles): Complete editing and update layout. Do not call back into the JTree, this could cause cycles. (prepareForUIInstall): Implemented. Moved some init code from installUI() to this method. (completeUIInstall): Implemented. Moved some init code from installUI() to this method. (createDefaultCellEditor): Check for type of renderer, and install with null renderer when not DefaultTreeCellRenderer. (updateLayoutCacheExpandedNodes): Added null check for tree root to avoid NPE. (updateRenderer): Call updateEditor(). (installListeners): Initialize the listeners here. Added some null checks to avoid NPEs. (installUI): Moved some init code to prepareForUIInstall() and completeUIInstall(). (completeEditing): Return immediately if editing component is null or if the setting is to not stop editing on complete editing. (checkForClickInExpandControl): Call handleExpandControlClick() instead of toggleExpandState() directly. (isLocationInExpandControl): Rewritten to correctly determine the expand click location. (MouseHandler.mousePressed): Rewritten to make better use of the instance methods of BasicTreeUI to handle the click. (PropertyHandler.propertyChange): Handle model and cell renderer updates. * javax/swing/tree/DefaultTreeCellEditor.java (DefaultTreeCellEditor): Removed initialization of the icon. This is done so that the constructor can deal with null renderer as the RI does. Maybe this needs more fixing. * javax/swing/tree/TreePath.java (isDescendant): Fixed this method. The previous version did too much and compared the wrong things, which lead to a ClassCastException in equals(). * javax/swing/tree/VariableHeightLayoutCache.java (update): Do nothing when model is null. (setModel): Clear the tables and update the layout. Added null check to prevent NPE. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/javax/swing/JTree.java?cvsroot=classpath&r1=1.68&r2=1.69 http://cvs.savannah.gnu.org/viewcvs/classpath/javax/swing/plaf/basic/BasicTreeUI.java?cvsroot=classpath&r1=1.139&r2=1.140 http://cvs.savannah.gnu.org/viewcvs/classpath/javax/swing/tree/DefaultTreeCellEditor.java?cvsroot=classpath&r1=1.21&r2=1.22 http://cvs.savannah.gnu.org/viewcvs/classpath/javax/swing/tree/TreePath.java?cvsroot=classpath&r1=1.11&r2=1.12 http://cvs.savannah.gnu.org/viewcvs/classpath/javax/swing/tree/VariableHeightLayoutCache.java?cvsroot=classpath&r1=1.15&r2=1.16 Patches: Index: JTree.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/JTree.java,v retrieving revision 1.68 retrieving revision 1.69 diff -u -b -r1.68 -r1.69 --- JTree.java 6 Jun 2006 15:34:56 -0000 1.68 +++ JTree.java 7 Jun 2006 14:36:02 -0000 1.69 @@ -1478,7 +1478,7 @@ */ public JTree() { - this(createTreeModel(null)); + this(getDefaultTreeModel()); } /** @@ -1513,7 +1513,12 @@ selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); // The root node appears expanded by default. - nodeStates.put(new TreePath(model.getRoot()), EXPANDED); + nodeStates = new Hashtable(); + + // Install the UI before installing the model. This way we avoid double + // initialization of lots of UI and model stuff inside the UI and related + // classes. The necessary UI updates are performed via property change + // events to the UI. updateUI(); setModel(model); } @@ -1897,6 +1902,10 @@ if (treeModel == model) return; + // Remove listeners from old model. + if (treeModel != null && treeModelListener != null) + treeModel.removeTreeModelListener(treeModelListener); + // add treeModelListener to the new model if (treeModelListener == null) treeModelListener = createTreeModelListener(); @@ -1905,6 +1914,20 @@ TreeModel oldValue = treeModel; treeModel = model; + clearToggledPaths(); + + if (treeModel != null) + { + if (treeModelListener == null) + treeModelListener = createTreeModelListener(); + if (treeModelListener != null) + treeModel.addTreeModelListener(treeModelListener); + Object root = treeModel.getRoot(); + if (root != null && !treeModel.isLeaf(root)) + { + nodeStates.put(new TreePath(root), Boolean.TRUE); + } + } firePropertyChange(TREE_MODEL_PROPERTY, oldValue, model); } Index: plaf/basic/BasicTreeUI.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTreeUI.java,v retrieving revision 1.139 retrieving revision 1.140 diff -u -b -r1.139 -r1.140 --- plaf/basic/BasicTreeUI.java 25 May 2006 08:51:13 -0000 1.139 +++ plaf/basic/BasicTreeUI.java 7 Jun 2006 14:36:03 -0000 1.140 @@ -49,7 +49,6 @@ import java.awt.Graphics; import java.awt.Insets; import java.awt.Label; -import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -307,17 +306,6 @@ nodeDimensions = createNodeDimensions(); configureLayoutCache(); - propertyChangeListener = createPropertyChangeListener(); - focusListener = createFocusListener(); - treeSelectionListener = createTreeSelectionListener(); - mouseListener = createMouseListener(); - keyListener = createKeyListener(); - selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener(); - componentListener = createComponentListener(); - cellEditorListener = createCellEditorListener(); - treeExpansionListener = createTreeExpansionListener(); - treeModelListener = createTreeModelListener(); - editingRow = - 1; lastSelectedRow = - 1; } @@ -513,9 +501,22 @@ */ protected void setModel(TreeModel model) { - tree.setModel(model); + completeEditing(); + + if (treeModel != null && treeModelListener != null) + treeModel.removeTreeModelListener(treeModelListener); + treeModel = tree.getModel(); + + if (treeModel != null && treeModelListener != null) + treeModel.addTreeModelListener(treeModelListener); + + if (treeState != null) + { treeState.setModel(treeModel); + updateLayoutCacheExpandedNodes(); + updateSize(); + } } /** @@ -555,7 +556,13 @@ */ protected void setShowsRootHandles(boolean newValue) { - tree.setShowsRootHandles(newValue); + completeEditing(); + updateDepthOffset(); + if (treeState != null) + { + treeState.invalidateSizes(); + updateSize(); + } } /** @@ -822,9 +829,12 @@ * default/listeners have been installed. */ protected void prepareForUIInstall() - throws NotImplementedException { - // TODO: Implement this properly. + lastSelectedRow = -1; + preferredSize = new Dimension(); + largeModel = tree.isLargeModel(); + preferredSize = new Dimension(); + setModel(tree.getModel()); } /** @@ -832,9 +842,15 @@ * installed. */ protected void completeUIInstall() - throws NotImplementedException { - // TODO: Implement this properly. + setShowsRootHandles(tree.getShowsRootHandles()); + updateRenderer(); + updateDepthOffset(); + setSelectionModel(tree.getSelectionModel()); + treeState = createLayoutCache(); + treeSelectionModel.setRowMapper(treeState); + configureLayoutCache(); + updateSize(); } /** @@ -997,15 +1013,14 @@ */ protected TreeCellEditor createDefaultCellEditor() { - if (currentCellRenderer != null) - return new DefaultTreeCellEditor( - tree, - (DefaultTreeCellRenderer) currentCellRenderer, - cellEditor); - return new DefaultTreeCellEditor( - tree, - (DefaultTreeCellRenderer) createDefaultCellRenderer(), - cellEditor); + DefaultTreeCellEditor ed; + if (currentCellRenderer != null + && currentCellRenderer instanceof DefaultTreeCellRenderer) + ed = new DefaultTreeCellEditor(tree, + (DefaultTreeCellRenderer) currentCellRenderer); + else + ed = new DefaultTreeCellEditor(tree, null); + return ed; } /** @@ -1102,7 +1117,7 @@ */ protected void updateLayoutCacheExpandedNodes() { - if (treeModel != null) + if (treeModel != null && treeModel.getRoot() != null) updateExpandedDescendants(new TreePath(treeModel.getRoot())); } @@ -1161,6 +1176,8 @@ if (currentCellRenderer == null) currentCellRenderer = createDefaultCellRenderer(); + + updateCellEditor(); } /** @@ -1317,16 +1334,41 @@ */ protected void installListeners() { + propertyChangeListener = createPropertyChangeListener(); tree.addPropertyChangeListener(propertyChangeListener); + + focusListener = createFocusListener(); tree.addFocusListener(focusListener); + + treeSelectionListener = createTreeSelectionListener(); tree.addTreeSelectionListener(treeSelectionListener); + + mouseListener = createMouseListener(); tree.addMouseListener(mouseListener); + + keyListener = createKeyListener(); tree.addKeyListener(keyListener); - tree.addPropertyChangeListener(selectionModelPropertyChangeListener); + + selectionModelPropertyChangeListener = + createSelectionModelPropertyChangeListener(); + if (treeSelectionModel != null + && selectionModelPropertyChangeListener != null) + { + treeSelectionModel.addPropertyChangeListener + (selectionModelPropertyChangeListener); + } + + componentListener = createComponentListener(); tree.addComponentListener(componentListener); + + treeExpansionListener = createTreeExpansionListener(); tree.addTreeExpansionListener(treeExpansionListener); + + treeModelListener = createTreeModelListener(); if (treeModel != null) treeModel.addTreeModelListener(treeModelListener); + + cellEditorListener = createCellEditorListener(); } /** @@ -1337,25 +1379,12 @@ public void installUI(JComponent c) { tree = (JTree) c; - treeModel = tree.getModel(); prepareForUIInstall(); - super.installUI(c); installDefaults(); installComponents(); installKeyboardActions(); installListeners(); - - setCellEditor(createDefaultCellEditor()); - createdCellEditor = true; - isEditing = false; - - setModel(tree.getModel()); - treeSelectionModel = tree.getSelectionModel(); - setRootVisible(tree.isRootVisible()); - treeState.setRootVisible(tree.isRootVisible()); - updateExpandedDescendants(new TreePath(new Object[] { treeModel.getRoot() })); - completeUIInstall(); } @@ -1613,6 +1642,9 @@ protected void completeEditing(boolean messageStop, boolean messageCancel, boolean messageTree) { + if (! stopEditingInCompleteEditing || editingComponent == null) + return; + if (messageStop) { getCellEditor().stopCellEditing(); @@ -1698,7 +1730,7 @@ int mouseY) { if (isLocationInExpandControl(path, mouseX, mouseY)) - toggleExpandState(path); + handleExpandControlClick(path, mouseX, mouseY); } /** @@ -1717,16 +1749,17 @@ int mouseY) { boolean cntlClick = false; - int row = getRowForPath(tree, path); - - if (! isLeaf(row)) + if (! treeModel.isLeaf(path.getLastPathComponent())) { - Rectangle bounds = getPathBounds(tree, path); - - if (hasControlIcons() - && (mouseX < bounds.x) - && (mouseX > (bounds.x - getCurrentControlIcon(path).getIconWidth() - gap))) - cntlClick = true; + int width = 8; // Only guessing. + Icon expandedIcon = getExpandedIcon(); + if (expandedIcon != null) + width = expandedIcon.getIconWidth(); + + Insets i = tree.getInsets(); + int left = getRowX(tree.getRowForPath(path), path.getPathCount() - 1) + -getRightChildIndent() - width / 2 + i.left; + cntlClick = mouseX >= left && mouseX <= left + width; } return cntlClick; } @@ -2203,95 +2236,30 @@ */ public void mousePressed(MouseEvent e) { - // Any mouse click cancels the previous waiting edit action, initiated - // by the single click on the selected node. - if (startEditTimer != null) + + if (tree != null && tree.isEnabled()) { - startEditTimer.stop(); - startEditTimer = null; - } + // Maybe stop editing and return. + if (isEditing(tree) && tree.getInvokesStopCellEditing() + && !stopEditing(tree)) + return; - Point click = e.getPoint(); - TreePath path = getClosestPathForLocation(tree, click.x, click.y); + int x = e.getX(); + int y = e.getY(); + TreePath path = getClosestPathForLocation(tree, x, y); if (path != null) { Rectangle bounds = getPathBounds(tree, path); - int row = getRowForPath(tree, path); + if (SwingUtilities.isLeftMouseButton(e)) + checkForClickInExpandControl(path, x, y); - // Cancel the editing session if clicked on the different row. - if (tree.isEditing() && row != editingRow) - cancelEditing(tree); - - boolean cntlClick = isLocationInExpandControl(path, click.x, click.y); - - boolean isLeaf = isLeaf(row); - - TreeCellRenderer tcr = getCellRenderer(); - Icon icon; - if (isLeaf) - icon = UIManager.getIcon("Tree.leafIcon"); - else if (tree.isExpanded(path)) - icon = UIManager.getIcon("Tree.openIcon"); - else - icon = UIManager.getIcon("Tree.closedIcon"); - - if (tcr instanceof DefaultTreeCellRenderer) + if (x > bounds.x && x <= (bounds.x + bounds.width)) { - Icon tmp = ((DefaultTreeCellRenderer) tcr).getIcon(); - if (tmp != null) - icon = tmp; - } - - // add gap*2 for the space before and after the text - if (icon != null) - bounds.width += icon.getIconWidth() + gap * 2; - - boolean inBounds = bounds.contains(click.x, click.y); - if ((inBounds || cntlClick) && tree.isVisible(path)) - { - if (inBounds) - { - TreePath currentLead = tree.getLeadSelectionPath(); - if (currentLead != null && currentLead.equals(path) - && e.getClickCount() == 1 && tree.isEditable()) - { - // Schedule the editing session. - final TreePath editPath = path; - - if (startEditTimer != null) - startEditTimer.stop(); - - startEditTimer = new Timer(WAIT_TILL_EDITING, - new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - startEditing(editPath, EDIT); - } - }); - startEditTimer.setRepeats(false); - startEditTimer.start(); - } - else - { - if (e.getClickCount() == 2 && ! isLeaf(row)) - toggleExpandState(path); - else + if (! startEditing(path, e)) selectPathForEvent(path, e); } } - - if (cntlClick) - { - handleExpandControlClick(path, click.x, click.y); - if (cellEditor != null) - cellEditor.cancelCellEditing(); - tree.scrollPathToVisible(path); - } - else if (tree.isEditable()) - startEditing(path, e); - } } } @@ -2555,8 +2523,14 @@ } else if (property.equals(JTree.TREE_MODEL_PROPERTY)) { - treeModel = tree.getModel(); - treeModel.addTreeModelListener(treeModelListener); + setModel(tree.getModel()); + } + else if (property.equals(JTree.CELL_RENDERER_PROPERTY)) + { + setCellRenderer(tree.getCellRenderer()); + // Update layout. + if (treeState != null) + treeState.invalidateSizes(); } } } Index: tree/DefaultTreeCellEditor.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/tree/DefaultTreeCellEditor.java,v retrieving revision 1.21 retrieving revision 1.22 diff -u -b -r1.21 -r1.22 --- tree/DefaultTreeCellEditor.java 20 Apr 2006 11:57:47 -0000 1.21 +++ tree/DefaultTreeCellEditor.java 7 Jun 2006 14:36:03 -0000 1.22 @@ -382,7 +382,6 @@ editingContainer = createContainer(); setFont(UIManager.getFont("Tree.font")); setBorderSelectionColor(UIManager.getColor("Tree.selectionBorderColor")); - editingIcon = renderer.getIcon(); } /** Index: tree/TreePath.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/tree/TreePath.java,v retrieving revision 1.11 retrieving revision 1.12 diff -u -b -r1.11 -r1.12 --- tree/TreePath.java 27 Apr 2006 08:23:45 -0000 1.11 +++ tree/TreePath.java 7 Jun 2006 14:36:03 -0000 1.12 @@ -262,14 +262,16 @@ if (path == null) return false; int count = getPathCount(); - if (path.getPathCount() < count) + int otherPathLength = path.getPathCount(); + if (otherPathLength < count) return false; - for (int i = 0; i < count; i++) + while (otherPathLength > count) { - if (!this.path[i].equals(path.getPathComponent(i))) - return false; + otherPathLength--; + path = path.getParentPath(); } - return true; + + return equals(path); } /** Index: tree/VariableHeightLayoutCache.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/tree/VariableHeightLayoutCache.java,v retrieving revision 1.15 retrieving revision 1.16 diff -u -b -r1.15 -r1.16 --- tree/VariableHeightLayoutCache.java 23 May 2006 16:01:38 -0000 1.15 +++ tree/VariableHeightLayoutCache.java 7 Jun 2006 14:36:03 -0000 1.16 @@ -232,6 +232,9 @@ totalHeight = maximalWidth = 0; + if (treeModel == null) + return; + Object root = treeModel.getRoot(); if (rootVisible) @@ -555,10 +558,17 @@ public void setModel(TreeModel newModel) { treeModel = newModel; + // We need to clear the table and update the layout, + // so that we don't end up with wrong data in the tables. + expanded.clear(); + update(); + if (treeModel != null) + { // The root node is expanded by default. expanded.add(treeModel.getRoot()); dirty = true; } + } /** * Inform the instance if the tree root node is visible. If this method