Index: trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 804)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 805)
@@ -11,4 +11,5 @@
 import java.awt.event.MouseEvent;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.LinkedList;
 
@@ -17,12 +18,18 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.MergeNodesAction;
+import org.openstreetmap.josm.command.AddCommand;
 import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.ChangeCommand;
 import org.openstreetmap.josm.command.MoveCommand;
 import org.openstreetmap.josm.command.RotateCommand;
+import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.data.coor.EastNorth;
 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.WaySegment;
 import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
 import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.SelectionManager;
 import org.openstreetmap.josm.gui.SelectionManager.SelectionEnded;
@@ -108,4 +115,5 @@
 		Main.map.mapView.addMouseListener(this);
 		Main.map.mapView.addMouseMotionListener(this);
+		Main.map.mapView.enableVirtualNodes(Main.pref.getInteger("mappaint.node.virtual-size", 4) != 0);
 	}
 
@@ -115,4 +123,5 @@
 		Main.map.mapView.removeMouseListener(this);
 		Main.map.mapView.removeMouseMotionListener(this);
+		Main.map.mapView.enableVirtualNodes(false);
 	}
 
@@ -195,4 +204,44 @@
 	}
 
+	private Collection<OsmPrimitive> getNearestCollectionVirtual(Point p) {
+		MapView c = Main.map.mapView;
+		OsmPrimitive osm = c.getNearestNode(p);
+		if (osm == null)
+		{
+			WaySegment nearestWaySeg = c.getNearestWaySegment(p);
+			if(nearestWaySeg != null)
+			{
+				osm = nearestWaySeg.way;
+				if(Main.pref.getInteger("mappaint.node.virtual-size", 4) > 0)
+				{
+					Way w = (Way)osm;
+					Point p1 = c.getPoint(w.nodes.get(nearestWaySeg.lowerIndex).eastNorth);
+					Point p2 = c.getPoint(w.nodes.get(nearestWaySeg.lowerIndex+1).eastNorth);
+					int xd = p2.x-p1.x; if(xd < 0) xd = -xd;
+					int yd = p2.y-p1.y; if(yd < 0) yd = -yd;
+					if(xd+yd > Main.pref.getInteger("mappaint.node.virtual-space", 50))
+					{
+						Point pc = new Point((p1.x+p2.x)/2, (p1.y+p2.y)/2);
+						if(p.distanceSq(pc) < Main.map.mapView.snapDistance)
+						{
+							Collection<Command> cmds = new LinkedList<Command>();
+							Node n = new Node(Main.map.mapView.getLatLon(pc.x, pc.y));
+							cmds.add(new AddCommand(n));
+
+							Way wnew = new Way(w);
+							wnew.nodes.add(nearestWaySeg.lowerIndex+1, n);
+							cmds.add(new ChangeCommand(w, wnew));
+							Main.main.undoRedo.add(new SequenceCommand(tr("Add a new node to an existing way"), cmds));
+							osm = n;
+						}
+					}
+				}
+			}
+		}
+		if (osm == null) 
+			return Collections.emptySet();
+		return Collections.singleton(osm);
+	}
+
 	/**
 	 * Look, whether any object is selected. If not, select the nearest node.
@@ -216,6 +265,5 @@
 		initialMoveThresholdExceeded = false;
 
-		Collection<OsmPrimitive> osmColl =
-			Main.map.mapView.getNearestCollection(e.getPoint());
+		Collection<OsmPrimitive> osmColl = getNearestCollectionVirtual(e.getPoint());
 
 		if (ctrl && shift) {
@@ -289,5 +337,5 @@
 
 	public void selectPrims(Collection<OsmPrimitive> selectionList, boolean shift, boolean ctrl) {
-	    if (shift && ctrl)
+		if (shift && ctrl)
 			return; // not allowed together
 
@@ -305,5 +353,5 @@
 		Main.ds.setSelected(curSel);
 		Main.map.mapView.repaint();
-    }
+	}
 	
 	@Override public String getModeHelpText() {
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 804)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 805)
@@ -27,4 +27,5 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor;
 import org.openstreetmap.josm.gui.NavigatableComponent;
 import org.openstreetmap.josm.gui.mappaint.AreaElemStyle;
@@ -34,117 +35,62 @@
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
 
-public class MapPaintVisitor implements Visitor {
-    
-    protected boolean useRealWidth;
-    protected boolean zoomLevelDisplay;
-    protected boolean fillAreas;
-    protected int fillAlpha;
-    protected Color untaggedColor;
-    protected Color textColor;
-    protected boolean currentDashed = false;
-    protected int currentWidth = 0;
-    protected Stroke currentStroke = null;    
-    protected static final Font orderFont = new Font("Helvetica", Font.PLAIN, 8);
-    
-    public boolean inactive;
-    
-    /**
-     * The environment to paint to.
-     */
-    protected Graphics g;
-    
-    /**
-     * MapView to get screen coordinates.
-     */
-    protected NavigatableComponent nc;
-    
-    /**
-     * Draw subsequent segments of same color as one Path
-     */
-    protected Color currentColor = null;
-    protected GeneralPath currentPath = new GeneralPath();
-    
-    protected static final double PHI = Math.toRadians(20);
-    
-    /**
-     * Preferences
-    */
-    protected Color inactiveColor;
-    protected Color selectedColor;
-    protected Color nodeColor;
-    protected Color dfltWayColor;
-    protected Color untaggedWayColor;
-    protected Color incompleteColor;
-    protected Color backgroundColor;
-    protected boolean showDirectionArrow;
-    protected boolean showRelevantDirectionsOnly;
-    protected boolean showOrderNumber;
-    
-	private boolean fillSelectedNode;
-
-	private boolean fillUnselectedNode;
-
-	private int selectedNodeRadius;
-
-	private int unselectedNodeRadius;
-	
-	private int taggedNodeRadius;
-
-	private int selectedNodeSize;
-
-	private int unselectedNodeSize;
-
-	private int defaultSegmentWidth = 2;
-	private int taggedNodeSize;
-
-    public final static Color darkerblue = new Color(0,0,96);
-    public final static Color darkblue = new Color(0,0,128);
-    
-    protected boolean isZoomOk(ElemStyle e) {
-        double circum = Main.map.mapView.getScale()*100*Main.proj.scaleFactor()*40041455; // circumference of the earth in meter
-
-        /* show everything if the user wishes so */
-        if (!zoomLevelDisplay) {
-            return true;
-        }
-
-        if (e == null) {
-            /* the default for things that don't have a rule (show, if scale is smaller than 1500m) */
-            if (circum < 1500)
-                return true;
-            return false;
-        }
-
-        // formula to calculate a map scale: natural size / map size = scale
-        // example: 876000mm (876m as displayed) / 22mm (roughly estimated screen size of legend bar) = 39818
-        //
-        // so the exact "correcting value" below depends only on the screen size and resolution
-        // XXX - do we need a Preference setting for this (if things vary widely)?
-        /*System.out.println(
-   "Circum: " + circum + 
-   " max: " + e.getMaxScale() + "(" + e.getMaxScale()/22 + ")" +
-   " min:" + e.getMinScale() + "(" + e.getMinScale()/22 + ")");*/
-        if(circum>=e.getMaxScale() / 22 || circum<e.getMinScale() / 22)
-            return false;
-        return true;
-    }
-
-    /**
-     * Draw a small rectangle.
-     * White if selected (as always) or red otherwise.
-     *
-     * @param n The node to draw.
-     */
-    public void visit(Node n) {
-        ElemStyle nodeStyle = MapPaintStyles.getStyle(n);
-        if (nodeStyle!=null) {
-            if (nodeStyle instanceof IconElemStyle) {
-                if (isZoomOk(nodeStyle)) {
-                    drawNode(n, ((IconElemStyle)nodeStyle).getIcon(), ((IconElemStyle)nodeStyle).doAnnotate());
-                }
-            } else {
-                // throw some sort of exception
-            }
-        } else {
+public class MapPaintVisitor extends SimplePaintVisitor {
+	protected boolean useRealWidth;
+	protected boolean zoomLevelDisplay;
+	protected boolean fillAreas;
+	protected int fillAlpha;
+	protected Color untaggedColor;
+	protected Color textColor;
+	protected boolean currentDashed = false;
+	protected int currentWidth = 0;
+	protected Stroke currentStroke = null;
+	protected static final Font orderFont = new Font("Helvetica", Font.PLAIN, 8);
+
+	protected boolean isZoomOk(ElemStyle e) {
+		double circum = Main.map.mapView.getScale()*100*Main.proj.scaleFactor()*40041455; // circumference of the earth in meter
+
+		/* show everything if the user wishes so */
+		if (!zoomLevelDisplay) {
+			return true;
+		}
+
+		if (e == null) {
+			/* the default for things that don't have a rule (show, if scale is smaller than 1500m) */
+			if (circum < 1500)
+				return true;
+			return false;
+		}
+
+		// formula to calculate a map scale: natural size / map size = scale
+		// example: 876000mm (876m as displayed) / 22mm (roughly estimated screen size of legend bar) = 39818
+		//
+		// so the exact "correcting value" below depends only on the screen size and resolution
+		// XXX - do we need a Preference setting for this (if things vary widely)?
+		/*System.out.println(
+		"Circum: " + circum +
+		" max: " + e.getMaxScale() + "(" + e.getMaxScale()/22 + ")" +
+		" min:" + e.getMinScale() + "(" + e.getMinScale()/22 + ")");*/
+		if(circum>=e.getMaxScale() / 22 || circum<e.getMinScale() / 22)
+			return false;
+		return true;
+	}
+
+	/**
+	 * Draw a small rectangle.
+	 * White if selected (as always) or red otherwise.
+	 *
+	 * @param n The node to draw.
+	 */
+	public void visit(Node n) {
+		ElemStyle nodeStyle = MapPaintStyles.getStyle(n);
+		if (nodeStyle!=null) {
+			if (nodeStyle instanceof IconElemStyle) {
+				if (isZoomOk(nodeStyle)) {
+					drawNode(n, ((IconElemStyle)nodeStyle).getIcon(), ((IconElemStyle)nodeStyle).doAnnotate());
+				}
+			} else {
+				// throw some sort of exception
+			}
+		} else {
 			if (n.selected)
 				drawNode(n, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
@@ -153,208 +99,194 @@
 			else
 				drawNode(n, nodeColor, unselectedNodeSize, unselectedNodeRadius, fillUnselectedNode);
-        }
-    }
-
-    /**
-     * Draw a line for all segments, according to tags.
-     * @param w The way to draw.
-     */
-    public void visit(Way w) {
-        double circum = Main.map.mapView.getScale()*100*Main.proj.scaleFactor()*40041455; // circumference of the earth in meter
-                // show direction arrows, if draw.segment.relevant_directions_only is not set, the way is tagged with a direction key
-                // (even if the tag is negated as in oneway=false) or the way is selected
-        boolean showDirection = w.selected ||
-                                        ((!useRealWidth) && (showDirectionArrow
-                                                             && (!showRelevantDirectionsOnly || w.hasDirectionKeys)));
-
-        Color colour = untaggedColor;
+		}
+	}
+
+	/**
+	 * Draw a line for all segments, according to tags.
+	 * @param w The way to draw.
+	 */
+	public void visit(Way w) {
+		double circum = Main.map.mapView.getScale()*100*Main.proj.scaleFactor()*40041455; // circumference of the earth in meter
+		// show direction arrows, if draw.segment.relevant_directions_only is not set, the way is tagged with a direction key
+		// (even if the tag is negated as in oneway=false) or the way is selected
+		boolean showDirection = w.selected || ((!useRealWidth) && (showDirectionArrow
+		 && (!showRelevantDirectionsOnly || w.hasDirectionKeys)));
+
+		Color colour = untaggedColor;
 		int width = defaultSegmentWidth;
-        int realWidth = 0; //the real width of the element in meters 
-        boolean dashed = false;
-        boolean area = false;
-        ElemStyle wayStyle = MapPaintStyles.getStyle(w);
-
-        if(!isZoomOk(wayStyle)) {
-            return;
-        }
-
-        if(wayStyle!=null)
-        {
-            if(wayStyle instanceof LineElemStyle)
-            {
-                colour = ((LineElemStyle)wayStyle).colour;
-                width = ((LineElemStyle)wayStyle).width;
-                realWidth = ((LineElemStyle)wayStyle).realWidth; 
-                dashed = ((LineElemStyle)wayStyle).dashed;
-            }
-            else if (wayStyle instanceof AreaElemStyle)
-            {
-                colour = ((AreaElemStyle)wayStyle).getColour();
-                area = true;
-            }
-        }
-
-        if (area && fillAreas)
-            drawWayAsArea(w, colour);
-        int orderNumber = 0;
-
-        Node lastN = null;
-        for (Node n : w.nodes) {
-            if (lastN == null) {
-                lastN = n;
-                continue;
-            }
-            orderNumber++;
-
-            if (area) {
-                if(fillAreas)
-                {
-                    // hack to make direction arrows visible against filled background
-                    if (showDirection)
-                        drawSeg(lastN, n, w.selected ? selectedColor : untaggedColor, showDirection, width, true);
-                }
-                else
-                    drawSeg(lastN, n, w.selected ? selectedColor : colour, showDirection, width, true);
-            } else {
-                if (realWidth > 0 && useRealWidth && !showDirection) {
-                    int tmpWidth = (int) (100 /  (float) (circum / realWidth));
-                    if (tmpWidth > width) width = tmpWidth;
-                }
-                drawSeg(lastN, n, w.selected ? selectedColor : colour, showDirection, width, dashed);
-            }
-
-            if (showOrderNumber)
-                drawOrderNumber(lastN, n, orderNumber);
-
-            lastN = n;
-        }
-    }
-
-    public void visit(Relation e) {
-        // relations are not (yet?) drawn.
-    }
-    
-    // This assumes that all segments are aligned in the same direction!
-    protected void drawWayAsArea(Way w, Color colour)
-    {
-        Polygon polygon = new Polygon();
-        Point p;
-        // set the opacity (alpha) level of the filled polygon
-        Color coloura = new Color( colour.getRed(), colour.getGreen(), colour.getBlue(), fillAlpha);
-
-        for (Node n : w.nodes)
-        {
-            p = nc.getPoint(n.eastNorth);
-            polygon.addPoint(p.x,p.y);
-        }
-
-        g.setColor( w.selected ?
-                selectedColor : coloura);
-
-        g.fillPolygon(polygon);
-    }
-
-    // NEW
-    protected void drawNode(Node n, ImageIcon icon, boolean annotate) {
-        Point p = nc.getPoint(n.eastNorth);
-        if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
-        int w = icon.getIconWidth(), h=icon.getIconHeight();
-        icon.paintIcon ( Main.map.mapView, g, p.x-w/2, p.y-h/2 );
-        String name = (n.keys==null) ? null : n.keys.get("name");
-        if (name!=null && annotate)
-        {
-            g.setColor(textColor);
-            Font defaultFont = g.getFont();
-            g.setFont (orderFont);
-            g.drawString (name, p.x+w/2+2, p.y+h/2+2);
-            g.setFont(defaultFont);
-        }
-        if (n.selected)
-        {
-            g.setColor (  selectedColor );
-            g.drawRect (p.x-w/2-2,p.y-w/2-2, w+4, h+4);
-        }
-    }
-
-    /**
-     * Draw a line with the given color.
-     */
-    protected void drawSegment(Node n1, Node n2, Color col, boolean showDirection) {
-        if (useRealWidth && showDirection) showDirection = false;
-        drawSeg(n1, n2, col, showDirection, 1, false);
-    }
-
-    private void drawSeg(Node n1, Node n2, Color col, boolean showDirection, int width, boolean dashed) {
-        if (col != currentColor || width != currentWidth || dashed != currentDashed) {
-            displaySegments(col, width, dashed);
-        }
-        Point p1 = nc.getPoint(n1.eastNorth);
-        Point p2 = nc.getPoint(n2.eastNorth);
-
-        if (!isSegmentVisible(p1, p2)) {
-            return;
-        }
-        //if (ls.selected)
-        // col = selectedColor;
-        //g.setColor(col);
-        //g.setWidth(width);
-        //if (dashed) 
-        // g2d.setStroke(new BasicStroke(width,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0,new float[] {9},0));
-        //else 
-        // g2d.setStroke(new BasicStroke(width,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
-
-        //g.drawLine(p1.x, p1.y, p2.x, p2.y);
-        currentPath.moveTo(p1.x, p1.y);
-        currentPath.lineTo(p2.x, p2.y);
-
-        if (showDirection) {
-            double t = Math.atan2(p2.y-p1.y, p2.x-p1.x) + Math.PI;
-            //g.drawLine(p2.x,p2.y, (int)(p2.x + 10*Math.cos(t-PHI)), (int)(p2.y + 10*Math.sin(t-PHI)));
-            //g.drawLine(p2.x,p2.y, (int)(p2.x + 10*Math.cos(t+PHI)), (int)(p2.y + 10*Math.sin(t+PHI)));
-            currentPath.lineTo((int)(p2.x + 10*Math.cos(t-PHI)), (int)(p2.y + 10*Math.sin(t-PHI)));
-            currentPath.moveTo((int)(p2.x + 10*Math.cos(t+PHI)), (int)(p2.y + 10*Math.sin(t+PHI)));
-            currentPath.lineTo(p2.x, p2.y);
-        }
-        //g2d.setStroke(new BasicStroke(1));
-
-    }
-
-    protected void displaySegments() {
-        displaySegments(null, 0, false);
-    }
-
-    protected void displaySegments(Color newColor, int newWidth, boolean newDash) {
-
-        if (currentPath != null) {
-            Graphics2D g2d = (Graphics2D)g;
-            g2d.setColor(inactive ? inactiveColor : currentColor);
-            if (currentStroke == null) {
-                if (currentDashed)
-                    g2d.setStroke(new BasicStroke(currentWidth,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0,new float[] {9},0));
-                else 
-                    g2d.setStroke(new BasicStroke(currentWidth,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
-            }
-            g2d.draw(currentPath);
-            g2d.setStroke(new BasicStroke(1));
-
-            currentPath = new GeneralPath();
-            currentColor = newColor;
-            currentWidth = newWidth;
-            currentDashed = newDash;
-            currentStroke = null;
-        }
-    }
-
-    /**
-     * Draw the node as small rectangle with the given color.
-     *
-     * @param n  The node to draw.
-     * @param color The color of the node.
-     */
-    public void drawNode(Node n, Color color, int size, int radius, boolean fill) {
+		int realWidth = 0; //the real width of the element in meters
+		boolean dashed = false;
+		boolean area = false;
+		ElemStyle wayStyle = MapPaintStyles.getStyle(w);
+
+		if(!isZoomOk(wayStyle)) {
+			return;
+		}
+
+		if(wayStyle!=null)
+		{
+			if(wayStyle instanceof LineElemStyle)
+			{
+				colour = ((LineElemStyle)wayStyle).colour;
+				width = ((LineElemStyle)wayStyle).width;
+				realWidth = ((LineElemStyle)wayStyle).realWidth;
+				dashed = ((LineElemStyle)wayStyle).dashed;
+			}
+			else if (wayStyle instanceof AreaElemStyle)
+			{
+				colour = ((AreaElemStyle)wayStyle).getColour();
+				area = true;
+			}
+		}
+
+		if (area && fillAreas)
+			drawWayAsArea(w, colour);
+		int orderNumber = 0;
+
+		Node lastN = null;
+		for (Node n : w.nodes) {
+			if (lastN == null) {
+				lastN = n;
+				continue;
+			}
+			orderNumber++;
+
+			if (area) {
+				if(fillAreas)
+				{
+					// hack to make direction arrows visible against filled background
+					if (showDirection)
+						drawSeg(lastN, n, w.selected ? selectedColor : untaggedColor, showDirection, width, true);
+				}
+				else
+					drawSeg(lastN, n, w.selected ? selectedColor : colour, showDirection, width, true);
+			} else {
+				if (realWidth > 0 && useRealWidth && !showDirection) {
+					int tmpWidth = (int) (100 /  (float) (circum / realWidth));
+					if (tmpWidth > width) width = tmpWidth;
+				}
+				drawSeg(lastN, n, w.selected ? selectedColor : colour, showDirection, width, dashed);
+			}
+
+			if (showOrderNumber)
+				drawOrderNumber(lastN, n, orderNumber);
+
+			lastN = n;
+		}
+	}
+
+	public void visit(Relation e) {
+		// relations are not (yet?) drawn.
+	}
+
+	// This assumes that all segments are aligned in the same direction!
+	protected void drawWayAsArea(Way w, Color colour)
+	{
+		Polygon polygon = new Polygon();
+		Point p;
+		// set the opacity (alpha) level of the filled polygon
+		Color coloura = new Color( colour.getRed(), colour.getGreen(), colour.getBlue(), fillAlpha);
+
+		for (Node n : w.nodes)
+		{
+			p = nc.getPoint(n.eastNorth);
+			polygon.addPoint(p.x,p.y);
+		}
+
+		g.setColor( w.selected ?
+				selectedColor : coloura);
+
+		g.fillPolygon(polygon);
+	}
+
+	// NEW
+	protected void drawNode(Node n, ImageIcon icon, boolean annotate) {
+		Point p = nc.getPoint(n.eastNorth);
+		if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
+		int w = icon.getIconWidth(), h=icon.getIconHeight();
+		icon.paintIcon ( Main.map.mapView, g, p.x-w/2, p.y-h/2 );
+		String name = (n.keys==null) ? null : n.keys.get("name");
+		if (name!=null && annotate)
+		{
+			g.setColor(textColor);
+			Font defaultFont = g.getFont();
+			g.setFont (orderFont);
+			g.drawString (name, p.x+w/2+2, p.y+h/2+2);
+			g.setFont(defaultFont);
+		}
+		if (n.selected)
+		{
+			g.setColor (  selectedColor );
+			g.drawRect (p.x-w/2-2,p.y-w/2-2, w+4, h+4);
+		}
+	}
+
+	/**
+	 * Draw a line with the given color.
+	 */
+	protected void drawSegment(Node n1, Node n2, Color col, boolean showDirection) {
+		if (useRealWidth && showDirection) showDirection = false;
+		drawSeg(n1, n2, col, showDirection, 1, false);
+	}
+
+	private void drawSeg(Node n1, Node n2, Color col, boolean showDirection, int width, boolean dashed) {
+		if (col != currentColor || width != currentWidth || dashed != currentDashed) {
+			displaySegments(col, width, dashed);
+		}
+		Point p1 = nc.getPoint(n1.eastNorth);
+		Point p2 = nc.getPoint(n2.eastNorth);
+
+		if (!isSegmentVisible(p1, p2)) {
+			return;
+		}
+		drawVirtualNode(p1, p2, col);
+		currentPath.moveTo(p1.x, p1.y);
+		currentPath.lineTo(p2.x, p2.y);
+
+		if (showDirection) {
+			double t = Math.atan2(p2.y-p1.y, p2.x-p1.x) + Math.PI;
+			currentPath.lineTo((int)(p2.x + 10*Math.cos(t-PHI)), (int)(p2.y + 10*Math.sin(t-PHI)));
+			currentPath.moveTo((int)(p2.x + 10*Math.cos(t+PHI)), (int)(p2.y + 10*Math.sin(t+PHI)));
+			currentPath.lineTo(p2.x, p2.y);
+		}
+	}
+
+	protected void displaySegments() {
+		displaySegments(null, 0, false);
+	}
+
+	protected void displaySegments(Color newColor, int newWidth, boolean newDash) {
+
+		if (currentPath != null) {
+			Graphics2D g2d = (Graphics2D)g;
+			g2d.setColor(inactive ? inactiveColor : currentColor);
+			if (currentStroke == null) {
+				if (currentDashed)
+					g2d.setStroke(new BasicStroke(currentWidth,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,0,new float[] {9},0));
+				else
+					g2d.setStroke(new BasicStroke(currentWidth,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
+			}
+			g2d.draw(currentPath);
+			g2d.setStroke(new BasicStroke(1));
+
+			currentPath = new GeneralPath();
+			currentColor = newColor;
+			currentWidth = newWidth;
+			currentDashed = newDash;
+			currentStroke = null;
+		}
+	}
+
+	/**
+	 * Draw the node as small rectangle with the given color.
+	 *
+	 * @param n  The node to draw.
+	 * @param color The color of the node.
+	 */
+	public void drawNode(Node n, Color color, int size, int radius, boolean fill) {
 		if (isZoomOk(null) && size > 1) {
 			Point p = nc.getPoint(n.eastNorth);
 			if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth())
-			        || (p.y > nc.getHeight()))
+					|| (p.y > nc.getHeight()))
 				return;
 			g.setColor(color);
@@ -367,108 +299,56 @@
 	}
 
-    // NW 111106 Overridden from SimplePaintVisitor in josm-1.4-nw1
-    // Shows areas before non-areas
-    public void visitAll(DataSet data) {
-        inactiveColor = Main.pref.getColor(marktr("inactive"), Color.DARK_GRAY);
-        selectedColor = Main.pref.getColor(marktr("selected"), Color.YELLOW);
-        nodeColor = Main.pref.getColor(marktr("node"), Color.RED);
-        dfltWayColor = Main.pref.getColor(marktr("way"), darkblue);
-        incompleteColor = Main.pref.getColor(marktr("incomplete way"), darkerblue);
-        backgroundColor = Main.pref.getColor(marktr("background"), Color.BLACK);
-        untaggedColor = Main.pref.getColor(marktr("untagged"),Color.GRAY);
-        textColor = Main.pref.getColor (marktr("text"), Color.WHITE);
-        showDirectionArrow = Main.pref.getBoolean("draw.segment.direction");
-        showRelevantDirectionsOnly = Main.pref.getBoolean("draw.segment.relevant_directions_only");
-        showOrderNumber = Main.pref.getBoolean("draw.segment.order_number");
-        useRealWidth = Main.pref.getBoolean("mappaint.useRealWidth",false);
-        zoomLevelDisplay = Main.pref.getBoolean("mappaint.zoomLevelDisplay",false);
-        fillAreas = Main.pref.getBoolean("mappaint.fillareas", true);
-
-		selectedNodeRadius = Main.pref.getInteger("mappaint.node.selected-size",
-		        5) / 2;
-		selectedNodeSize = selectedNodeRadius * 2;
-
-		unselectedNodeRadius = Main.pref.getInteger(
-		        "mappaint.node.unselected-size", 3) / 2;
-		unselectedNodeSize = unselectedNodeRadius * 2;
-
-		taggedNodeRadius = Main.pref.getInteger(
-				"mappaint.node.tagged-size", 5) / 2;
-		taggedNodeSize = taggedNodeRadius * 2;
-
-		defaultSegmentWidth = Main.pref.getInteger(
-		        "mappaint.segment.default-width", 2);
-
-		fillSelectedNode = Main.pref.getBoolean("mappaint.node.fill-selected",
-		        true);
-		fillUnselectedNode = Main.pref.getBoolean(
-		        "mappaint.node.fill-unselected", false);
-
-		((Graphics2D)g)
-		        .setRenderingHint(
-		                RenderingHints.KEY_ANTIALIASING,
-		                Main.pref.getBoolean("mappaint.use-antialiasing", true) ? RenderingHints.VALUE_ANTIALIAS_ON
-		                        : RenderingHints.VALUE_ANTIALIAS_OFF);
-
-		fillAlpha = Math.min(255, Math.max(0, Integer.valueOf(Main.pref
-		        .getInteger("mappaint.fillalpha", 50))));
-
-        Collection<Way> noAreaWays = new LinkedList<Way>();
-
-        for (final OsmPrimitive osm : data.ways)
-            if (!osm.incomplete && !osm.deleted && MapPaintStyles.isArea(osm))
-                osm.visit(this);
-            else if (!osm.deleted && !osm.incomplete)
-                noAreaWays.add((Way)osm);
-
-        for (final OsmPrimitive osm : noAreaWays)
-            osm.visit(this);
-
-        for (final OsmPrimitive osm : data.nodes)
-            if (!osm.incomplete && !osm.deleted)
-                osm.visit(this);
-
-        for (final OsmPrimitive osm : data.getSelected())
-            if (!osm.incomplete && !osm.deleted){
-                osm.visit(this);
-            }
-        displaySegments();
-    }
-    
-    /**
-     * Draw a number of the order of the two consecutive nodes within the
-     * parents way
-     */
-    protected void drawOrderNumber(Node n1, Node n2, int orderNumber) {
-        Point p1 = nc.getPoint(n1.eastNorth);
-        Point p2 = nc.getPoint(n2.eastNorth);
-        if (!isSegmentVisible(p1, p2)) {
-            return;
-        }
-        int strlen = (""+orderNumber).length();
-        int x = (p1.x+p2.x)/2 - 4*strlen;
-        int y = (p1.y+p2.y)/2 + 4;
-
-        Color c = g.getColor();
-        g.setColor(backgroundColor);
-        g.fillRect(x-1, y-12, 8*strlen+1, 14);
-        g.setColor(c);
-        g.drawString(""+orderNumber, x, y);
-      }
-
-    private boolean isSegmentVisible(Point p1, Point p2) {
-        if ((p1.x < 0) && (p2.x < 0)) return false;
-        if ((p1.y < 0) && (p2.y < 0)) return false;
-        if ((p1.x > nc.getWidth()) && (p2.x > nc.getWidth())) return false;
-        if ((p1.y > nc.getHeight()) && (p2.y > nc.getHeight())) return false;
-        return true;
-    }
-    
-    public void setGraphics(Graphics g) {
-        this.g = g;
-    }
-
-    public void setNavigatableComponent(NavigatableComponent nc) {
-        this.nc = nc;
-    }
+	// NW 111106 Overridden from SimplePaintVisitor in josm-1.4-nw1
+	// Shows areas before non-areas
+	public void visitAll(DataSet data, Boolean virtual) {
+		getSettings(virtual);
+		untaggedColor = Main.pref.getColor(marktr("untagged"),Color.GRAY);
+		textColor = Main.pref.getColor (marktr("text"), Color.WHITE);
+		useRealWidth = Main.pref.getBoolean("mappaint.useRealWidth",false);
+		zoomLevelDisplay = Main.pref.getBoolean("mappaint.zoomLevelDisplay",false);
+		fillAreas = Main.pref.getBoolean("mappaint.fillareas", true);
+		fillAlpha = Math.min(255, Math.max(0, Integer.valueOf(Main.pref.getInteger("mappaint.fillalpha", 50))));
+
+		Collection<Way> noAreaWays = new LinkedList<Way>();
+
+		for (final OsmPrimitive osm : data.ways)
+			if (!osm.incomplete && !osm.deleted && MapPaintStyles.isArea(osm))
+				osm.visit(this);
+			else if (!osm.deleted && !osm.incomplete)
+				noAreaWays.add((Way)osm);
+
+		for (final OsmPrimitive osm : noAreaWays)
+			osm.visit(this);
+
+		for (final OsmPrimitive osm : data.nodes)
+			if (!osm.incomplete && !osm.deleted)
+				osm.visit(this);
+
+		for (final OsmPrimitive osm : data.getSelected())
+			if (!osm.incomplete && !osm.deleted){
+				osm.visit(this);
+			}
+		displaySegments();
+	}
+
+	/**
+	 * Draw a number of the order of the two consecutive nodes within the
+	 * parents way
+	 */
+	protected void drawOrderNumber(Node n1, Node n2, int orderNumber) {
+		Point p1 = nc.getPoint(n1.eastNorth);
+		Point p2 = nc.getPoint(n2.eastNorth);
+		if (!isSegmentVisible(p1, p2)) {
+			return;
+		}
+		int strlen = (""+orderNumber).length();
+		int x = (p1.x+p2.x)/2 - 4*strlen;
+		int y = (p1.y+p2.y)/2 + 4;
+
+		Color c = g.getColor();
+		g.setColor(backgroundColor);
+		g.fillRect(x-1, y-12, 8*strlen+1, 14);
+		g.setColor(c);
+		g.drawString(""+orderNumber, x, y);
+	}
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 804)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 805)
@@ -27,7 +27,7 @@
 
 /**
- * A visitor that paints a simple scheme of every primitive it visits to a 
+ * A visitor that paints a simple scheme of every primitive it visits to a
  * previous set graphic environment.
- * 
+ *
  * @author imi
  */
@@ -47,9 +47,9 @@
 	 */
 	protected NavigatableComponent nc;
-	
+
 	public boolean inactive;
 
 	protected static final double PHI = Math.toRadians(20);
-	
+
 	/**
 	 * Preferences
@@ -63,21 +63,18 @@
 	protected Color incompleteColor;
 	protected Color backgroundColor;
-    protected boolean showDirectionArrow;
-    protected boolean showRelevantDirectionsOnly;
+	protected boolean showDirectionArrow;
+	protected boolean showRelevantDirectionsOnly;
 	protected boolean showOrderNumber;
-	
-	private boolean fillSelectedNode;
-
-	private boolean fillUnselectedNode;
-
-	private int selectedNodeRadius;
-
-	private int unselectedNodeRadius;
-
-	private int selectedNodeSize;
-
-	private int unselectedNodeSize;
-
-	private int defaultSegmentWidth = 2;
+	protected boolean fillSelectedNode;
+	protected boolean fillUnselectedNode;
+	protected int selectedNodeRadius;
+	protected int unselectedNodeRadius;
+	protected int selectedNodeSize;
+	protected int unselectedNodeSize;
+	protected int defaultSegmentWidth = 2;
+	protected int virtualNodeSize;
+	protected int virtualNodeSpace;
+	protected int taggedNodeRadius;
+	protected int taggedNodeSize;
 
 	/**
@@ -88,8 +85,6 @@
 
 	Rectangle bbox = new Rectangle();
-	private int taggedNodeRadius;
-	private int taggedNodeSize;
-
-	public void visitAll(DataSet data) {
+
+	protected void getSettings(Boolean virtual) {
 		inactiveColor = Main.pref.getColor(marktr("inactive"), Color.DARK_GRAY);
 		selectedColor = Main.pref.getColor(marktr("selected"), Color.WHITE);
@@ -103,30 +98,25 @@
 		showRelevantDirectionsOnly = Main.pref.getBoolean("draw.segment.relevant_directions_only");
 		showOrderNumber = Main.pref.getBoolean("draw.segment.order_number");
-		
-		selectedNodeRadius = Main.pref.getInteger("mappaint.node.selected-size",
-		        5) / 2;
+		selectedNodeRadius = Main.pref.getInteger("mappaint.node.selected-size", 5) / 2;
 		selectedNodeSize = selectedNodeRadius * 2;
-		unselectedNodeRadius = Main.pref.getInteger(
-		        "mappaint.node.unselected-size", 3) / 2;
+		unselectedNodeRadius = Main.pref.getInteger("mappaint.node.unselected-size", 3) / 2;
 		unselectedNodeSize = unselectedNodeRadius * 2;
-
-		taggedNodeRadius = Main.pref.getInteger(
-				"mappaint.node.tagged-size", 5) / 2;
+		taggedNodeRadius = Main.pref.getInteger("mappaint.node.tagged-size", 5) / 2;
 		taggedNodeSize = taggedNodeRadius * 2;
-
-		defaultSegmentWidth = Main.pref.getInteger(
-		        "mappaint.segment.default-width", 2);
-
-		fillSelectedNode = Main.pref.getBoolean("mappaint.node.fill-selected",
-		        true);
-		fillUnselectedNode = Main.pref.getBoolean(
-		        "mappaint.node.fill-unselected", false);
+		defaultSegmentWidth = Main.pref.getInteger("mappaint.segment.default-width", 2);
+		fillSelectedNode = Main.pref.getBoolean("mappaint.node.fill-selected", true);
+		fillUnselectedNode = Main.pref.getBoolean("mappaint.node.fill-unselected", false);
+		virtualNodeSize = virtual ? Main.pref.getInteger("mappaint.node.virtual-size", 4) / 2 : 0;
+		virtualNodeSpace = Main.pref.getInteger("mappaint.node.virtual-space", 50);
 
 		((Graphics2D)g)
-		        .setRenderingHint(
-		                RenderingHints.KEY_ANTIALIASING,
-		                Main.pref.getBoolean("mappaint.use-antialiasing", true) ? RenderingHints.VALUE_ANTIALIAS_ON
-		                        : RenderingHints.VALUE_ANTIALIAS_OFF);
-
+				.setRenderingHint(
+						RenderingHints.KEY_ANTIALIASING,
+						Main.pref.getBoolean("mappaint.use-antialiasing", true) ? RenderingHints.VALUE_ANTIALIAS_ON
+								: RenderingHints.VALUE_ANTIALIAS_OFF);
+	}
+
+	public void visitAll(DataSet data, Boolean virtual) {
+		getSettings(virtual);
 		// draw tagged ways first, then untagged ways. takes
 		// time to iterate through list twice, OTOH does not
@@ -141,23 +131,23 @@
 		displaySegments(null);
 
-	    for (final OsmPrimitive osm : data.ways)
+		for (final OsmPrimitive osm : data.ways)
 			if (!osm.deleted && !osm.selected && !osm.tagged)
 				osm.visit(this);
 		displaySegments(null);
-	    
+
 		for (final OsmPrimitive osm : data.nodes)
 			if (!osm.deleted && !osm.selected)
 				osm.visit(this);
-	
+
 		for (final OsmPrimitive osm : data.getSelected())
 			if (!osm.deleted)
 				osm.visit(this);
 		displaySegments(null);
-        }
-
-	/**
-	 * Draw a small rectangle. 
+	}
+
+	/**
+	 * Draw a small rectangle.
 	 * White if selected (as always) or red otherwise.
-	 * 
+	 *
 	 * @param n The node to draw.
 	 */
@@ -171,5 +161,5 @@
 		else if(n.tagged)
 			drawNode(n, nodeColor, taggedNodeSize, taggedNodeRadius, fillUnselectedNode);
-		else 
+		else
 			drawNode(n, nodeColor, unselectedNodeSize, unselectedNodeRadius, fillUnselectedNode);
 	}
@@ -182,12 +172,12 @@
 		if (w.incomplete) return;
 
-                // show direction arrows, if draw.segment.relevant_directions_only is not set, the way is tagged with a direction key
-                // (even if the tag is negated as in oneway=false) or the way is selected
-
-                boolean showThisDirectionArrow = w.selected
-                                                 || (showDirectionArrow
-                                                     && (!showRelevantDirectionsOnly || w.hasDirectionKeys));
+				// show direction arrows, if draw.segment.relevant_directions_only is not set, the way is tagged with a direction key
+				// (even if the tag is negated as in oneway=false) or the way is selected
+
+				boolean showThisDirectionArrow = w.selected
+												 || (showDirectionArrow
+													 && (!showRelevantDirectionsOnly || w.hasDirectionKeys));
 		Color wayColor;
-		
+
 		if (inactive) {
 			wayColor = inactiveColor;
@@ -254,5 +244,5 @@
 		}
 	}
-	
+
 	/**
 	 * Draw an number of the order of the two consecutive nodes within the
@@ -271,5 +261,5 @@
 			g.drawString(""+orderNumber, x, y);
 		}
-    }
+	}
 
 	/**
@@ -283,5 +273,5 @@
 			Point p = nc.getPoint(n.eastNorth);
 			if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth())
-			        || (p.y > nc.getHeight()))
+					|| (p.y > nc.getHeight()))
 				return;
 			g.setColor(color);
@@ -294,4 +284,22 @@
 	}
 
+	protected void drawVirtualNode(Point p1, Point p2, Color col)
+	{
+		if(virtualNodeSize > 0)
+		{
+			int xd = p2.x-p1.x; if(xd < 0) xd = -xd;
+			int yd = p2.y-p1.y; if(yd < 0) yd = -yd;
+			if(xd+yd > virtualNodeSpace)
+			{
+				int x = (p1.x+p2.x)/2;
+				int y = (p1.y+p2.y)/2;
+				currentPath.moveTo(x-5, y);
+				currentPath.lineTo(x+5, y);
+				currentPath.moveTo(x, y-5);
+				currentPath.lineTo(x, y+5);
+			}
+		}
+	}
+
 	/**
 	 * Draw a line with the given color.
@@ -300,26 +308,28 @@
 
 		if (col != currentColor) displaySegments(col);
-		
+
 		if (isSegmentVisible(p1, p2)) {
+			drawVirtualNode(p1, p2, col);
+
 			currentPath.moveTo(p1.x, p1.y);
 			currentPath.lineTo(p2.x, p2.y);
-			
+
 			if (showDirection) {
 				double t = Math.atan2(p2.y-p1.y, p2.x-p1.x) + Math.PI;
 				currentPath.lineTo((int)(p2.x + 10*Math.cos(t-PHI)), (int)(p2.y + 10*Math.sin(t-PHI)));
 				currentPath.moveTo((int)(p2.x + 10*Math.cos(t+PHI)), (int)(p2.y + 10*Math.sin(t+PHI)));
-				currentPath.lineTo(p2.x, p2.y);  
+				currentPath.lineTo(p2.x, p2.y);
 			}
 		}
 	}
-        
-    private boolean isSegmentVisible(Point p1, Point p2) {
-        if ((p1.x < 0) && (p2.x < 0)) return false;
-        if ((p1.y < 0) && (p2.y < 0)) return false;
-        if ((p1.x > nc.getWidth()) && (p2.x > nc.getWidth())) return false;
-        if ((p1.y > nc.getHeight()) && (p2.y > nc.getHeight())) return false;
-        return true;
-    }
-	
+
+	protected boolean isSegmentVisible(Point p1, Point p2) {
+		if ((p1.x < 0) && (p2.x < 0)) return false;
+		if ((p1.y < 0) && (p2.y < 0)) return false;
+		if ((p1.x > nc.getWidth()) && (p2.x > nc.getWidth())) return false;
+		if ((p1.y > nc.getHeight()) && (p2.y > nc.getHeight())) return false;
+		return true;
+	}
+
 	public void setGraphics(Graphics g) {
 		this.g = g;
@@ -327,6 +337,6 @@
 
 	public void setNavigatableComponent(NavigatableComponent nc) {
-    	this.nc = nc;
-    }
+		this.nc = nc;
+	}
 
 	protected void displaySegments(Color newColor) {
@@ -338,11 +348,3 @@
 		}
 	}
-	
-	/**
-	 * Provided for backwards compatibility only.
-	 * FIXME: remove this once not used by plugins any longer.
-	 */
-	public static Color getPreferencesColor(String name, Color dflt) {
-		return Main.pref.getColor(name, dflt);
-	}
 }
Index: trunk/src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 804)
+++ trunk/src/org/openstreetmap/josm/gui/MapView.java	(revision 805)
@@ -182,4 +182,18 @@
 	}
 
+	private Boolean virtualnodes = false;
+	public void enableVirtualNodes(Boolean state)
+	{
+		if(virtualnodes != state)
+		{
+			virtualnodes = state;
+			repaint();
+		}
+	}
+	public Boolean useVirtualNodes()
+	{
+		return virtualnodes;
+	}
+
 	/**
 	 * Moves the layer to the given new position. No event is fired.
Index: trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 804)
+++ trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 805)
@@ -32,7 +32,8 @@
 public class NavigatableComponent extends JComponent implements Helpful {
 
-
 	public static final EastNorth world = Main.proj.latlon2eastNorth(new LatLon(Projection.MAX_LAT, Projection.MAX_LON));
-
+	public static final int snapDistance = sqr(Main.pref.getInteger("node.snap-distance", 10));
+
+	private static int sqr(int a) { return a*a;}
 	/**
 	 * The scale factor in x or y-units per pixel. This means, if scale = 10,
@@ -141,5 +142,5 @@
 			Point sp = getPoint(n.eastNorth);
 			double dist = p.distanceSq(sp);
-			if (minDistanceSq > dist && dist < 100) {
+			if (minDistanceSq > dist && dist < snapDistance) {
 				minDistanceSq = p.distanceSq(sp);
 				minPrimitive = n;
@@ -180,5 +181,5 @@
 				double b = p.distanceSq(A);
 				double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
-				if (perDist < 100 && a < c+100 && b < c+100) {
+				if (perDist < snapDistance && a < c+snapDistance && b < c+snapDistance) {
 					List<WaySegment> l;
 					if (nearest.containsKey(perDist)) {
@@ -228,5 +229,5 @@
 		WaySegment nearestWaySeg = getNearestWaySegment(p);
 		return nearestWaySeg == null ? null : nearestWaySeg.way;
-    }
+	}
 
 	/**
@@ -240,11 +241,13 @@
 	 * If nothing is found, return <code>null</code>.
 	 *
-	 * @param p				 The point on screen.
-	 * @return	The primitive that is nearest to the point p.
+	 * @param p The point on screen.
+	 * @return  The primitive that is nearest to the point p.
 	 */
 	public OsmPrimitive getNearest(Point p) {
 		OsmPrimitive osm = getNearestNode(p);
 		if (osm == null)
+		{
 			osm = getNearestWay(p);
+		}
 		return osm;
 	}
@@ -258,9 +261,4 @@
 			return Collections.emptySet();
 		return Collections.singleton(osm);
-	}
-
-	@Deprecated
-	public OsmPrimitive getNearest(Point p, boolean segmentInsteadWay) {
-		return getNearest(p);
 	}
 
@@ -290,5 +288,5 @@
 				double b = p.distanceSq(A);
 				double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
-				if (perDist < 100 && a < c+100 && b < c+100) {
+				if (perDist < snapDistance && a < c+snapDistance && b < c+snapDistance) {
 					nearest.add(w);
 						break;
@@ -299,5 +297,5 @@
 		for (Node n : Main.ds.nodes) {
 			if (!n.deleted && !n.incomplete
-					&& getPoint(n.eastNorth).distanceSq(p) < 100) {
+					&& getPoint(n.eastNorth).distanceSq(p) < snapDistance) {
 				nearest.add(n);
 			}
@@ -318,5 +316,5 @@
 		for (Node n : Main.ds.nodes) {
 			if (!n.deleted && !n.incomplete
-					&& getPoint(n.eastNorth).distanceSq(p) < 100) {
+					&& getPoint(n.eastNorth).distanceSq(p) < snapDistance) {
 				nearest.add(n);
 			}
Index: trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 804)
+++ trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 805)
@@ -148,4 +148,5 @@
 	@Override public void paint(final Graphics g, final MapView mv) {
 		boolean inactive = Main.map.mapView.getActiveLayer() != this && Main.pref.getBoolean("draw.data.inactive_color", true);
+		boolean virtual = !inactive && Main.map.mapView.useVirtualNodes();
 		if (Main.pref.getBoolean("draw.data.downloaded_area", true)) {
 			// FIXME this is inefficient; instead a proper polygon has to be built, and instead
@@ -169,5 +170,5 @@
 			wireframeMapPainter.setNavigatableComponent(mv);
 			wireframeMapPainter.inactive = inactive;
-			wireframeMapPainter.visitAll(data);
+			wireframeMapPainter.visitAll(data, virtual);
 		}
 		else
@@ -176,5 +177,5 @@
 			standardMapPainter.setNavigatableComponent(mv);
 			standardMapPainter.inactive = inactive;
-			standardMapPainter.visitAll(data);
+			standardMapPainter.visitAll(data, virtual);
 		}
 		Main.map.conflictDialog.paintConflicts(g, mv);
Index: trunk/src/org/openstreetmap/josm/gui/preferences/DrawingPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/DrawingPreference.java	(revision 804)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/DrawingPreference.java	(revision 805)
@@ -27,4 +27,5 @@
 	private JCheckBox segmentOrderNumber = new JCheckBox(tr("Draw segment order numbers"));
 	private JCheckBox sourceBounds = new JCheckBox(tr("Draw boundaries of downloaded data"));
+	private JCheckBox virtualNodes = new JCheckBox(tr("Draw virtual nodes in select mode"));
 	private JCheckBox inactive = new JCheckBox(tr("Draw inactive layers in other color"));
 	private JCheckBox useAntialiasing = new JCheckBox(tr("Smooth map graphics (antialiasing)"));
@@ -121,5 +122,10 @@
 		sourceBounds.setSelected(Main.pref.getBoolean("draw.data.downloaded_area", true));
 		gui.display.add(sourceBounds, GBC.eop().insets(20,0,0,0));
-		
+
+		// virtual nodes
+		virtualNodes.setToolTipText(tr("Draw virtual nodes in select mode for easy way modification."));
+		virtualNodes.setSelected(Main.pref.getInteger("mappaint.node.virtual-size", 4) != 0);
+		gui.display.add(virtualNodes, GBC.eop().insets(20,0,0,0));
+
 		// background layers in inactive color
 		inactive.setToolTipText(tr("Draw the inactive data layers in a different color."));
@@ -142,4 +148,5 @@
 		Main.pref.put("draw.data.inactive_color", inactive.isSelected());
 		Main.pref.put("mappaint.use-antialiasing", useAntialiasing.isSelected());
+		Main.pref.put("mappaint.node.virtual-size", virtualNodes.isSelected() ? "4" : "0");
     }
 }
