Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 8549)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 8550)
@@ -586,4 +586,8 @@
 
         if (mode == Mode.SELECT) {
+            if (e.getButton() != MouseEvent.BUTTON1) {
+                return;
+            }
+            selectionManager.endSelecting(e);
             selectionManager.unregister(mv);
 
Index: /trunk/src/org/openstreetmap/josm/gui/SelectionManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 8549)
+++ /trunk/src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 8550)
@@ -2,5 +2,6 @@
 package org.openstreetmap.josm.gui;
 
-import java.awt.Component;
+import java.awt.Color;
+import java.awt.Graphics2D;
 import java.awt.Point;
 import java.awt.Polygon;
@@ -17,22 +18,28 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.SelectByInternalPointAction;
+import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
+import org.openstreetmap.josm.gui.layer.MapViewPaintable;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
- * Manages the selection of a rectangle. Listening to left and right mouse button
+ * Manages the selection of a rectangle or a lasso loop. Listening to left and right mouse button
  * presses and to mouse motions and draw the rectangle accordingly.
  *
  * Left mouse button selects a rectangle from the press until release. Pressing
- * right mouse button while left is still pressed enable the rectangle to move
+ * right mouse button while left is still pressed enable the selection area to move
  * around. Releasing the left button fires an action event to the listener given
  * at constructor, except if the right is still pressed, which just remove the
  * selection rectangle and does nothing.
  *
+ * It is possible to switch between lasso selection and rectangle selection by using {@link #setLassoMode(boolean)}.
+ *
  * The point where the left mouse button was pressed and the current mouse
  * position are two opposite corners of the selection rectangle.
  *
- * It is possible to specify an aspect ratio (width per height) which the
+ * For rectangle mode, it is possible to specify an aspect ratio (width per height) which the
  * selection rectangle always must have. In this case, the selection rectangle
  * will be the largest window with this aspect ratio, where the position the left
@@ -56,7 +63,8 @@
         /**
          * Called, when the left mouse button was released.
-         * @param r The rectangle that is currently the selection.
+         * @param r The rectangle that encloses the current selection.
          * @param e The mouse event.
          * @see InputEvent#getModifiersEx()
+         * @see SelectionManager#getSelectedObjects(boolean)
          */
         void selectionEnded(Rectangle r, MouseEvent e);
@@ -75,4 +83,29 @@
         void removePropertyChangeListener(PropertyChangeListener listener);
     }
+
+    /**
+     * This draws the selection hint (rectangle or lasso polygon) on the screen.
+     *
+     * @author Michael Zangl
+     */
+    private class SelectionHintLayer implements MapViewPaintable {
+        @Override
+        public void paint(Graphics2D g, MapView mv, Bounds bbox) {
+            if (mousePos == null || mousePosStart == null || mousePos == mousePosStart)
+                return;
+            Color color = Utils.complement(PaintColors.getBackgroundColor());
+            g.setColor(color);
+            if (lassoMode) {
+                g.drawPolygon(lasso);
+
+                g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha() / 8));
+                g.fillPolygon(lasso);
+            } else {
+                Rectangle paintRect = getSelectionRectangle();
+                g.drawRect(paintRect.x, paintRect.y, paintRect.width, paintRect.height);
+            }
+        }
+    }
+
     /**
      * The listener that receives the events after left mouse button is released.
@@ -81,13 +114,14 @@
     /**
      * Position of the map when the mouse button was pressed.
-     * If this is not <code>null</code>, a rectangle is drawn on screen.
+     * If this is not <code>null</code>, a rectangle/lasso line is drawn on screen.
+     * If this is <code>null</code>, no selection is active.
      */
     private Point mousePosStart;
     /**
-     * Position of the map when the selection rectangle was last drawn.
+     * The last position of the mouse while the mouse button was pressed.
      */
     private Point mousePos;
     /**
-     * The Component, the selection rectangle is drawn onto.
+     * The Component that provides us with OSM data and the aspect is taken from.
      */
     private final NavigatableComponent nc;
@@ -98,6 +132,19 @@
     private boolean aspectRatio;
 
+    /**
+     * <code>true</code> if we should paint a lasso instead of a rectangle.
+     */
     private boolean lassoMode;
+    /**
+     * The polygon to store the selection outline if {@link #lassoMode} is used.
+     */
     private Polygon lasso = new Polygon();
+
+    /**
+     * The result of the last selection.
+     */
+    private Polygon selectionResult = new Polygon();
+
+    private final SelectionHintLayer selectionHintLayer = new SelectionHintLayer();
 
     /**
@@ -108,5 +155,5 @@
      * @param aspectRatio If true, the selection window must obtain the aspect
      *      ratio of the drawComponent.
-     * @param navComp The component, the rectangle is drawn onto.
+     * @param navComp The component that provides us with OSM data and the aspect is taken from.
      */
     public SelectionManager(SelectionEnded selectionEndedListener, boolean aspectRatio, NavigatableComponent navComp) {
@@ -117,9 +164,9 @@
 
     /**
-     * Register itself at the given event source.
+     * Register itself at the given event source and add a hint layer.
      * @param eventSource The emitter of the mouse events.
      * @param lassoMode {@code true} to enable lasso mode, {@code false} to disable it.
      */
-    public void register(NavigatableComponent eventSource, boolean lassoMode) {
+    public void register(MapView eventSource, boolean lassoMode) {
        this.lassoMode = lassoMode;
         eventSource.addMouseListener(this);
@@ -129,18 +176,17 @@
             @Override
             public void propertyChange(PropertyChangeEvent evt) {
-                if (mousePosStart != null) {
-                    paintRect();
-                    mousePos = mousePosStart = null;
-                }
+                abortSelecting();
             }
         });
-    }
-    /**
-     * Unregister itself from the given event source. If a selection rectangle is
-     * shown, hide it first.
+        eventSource.addTemporaryLayer(selectionHintLayer);
+    }
+    /**
+     * Unregister itself from the given event source and hide the selection hint layer.
      *
      * @param eventSource The emitter of the mouse events.
      */
-    public void unregister(Component eventSource) {
+    public void unregister(MapView eventSource) {
+        abortSelecting();
+        eventSource.removeTemporaryLayer(selectionHintLayer);
         eventSource.removeMouseListener(this);
         eventSource.removeMouseMotionListener(this);
@@ -176,22 +222,27 @@
                 mousePosStart = mousePos = e.getPoint();
             }
-            if (!lassoMode) {
-                paintRect();
-            }
+            selectionAreaChanged();
         }
 
         if (buttonPressed == MouseEvent.BUTTON1_DOWN_MASK) {
             mousePos = e.getPoint();
-            if (lassoMode) {
-                paintLasso();
-            } else {
-                paintRect();
-            }
+            addLassoPoint(e.getPoint());
+            selectionAreaChanged();
         } else if (buttonPressed == (MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK)) {
-            mousePosStart.x += e.getX()-mousePos.x;
-            mousePosStart.y += e.getY()-mousePos.y;
+            moveSelection(e.getX()-mousePos.x, e.getY()-mousePos.y);
             mousePos = e.getPoint();
-            paintRect();
-        }
+            selectionAreaChanged();
+        }
+    }
+
+    /**
+     * Moves the current selection by some pixels.
+     * @param dx How much to move it in x direction.
+     * @param dy How much to move it in y direction.
+     */
+    private void moveSelection(int dx, int dy) {
+        mousePosStart.x += dx;
+        mousePosStart.y += dy;
+        lasso.translate(dx, dy);
     }
 
@@ -201,43 +252,37 @@
     @Override
     public void mouseReleased(MouseEvent e) {
-        if (e.getButton() != MouseEvent.BUTTON1)
+        if (e.getButton() == MouseEvent.BUTTON1) {
+            endSelecting(e);
+        }
+    }
+
+    /**
+     * Ends the selection of the current area. This simulates a release of mouse button 1.
+     * @param e A mouse event that caused this. Needed for backward compatibility.
+     */
+    public void endSelecting(MouseEvent e) {
+        mousePos = e.getPoint();
+        if (lassoMode) {
+            addLassoPoint(e.getPoint());
+        }
+
+        // Left mouse was released while right is still pressed.
+        boolean rightMouseStillPressed = (e.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) != 0;
+
+        if (!rightMouseStillPressed) {
+            selectingDone(e);
+        }
+        abortSelecting();
+    }
+
+    private void addLassoPoint(Point point) {
+        if (isNoSelection()) {
             return;
-        if (mousePos == null || mousePosStart == null)
-            return; // injected release from outside
-        // disable the selection rect
-        Rectangle r;
-        if (!lassoMode) {
-            nc.requestClearRect();
-            r = getSelectionRectangle();
-
-            lasso = rectToPolygon(r);
-        } else {
-            nc.requestClearPoly();
-            lasso.addPoint(mousePos.x, mousePos.y);
-            r = lasso.getBounds();
-        }
-        mousePosStart = null;
-        mousePos = null;
-
-        if ((e.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) == 0) {
-            selectionEndedListener.selectionEnded(r, e);
-        }
-    }
-
-    /**
-     * Draws a selection rectangle on screen.
-     */
-    private void paintRect() {
-        if (mousePos == null || mousePosStart == null || mousePos == mousePosStart)
-            return;
-        nc.requestPaintRect(getSelectionRectangle());
-    }
-
-    private void paintLasso() {
-        if (mousePos == null || mousePosStart == null || mousePos == mousePosStart) {
-            return;
-        }
-        lasso.addPoint(mousePos.x, mousePos.y);
-        nc.requestPaintPoly(lasso);
+        }
+        lasso.addPoint(point.x, point.y);
+    }
+
+    private boolean isNoSelection() {
+        return mousePos == null || mousePosStart == null || mousePos == mousePosStart;
     }
 
@@ -287,13 +332,47 @@
     @Override
     public void propertyChange(PropertyChangeEvent evt) {
-        if ("active".equals(evt.getPropertyName()) && !(Boolean) evt.getNewValue() && mousePosStart != null) {
-            paintRect();
-            mousePosStart = null;
-            mousePos = null;
-        }
-    }
-
-    /**
-     * Return a list of all objects in the selection, respecting the different
+        if ("active".equals(evt.getPropertyName()) && !(Boolean)evt.getNewValue()) {
+            abortSelecting();
+        }
+    }
+
+    /**
+     * Stores the  current selection and stores the result in {@link #selectionResult} to  be retrieved by {@link #getSelectedObjects(boolean)} later.
+     * @param e The mouse event that caused the selection to be finished.
+     */
+    private void selectingDone(MouseEvent e) {
+        if (isNoSelection()) {
+            // Nothing selected.
+            return;
+        }
+        Rectangle r;
+        if (lassoMode) {
+            r = lasso.getBounds();
+
+            selectionResult = new Polygon(lasso.xpoints, lasso.ypoints, lasso.npoints);
+        } else {
+            r = getSelectionRectangle();
+
+            selectionResult = rectToPolygon(r);
+        }
+        selectionEndedListener.selectionEnded(r, e);
+    }
+
+    private void abortSelecting() {
+        if (mousePosStart != null) {
+            mousePos = mousePosStart = null;
+            lasso.reset();
+            selectionAreaChanged();
+        }
+    }
+
+    private void selectionAreaChanged() {
+        // Trigger a redraw of the map view.
+        // A nicer way would be to provide change events for the temporary layer.
+        Main.map.mapView.repaint();
+    }
+
+    /**
+     * Return a list of all objects in the active/last selection, respecting the different
      * modifier.
      *
@@ -308,5 +387,5 @@
         // whether user only clicked, not dragged.
         boolean clicked = false;
-        Rectangle bounding = lasso.getBounds();
+        Rectangle bounding = selectionResult.getBounds();
         if (bounding.height <= 2 && bounding.width <= 2) {
             clicked = true;
@@ -314,5 +393,5 @@
 
         if (clicked) {
-            Point center = new Point(lasso.xpoints[0], lasso.ypoints[0]);
+            Point center = new Point(selectionResult.xpoints[0], selectionResult.ypoints[0]);
             OsmPrimitive osm = nc.getNearestNodeOrWay(center, OsmPrimitive.isSelectablePredicate, false);
             if (osm != null) {
@@ -322,5 +401,5 @@
             // nodes
             for (Node n : nc.getCurrentDataSet().getNodes()) {
-                if (n.isSelectable() && lasso.contains(nc.getPoint2D(n))) {
+                if (n.isSelectable() && selectionResult.contains(nc.getPoint2D(n))) {
                     selection.add(n);
                 }
@@ -334,5 +413,5 @@
                 if (alt) {
                     for (Node n : w.getNodes()) {
-                        if (!n.isIncomplete() && lasso.contains(nc.getPoint2D(n))) {
+                        if (!n.isIncomplete() && selectionResult.contains(nc.getPoint2D(n))) {
                             selection.add(w);
                             break;
@@ -342,5 +421,5 @@
                     boolean allIn = true;
                     for (Node n : w.getNodes()) {
-                        if (!n.isIncomplete() && !lasso.contains(nc.getPoint(n))) {
+                        if (!n.isIncomplete() && !selectionResult.contains(nc.getPoint(n))) {
                             allIn = false;
                             break;
