Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 2353)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 2354)
@@ -27,4 +27,6 @@
 import java.util.LinkedList;
 import java.util.List;
+import java.util.TreeSet;
+import java.util.Comparator;
 
 import javax.swing.ImageIcon;
@@ -53,5 +55,4 @@
     protected boolean useRealWidth;
     protected boolean zoomLevelDisplay;
-    protected int fillAreas;
     protected boolean drawMultipolygon;
     protected boolean drawRestriction;
@@ -74,5 +75,4 @@
     protected double dist;
     protected Collection<String> regionalNameOrder;
-    protected Boolean selectedCall;
     protected Boolean useStyleCache;
     private static int paintid = 0;
@@ -140,5 +140,6 @@
      */
     @Override
-    public void visit(Node n) {
+    public void visit(Node n) {}
+    public void drawNode(Node n) {
         /* check, if the node is visible at all */
         if((n.getEastNorth().east()  > maxEN.east() ) ||
@@ -177,5 +178,6 @@
      */
     @Override
-    public void visit(Way w) {
+    public void visit(Way w) {}
+    public void drawWay(Way w, int fillAreas) {
         if(w.getNodesCount() < 2)
         {
@@ -492,5 +494,5 @@
             PolyData pd = new PolyData(w);
             pd.selected = selected;
-            res.add(new PolyData(w));
+            res.add(pd);
         } /* while(left != 0) */
 
@@ -503,4 +505,5 @@
         if(osm instanceof Way)
         {
+            Way w = (Way)osm;
             if(style instanceof AreaElemStyle)
             {
@@ -529,25 +532,9 @@
     }
 
-    @Override
-    public void visit(Relation r) {
-
+    public void visit(Relation r) {};
+    public void paintUnselectedRelation(Relation r) {
         r.mappaintVisibleCode = 0;
 
-        /* TODO: is it possible to do this like the nodes/ways code? */
-        //if(profilerOmitDraw)
-        //    return;
-
-        if(selectedCall)
-        {
-            for (RelationMember m : r.getMembers())
-            {
-                if (m.isNode() && !m.getMember().incomplete && !m.getMember().isDeleted() && !m.getMember().isFiltered())
-                {
-                    drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember()) : null, true, true);
-                }
-            }
-            return;
-        }
-        else if (drawMultipolygon && "multipolygon".equals(r.get("type")))
+        if (drawMultipolygon && "multipolygon".equals(r.get("type")))
         {
             if(drawMultipolygon(r))
@@ -563,5 +550,5 @@
             for (RelationMember m : r.getMembers())
             {
-                if (m.isWay() && !m.getMember().incomplete && !m.getMember().isDeleted()) /* nodes drawn on second call */
+                if (m.isWay() && drawable(m.getMember()))
                 {
                     drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember())
@@ -953,11 +940,8 @@
             } else if(m.getMember().incomplete) {
                 incomplete = true;
-            } else
-            {
-                if(m.isWay())
-                {
+            } else {
+                if(m.isWay()) {
                     Way w = m.getWay();
-                    if(w.getNodesCount() < 2)
-                    {
+                    if(w.getNodesCount() < 2) {
                         r.putError(tr("Way ''{0}'' with less than two points.",
                                 w.getDisplayName(DefaultNameFormatter.getInstance())), true);
@@ -967,6 +951,5 @@
                     } else if("outer".equals(m.getRole())) {
                         outer.add(w);
-                    } else
-                    {
+                    } else {
                         r.putError(tr("No useful role ''{0}'' for Way ''{1}''.",
                                 m.getRole(), w.getDisplayName(DefaultNameFormatter.getInstance())), true);
@@ -1031,28 +1014,27 @@
             else if(zoomok)
             {
-                LinkedList<PolyData> poly = new LinkedList<PolyData>();
+                LinkedList<PolyData> outerPoly = new LinkedList<PolyData>();
                 for (Way w : outerclosed) {
-                    poly.add(new PolyData(w));
-                }
-                poly.addAll(joinWays(outerjoin, incomplete ? null : r));
+                    outerPoly.add(new PolyData(w));
+                }
+                outerPoly.addAll(joinWays(outerjoin, incomplete ? null : r));
                 for (Way wInner : innerclosed)
                 {
                     PolyData pdInner = new PolyData(wInner);
                     // incomplete is probably redundant
-                    addInnerToOuters(r, incomplete, pdInner, poly);
+                    addInnerToOuters(r, incomplete, pdInner, outerPoly);
                 }
                 for (PolyData pdInner : joinWays(innerjoin, incomplete ? null : r)) {
-                    addInnerToOuters(r, incomplete, pdInner, poly);
+                    addInnerToOuters(r, incomplete, pdInner, outerPoly);
                 }
                 AreaElemStyle areaStyle = (AreaElemStyle)wayStyle;
-                for (PolyData pd : poly)
-                {
+                for (PolyData pd : outerPoly) {
                     Polygon p = pd.get();
-                    if(isPolygonVisible(p))
-                    {
-                        boolean selected = (data.isSelected(pd.way) || data.isSelected(r));
-                        drawAreaPolygon(p, selected ? selectedColor : areaStyle.color);
-                        visible = true;
-                    }
+                    if(!isPolygonVisible(p))
+                        continue;
+
+                    boolean selected = pd.selected || data.isSelected(pd.way) || data.isSelected(r);
+                    drawAreaPolygon(p, selected ? selectedColor : areaStyle.color);
+                    visible = true;
                 }
             }
@@ -1073,4 +1055,6 @@
                 if(innerStyle == null)
                 {
+                    if (data.isSelected(wInner))
+                        continue;
                     if(zoomok && (wInner.mappaintDrawnCode != paintid
                             || outer.size() == 0))
@@ -1104,4 +1088,7 @@
                 if(outerStyle == null)
                 {
+                    // Selected ways are drawn at the very end
+                    if (data.isSelected(wOuter))
+                        continue;
                     if(zoomok)
                     {
@@ -1404,4 +1391,9 @@
     }
 
+    boolean drawable(OsmPrimitive osm)
+    {
+        return !osm.isDeleted() && !osm.isFiltered() && !osm.incomplete;
+    }
+
     @Override
     public void getColors()
@@ -1415,4 +1407,21 @@
     DataSet data;
 
+    <T extends OsmPrimitive> Collection<T> selectedLast(final DataSet data, Collection <T> prims) {
+        ArrayList<T> sorted = new ArrayList<T>(prims);
+        Collections.sort(sorted,
+            new Comparator<T>() {
+                public int compare(T o1, T o2) {
+                    boolean s1 = data.isSelected(o1);
+                    boolean s2 = data.isSelected(o2);
+                    if (s1 && !s2)
+                        return 1;
+                    if (!s1 && s2)
+                        return -1;
+                    return o1.compareTo(o2);
+                }
+            });
+        return sorted;
+    }
+
     /* Shows areas before non-areas */
     @Override
@@ -1423,5 +1432,5 @@
 
         useStyleCache = Main.pref.getBoolean("mappaint.cache",true);
-        fillAreas = Main.pref.getInteger("mappaint.fillareas", 10000000);
+        int fillAreas = Main.pref.getInteger("mappaint.fillareas", 10000000);
         fillAlpha = Math.min(255, Math.max(0, Integer.valueOf(Main.pref.getInteger("mappaint.fillalpha", 50))));
         showNames = Main.pref.getInteger("mappaint.shownames", 10000000);
@@ -1458,5 +1467,4 @@
 
 
-        selectedCall = false;
         ++paintid;
         viewid = nc.getViewID();
@@ -1481,7 +1489,7 @@
             for (final Relation osm : data.relations)
             {
-                if(!osm.isDeleted() && !osm.isFiltered() && !osm.incomplete && osm.mappaintVisibleCode != viewid)
-                {
-                    osm.visit(this);
+                if(drawable(osm) && osm.mappaintVisibleCode != viewid)
+                {
+                    paintUnselectedRelation(osm);
                     //            profilerN++;
                 }
@@ -1496,16 +1504,15 @@
             /*** AREAS ***/
             //    profilerN = 0;
-            for (final Way osm : data.ways)
-            {
-                if (!osm.incomplete && !osm.isDeleted() && !osm.isFiltered()
+            for (final Way osm : selectedLast(data, data.ways)) {
+                if (drawable(osm)
                         && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
                 {
                     if(isPrimitiveArea(osm) && osm.mappaintDrawnAreaCode != paintid)
                     {
-                        osm.visit(this);
+                        drawWay(osm, fillAreas);
                         //                profilerN++;
-                    } else {
+                    }// else {
                         noAreaWays.add(osm);
-                    }
+                    //}
                 }
             }
@@ -1520,8 +1527,7 @@
             /*** WAYS ***/
             //    profilerN = 0;
-            fillAreas = 0;
-            for (final OsmPrimitive osm : noAreaWays)
-            {
-                osm.visit(this);
+            for (final Way osm : noAreaWays)
+            {
+                drawWay(osm, 0);
                 //        profilerN++;
             }
@@ -1538,9 +1544,9 @@
             /*** WAYS (filling disabled)  ***/
             //    profilerN = 0;
-            for (final OsmPrimitive osm : data.ways)
-                if (!osm.incomplete && !osm.isDeleted() && !osm.isFiltered() && !data.isSelected(osm)
-                        && osm.mappaintVisibleCode != viewid )
-                {
-                    osm.visit(this);
+            for (final Way way : data.ways)
+                if (drawable(way) && !data.isSelected(way)
+                        && way.mappaintVisibleCode != viewid )
+                {
+                    drawWay(way, 0);
                     //            profilerN++;
                 }
@@ -1555,11 +1561,29 @@
 
         /*** SELECTED  ***/
-        selectedCall = true;
         //profilerN = 0;
         for (final OsmPrimitive osm : data.getSelected()) {
             if (!osm.incomplete && !osm.isDeleted() && !(osm instanceof Node)
-                    && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
-            {
-                osm.visit(this);
+                    && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid
+                    )
+            {
+                osm.visit(new AbstractVisitor() {
+                    public void visit(Way w) {
+                        drawWay(w, 0);
+                    }
+                    public void visit(Node n) {
+                        drawNode(n);
+                    }
+                    public void visit(Relation r) {
+                        /* TODO: is it possible to do this like the nodes/ways code? */
+                        //if(profilerOmitDraw)
+                        //    return;
+                        r.mappaintVisibleCode = 0;
+                        for (RelationMember m : r.getMembers()) {
+                            if (m.isNode() && drawable(m.getMember())) {
+                                drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember()) : null, true, true);
+                            }
+                        }
+                    }
+                });
                 //        profilerN++;
             }
@@ -1577,9 +1601,9 @@
         /*** NODES ***/
         //profilerN = 0;
-        for (final OsmPrimitive osm : data.nodes)
+        for (final Node osm : data.nodes)
             if (!osm.incomplete && !osm.isDeleted() && (data.isSelected(osm) || !osm.isFiltered())
                     && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
             {
-                osm.visit(this);
+                drawNode(osm);
                 //        profilerN++;
             }
