As we have the row mapper now, it is simple to implement missing methods in DefaultTreeSelectionModel.

2006-04-22  Audrius Meskauskas  <[EMAIL PROTECTED]>

   * javax/swing/tree/DefaultTreeSelectionModel.java
   (addSelectionPath): If the path cannot be added, set it.
   (addSelectionPaths): Call insureRowContinuity.
   (arePathsContiguous): Implemented.
   (canPathsBeAdded): New private method.
   (canPathsBeAdded): Implemented.
   (canPathsBeRemoved): Implemented.
   (getPath): New private method.
   (insureRowContinuity): Implemented.
   (removeSelectionPath): Call insureRowContinuity.
   (removeSelectionPaths): Call insureRowContinuity.
(resetRowSelection): Removed stub marking, not used in implementation (nothing to do there).
   (selectOne): New private method.
   (setSelectionMode) Call insureRowContinuity.
   (setSelectionPaths) Remove the current selection by clearing it.
Index: DefaultTreeSelectionModel.java
===================================================================
RCS file: /sources/classpath/classpath/javax/swing/tree/DefaultTreeSelectionModel.java,v
retrieving revision 1.25
diff -u -r1.25 DefaultTreeSelectionModel.java
--- DefaultTreeSelectionModel.java	21 Apr 2006 10:13:12 -0000	1.25
+++ DefaultTreeSelectionModel.java	22 Apr 2006 06:54:53 -0000
@@ -45,7 +45,10 @@
 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 void setSelectionMode(int mode)
   {
     selectionMode = mode;
+    insureRowContinuity();
   }
 
   /**
@@ -312,7 +316,7 @@
   {
     // Must be called, as defined in JDK API 1.4.
     insureUniqueness();
-    removeSelectionPaths(selection);
+    clearSelection();
     addSelectionPaths(paths);
   }
 
@@ -327,7 +331,8 @@
   {
     if (! isPathSelected(path))
       {
-        if (isSelectionEmpty())
+        if (selectionMode == SINGLE_TREE_SELECTION || isSelectionEmpty()
+            || ! canPathBeAdded(path))
           setSelectionPath(path);
         else
           {
@@ -339,7 +344,7 @@
           }
         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 @@
   {
     // Must be called, as defined in JDK API 1.4.
     insureUniqueness();
-    
+
     if (paths != null)
       {
         TreePath v0 = null;
@@ -377,12 +382,13 @@
                   }
                 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 @@
 
         fireValueChanged(new TreeSelectionEvent(this, path, false, leadPath,
                                                 path));
+        insureRowContinuity();
       }
   }
 
@@ -458,6 +465,7 @@
                                                         leadPath, paths[0]));
               }
           }
+        insureRowContinuity();
       }
   }
 
@@ -685,9 +693,9 @@
   /**
    * 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 @@
    * 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 @@
    *         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 @@
    *         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);
   }
 
   /**

Reply via email to