diff options
Diffstat (limited to 'javax/swing/tree/DefaultTreeSelectionModel.java')
-rw-r--r-- | javax/swing/tree/DefaultTreeSelectionModel.java | 153 |
1 files changed, 135 insertions, 18 deletions
diff --git a/javax/swing/tree/DefaultTreeSelectionModel.java b/javax/swing/tree/DefaultTreeSelectionModel.java index 87028c326..0cabd426f 100644 --- a/javax/swing/tree/DefaultTreeSelectionModel.java +++ b/javax/swing/tree/DefaultTreeSelectionModel.java @@ -45,7 +45,10 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.Arrays; import java.util.EventListener; +import java.util.HashSet; +import java.util.Iterator; import java.util.Vector; import javax.swing.DefaultListSelectionModel; @@ -235,6 +238,7 @@ public class DefaultTreeSelectionModel public void setSelectionMode(int mode) { selectionMode = mode; + insureRowContinuity(); } /** @@ -312,7 +316,7 @@ public class DefaultTreeSelectionModel { // Must be called, as defined in JDK API 1.4. insureUniqueness(); - removeSelectionPaths(selection); + clearSelection(); addSelectionPaths(paths); } @@ -327,7 +331,8 @@ public class DefaultTreeSelectionModel { if (! isPathSelected(path)) { - if (isSelectionEmpty()) + if (selectionMode == SINGLE_TREE_SELECTION || isSelectionEmpty() + || ! canPathBeAdded(path)) setSelectionPath(path); else { @@ -339,7 +344,7 @@ public class DefaultTreeSelectionModel } leadPath = path; leadRow = getRow(path); - leadIndex = selection.length-1; + leadIndex = selection.length - 1; fireValueChanged(new TreeSelectionEvent(this, path, true, leadPath, path)); } @@ -356,7 +361,7 @@ public class DefaultTreeSelectionModel { // Must be called, as defined in JDK API 1.4. insureUniqueness(); - + if (paths != null) { TreePath v0 = null; @@ -377,12 +382,13 @@ public class DefaultTreeSelectionModel } leadPath = paths[paths.length - 1]; leadRow = getRow(leadPath); - leadIndex = selection.length-1; - + leadIndex = selection.length - 1; + fireValueChanged(new TreeSelectionEvent(this, v0, true, leadPath, paths[0])); } } + insureRowContinuity(); } } @@ -417,6 +423,7 @@ public class DefaultTreeSelectionModel fireValueChanged(new TreeSelectionEvent(this, path, false, leadPath, path)); + insureRowContinuity(); } } @@ -458,6 +465,7 @@ public class DefaultTreeSelectionModel leadPath, paths[0])); } } + insureRowContinuity(); } } @@ -685,9 +693,9 @@ public class DefaultTreeSelectionModel /** * Updates the mappings from TreePaths to row indices. */ - public void resetRowSelection() throws NotImplementedException + public void resetRowSelection() { - // TODO + // Nothing to do here. } /** @@ -753,23 +761,93 @@ public class DefaultTreeSelectionModel * has more than one path, the selection is reset to the contain only the * first path. */ - protected void insureRowContinuity() throws NotImplementedException + protected void insureRowContinuity() { - // TODO + if (selection == null || selection.length < 2) + return; + else if (selectionMode == CONTIGUOUS_TREE_SELECTION) + { + if (rowMapper == null) + // This is the best we can do without the row mapper: + selectOne(); + else + { + int[] rows = rowMapper.getRowsForPaths(selection); + Arrays.sort(rows); + int i; + for (i = 1; i < rows.length; i++) + { + if (rows[i - 1] != rows[i] - 1) + // Break if no longer continuous. + break; + } + + if (i < rows.length) + { + TreePath[] ns = new TreePath[i]; + for (int j = 0; j < ns.length; j++) + ns[i] = getPath(j); + setSelectionPaths(ns); + } + } + } + else if (selectionMode == SINGLE_TREE_SELECTION) + selectOne(); + } + + /** + * Keep only one (normally last or leading) path in the selection. + */ + private void selectOne() + { + if (leadIndex > 0 && leadIndex < selection.length) + setSelectionPath(selection[leadIndex]); + else + setSelectionPath(selection[selection.length -1]); + } + + /** + * Get path for the given row that must be in the current selection. + */ + private TreePath getPath(int row) + { + if (rowMapper instanceof AbstractLayoutCache) + return ((AbstractLayoutCache) rowMapper).getPathForRow(row); + else + { + int[] rows = rowMapper.getRowsForPaths(selection); + for (int i = 0; i < rows.length; i++) + if (rows[i] == row) + return selection[i]; + } + throw new InternalError(row + " not in selection"); } /** - * Returns <code>true</code> if the paths are contiguous or we have no - * RowMapper assigned. + * Returns <code>true</code> if the paths are contiguous (take subsequent + * rows in the diplayed tree view. The method returns <code>true</code> if + * we have no RowMapper assigned. * * @param paths the paths to check for continuity * @return <code>true</code> if the paths are contiguous or we have no * RowMapper assigned */ protected boolean arePathsContiguous(TreePath[] paths) - throws NotImplementedException { - return false; // STUB + if (rowMapper == null || paths.length < 2) + return true; + + int[] rows = rowMapper.getRowsForPaths(paths); + + // The patches may not be sorted. + Arrays.sort(rows); + + for (int i = 1; i < rows.length; i++) + { + if (rows[i-1] != rows[i] - 1) + return false; + } + return true; } /** @@ -787,9 +865,32 @@ public class DefaultTreeSelectionModel * selectionMode */ protected boolean canPathsBeAdded(TreePath[] paths) - throws NotImplementedException { - return false; // STUB + if (rowMapper == null || isSelectionEmpty() + || selectionMode == DISCONTIGUOUS_TREE_SELECTION) + return true; + + TreePath [] all = new TreePath[paths.length + selection.length]; + System.arraycopy(paths, 0, all, 0, paths.length); + System.arraycopy(selection, 0, all, paths.length, selection.length); + + return arePathsContiguous(all); + } + + /** + * Checks if the single path can be added to selection. + */ + private boolean canPathBeAdded(TreePath path) + { + if (rowMapper == null || isSelectionEmpty() + || selectionMode == DISCONTIGUOUS_TREE_SELECTION) + return true; + + TreePath[] all = new TreePath[selection.length + 1]; + System.arraycopy(selection, 0, all, 0, selection.length); + all[all.length - 1] = path; + + return arePathsContiguous(all); } /** @@ -801,9 +902,25 @@ public class DefaultTreeSelectionModel * selectionMode */ protected boolean canPathsBeRemoved(TreePath[] paths) - throws NotImplementedException { - return false; // STUB + if (rowMapper == null || isSelectionEmpty() + || selectionMode == DISCONTIGUOUS_TREE_SELECTION) + return true; + + HashSet set = new HashSet(); + for (int i = 0; i < selection.length; i++) + set.add(selection[i]); + + for (int i = 0; i < paths.length; i++) + set.remove(paths[i]); + + TreePath[] remaining = new TreePath[set.size()]; + Iterator iter = set.iterator(); + + for (int i = 0; i < remaining.length; i++) + remaining[i] = (TreePath) iter.next(); + + return arePathsContiguous(remaining); } /** |