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