diff options
Diffstat (limited to 'libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java')
-rw-r--r-- | libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java | 800 |
1 files changed, 554 insertions, 246 deletions
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java index be61ccaec22..8cbea7f592d 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java @@ -38,6 +38,7 @@ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; import gnu.javax.swing.tree.GnuPath; import java.awt.Color; @@ -48,7 +49,6 @@ import java.awt.FontMetrics; 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; @@ -80,7 +80,6 @@ import javax.swing.JComponent; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JTree; -import javax.swing.KeyStroke; import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.Timer; @@ -96,7 +95,6 @@ import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.TreeUI; import javax.swing.tree.AbstractLayoutCache; import javax.swing.tree.DefaultTreeCellEditor; @@ -251,6 +249,9 @@ public class BasicTreeUI /** The max height of the nodes in the tree. */ int maxHeight = 0; + + /** The hash color. */ + Color hashColor; /** Listeners */ PropertyChangeListener propertyChangeListener; @@ -279,6 +280,11 @@ public class BasicTreeUI * not the double mouse click) on the selected tree node. */ Timer startEditTimer; + + /** + * The zero size icon, used for expand controls, if they are not visible. + */ + static Icon nullIcon; /** * The special value of the mouse event is sent indicating that this is not @@ -298,17 +304,6 @@ public class BasicTreeUI 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; } @@ -331,7 +326,7 @@ public class BasicTreeUI */ protected Color getHashColor() { - return UIManager.getColor("Tree.hash"); + return hashColor; } /** @@ -341,8 +336,7 @@ public class BasicTreeUI */ protected void setHashColor(Color color) { - // FIXME: Putting something in the UIDefaults map is certainly wrong. - UIManager.put("Tree.hash", color); + hashColor = color; } /** @@ -505,9 +499,22 @@ public class BasicTreeUI */ protected void setModel(TreeModel model) { - tree.setModel(model); + completeEditing(); + + if (treeModel != null && treeModelListener != null) + treeModel.removeTreeModelListener(treeModelListener); + treeModel = tree.getModel(); - treeState.setModel(treeModel); + + if (treeModel != null && treeModelListener != null) + treeModel.addTreeModelListener(treeModelListener); + + if (treeState != null) + { + treeState.setModel(treeModel); + updateLayoutCacheExpandedNodes(); + updateSize(); + } } /** @@ -547,7 +554,13 @@ public class BasicTreeUI */ protected void setShowsRootHandles(boolean newValue) { - tree.setShowsRootHandles(newValue); + completeEditing(); + updateDepthOffset(); + if (treeState != null) + { + treeState.invalidateSizes(); + updateSize(); + } } /** @@ -673,6 +686,20 @@ public class BasicTreeUI treeState.setRowHeight(maxHeight); return maxHeight; } + + /** + * Get the tree node icon. + */ + Icon getNodeIcon(TreePath path) + { + Object node = path.getLastPathComponent(); + if (treeModel.isLeaf(node)) + return UIManager.getIcon("Tree.leafIcon"); + else if (treeState.getExpandedState(path)) + return UIManager.getIcon("Tree.openIcon"); + else + return UIManager.getIcon("Tree.closedIcon"); + } /** * Returns the path for passed in row. If row is not visible null is returned. @@ -801,7 +828,11 @@ public class BasicTreeUI */ protected void prepareForUIInstall() { - // TODO: Implement this properly. + lastSelectedRow = -1; + preferredSize = new Dimension(); + largeModel = tree.isLargeModel(); + preferredSize = new Dimension(); + setModel(tree.getModel()); } /** @@ -810,7 +841,14 @@ public class BasicTreeUI */ protected void completeUIInstall() { - // TODO: Implement this properly. + setShowsRootHandles(tree.getShowsRootHandles()); + updateRenderer(); + updateDepthOffset(); + setSelectionModel(tree.getSelectionModel()); + treeState = createLayoutCache(); + treeSelectionModel.setRowMapper(treeState); + configureLayoutCache(); + updateSize(); } /** @@ -819,7 +857,7 @@ public class BasicTreeUI */ protected void completeUIUninstall() { - // TODO: Implement this properly. + tree = null; } /** @@ -972,15 +1010,14 @@ public class BasicTreeUI */ 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; } /** @@ -1077,7 +1114,7 @@ public class BasicTreeUI */ protected void updateLayoutCacheExpandedNodes() { - if (treeModel != null) + if (treeModel != null && treeModel.getRoot() != null) updateExpandedDescendants(new TreePath(treeModel.getRoot())); } @@ -1132,14 +1169,12 @@ public class BasicTreeUI protected void updateRenderer() { if (tree != null) - { - if (tree.getCellRenderer() == null) - { - if (currentCellRenderer == null) - currentCellRenderer = createDefaultCellRenderer(); - tree.setCellRenderer(currentCellRenderer); - } - } + currentCellRenderer = tree.getCellRenderer(); + + if (currentCellRenderer == null) + currentCellRenderer = createDefaultCellRenderer(); + + updateCellEditor(); } /** @@ -1206,6 +1241,7 @@ public class BasicTreeUI rightChildIndent = UIManager.getInt("Tree.rightChildIndent"); leftChildIndent = UIManager.getInt("Tree.leftChildIndent"); + totalChildIndent = rightChildIndent + leftChildIndent; setRowHeight(UIManager.getInt("Tree.rowHeight")); tree.setRowHeight(getRowHeight()); tree.setScrollsOnExpand(UIManager.getBoolean("Tree.scrollsOnExpand")); @@ -1218,40 +1254,103 @@ public class BasicTreeUI */ protected void installKeyboardActions() { - InputMap focusInputMap = (InputMap) UIManager.get("Tree.focusInputMap"); - InputMapUIResource parentInputMap = new InputMapUIResource(); - ActionMap parentActionMap = new ActionMapUIResource(); + InputMap focusInputMap = + (InputMap) SharedUIDefaults.get("Tree.focusInputMap"); + SwingUtilities.replaceUIInputMap(tree, JComponent.WHEN_FOCUSED, + focusInputMap); + InputMap ancestorInputMap = + (InputMap) SharedUIDefaults.get("Tree.ancestorInputMap"); + SwingUtilities.replaceUIInputMap(tree, + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, + ancestorInputMap); + action = new TreeAction(); - Object keys[] = focusInputMap.allKeys(); - for (int i = 0; i < keys.length; i++) - { - parentInputMap.put( - KeyStroke.getKeyStroke( - ((KeyStroke) keys[i]).getKeyCode(), - convertModifiers(((KeyStroke) keys[i]).getModifiers())), - (String) focusInputMap.get((KeyStroke) keys[i])); - - parentInputMap.put( - KeyStroke.getKeyStroke( - ((KeyStroke) keys[i]).getKeyCode(), - ((KeyStroke) keys[i]).getModifiers()), - (String) focusInputMap.get((KeyStroke) keys[i])); - - parentActionMap.put( - (String) focusInputMap.get((KeyStroke) keys[i]), - new ActionListenerProxy( - action, - (String) focusInputMap.get((KeyStroke) keys[i]))); + SwingUtilities.replaceUIActionMap(tree, getActionMap()); + } + /** + * Creates and returns the shared action map for JTrees. + * + * @return the shared action map for JTrees + */ + private ActionMap getActionMap() + { + ActionMap am = (ActionMap) UIManager.get("Tree.actionMap"); + if (am == null) + { + am = createDefaultActions(); + UIManager.getLookAndFeelDefaults().put("Tree.actionMap", am); } + return am; + } + + /** + * Creates the default actions when there are none specified by the L&F. + * + * @return the default actions + */ + private ActionMap createDefaultActions() + { + ActionMapUIResource am = new ActionMapUIResource(); + Action action; + + action= new TreeAction(); + am.put(action.getValue(Action.NAME), action); + + // TreeHomeAction. + action= new TreeHomeAction(-1, "selectFirst"); + am.put(action.getValue(Action.NAME), action); + action= new TreeHomeAction(-1, "selectFirstChangeLead"); + am.put(action.getValue(Action.NAME), action); + action= new TreeHomeAction(-1, "selectFirstExtendSelection"); + am.put(action.getValue(Action.NAME), action); + action= new TreeHomeAction(1, "selectLast"); + am.put(action.getValue(Action.NAME), action); + action= new TreeHomeAction(1, "selectLastChangeLead"); + am.put(action.getValue(Action.NAME), action); + action= new TreeHomeAction(1, "selectLastExtendSelection"); + am.put(action.getValue(Action.NAME), action); + + // TreeIncrementAction. + action = new TreeIncrementAction(-1, "selectPrevious"); + am.put(action.getValue(Action.NAME), action); + action = new TreeIncrementAction(-1, "selectPreviousExtendSelection"); + am.put(action.getValue(Action.NAME), action); + action = new TreeIncrementAction(-1, "selectPreviousChangeLead"); + am.put(action.getValue(Action.NAME), action); + action = new TreeIncrementAction(1, "selectNext"); + am.put(action.getValue(Action.NAME), action); + action = new TreeIncrementAction(1, "selectNextExtendSelection"); + am.put(action.getValue(Action.NAME), action); + action = new TreeIncrementAction(1, "selectNextChangeLead"); + am.put(action.getValue(Action.NAME), action); + + // TreeTraverseAction. + action = new TreeTraverseAction(-1, "selectParent"); + am.put(action.getValue(Action.NAME), action); + action = new TreeTraverseAction(1, "selectChild"); + am.put(action.getValue(Action.NAME), action); + + // TreeToggleAction. + action = new TreeToggleAction("toggleAndAnchor"); + am.put(action.getValue(Action.NAME), action); - parentInputMap.setParent(tree.getInputMap( - JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).getParent()); - parentActionMap.setParent(tree.getActionMap().getParent()); - tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).setParent( - parentInputMap); - tree.getActionMap().setParent(parentActionMap); + // TreePageAction. + action = new TreePageAction(-1, "scrollUpChangeSelection"); + am.put(action.getValue(Action.NAME), action); + action = new TreePageAction(-1, "scrollUpExtendSelection"); + am.put(action.getValue(Action.NAME), action); + action = new TreePageAction(-1, "scrollUpChangeLead"); + am.put(action.getValue(Action.NAME), action); + action = new TreePageAction(1, "scrollDownChangeSelection"); + am.put(action.getValue(Action.NAME), action); + action = new TreePageAction(1, "scrollDownExtendSelection"); + am.put(action.getValue(Action.NAME), action); + action = new TreePageAction(1, "scrollDownChangeLead"); + am.put(action.getValue(Action.NAME), action); + + return am; } /** @@ -1295,16 +1394,41 @@ public class BasicTreeUI */ 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(); } /** @@ -1315,27 +1439,15 @@ public class BasicTreeUI 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()); - completeUIInstall(); } - + /** * Uninstall the defaults for the tree */ @@ -1353,11 +1465,12 @@ public class BasicTreeUI */ public void uninstallUI(JComponent c) { + completeEditing(); + prepareForUIUninstall(); uninstallDefaults(); uninstallKeyboardActions(); uninstallListeners(); - tree = null; uninstallComponents(); completeUIUninstall(); } @@ -1590,6 +1703,9 @@ public class BasicTreeUI protected void completeEditing(boolean messageStop, boolean messageCancel, boolean messageTree) { + if (! stopEditingInCompleteEditing || editingComponent == null) + return; + if (messageStop) { getCellEditor().stopCellEditing(); @@ -1675,7 +1791,7 @@ public class BasicTreeUI int mouseY) { if (isLocationInExpandControl(path, mouseX, mouseY)) - toggleExpandState(path); + handleExpandControlClick(path, mouseX, mouseY); } /** @@ -1694,16 +1810,17 @@ public class BasicTreeUI 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; } @@ -1786,7 +1903,14 @@ public class BasicTreeUI */ protected boolean isToggleEvent(MouseEvent event) { - return true; + boolean toggle = false; + if (SwingUtilities.isLeftMouseButton(event)) + { + int clickCount = tree.getToggleClickCount(); + if (clickCount > 0 && event.getClickCount() == clickCount) + toggle = true; + } + return toggle; } /** @@ -1831,7 +1955,8 @@ public class BasicTreeUI { // This is an ordinary event that just selects the clicked row. tree.setSelectionPath(path); - tree.setAnchorSelectionPath(path); + if (isToggleEvent(event)) + toggleExpandState(path); } } @@ -1969,7 +2094,32 @@ public class BasicTreeUI */ public void componentMoved(ComponentEvent e) { - // TODO: What should be done here, if anything? + if (timer == null) + { + JScrollPane scrollPane = getScrollPane(); + if (scrollPane == null) + updateSize(); + else + { + // Determine the scrollbar that is adjusting, if any, and + // start the timer for that. If no scrollbar is adjusting, + // we simply call updateSize(). + scrollBar = scrollPane.getVerticalScrollBar(); + if (scrollBar == null || !scrollBar.getValueIsAdjusting()) + { + // It's not the vertical scrollbar, try the horizontal one. + scrollBar = scrollPane.getHorizontalScrollBar(); + if (scrollBar != null && scrollBar.getValueIsAdjusting()) + startTimer(); + else + updateSize(); + } + else + { + startTimer(); + } + } + } } /** @@ -1978,7 +2128,12 @@ public class BasicTreeUI */ protected void startTimer() { - // TODO: Implement this properly. + if (timer == null) + { + timer = new Timer(200, this); + timer.setRepeats(true); + } + timer.start(); } /** @@ -1988,7 +2143,13 @@ public class BasicTreeUI */ protected JScrollPane getScrollPane() { - return null; + JScrollPane found = null; + Component p = tree.getParent(); + while (p != null && !(p instanceof JScrollPane)) + p = p.getParent(); + if (p instanceof JScrollPane) + found = (JScrollPane) p; + return found; } /** @@ -1999,7 +2160,14 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent ae) { - // TODO: Implement this properly. + if (scrollBar == null || !scrollBar.getValueIsAdjusting()) + { + if (timer != null) + timer.stop(); + updateSize(); + timer = null; + scrollBar = null; + } } } @@ -2080,7 +2248,7 @@ public class BasicTreeUI { repaintLeadRow(); } - + /** * Repaint the lead row. */ @@ -2122,6 +2290,7 @@ public class BasicTreeUI * @param e the key typed */ public void keyTyped(KeyEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2132,6 +2301,7 @@ public class BasicTreeUI * @param e the key pressed */ public void keyPressed(KeyEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2142,6 +2312,7 @@ public class BasicTreeUI * @param e the key released */ public void keyReleased(KeyEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2170,94 +2341,29 @@ public class BasicTreeUI */ 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) - { - startEditTimer.stop(); - startEditTimer = null; - } - - Point click = e.getPoint(); - TreePath path = getClosestPathForLocation(tree, click.x, click.y); - if (path != null) + if (tree != null && tree.isEnabled()) { - Rectangle bounds = getPathBounds(tree, path); - int row = getRowForPath(tree, path); - - // 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) - { - Icon tmp = ((DefaultTreeCellRenderer) tcr).getIcon(); - if (tmp != null) - icon = tmp; - } + // Maybe stop editing and return. + if (isEditing(tree) && tree.getInvokesStopCellEditing() + && !stopEditing(tree)) + return; - // add gap*2 for the space before and after the text - if (icon != null) - bounds.width += icon.getIconWidth() + gap * 2; + int x = e.getX(); + int y = e.getY(); + TreePath path = getClosestPathForLocation(tree, x, y); - boolean inBounds = bounds.contains(click.x, click.y); - if ((inBounds || cntlClick) && tree.isVisible(path)) + if (path != null) { - 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 - selectPathForEvent(path, e); - } - } + Rectangle bounds = getPathBounds(tree, path); + if (SwingUtilities.isLeftMouseButton(e)) + checkForClickInExpandControl(path, x, y); - if (cntlClick) + if (x > bounds.x && x <= (bounds.x + bounds.width)) { - handleExpandControlClick(path, click.x, click.y); - if (cellEditor != null) - cellEditor.cancelCellEditing(); - tree.scrollPathToVisible(path); + if (! startEditing(path, e)) + selectPathForEvent(path, e); } - else if (tree.isEditable()) - startEditing(path, e); } } } @@ -2271,6 +2377,7 @@ public class BasicTreeUI * @param e is the mouse event that occured */ public void mouseDragged(MouseEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2282,6 +2389,7 @@ public class BasicTreeUI * @param e the mouse event that occured */ public void mouseMoved(MouseEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2292,6 +2400,7 @@ public class BasicTreeUI * @param e is the mouse event that occured */ public void mouseReleased(MouseEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2332,6 +2441,7 @@ public class BasicTreeUI * @param e mouse event that occured */ public void mouseClicked(MouseEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2342,6 +2452,7 @@ public class BasicTreeUI * @param e mouse event that occured */ public void mousePressed(MouseEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2352,6 +2463,7 @@ public class BasicTreeUI * @param e mouse event that occured */ public void mouseReleased(MouseEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2362,6 +2474,7 @@ public class BasicTreeUI * @param e mouse event that occured */ public void mouseEntered(MouseEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2372,6 +2485,7 @@ public class BasicTreeUI * @param e mouse event that occured */ public void mouseExited(MouseEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2385,6 +2499,7 @@ public class BasicTreeUI * @param e mouse event that occured */ public void mouseDragged(MouseEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2396,6 +2511,7 @@ public class BasicTreeUI * @param e mouse event that occured */ public void mouseMoved(MouseEvent e) + throws NotImplementedException { // TODO: What should be done here, if anything? } @@ -2404,6 +2520,7 @@ public class BasicTreeUI * Removes event from the source */ protected void removeFromSource() + throws NotImplementedException { // TODO: Implement this properly. } @@ -2450,10 +2567,11 @@ public class BasicTreeUI if (s != null) { + TreePath path = treeState.getPathForRow(row); size.x = getRowX(row, depth); size.width = SwingUtilities.computeStringWidth(fm, s); - size.width = size.width + getCurrentControlIcon(null).getIconWidth() - + gap; + size.width = size.width + getCurrentControlIcon(path).getIconWidth() + + gap + getNodeIcon(path).getIconWidth(); size.height = getMaxHeight(tree); size.y = size.height * row; } @@ -2468,8 +2586,7 @@ public class BasicTreeUI */ protected int getRowX(int row, int depth) { - int iw = getCurrentControlIcon(null).getIconWidth(); - return depth * (rightChildIndent + iw/2); + return BasicTreeUI.this.getRowX(row, depth); } }// NodeDimensionsHandler @@ -2511,8 +2628,14 @@ public class BasicTreeUI } 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(); } } } @@ -2540,45 +2663,38 @@ public class BasicTreeUI * the property that has changed. */ public void propertyChange(PropertyChangeEvent event) + throws NotImplementedException { // TODO: What should be done here, if anything? } } /** - * ActionListener that invokes cancelEditing when action performed. + * The action to cancel editing on this tree. */ public class TreeCancelEditingAction extends AbstractAction { - /** - * Constructor + * Creates the new tree cancel editing action. + * + * @param name the name of the action (used in toString). */ public TreeCancelEditingAction(String name) { - // TODO: Implement this properly. + super(name); } /** - * Invoked when an action occurs. + * Invoked when an action occurs, cancels the cell editing (if the + * tree cell is being edited). * * @param e event that occured */ public void actionPerformed(ActionEvent e) { - // TODO: Implement this properly. - } - - /** - * Returns true if the action is enabled. - * - * @return true if the action is enabled, false otherwise - */ - public boolean isEnabled() - { - // TODO: Implement this properly. - return false; + if (isEnabled() && tree.isEditing()) + tree.cancelEditing(); } } @@ -2606,6 +2722,8 @@ public class BasicTreeUI { validCachedPreferredSize = false; treeState.setExpandedState(event.getPath(), true); + // The maximal cell height may change + maxHeight = 0; tree.revalidate(); tree.repaint(); } @@ -2619,6 +2737,8 @@ public class BasicTreeUI { validCachedPreferredSize = false; treeState.setExpandedState(event.getPath(), false); + // The maximal cell height may change + maxHeight = 0; tree.revalidate(); tree.repaint(); } @@ -2636,14 +2756,16 @@ public class BasicTreeUI protected int direction; /** - * Constructor + * Creates a new TreeHomeAction instance. * - * @param direction - it is home or end - * @param name is the name of the direction + * @param dir the direction to go to, <code>-1</code> for home, + * <code>1</code> for end + * @param name the name of the action */ - public TreeHomeAction(int direction, String name) + public TreeHomeAction(int dir, String name) { - // TODO: Implement this properly + direction = dir; + putValue(Action.NAME, name); } /** @@ -2653,7 +2775,61 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { - // TODO: Implement this properly + if (tree != null) + { + String command = (String) getValue(Action.NAME); + if (command.equals("selectFirst")) + { + ensureRowsAreVisible(0, 0); + tree.setSelectionInterval(0, 0); + } + if (command.equals("selectFirstChangeLead")) + { + ensureRowsAreVisible(0, 0); + tree.setLeadSelectionPath(getPathForRow(tree, 0)); + } + if (command.equals("selectFirstExtendSelection")) + { + ensureRowsAreVisible(0, 0); + TreePath anchorPath = tree.getAnchorSelectionPath(); + if (anchorPath == null) + tree.setSelectionInterval(0, 0); + else + { + int anchorRow = getRowForPath(tree, anchorPath); + tree.setSelectionInterval(0, anchorRow); + tree.setAnchorSelectionPath(anchorPath); + tree.setLeadSelectionPath(getPathForRow(tree, 0)); + } + } + else if (command.equals("selectLast")) + { + int end = getRowCount(tree) - 1; + ensureRowsAreVisible(end, end); + tree.setSelectionInterval(end, end); + } + else if (command.equals("selectLastChangeLead")) + { + int end = getRowCount(tree) - 1; + ensureRowsAreVisible(end, end); + tree.setLeadSelectionPath(getPathForRow(tree, end)); + } + else if (command.equals("selectLastExtendSelection")) + { + int end = getRowCount(tree) - 1; + ensureRowsAreVisible(end, end); + TreePath anchorPath = tree.getAnchorSelectionPath(); + if (anchorPath == null) + tree.setSelectionInterval(end, end); + else + { + int anchorRow = getRowForPath(tree, anchorPath); + tree.setSelectionInterval(end, anchorRow); + tree.setAnchorSelectionPath(anchorPath); + tree.setLeadSelectionPath(getPathForRow(tree, end)); + } + } + } } /** @@ -2663,8 +2839,7 @@ public class BasicTreeUI */ public boolean isEnabled() { - // TODO: Implement this properly - return false; + return (tree != null) && tree.isEnabled(); } } @@ -2673,21 +2848,24 @@ public class BasicTreeUI * up or down based on direction. */ public class TreeIncrementAction - extends AbstractAction + extends AbstractAction { - /** Specifies the direction to adjust the selection by. */ + /** + * Specifies the direction to adjust the selection by. + */ protected int direction; /** - * Constructor + * Creates a new TreeIncrementAction. * - * @param direction up or down + * @param dir up or down, <code>-1</code> for up, <code>1</code> for down * @param name is the name of the direction */ - public TreeIncrementAction(int direction, String name) + public TreeIncrementAction(int dir, String name) { - // TODO: Implement this properly + direction = dir; + putValue(Action.NAME, name); } /** @@ -2712,7 +2890,7 @@ public class BasicTreeUI boolean hasNext = nextRow < rows; boolean hasPrev = prevRow >= 0 && rows > 0; TreePath newPath; - String command = e.getActionCommand(); + String command = (String) getValue(Action.NAME); if (command.equals("selectPreviousChangeLead") && hasPrev) { @@ -2776,8 +2954,7 @@ public class BasicTreeUI */ public boolean isEnabled() { - // TODO: Implement this properly - return false; + return (tree != null) && tree.isEnabled(); } } @@ -2883,6 +3060,7 @@ public class BasicTreeUI public TreePageAction(int direction, String name) { this.direction = direction; + putValue(Action.NAME, name); } /** @@ -2892,7 +3070,94 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { - // TODO: Implement this properly. + String command = (String) getValue(Action.NAME); + boolean extendSelection = command.equals("scrollUpExtendSelection") + || command.equals("scrollDownExtendSelection"); + boolean changeSelection = command.equals("scrollUpChangeSelection") + || command.equals("scrollDownChangeSelection"); + + // Disable change lead, unless we are in discontinuous mode. + if (!extendSelection && !changeSelection + && tree.getSelectionModel().getSelectionMode() != + TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) + { + changeSelection = true; + } + + int rowCount = getRowCount(tree); + if (rowCount > 0 && treeSelectionModel != null) + { + Dimension maxSize = tree.getSize(); + TreePath lead = tree.getLeadSelectionPath(); + TreePath newPath = null; + Rectangle visible = tree.getVisibleRect(); + if (direction == -1) // The RI handles -1 as up. + { + newPath = getClosestPathForLocation(tree, visible.x, visible.y); + if (newPath.equals(lead)) // Corner case, adjust one page up. + { + visible.y = Math.max(0, visible.y - visible.height); + newPath = getClosestPathForLocation(tree, visible.x, + visible.y); + } + } + else // +1 is down. + { + visible.y = Math.min(maxSize.height, + visible.y + visible.height - 1); + newPath = getClosestPathForLocation(tree, visible.x, visible.y); + if (newPath.equals(lead)) // Corner case, adjust one page down. + { + visible.y = Math.min(maxSize.height, + visible.y + visible.height - 1); + newPath = getClosestPathForLocation(tree, visible.x, + visible.y); + } + } + + // Determine new visible rect. + Rectangle newVisible = getPathBounds(tree, newPath); + newVisible.x = visible.x; + newVisible.width = visible.width; + if (direction == -1) + { + newVisible.height = visible.height; + } + else + { + newVisible.y -= (visible.height - newVisible.height); + newVisible.height = visible.height; + } + + if (extendSelection) + { + // Extend selection. + TreePath anchorPath = tree.getAnchorSelectionPath(); + if (anchorPath == null) + { + tree.setSelectionPath(newPath); + } + else + { + int newIndex = getRowForPath(tree, newPath); + int anchorIndex = getRowForPath(tree, anchorPath); + tree.setSelectionInterval(Math.min(anchorIndex, newIndex), + Math.max(anchorIndex, newIndex)); + tree.setAnchorSelectionPath(anchorPath); + tree.setLeadSelectionPath(newPath); + } + } + else if (changeSelection) + { + tree.setSelectionPath(newPath); + } + else // Change lead. + { + tree.setLeadSelectionPath(newPath); + } + + tree.scrollRectToVisible(newVisible); + } } /** @@ -2902,7 +3167,7 @@ public class BasicTreeUI */ public boolean isEnabled() { - return false; + return (tree != null) && tree.isEnabled(); } }// TreePageAction @@ -2958,13 +3223,13 @@ public class BasicTreeUI extends AbstractAction { /** - * Constructor + * Creates a new TreeToggleAction. * * @param name is the name of <code>Action</code> field */ public TreeToggleAction(String name) { - // Nothing to do here. + putValue(Action.NAME, name); } /** @@ -2974,7 +3239,17 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { - // TODO: Implement this properly. + int selected = tree.getLeadSelectionRow(); + if (selected != -1 && isLeaf(selected)) + { + TreePath anchorPath = tree.getAnchorSelectionPath(); + TreePath leadPath = tree.getLeadSelectionPath(); + toggleExpandState(getPathForRow(tree, selected)); + // Need to do this, so that the toggling doesn't mess up the lead + // and anchor. + tree.setLeadSelectionPath(leadPath); + tree.setAnchorSelectionPath(anchorPath); + } } /** @@ -2984,7 +3259,7 @@ public class BasicTreeUI */ public boolean isEnabled() { - return false; + return (tree != null) && tree.isEnabled(); } } // TreeToggleAction @@ -3009,6 +3284,7 @@ public class BasicTreeUI public TreeTraverseAction(int direction, String name) { this.direction = direction; + putValue(Action.NAME, name); } /** @@ -3022,7 +3298,8 @@ public class BasicTreeUI if (current == null) return; - if (e.getActionCommand().equals("selectParent")) + String command = (String) getValue(Action.NAME); + if (command.equals("selectParent")) { if (current == null) return; @@ -3042,7 +3319,7 @@ public class BasicTreeUI tree.setSelectionPath(parent); } } - else if (e.getActionCommand().equals("selectChild")) + else if (command.equals("selectChild")) { Object node = current.getLastPathComponent(); int nc = treeModel.getChildCount(node); @@ -3068,8 +3345,7 @@ public class BasicTreeUI */ public boolean isEnabled() { - // TODO: Implement this properly - return false; + return (tree != null) && tree.isEnabled(); } } @@ -3094,9 +3370,35 @@ public class BasicTreeUI */ Icon getCurrentControlIcon(TreePath path) { - if (tree.isExpanded(path)) - return expandedIcon; - return collapsedIcon; + if (hasControlIcons()) + { + if (tree.isExpanded(path)) + return expandedIcon; + else + return collapsedIcon; + } + else + { + if (nullIcon == null) + nullIcon = new Icon() + { + public int getIconHeight() + { + return 0; + } + + public int getIconWidth() + { + return 0; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + // No action here. + } + }; + return nullIcon; + } } /** @@ -3323,10 +3625,8 @@ public class BasicTreeUI { if (row != 0) { - Icon icon = getCurrentControlIcon(path); - int iconW = icon.getIconWidth(); paintHorizontalLine(g, tree, bounds.y + bounds.height / 2, - bounds.x - iconW/2 - gap, bounds.x - gap); + bounds.x - leftChildIndent - gap, bounds.x - gap); } } @@ -3379,15 +3679,13 @@ public class BasicTreeUI paintExpandControl(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf); - TreeCellRenderer dtcr = tree.getCellRenderer(); - if (dtcr == null) - dtcr = createDefaultCellRenderer(); + TreeCellRenderer dtcr = currentCellRenderer; boolean focused = false; - if (treeSelectionModel!= null) - focused = treeSelectionModel.getLeadSelectionRow() == row - && tree.isFocusOwner(); - + if (treeSelectionModel != null) + focused = treeSelectionModel.getLeadSelectionRow() == row + && tree.isFocusOwner(); + Component c = dtcr.getTreeCellRendererComponent(tree, node, selected, isExpanded, isLeaf, row, focused); @@ -3400,7 +3698,7 @@ public class BasicTreeUI */ protected void prepareForUIUninstall() { - // TODO: Implement this properly. + // Nothing to do here yet. } /** @@ -3440,4 +3738,14 @@ public class BasicTreeUI editingComponent = null; tree.requestFocus(); } + + /** + * Returns the amount to indent the given row + * + * @return amount to indent the given row. + */ + protected int getRowX(int row, int depth) + { + return depth * totalChildIndent; + } } // BasicTreeUI |