

---

 core-dave/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java |   40 +++++-----
 core-dave/src/org/openstreetmap/josm/data/osm/DataSet.java             |   31 +++++--
 2 files changed, 41 insertions(+), 30 deletions(-)

diff -puN src/org/openstreetmap/josm/gui/SelectionManager.java~fix-shift-selection src/org/openstreetmap/josm/gui/SelectionManager.java
diff -puN src/org/openstreetmap/josm/actions/mapmode/SelectAction.java~fix-shift-selection src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
--- core/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java~fix-shift-selection	2009-10-28 11:32:40.000000000 -0700
+++ core-dave/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	2009-10-28 12:56:28.000000000 -0700
@@ -498,7 +498,7 @@ public class SelectAction extends MapMod
                         }
                     }
                 }
-                DataSet.fireSelectionChanged(selection);
+                getCurrentDataSet().fireSelectionChanged();
             }
         }
 
@@ -514,30 +514,30 @@ public class SelectAction extends MapMod
 
     public void selectPrims(Collection<OsmPrimitive> selectionList, boolean shift,
             boolean ctrl, boolean released, boolean area) {
+        DataSet ds = getCurrentDataSet();
         if ((shift && ctrl) || (ctrl && !released))
             return; // not allowed together
 
-        Collection<OsmPrimitive> curSel;
-        if (!ctrl && !shift) {
-            curSel = new LinkedList<OsmPrimitive>(); // new selection will replace the old.
+        // plain clicks with no modifiers clear the selection
+        if (!ctrl && !shift)
+            ds.clearSelection();
+
+        if (ctrl) {
+            // Ctrl on an item toggles its selection status,
+            // but Ctrl on an *area* just clears those items
+            // out of the selection.
+            if (area)
+                ds.clearSelection(selectionList);
+            else
+                ds.toggleSelected(selectionList);
         } else {
-            curSel = getCurrentDataSet().getSelected();
+            // This is either a plain click (which means we
+            // previously cleared the selection), or a
+            // shift-click where we are adding things to an
+            // existing selection.
+            ds.addSelected(selectionList);
         }
-
-        for (OsmPrimitive osm : selectionList)
-        {
-            if (ctrl)
-            {
-                if(curSel.contains(osm)) {
-                    curSel.remove(osm);
-                } else if(!area) {
-                    curSel.add(osm);
-                }
-            } else {
-                curSel.add(osm);
-            }
-        }
-        getCurrentDataSet().setSelected(curSel);
+        ds.fireSelectionChanged();
         Main.map.mapView.repaint();
     }
 
diff -puN src/org/openstreetmap/josm/data/osm/DataSet.java~fix-shift-selection src/org/openstreetmap/josm/data/osm/DataSet.java
--- core/src/org/openstreetmap/josm/data/osm/DataSet.java~fix-shift-selection	2009-10-28 11:33:04.000000000 -0700
+++ core-dave/src/org/openstreetmap/josm/data/osm/DataSet.java	2009-10-28 12:55:29.000000000 -0700
@@ -241,6 +241,14 @@ public class DataSet implements Cloneabl
 
     LinkedHashSet<OsmPrimitive> selectedPrimitives = new LinkedHashSet<OsmPrimitive>();
 
+    public boolean toggleSelected(Collection<OsmPrimitive> osm) {
+        for (OsmPrimitive o : osm)
+            this.toggleSelected(o);
+        return true;
+    }
+    public boolean toggleSelected(OsmPrimitive... osm) {
+        return this.toggleSelected(Arrays.asList(osm));
+    }
     public boolean toggleSelected(OsmPrimitive osm) {
         if (!selectedPrimitives.remove(osm)) {
             selectedPrimitives.add(osm);
@@ -275,7 +283,7 @@ public class DataSet implements Cloneabl
     public void setSelected(Collection<? extends OsmPrimitive> selection, boolean fireSelectionChangeEvent) {
         selectedPrimitives = new LinkedHashSet<OsmPrimitive>(selection);
         if (fireSelectionChangeEvent) {
-            fireSelectionChanged(selection);
+            fireSelectionChanged();
         }
     }
 
@@ -313,7 +321,7 @@ public class DataSet implements Cloneabl
     public void addSelected(Collection<? extends OsmPrimitive> selection, boolean fireSelectionChangeEvent) {
         selectedPrimitives.addAll(selection);
         if (fireSelectionChangeEvent) {
-            fireSelectionChanged(selection);
+            fireSelectionChanged();
         }
     }
 
@@ -325,7 +333,7 @@ public class DataSet implements Cloneabl
         }
         List<OsmPrimitive> list = Arrays.asList(osm);
         setSelected(list);
-        fireSelectionChanged(list);
+        fireSelectionChanged();
     }
 
     /**
@@ -358,11 +366,14 @@ public class DataSet implements Cloneabl
     public void clearSelection(OsmPrimitive... osm) {
         clearSelection(Arrays.asList(osm));
     }
-    private void clearSelection(Collection<? extends OsmPrimitive> list) {
+    public void clearSelection(Collection<? extends OsmPrimitive> list) {
         if (list == null)
             return;
         selectedPrimitives.removeAll(list);
     }
+    public void clearSelection() {
+        selectedPrimitives = new LinkedHashSet<OsmPrimitive>();
+    }
 
     /**
      * Return all selected items in the collection.
@@ -379,12 +390,12 @@ public class DataSet implements Cloneabl
         return sel;
     }
 
-    /**
-     * Remember to fire an selection changed event. A call to this will not fire the event
-     * immediately. For more,
-     * @see SelectionChangedListener
-     */
-    public static void fireSelectionChanged(Collection<? extends OsmPrimitive> sel) {
+    public void fireSelectionChanged()
+    {
+        __fireSelectionChanged(selectedPrimitives);
+    }
+
+    public static void __fireSelectionChanged(Collection<? extends OsmPrimitive> sel) {
         for (SelectionChangedListener l : selListeners) {
             l.selectionChanged(sel);
         }
_
