This patch improves JList's multiple selection capabilities, most
notably by adding shift-click abilities.

Patch is attached.

Patch is pending approval.


2005-06-29  Anthony Balkissoon  <[EMAIL PROTECTED]>

        * javax/swing/DefaultListSelectionModel.java:
        (addSelectionInterval): Don't clear the selection state if JList's
        selection mode is SINGLE_SELECTION_INTERVAL and index0 and index1
        correspond to an interval adjacent to an already selected interval.
        (removeSelectionInterval): Added check for a middle interval being
        removed when selection mode is SINGLE_SELECTION_INTERVAL.
        * javax/swing/plaf/basic/BasicListUI.java:
        (KeyHandler.keyPressed): Added check for scrolling past bottom of list.
        (MouseHandler.mouseClicked): Added check for shift key being
        pressed.
Index: javax/swing/DefaultListSelectionModel.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/DefaultListSelectionModel.java,v
retrieving revision 1.16
diff -u -r1.16 DefaultListSelectionModel.java
--- javax/swing/DefaultListSelectionModel.java	29 Jun 2005 19:28:44 -0000	1.16
+++ javax/swing/DefaultListSelectionModel.java	29 Jun 2005 19:35:40 -0000
@@ -141,13 +141,13 @@
    * Used to make sure we only fireValueChanged when the BitSet
    * actually does change.
    */
-  Object oldSel;
+  private Object oldSel;
 
   /**
    * Whether this call of setLeadSelectionInterval was called locally
    * from addSelectionInterval
    */
-  boolean setLeadCalledFromAdd = false;
+  private boolean setLeadCalledFromAdd = false;
 
   /**
    * Gets the value of the [EMAIL PROTECTED] #selectionMode} property.
@@ -393,10 +393,14 @@
 
   /**
    * If the [EMAIL PROTECTED] #selectionMode} property is equal to
-   * <code>SINGLE_SELECTION</code> or
-   * <code>SINGLE_INTERVAL_SELECTION</code>, equivalent to calling
-   * <code>setSelectionInterval(index1, index2)</code>; otherwise adds the
-   * range <code>[index0, index1]</code> to the selection interval set.
+   * <code>SINGLE_SELECTION</code> equivalent to calling
+   * <code>setSelectionInterval(index1, index2)</code>; 
+   * If the [EMAIL PROTECTED] #selectionMode} property is equal to 
+   * <code>SINGLE_INTERVAL_SELECTION</code> and the interval being
+   * added is not adjacent to an already selected interval,
+   * equivalent to <code>setSelectionInterval(index1, index2)</code>.
+   * Otherwise adds the range <code>[index0, index1]</code> 
+   * to the selection interval set.
    *
    * @param index0 The beginning of the range of indices to select
    * @param index1 The end of the range of indices to select
@@ -406,17 +410,24 @@
    */
   public void addSelectionInterval(int index0, int index1) 
   {
+    int lo = Math.min(index0, index1);
+    int hi = Math.max(index0, index1);
     oldSel = sel.clone();
-    if (selectionMode == SINGLE_SELECTION
-        || selectionMode == SINGLE_INTERVAL_SELECTION)
+
+    if (selectionMode == SINGLE_SELECTION)
       sel.clear();
+
+    /* COMPAT: Like Sun (but not like IBM), we allow calls to 
+       addSelectionInterval when selectionMode is
+       SINGLE_SELECTION_INTERVAL iff the interval being added
+       is adjacent to an already selected interval */
+    if (selectionMode == SINGLE_INTERVAL_SELECTION)
+      if (!(isSelectedIndex(index0) || isSelectedIndex(index1) || isSelectedIndex(Math.max(lo-1,0)) || isSelectedIndex(Math.min(hi+1,sel.size()))))
+        sel.clear();
     
     if (selectionMode == SINGLE_SELECTION)
       index0 = index1;
 
-    int lo = Math.min(index0, index1);
-    int hi = Math.max(index0, index1);
-
     /* We have to update the anchorSelectionIndex and leadSelectionIndex
        variables */
     
@@ -461,6 +472,13 @@
     oldSel = sel.clone();
     int lo = Math.min(index0, index1);
     int hi = Math.max(index0, index1);
+
+    /* if selectionMode is SINGLE_INTERVAL_SELECTION and removing the interval
+       (index0,index1) would leave two disjoint selection intervals, remove all
+       selected indices from lo to the last selected index */
+    if (getMinSelectionIndex() > 0 && getMinSelectionIndex() < lo && selectionMode == SINGLE_INTERVAL_SELECTION)
+      hi = sel.size() - 1;
+
     sel.clear(lo, hi+1); 
     //update anchorSelectionIndex and leadSelectionIndex variables
     //TODO: will probably need MouseDragged to test properly and know if this works
Index: javax/swing/plaf/basic/BasicListUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicListUI.java,v
retrieving revision 1.19
diff -u -r1.19 BasicListUI.java
--- javax/swing/plaf/basic/BasicListUI.java	17 Jun 2005 10:12:29 -0000	1.19
+++ javax/swing/plaf/basic/BasicListUI.java	29 Jun 2005 19:35:40 -0000
@@ -200,14 +200,15 @@
       if (evt.getKeyCode() == KeyEvent.VK_DOWN)
         {
           int lead = BasicListUI.this.list.getLeadSelectionIndex();
+          int max = BasicListUI.this.list.getModel().getSize() - 1;
           if (!evt.isShiftDown())
             {
               BasicListUI.this.list.clearSelection();
-              BasicListUI.this.list.setSelectedIndex(lead+1);
+              BasicListUI.this.list.setSelectedIndex(Math.min(lead+1,max));
             }
           else 
             {
-              BasicListUI.this.list.getSelectionModel().setLeadSelectionIndex(lead+1);
+              BasicListUI.this.list.getSelectionModel().setLeadSelectionIndex(Math.min(lead+1,max));
             }
         }
       else if (evt.getKeyCode() == KeyEvent.VK_UP)
@@ -244,8 +245,7 @@
       int index = BasicListUI.this.locationToIndex(list, click);
       if (index == -1)
         return;
-      boolean controlPressed = event.isControlDown();
-      if (controlPressed)
+      if (event.isControlDown())
         {
           if (BasicListUI.this.list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION)
             BasicListUI.this.list.setSelectedIndex(index);
@@ -254,6 +254,22 @@
           else
             BasicListUI.this.list.addSelectionInterval(index,index);
         }
+      else if (event.isShiftDown())
+        {
+          if (BasicListUI.this.list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION)
+            BasicListUI.this.list.setSelectedIndex(index);
+          else if (BasicListUI.this.list.getSelectionMode() == ListSelectionModel.SINGLE_INTERVAL_SELECTION)
+            /*COMPAT: the IBM VM is compatible with the following line of code.  However, compliance with
+              Sun's VM would correspond to replacing getAnchorSelectionIndex() with getLeadSelectionIndex().
+              This is both unnatural and contradictory to the way they handle other similar UI interactions */
+            BasicListUI.this.list.setSelectionInterval(BasicListUI.this.list.getAnchorSelectionIndex(), index);
+          else
+            /*COMPAT: both Sun and IBM are compatible instead with:
+              BasicListUI.this.list.setSelectionInterval(BasicListUI.this.list.getLeadSelectionIndex(),index);
+              Note that for IBM this is contradictory to what they did in the above situation for
+              SINGLE_INTERVAL_SELECTION.  The most natural thing to do is the following: */
+            BasicListUI.this.list.getSelectionModel().setLeadSelectionIndex(index);
+        }
       else
         BasicListUI.this.list.setSelectedIndex(index);
     }
_______________________________________________
Classpath-patches mailing list
Classpath-patches@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath-patches

Reply via email to