summaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/JTree.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/JTree.java')
-rw-r--r--libjava/classpath/javax/swing/JTree.java232
1 files changed, 188 insertions, 44 deletions
diff --git a/libjava/classpath/javax/swing/JTree.java b/libjava/classpath/javax/swing/JTree.java
index 7876eeb6aaa..e3b8b7e7ca5 100644
--- a/libjava/classpath/javax/swing/JTree.java
+++ b/libjava/classpath/javax/swing/JTree.java
@@ -1276,10 +1276,16 @@ public class JTree extends JComponent implements Scrollable, Accessible
*/
public void valueChanged(TreeSelectionEvent ev)
{
- TreeSelectionEvent rewritten =
+ TreeSelectionEvent rewritten =
(TreeSelectionEvent) ev.cloneWithSource(JTree.this);
fireValueChanged(rewritten);
- JTree.this.repaint();
+
+ // Only repaint the changed nodes.
+ TreePath[] changed = ev.getPaths();
+ for (int i = 0; i < changed.length; i++)
+ {
+ repaint(getPathBounds(changed[i]));
+ }
}
}
@@ -1396,8 +1402,6 @@ public class JTree extends JComponent implements Scrollable, Accessible
private TreePath anchorSelectionPath;
- private TreePath leadSelectionPath;
-
/**
* This contains the state of all nodes in the tree. Al/ entries map the
* TreePath of a note to to its state. Valid states are EXPANDED and
@@ -1443,6 +1447,33 @@ public class JTree extends JComponent implements Scrollable, Accessible
new TreeSelectionRedirector();
/**
+ * Indicates if the rowHeight property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientRowHeightSet = false;
+
+ /**
+ * Indicates if the scrollsOnExpand property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientScrollsOnExpandSet = false;
+
+ /**
+ * Indicates if the showsRootHandles property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientShowsRootHandlesSet = false;
+
+ /**
* Creates a new <code>JTree</code> object.
*/
public JTree()
@@ -1477,8 +1508,8 @@ public class JTree extends JComponent implements Scrollable, Accessible
*/
public JTree(TreeModel model)
{
- updateUI();
setRootVisible(true);
+ // The setModel also calls the updateUI
setModel(model);
setSelectionModel(new EmptySelectionModel());
selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
@@ -1535,7 +1566,15 @@ public class JTree extends JComponent implements Scrollable, Accessible
TreeUI ui = getUI();
return ui != null ? ui.getPathForRow(this, row) : null;
}
-
+
+ /**
+ * Get the pathes that are displayes between the two given rows.
+ *
+ * @param index0 the starting row, inclusive
+ * @param index1 the ending row, inclusive
+ *
+ * @return the array of the tree pathes
+ */
protected TreePath[] getPathBetweenRows(int index0, int index1)
{
TreeUI ui = getUI();
@@ -1619,19 +1658,48 @@ public class JTree extends JComponent implements Scrollable, Accessible
*/
public Dimension getPreferredScrollableViewportSize()
{
- return new Dimension (getPreferredSize().width, getVisibleRowCount()*getRowHeight());
+ return getPreferredSize();
}
-
- public int getScrollableUnitIncrement(Rectangle visibleRect,
- int orientation, int direction)
+
+ /**
+ * Return the preferred scrolling amount (in pixels) for the given scrolling
+ * direction and orientation. This method handles a partially exposed row by
+ * returning the distance required to completely expose the item.
+ *
+ * @param visibleRect the currently visible part of the component.
+ * @param orientation the scrolling orientation
+ * @param direction the scrolling direction (negative - up, positive -down).
+ * The values greater than one means that more mouse wheel or similar
+ * events were generated, and hence it is better to scroll the longer
+ * distance.
+ * @author Audrius Meskauskas (audriusa@bioinformatics.org)
+ */
+ public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
+ int direction)
{
- return 1;
+ int delta;
+
+ // Round so that the top would start from the row boundary
+ if (orientation == SwingConstants.VERTICAL)
+ {
+ // One pixel down, otherwise picks another row too high.
+ int row = getClosestRowForLocation(visibleRect.x, visibleRect.y + 1);
+ row = row + direction;
+ if (row < 0)
+ row = 0;
+
+ Rectangle newTop = getRowBounds(row);
+ delta = newTop.y - visibleRect.y;
+ }
+ else
+ delta = direction * rowHeight == 0 ? 20 : rowHeight;
+ return delta;
}
public int getScrollableBlockIncrement(Rectangle visibleRect,
int orientation, int direction)
{
- return 1;
+ return getScrollableUnitIncrement(visibleRect, orientation, direction);
}
public boolean getScrollableTracksViewportHeight()
@@ -1885,9 +1953,19 @@ public class JTree extends JComponent implements Scrollable, Accessible
if (rootVisible == flag)
return;
+ // If the root is currently selected, unselect it
+ if (rootVisible && !flag)
+ {
+ TreeSelectionModel model = getSelectionModel();
+ // The root is always shown in the first row
+ TreePath rootPath = getPathForRow(0);
+ model.removeSelectionPath(rootPath);
+ }
+
boolean oldValue = rootVisible;
rootVisible = flag;
firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag);
+
}
public boolean getShowsRootHandles()
@@ -1897,6 +1975,8 @@ public class JTree extends JComponent implements Scrollable, Accessible
public void setShowsRootHandles(boolean flag)
{
+ clientShowsRootHandlesSet = true;
+
if (showsRootHandles == flag)
return;
@@ -1996,6 +2076,8 @@ public class JTree extends JComponent implements Scrollable, Accessible
public void setRowHeight(int height)
{
+ clientRowHeightSet = true;
+
if (rowHeight == height)
return;
@@ -2050,27 +2132,8 @@ public class JTree extends JComponent implements Scrollable, Accessible
{
if (path == null)
return;
-
- Object[] oPath = path.getPath();
- TreePath temp = new TreePath(oPath[0]);
- boolean stop = false;
- int i = 1;
- while (!stop)
- {
- while (isVisible(temp))
- if (i < oPath.length)
- temp = temp.pathByAddingChild(oPath[i++]);
- else
- {
- stop = true;
- break;
- }
- makeVisible(temp);
- }
Rectangle rect = getPathBounds(path);
scrollRectToVisible(rect);
- revalidate();
- repaint();
}
public void scrollRowToVisible(int row)
@@ -2085,6 +2148,7 @@ public class JTree extends JComponent implements Scrollable, Accessible
public void setScrollsOnExpand(boolean scroll)
{
+ clientScrollsOnExpandSet = true;
if (scrollsOnExpand == scroll)
return;
@@ -2164,7 +2228,15 @@ public class JTree extends JComponent implements Scrollable, Accessible
addSelectionPaths(paths);
}
-
+
+ /**
+ * Select all rows between the two given indexes, inclusive. The method
+ * will not select the inner leaves and braches of the currently collapsed
+ * nodes in this interval.
+ *
+ * @param index0 the starting row, inclusive
+ * @param index1 the ending row, inclusive
+ */
public void addSelectionInterval(int index0, int index1)
{
TreePath[] paths = getPathBetweenRows(index0, index1);
@@ -2220,7 +2292,10 @@ public class JTree extends JComponent implements Scrollable, Accessible
public TreePath getLeadSelectionPath()
{
- return leadSelectionPath;
+ if (selectionModel == null)
+ return null;
+ else
+ return selectionModel.getLeadSelectionPath();
}
/**
@@ -2228,12 +2303,24 @@ public class JTree extends JComponent implements Scrollable, Accessible
*/
public void setLeadSelectionPath(TreePath path)
{
- if (leadSelectionPath == path)
- return;
-
- TreePath oldValue = leadSelectionPath;
- leadSelectionPath = path;
- firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path);
+ if (selectionModel != null)
+ {
+ TreePath oldValue = selectionModel.getLeadSelectionPath();
+ if (path.equals(oldValue))
+ return;
+
+ // Repaint the previous and current rows with the lead selection path.
+ if (path != null)
+ {
+ repaint(getPathBounds(path));
+ selectionModel.addSelectionPath(path);
+ }
+
+ if (oldValue!=null)
+ repaint(getPathBounds(oldValue));
+
+ firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path);
+ }
}
/**
@@ -2369,7 +2456,8 @@ public class JTree extends JComponent implements Scrollable, Accessible
public void expandPath(TreePath path)
{
// Don't expand if path is null
- if (path == null)
+ // or is already expanded.
+ if (path == null || isExpanded(path))
return;
try
@@ -2906,13 +2994,69 @@ public class JTree extends JComponent implements Scrollable, Accessible
}
/**
- * Sent when the tree has changed enough that we need to resize the bounds,
- * but not enough that we need to remove the expanded node set (e.g nodes
- * were expanded or collapsed, or nodes were inserted into the tree). You
- * should never have to invoke this, the UI will invoke this as it needs to.
+ * <p>
+ * Sent when the tree has changed enough that we need to resize the bounds,
+ * but not enough that we need to remove the expanded node set (e.g nodes were
+ * expanded or collapsed, or nodes were inserted into the tree). You should
+ * never have to invoke this, the UI will invoke this as it needs to.
+ * </p>
+ * <p>
+ * If the tree uses {@link DefaultTreeModel}, you must call
+ * {@link DefaultTreeModel#reload(TreeNode)} or
+ * {@link DefaultTreeModel#reload()} after adding or removing nodes. Following
+ * the official Java 1.5 API standard, just calling treeDidChange, repaint()
+ * or revalidate() does <i>not</i> update the tree appearance properly.
+ *
+ * @see DefaultTreeModel#reload()
*/
public void treeDidChange()
{
repaint();
}
+
+ /**
+ * Helper method for
+ * {@link LookAndFeel#installProperty(JComponent, String, Object)}.
+ *
+ * @param propertyName the name of the property
+ * @param value the value of the property
+ *
+ * @throws IllegalArgumentException if the specified property cannot be set
+ * by this method
+ * @throws ClassCastException if the property value does not match the
+ * property type
+ * @throws NullPointerException if <code>c</code> or
+ * <code>propertyValue</code> is <code>null</code>
+ */
+ void setUIProperty(String propertyName, Object value)
+ {
+ if (propertyName.equals("rowHeight"))
+ {
+ if (! clientRowHeightSet)
+ {
+ setRowHeight(((Integer) value).intValue());
+ clientRowHeightSet = false;
+ }
+ }
+ else if (propertyName.equals("scrollsOnExpand"))
+ {
+ if (! clientScrollsOnExpandSet)
+ {
+ setScrollsOnExpand(((Boolean) value).booleanValue());
+ clientScrollsOnExpandSet = false;
+ }
+ }
+ else if (propertyName.equals("showsRootHandles"))
+ {
+ if (! clientShowsRootHandlesSet)
+ {
+ setShowsRootHandles(((Boolean) value).booleanValue());
+ clientShowsRootHandlesSet = false;
+ }
+ }
+ else
+ {
+ super.setUIProperty(propertyName, value);
+ }
+ }
}