This is an automated email from the git hooks/post-receive script.

sebastic-guest pushed a commit to branch master
in repository josm-plugins.

commit 2621cc5d454f90274dbb5fa9e32a114080f2832d
Author: David Paleino <da...@debian.org>
Date:   Sun Jul 18 17:25:49 2010 +0200

    Imported Upstream version 0.0.svn22363
---
 DirectUpload/build.xml                             |  17 +-
 .../josm/plugins/DirectUpload/UploadDataGui.java   |  17 +-
 cadastre-fr/build.xml                              |   1 +
 cadastre-fr/src/cadastre_fr/Address.java           | 510 ++++++++++++
 cadastre-fr/src/cadastre_fr/CadastreInterface.java |  19 +-
 cadastre-fr/src/cadastre_fr/CadastrePlugin.java    |   9 +-
 .../src/cadastre_fr/CadastrePreferenceSetting.java |  23 +-
 cadastre-fr/src/cadastre_fr/GeorefImage.java       |   5 +-
 cadastre-fr/src/cadastre_fr/WMSLayer.java          |   8 +-
 editgpx/build.xml                                  |   1 +
 lakewalker/build.xml                               |   1 +
 livegps/build.xml                                  |   1 +
 measurement/build.xml                              |   1 +
 openvisible/build.xml                              |   1 +
 routing/build.xml                                  |   1 +
 slippymap/build.xml                                |   1 +
 surveyor/build.xml                                 |   1 +
 svn-info.xml                                       |   8 +-
 wmsplugin/build.xml                                |   3 +-
 wmsplugin/src/wmsplugin/GeorefImage.java           |   1 +
 wmsplugin/src/wmsplugin/Grabber.java               |   4 +-
 wmsplugin/src/wmsplugin/WMSGrabber.java            |   4 +-
 wmsplugin/src/wmsplugin/WMSLayer.java              | 883 +++++++++++----------
 wmsplugin/src/wmsplugin/WMSPlugin.java             |   6 +
 wmsplugin/src/wmsplugin/WMSPreferenceEditor.java   |  15 +-
 25 files changed, 1062 insertions(+), 479 deletions(-)

diff --git a/DirectUpload/build.xml b/DirectUpload/build.xml
index 196d3fa..555c2c4 100644
--- a/DirectUpload/build.xml
+++ b/DirectUpload/build.xml
@@ -17,7 +17,7 @@
 **    > ant  install
 **
 ** To build against the core in ../../core, create a correct manifest and 
deploy to
-** SVN, 
+** SVN,
 **    set the properties commit.message and plugin.main.version
 ** and run
 **    > ant  publish
@@ -27,7 +27,7 @@
 <project name="DirectUpload" default="dist" basedir=".">
 
        <property name="commit.message" value="Changed constructor signature of 
plugin main class" />
-       <property name="plugin.main.version" value="2830" />
+       <property name="plugin.main.version" value="3338" />
 
        <property name="josm"                   
location="../../core/dist/josm-custom.jar"/>
        <property name="plugin.dist.dir"        value="../../dist"/>
@@ -54,6 +54,7 @@
                                <attribute name="Plugin-Class" 
value="org.openstreetmap.josm.plugins.DirectUpload.UploadDataGuiPlugin"/>
                                <attribute name="Plugin-Date" 
value="${version.entry.commit.date}"/>
                                <attribute name="Plugin-Description" 
value="This plugin directly upload GPS Traces from current active layer in JOSM 
to openstreetmap.org."/>
+                               <attribute name="Plugin-Icon" 
value="images/UploadAction.png"/>
                                <attribute name="Plugin-Link" 
value="http://wiki.openstreetmap.org/index.php/User:Subhodip/GSoC_Doc#DirectUpload_Plugin_in_JOSM_:"/>
                                <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}"/>
                                <attribute name="Plugin-Version" 
value="${version.entry.commit.revision}"/>
@@ -84,10 +85,10 @@
                <copy file="${plugin.jar}" todir="${josm.plugins.dir}"/>
        </target>
        <!--
-        ************************** Publishing the plugin 
*********************************** 
+        ************************** Publishing the plugin 
***********************************
        -->
        <!--
-       ** extracts the JOSM release for the JOSM version in ../core and saves 
it in the 
+       ** extracts the JOSM release for the JOSM version in ../core and saves 
it in the
        ** property ${coreversion.info.entry.revision}
        **
        -->
@@ -136,17 +137,17 @@
        </target>
 
        <!--
-       ** commits the plugin.jar 
+       ** commits the plugin.jar
        -->
        <target name="commit-dist">
                <echo>
 ***** Properties of published ${plugin.jar} *****
-Commit message    : '${commit.message}'                                        
+Commit message    : '${commit.message}'
 Plugin-Mainversion: ${plugin.main.version}
 JOSM build version: ${coreversion.info.entry.revision}
 Plugin-Version    : ${version.entry.commit.revision}
-***** / Properties of published ${plugin.jar} *****                            
        
-                                       
+***** / Properties of published ${plugin.jar} *****
+
 Now commiting ${plugin.jar} ...
 </echo>
                <exec append="true" output="svn.log" executable="svn" 
failifexecutionfails="false">
diff --git 
a/DirectUpload/src/org/openstreetmap/josm/plugins/DirectUpload/UploadDataGui.java
 
b/DirectUpload/src/org/openstreetmap/josm/plugins/DirectUpload/UploadDataGui.java
index 25f9416..2e48017 100644
--- 
a/DirectUpload/src/org/openstreetmap/josm/plugins/DirectUpload/UploadDataGui.java
+++ 
b/DirectUpload/src/org/openstreetmap/josm/plugins/DirectUpload/UploadDataGui.java
@@ -60,12 +60,12 @@ public class UploadDataGui extends ExtendedDialog {
         PUBLIC       (tr("Public (shown in trace list and as anonymous, 
unordered points)")),
         TRACKABLE    (tr("Trackable (only shared as anonymous, ordered points 
with timestamps)")),
         IDENTIFIABLE (tr("Identifiable (shown in trace list and as 
identifiable, ordered points with timestamps)"));
-        
+
         public final String description;
         visibility(String description) {
             this.description = description;
         }
-        
+
         /**
          * "Converts" a given description into the actual enum. Returns null 
if no matching description
          * is found.
@@ -74,18 +74,19 @@ public class UploadDataGui extends ExtendedDialog {
          */
         public static visibility desc2visi(Object desc) {
             for (visibility v : visibility.values()) {
-                if(desc.equals((String)v.description))
+                if(desc.equals(v.description))
                     return v;
             }
             return null;
         }
-        
-        public String toString() {
+
+        @Override
+               public String toString() {
             return this.name().toLowerCase();
         }
     }
 
-       
+
     // User for log in when uploading trace
     private String username = Main.pref.get("osm-server.username");
     private String password = Main.pref.get("osm-server.password");
@@ -135,7 +136,7 @@ public class UploadDataGui extends ExtendedDialog {
        JLabel visibilityLabel = new JLabel(tr("Visibility"));
         visibilityLabel.setToolTipText(tr("Defines the visibility of your 
trace for other OSM users."));
         for(visibility v : visibility.values()) {
-               visibilityCombo.addItem((String)v.description);
+               visibilityCombo.addItem(v.description);
         }
         UrlLabel visiUrl = new 
UrlLabel(tr("http://wiki.openstreetmap.org/wiki/Visibility_of_GPS_traces";), 
tr("(What does that mean?)"));
 
@@ -507,7 +508,7 @@ public class UploadDataGui extends ExtendedDialog {
     /**
      * Overrides the default actions. Will not close the window when upload 
trace is clicked
      */
-    @Override protected void buttonAction(ActionEvent evt) {
+    @Override protected void buttonAction(int buttonIndex, ActionEvent evt) {
         String a = evt.getActionCommand();
         if(uploadTraceText.equals(a))
             setupUpload();
diff --git a/cadastre-fr/build.xml b/cadastre-fr/build.xml
index 785ab37..fd5d8da 100644
--- a/cadastre-fr/build.xml
+++ b/cadastre-fr/build.xml
@@ -55,6 +55,7 @@
                 <attribute name="Plugin-Class" 
value="cadastre_fr.CadastrePlugin"/>
                 <attribute name="Plugin-Date" 
value="${version.entry.commit.date}"/>
                 <attribute name="Plugin-Description" value="A special handler 
for the French land registry WMS server."/>
+                <attribute name="Plugin-Icon" 
value="images/preferences/cadastrewms.gif"/>
                 <attribute name="Plugin-Link" 
value="http://wiki.openstreetmap.org/wiki/FR:JOSM/Fr:Plugin/Cadastre"/>
                 <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}"/>
                 <attribute name="Plugin-Stage" value="60"/>
diff --git a/cadastre-fr/src/cadastre_fr/Address.java 
b/cadastre-fr/src/cadastre_fr/Address.java
new file mode 100644
index 0000000..8d398f9
--- /dev/null
+++ b/cadastre-fr/src/cadastre_fr/Address.java
@@ -0,0 +1,510 @@
+package cadastre_fr;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Cursor;
+import java.awt.GridBagLayout;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.ButtonGroup;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.AddCommand;
+import org.openstreetmap.josm.command.ChangeCommand;
+import org.openstreetmap.josm.command.ChangePropertyCommand;
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.SequenceCommand;
+import org.openstreetmap.josm.actions.mapmode.MapMode;
+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.Relation;
+import org.openstreetmap.josm.data.osm.RelationMember;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.WaySegment;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.Pair;
+import org.openstreetmap.josm.tools.Shortcut;
+
+public class Address extends MapMode implements MouseListener, 
MouseMotionListener, ActionListener {
+    private static final long serialVersionUID = 1L;
+    
+    // perhaps make all these tags configurable in the future
+    private String tagHighway = "highway";
+    private String tagHighwayName = "name";
+    private String tagHouseNumber = "addr:housenumber";
+    private String tagHouseStreet = "addr:street";
+    private String tagBuilding = "building";
+    private String relationAddrType = "associatedStreet";
+    private String relationAddrName = "name";
+    private String relationAddrStreetRole = "street";
+    private String relationMemberHouse = "house";
+    
+    private JRadioButton plus_one = new JRadioButton("+1", false);
+    private JRadioButton plus_two = new JRadioButton("+2", true); // enable 
this by default
+    private JRadioButton minus_one = new JRadioButton("-1", false);
+    private JRadioButton minus_two = new JRadioButton("-2", false);
+    final JCheckBox tagPolygon = new JCheckBox(tr("on polygon"));
+
+    JDialog dialog = null;
+    JButton clearButton = null;
+    final JTextField inputNumber = new JTextField();
+    final JTextField inputStreet = new JTextField();
+    JLabel link = new JLabel();
+    private Way selectedWay;
+    //private Relation selectedRelation;
+    private boolean shift;
+
+    public Address(MapFrame mapFrame) {
+        super(tr("Add address"), "buildings", 
+                tr("Helping tool for tag address"),
+                Shortcut.registerShortcut("mapmode:buildings", tr("Mode: {0}", 
tr("Buildings")), KeyEvent.VK_E, Shortcut.GROUP_EDIT),
+                mapFrame, getCursor());
+    }
+
+    @Override public void enterMode() {
+        super.enterMode();
+        if (dialog == null) {
+            createDialog();
+        }
+        dialog.setVisible(true);
+        Main.map.mapView.addMouseListener(this);
+    }
+
+    @Override public void exitMode() {
+        if (Main.map.mapView != null) {
+            super.exitMode();
+            Main.map.mapView.removeMouseListener(this);
+        }
+        dialog.setVisible(false);
+    }
+
+    @Override
+    public void mousePressed(MouseEvent e) {
+        if (e.getButton() != MouseEvent.BUTTON1)
+            return;
+        shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
+        MapView mv = Main.map.mapView;
+        Point mousePos = e.getPoint();
+        List<Way> mouseOnExistingWays = new ArrayList<Way>();
+        List<Way> mouseOnExistingBuildingWays = new ArrayList<Way>();
+        mouseOnExistingWays = new ArrayList<Way>();
+        Node currentMouseNode = mv.getNearestNode(mousePos, 
OsmPrimitive.isSelectablePredicate);
+        if (currentMouseNode != null) {
+            // click on existing node
+            setNewSelection(currentMouseNode);
+            String num = currentMouseNode.get(tagHouseNumber);
+            if (num != null) {
+                try {
+                    // add new address
+                    Integer.parseInt(num); 
+                    inputNumber.setText(num);
+                    applyInputNumberChange();
+                } catch (NumberFormatException en) {
+                    System.out.println("Unable to parse house number \"" + num 
+ "\"");
+                }
+            }
+            if (currentMouseNode.get(tagHouseStreet) != null) {
+                inputStreet.setText(currentMouseNode.get(tagHouseStreet));
+                setSelectedWay((Way)null);
+            } else {
+                // check if the node belongs to an associatedStreet relation
+                Way wayInRelationAddr = 
findWayInRelationAddr(currentMouseNode);
+                if (wayInRelationAddr == null) {
+                    // node exists but doesn't carry address information : add 
tags like a new node
+                    Collection<Command> cmds = new LinkedList<Command>();
+                    addAddrToPrimitive(currentMouseNode, cmds);
+                } else {
+                    inputStreet.setText(wayInRelationAddr.get(tagHighwayName));
+                    setSelectedWay(wayInRelationAddr);
+                }
+            }
+        } else {
+            List<WaySegment> wss = mv.getNearestWaySegments(mousePos, 
OsmPrimitive.isSelectablePredicate);
+            for(WaySegment ws : wss) {
+                if (ws.way.get(tagHighway) != null && 
ws.way.get(tagHighwayName) != null)
+                    mouseOnExistingWays.add(ws.way);
+                else if (ws.way.get(tagBuilding) != null && 
ws.way.get(tagHouseNumber) == null)
+                    mouseOnExistingBuildingWays.add(ws.way);
+            }
+            if (mouseOnExistingWays.size() == 1) {
+                // clicked on existing highway => set new street name
+                
inputStreet.setText(mouseOnExistingWays.get(0).get(tagHighwayName));
+                setSelectedWay(mouseOnExistingWays.get(0));
+                inputNumber.setText("");
+                setNewSelection(mouseOnExistingWays.get(0));
+            } else if (mouseOnExistingWays.size() == 0) {
+                // clicked a non highway and not a node => add the new address 
+                if (inputStreet.getText().equals("") || 
inputNumber.getText().equals("")) {
+                    Toolkit.getDefaultToolkit().beep();
+                } else {
+                    Collection<Command> cmds = new LinkedList<Command>();
+                    if (tagPolygon.isSelected()) {
+                        addAddrToPolygon(mouseOnExistingBuildingWays, cmds);
+                    } else {
+                        Node n = createNewNode(e, cmds);
+                        addAddrToPrimitive(n, cmds);
+                    }
+                }
+            }
+        }
+
+    }
+    
+    private Way findWayInRelationAddr(Node n) {
+        List<OsmPrimitive> l = n.getReferrers();
+        for (OsmPrimitive osm : l) {
+            if (osm instanceof Relation && osm.hasKey("type") && 
osm.get("type").equals(relationAddrType)) {
+                for (RelationMember rm : ((Relation)osm).getMembers()) {
+                    if (rm.getRole().equals(relationAddrStreetRole)) {
+                        OsmPrimitive osp = rm.getMember();
+                        if (osp instanceof Way && osp.hasKey(tagHighwayName)) {
+                            return (Way)osp;
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+    
+    private void addAddrToPolygon(List<Way> mouseOnExistingBuildingWays, 
Collection<Command> cmds) {
+        for (Way w:mouseOnExistingBuildingWays) {
+            addAddrToPrimitive(w, cmds);
+        }
+    }
+    
+    private void addAddrToPrimitive(OsmPrimitive osm, Collection<Command> 
cmds) {
+        // add the current tag addr:housenumber in node and member in relation
+        if (shift) {
+            try {
+                revertInputNumberChange();
+            } catch (NumberFormatException en) {
+                System.out.println("Unable to parse house number \"" + 
inputNumber.getText() + "\"");
+            }
+
+        }
+        cmds.add(new ChangePropertyCommand(osm, tagHouseNumber, 
inputNumber.getText()));            
+        if (Main.pref.getBoolean("cadastrewms.addr.dontUseRelation", false)) {
+            cmds.add(new ChangePropertyCommand(osm, tagHouseStreet, 
inputStreet.getText()));
+        } else if (selectedWay != null) {
+            Relation selectedRelation = findRelationAddr(selectedWay);
+            // add the node to its relation
+            if (selectedRelation != null) {
+                RelationMember rm = new RelationMember(relationMemberHouse, 
osm);
+                Relation newRel = new Relation(selectedRelation);
+                newRel.addMember(rm);
+                cmds.add(new ChangeCommand(selectedRelation, newRel));
+            } else {
+                // create new relation
+                Relation newRel = new Relation();
+                newRel.put("type", relationAddrType);
+                newRel.put(relationAddrName, selectedWay.get(tagHighwayName));
+                newRel.addMember(new RelationMember(relationAddrStreetRole, 
selectedWay));
+                newRel.addMember(new RelationMember(relationMemberHouse, osm));
+                cmds.add(new AddCommand(newRel));
+            }
+        }
+        try {
+            applyInputNumberChange();
+            Command c = new SequenceCommand("Add node address", cmds);
+            Main.main.undoRedo.add(c);
+            setNewSelection(osm);
+        } catch (NumberFormatException en) {
+            System.out.println("Unable to parse house number \"" + 
inputNumber.getText() + "\"");
+        }
+    }
+    
+    private Relation findRelationAddr(Way w) {
+        List<OsmPrimitive> l = w.getReferrers();
+        for (OsmPrimitive osm : l) {
+            if (osm instanceof Relation && osm.hasKey("type") && 
osm.get("type").equals(relationAddrType)) {
+                return (Relation)osm;
+            }
+        }
+        return null;
+    }
+    
+    private Node createNewNode(MouseEvent e, Collection<Command> cmds) {
+        // DrawAction.mouseReleased() but without key modifiers
+        Node n = new Node(Main.map.mapView.getLatLon(e.getX(), e.getY()));
+        cmds.add(new AddCommand(n));
+        List<WaySegment> wss = 
Main.map.mapView.getNearestWaySegments(e.getPoint(), 
OsmPrimitive.isSelectablePredicate);
+        Map<Way, List<Integer>> insertPoints = new HashMap<Way, 
List<Integer>>();
+        for (WaySegment ws : wss) {
+            List<Integer> is;
+            if (insertPoints.containsKey(ws.way)) {
+                is = insertPoints.get(ws.way);
+            } else {
+                is = new ArrayList<Integer>();
+                insertPoints.put(ws.way, is);
+            }
+
+            is.add(ws.lowerIndex);
+        }
+        Set<Pair<Node,Node>> segSet = new HashSet<Pair<Node,Node>>();
+        ArrayList<Way> replacedWays = new ArrayList<Way>();
+        ArrayList<Way> reuseWays = new ArrayList<Way>();
+        for (Map.Entry<Way, List<Integer>> insertPoint : 
insertPoints.entrySet()) {
+            Way w = insertPoint.getKey();
+            List<Integer> is = insertPoint.getValue();
+            Way wnew = new Way(w);
+            pruneSuccsAndReverse(is);
+            for (int i : is) {
+                segSet.add(Pair.sort(new Pair<Node,Node>(w.getNode(i), 
w.getNode(i+1))));
+            }
+            for (int i : is) {
+                wnew.addNode(i + 1, n);
+            }
+            cmds.add(new ChangeCommand(insertPoint.getKey(), wnew));
+            replacedWays.add(insertPoint.getKey());
+            reuseWays.add(wnew);
+        }
+        adjustNode(segSet, n);
+
+        return n;
+    }
+    
+    private static void adjustNode(Collection<Pair<Node,Node>> segs, Node n) {
+
+        switch (segs.size()) {
+        case 0:
+            return;
+        case 2:
+            // This computes the intersection between
+            // the two segments and adjusts the node position.
+            Iterator<Pair<Node,Node>> i = segs.iterator();
+            Pair<Node,Node> seg = i.next();
+            EastNorth A = seg.a.getEastNorth();
+            EastNorth B = seg.b.getEastNorth();
+            seg = i.next();
+            EastNorth C = seg.a.getEastNorth();
+            EastNorth D = seg.b.getEastNorth();
+
+            double u=det(B.east() - A.east(), B.north() - A.north(), C.east() 
- D.east(), C.north() - D.north());
+
+            // Check for parallel segments and do nothing if they are
+            // In practice this will probably only happen when a way has been 
duplicated
+
+            if (u == 0) return;
+
+            // q is a number between 0 and 1
+            // It is the point in the segment where the intersection occurs
+            // if the segment is scaled to lenght 1
+
+            double q = det(B.north() - C.north(), B.east() - C.east(), 
D.north() - C.north(), D.east() - C.east()) / u;
+            EastNorth intersection = new EastNorth(
+                    B.east() + q * (A.east() - B.east()),
+                    B.north() + q * (A.north() - B.north()));
+
+            int snapToIntersectionThreshold
+            = Main.pref.getInteger("edit.snap-intersection-threshold",10);
+
+            // only adjust to intersection if within 
snapToIntersectionThreshold pixel of mouse click; otherwise
+            // fall through to default action.
+            // (for semi-parallel lines, intersection might be miles away!)
+            if 
(Main.map.mapView.getPoint(n).distance(Main.map.mapView.getPoint(intersection)) 
< snapToIntersectionThreshold) {
+                n.setEastNorth(intersection);
+                return;
+            }
+
+        default:
+            EastNorth P = n.getEastNorth();
+            seg = segs.iterator().next();
+            A = seg.a.getEastNorth();
+            B = seg.b.getEastNorth();
+            double a = P.distanceSq(B);
+            double b = P.distanceSq(A);
+            double c = A.distanceSq(B);
+            q = (a - b + c) / (2*c);
+            n.setEastNorth(new EastNorth(B.east() + q * (A.east() - B.east()), 
B.north() + q * (A.north() - B.north())));
+        }
+    }
+    
+    static double det(double a, double b, double c, double d) {
+        return a * d - b * c;
+    }
+
+    private static void pruneSuccsAndReverse(List<Integer> is) {
+        //if (is.size() < 2) return;
+
+        HashSet<Integer> is2 = new HashSet<Integer>();
+        for (int i : is) {
+            if (!is2.contains(i - 1) && !is2.contains(i + 1)) {
+                is2.add(i);
+            }
+        }
+        is.clear();
+        is.addAll(is2);
+        Collections.sort(is);
+        Collections.reverse(is);
+    }
+
+    private static Cursor getCursor() {
+        try {
+            return ImageProvider.getCursor("crosshair", null);
+        } catch (Exception e) {
+        }
+        return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
+    }
+    
+    private void applyInputNumberChange() {
+        Integer num = Integer.parseInt(inputNumber.getText());
+        if (plus_one.isSelected())
+            num = num + 1;
+        if (plus_two.isSelected())
+            num = num + 2;
+        if (minus_one.isSelected() && num > 1)
+            num = num - 1;
+        if (minus_two.isSelected() && num > 2)
+            num = num - 2;
+        inputNumber.setText(num.toString());
+    }
+    
+    private void revertInputNumberChange() {
+        Integer num = Integer.parseInt(inputNumber.getText());
+        if (plus_one.isSelected())
+            num = num - 1;
+        if (plus_two.isSelected())
+            num = num - 2;
+        if (minus_one.isSelected() && num > 1)
+            num = num + 1;
+        if (minus_two.isSelected() && num > 2)
+            num = num + 2;
+        inputNumber.setText(num.toString());
+    }
+    
+    private void createDialog() {
+        ImageIcon iconLink = ImageProvider.get(null, "Mf_relation.png");
+        link.setIcon(iconLink);
+        link.setEnabled(false);
+        JPanel p = new JPanel(new GridBagLayout());
+        JLabel number = new JLabel(tr("Next no"));
+        JLabel street = new JLabel(tr("Street"));
+        p.add(number, GBC.std().insets(0, 0, 0, 0));
+        p.add(inputNumber, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 0, 5));
+        p.add(street, GBC.std().insets(0, 0, 0, 0));
+        JPanel p2 = new JPanel(new GridBagLayout());
+        inputStreet.setEditable(false);
+        p2.add(inputStreet, GBC.std().fill(GBC.HORIZONTAL).insets(5, 0, 0, 0));
+        p2.add(link, GBC.eol().insets(10, 0, 0, 0));
+        p.add(p2, GBC.eol().fill(GBC.HORIZONTAL));
+        clearButton = new JButton("Clear");
+        clearButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                inputNumber.setText("");
+                inputStreet.setText("");
+                setSelectedWay((Way)null);
+            }
+        });
+        ButtonGroup bgIncremental = new ButtonGroup();
+        bgIncremental.add(plus_one);
+        bgIncremental.add(plus_two);
+        bgIncremental.add(minus_one);
+        bgIncremental.add(minus_two);
+        p.add(minus_one, GBC.std().insets(10, 0, 10, 0));
+//        p.add(plus_one, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 0, 0, 0));
+        p.add(plus_one, GBC.std().insets(0, 0, 10, 0));
+        
tagPolygon.setSelected(Main.pref.getBoolean("cadastrewms.addr.onBuilding", 
false));
+        tagPolygon.addChangeListener(new ChangeListener() {
+            @Override
+            public void stateChanged(ChangeEvent arg0) {
+                Main.pref.put("cadastrewms.addr.onBuilding", 
tagPolygon.isSelected());
+            }
+        });
+        p.add(tagPolygon, GBC.eol().fill(GBC.HORIZONTAL).insets(0, 0, 0, 0));
+        p.add(minus_two, GBC.std().insets(10, 0, 10, 0));
+        p.add(plus_two, GBC.std().insets(0, 0, 10, 0));
+        p.add(clearButton, GBC.eol().fill(GBC.HORIZONTAL).insets(0, 0, 0, 0));
+    
+        final Object[] options = {};
+        final JOptionPane pane = new JOptionPane(p,
+                JOptionPane.PLAIN_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION,
+                null, options, null);
+        dialog = pane.createDialog(Main.parent, tr("Enter addresses"));
+        dialog.setModal(false);
+        dialog.setAlwaysOnTop(true);
+        dialog.addComponentListener(new ComponentAdapter() {
+            protected void rememberGeometry() {
+                Main.pref.put("cadastrewms.addr.bounds", 
dialog.getX()+","+dialog.getY()+","+dialog.getWidth()+","+dialog.getHeight());
+            }
+            @Override public void componentMoved(ComponentEvent e) {
+                rememberGeometry();
+            }
+            @Override public void componentResized(ComponentEvent e) {
+                rememberGeometry();
+            }
+        });
+        dialog.addWindowListener(new WindowListener() {
+            @Override
+            public void windowClosing(WindowEvent arg0) {
+                exitMode();
+                
Main.map.selectMapMode((MapMode)Main.map.getDefaultButtonAction());
+            }
+            public void windowClosed(WindowEvent e) {}
+            public void windowActivated(WindowEvent arg0) {}
+            public void windowDeactivated(WindowEvent arg0) {}
+            public void windowDeiconified(WindowEvent arg0) {}
+            public void windowIconified(WindowEvent arg0) {}
+            public void windowOpened(WindowEvent arg0) {}
+        });
+        String bounds = Main.pref.get("cadastrewms.addr.bounds",null);
+        if (bounds != null) {
+            String[] b = bounds.split(",");
+            dialog.setBounds(new Rectangle(
+                    
Integer.parseInt(b[0]),Integer.parseInt(b[1]),Integer.parseInt(b[2]),Integer.parseInt(b[3])));
+        }
+}
+    
+    private void setSelectedWay(Way w) {
+        this.selectedWay = w;
+        if (w == null) {
+            link.setEnabled(false);
+        } else
+            link.setEnabled(true);
+    }
+    
+    private void setNewSelection(OsmPrimitive osm) {
+        Collection<OsmPrimitive> newSelection = new 
LinkedList<OsmPrimitive>(Main.main.getCurrentDataSet().getSelected());
+        newSelection.clear();
+        newSelection.add(osm);
+        getCurrentDataSet().setSelected(osm);
+    }
+
+}
diff --git a/cadastre-fr/src/cadastre_fr/CadastreInterface.java 
b/cadastre-fr/src/cadastre_fr/CadastreInterface.java
index 58484fd..0169279 100644
--- a/cadastre-fr/src/cadastre_fr/CadastreInterface.java
+++ b/cadastre-fr/src/cadastre_fr/CadastreInterface.java
@@ -495,9 +495,12 @@ public class CadastreInterface {
             input = 
input.substring(input.indexOf(cBBoxCommunEnd)+cBBoxCommunEnd.length());
             int i = input.indexOf(",");
             int j = input.indexOf(",", i+1);
-            double angle = Double.parseDouble(input.substring(i+1, j));
-            int k = input.indexOf(",", j+1);
-            double scale_origin = Double.parseDouble(input.substring(j+1, k));
+            String str = input.substring(i+1, j);
+            double unknown_yet = tryParseDouble(str);
+            int j_ = input.indexOf(",", j+1);
+            double angle = Double.parseDouble(input.substring(j+1, j_));
+            int k = input.indexOf(",", j_+1);
+            double scale_origin = Double.parseDouble(input.substring(j_+1, k));
             int l = input.indexOf(",", k+1);
             double dpi = Double.parseDouble(input.substring(k+1, l));
             int m = input.indexOf(",", l+1);
@@ -516,10 +519,18 @@ public class CadastreInterface {
                 wmsLayer.X0 = X0;
                 wmsLayer.Y0 = Y0;
             }
-            System.out.println("parse 
georef:"+angle+","+scale_origin+","+dpi+","+fX+","+
+            System.out.println("parse 
georef:"+unknown_yet+","+angle+","+scale_origin+","+dpi+","+fX+","+
                     fY+","+X0+","+Y0);
         }
     }
+    
+    private double tryParseDouble(String str) {
+        try {
+            return Double.parseDouble(str);
+        } catch (NumberFormatException e) {
+            return 0;
+        }
+    }
 
     private void checkLayerDuplicates(WMSLayer wmsLayer) throws 
DuplicateLayerException {
         if (Main.map != null) {
diff --git a/cadastre-fr/src/cadastre_fr/CadastrePlugin.java 
b/cadastre-fr/src/cadastre_fr/CadastrePlugin.java
index 68bf39a..3443cf3 100644
--- a/cadastre-fr/src/cadastre_fr/CadastrePlugin.java
+++ b/cadastre-fr/src/cadastre_fr/CadastrePlugin.java
@@ -196,7 +196,7 @@ public class CadastrePlugin extends Plugin {
             JMenuItem menuLoadFromCache = new JMenuItem(new 
MenuActionLoadFromCache());
             // temporary disabled:
             //JMenuItem menuActionBoundaries = new JMenuItem(new 
MenuActionBoundaries());
-            JMenuItem menuActionBuildings = new JMenuItem(new 
MenuActionBuildings());
+            //JMenuItem menuActionBuildings = new JMenuItem(new 
MenuActionBuildings());
 
             cadastreJMenu.add(menuGrab);
             cadastreJMenu.add(menuActionGrabPlanImage);
@@ -204,8 +204,8 @@ public class CadastrePlugin extends Plugin {
             cadastreJMenu.add(menuSource);
             //cadastreJMenu.add(menuResetCookie); not required any more
             //cadastreJMenu.add(menuLambertZone);
-            if (Main.pref.getBoolean("cadastrewms.buildingsMenu", false))
-                cadastreJMenu.add(menuActionBuildings);
+            //if (Main.pref.getBoolean("cadastrewms.buildingsMenu", false))
+            //    cadastreJMenu.add(menuActionBuildings);
             cadastreJMenu.add(menuLoadFromCache);
             // all SVG features disabled until official WMS is released
             //cadastreJMenu.add(menuActionBoundaries);
@@ -334,8 +334,7 @@ public class CadastrePlugin extends Plugin {
             if (oldFrame == null && newFrame != null) {
                 setEnabledAll(true);
                 Main.map.addMapMode(new IconToggleButton(new 
WMSAdjustAction(Main.map)));
-                if (Main.pref.getBoolean("cadastrewms.buildingsMenu", false))
-                    Main.map.addMapMode(new IconToggleButton(new 
Buildings(Main.map)));
+                Main.map.addMapMode(new IconToggleButton(new 
Address(Main.map)));
             } else if (oldFrame != null && newFrame == null) {
                 setEnabledAll(false);
                 //Lambert.layoutZone = -1;
diff --git a/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java 
b/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java
index ca4c30b..b4ab592 100644
--- a/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java
+++ b/cadastre-fr/src/cadastre_fr/CadastrePreferenceSetting.java
@@ -40,6 +40,10 @@ public class CadastrePreferenceSetting implements 
PreferenceSetting {
 
     private JCheckBox disableImageCropping = new JCheckBox(tr("Disable image 
cropping during georeferencing."));
     
+    private JCheckBox autoFirstLayer = new JCheckBox(tr("Select first WMS 
layer in list."));
+    
+    private JCheckBox dontUseRelation = new JCheckBox(tr("Don't use relation 
for addresses (but \"addr:street\" on elements)."));
+    
     private JRadioButton grabMultiplier1 = new JRadioButton("", true);
 
     private JRadioButton grabMultiplier2 = new JRadioButton("", true);
@@ -56,8 +60,6 @@ public class CadastrePreferenceSetting implements 
PreferenceSetting {
 
     private JRadioButton crosspiece4 = new JRadioButton("100m");
 
-    private JCheckBox autoFirstLayer = new JCheckBox(tr("Select first WMS 
layer in list."));
-    
     private JRadioButton grabRes1 = new JRadioButton("high");
 
     private JRadioButton grabRes2 = new JRadioButton("medium");
@@ -323,18 +325,28 @@ public class CadastrePreferenceSetting implements 
PreferenceSetting {
         cacheSize.setToolTipText(tr("Oldest files are automatically deleted 
when this size is exceeded"));
         cadastrewms.add(jLabelCacheSize, GBC.std().insets(20, 0, 0, 0));
         cadastrewms.add(cacheSize, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 
200, 5));
+
         // separator
         cadastrewms.add(new JSeparator(SwingConstants.HORIZONTAL), 
GBC.eol().fill(GBC.HORIZONTAL));
+        
+        // option to select the first WMS layer
         
autoFirstLayer.setSelected(Main.pref.getBoolean("cadastrewms.autoFirstLayer", 
false));
         autoFirstLayer.setToolTipText(tr("Automatically selects the first WMS 
layer if multiple layers exist when grabbing."));
         cadastrewms.add(autoFirstLayer, GBC.eop().insets(0, 0, 0, 0));
+
+        // separator
+        cadastrewms.add(new JSeparator(SwingConstants.HORIZONTAL), 
GBC.eol().fill(GBC.HORIZONTAL));
+
+        // option to use or not relations in addresses
+        
dontUseRelation.setSelected(Main.pref.getBoolean("cadastrewms.addr.dontUseRelation",
 false));
+        dontUseRelation.setToolTipText(tr("Enable this to use the tag 
\"add:street\" on nodes."));
+        cadastrewms.add(dontUseRelation, GBC.eop().insets(0, 0, 0, 0));
+        
+        // end of dialog, scroll bar
         cadastrewms.add(Box.createVerticalGlue(), 
GBC.eol().fill(GBC.VERTICAL));
-//        JTabbedPane cadastrecontent = new JTabbedPane();
-//        cadastrecontent.add(cadastrewms);
         JScrollPane scrollpane = new JScrollPane(cadastrewms);
         scrollpane.setBorder(BorderFactory.createEmptyBorder( 0, 0, 0, 0 ));
         cadastrewmsMast.add(scrollpane, GBC.eol().fill(GBC.BOTH));
-
     }
 
     public boolean ok() {
@@ -402,6 +414,7 @@ public class CadastrePreferenceSetting implements 
PreferenceSetting {
         }
         Main.pref.put("cadastrewms.autoFirstLayer", 
autoFirstLayer.isSelected());
         CacheControl.cacheEnabled = enableCache.isSelected();
+        Main.pref.put("cadastrewms.addr.dontUseRelation", 
dontUseRelation.isSelected());
         CadastrePlugin.refreshConfiguration();
         CadastrePlugin.refreshMenu();
 
diff --git a/cadastre-fr/src/cadastre_fr/GeorefImage.java 
b/cadastre-fr/src/cadastre_fr/GeorefImage.java
index b027861..735c86a 100644
--- a/cadastre-fr/src/cadastre_fr/GeorefImage.java
+++ b/cadastre-fr/src/cadastre_fr/GeorefImage.java
@@ -56,8 +56,9 @@ public class GeorefImage implements Serializable, 
ImageObserver {
         this.orgCroppedRaster[1] = new EastNorth(min.east(), max.north());
         this.orgCroppedRaster[2] = max;
         this.orgCroppedRaster[3] = new EastNorth(max.east(), min.north());
-        this.imageOriginalHeight = img.getHeight();
-        this.imageOriginalWidth = img.getWidth();
+        // img can be null for a hack used in overlapping detection
+        this.imageOriginalHeight = (img == null ? 1 : img.getHeight());
+        this.imageOriginalWidth = (img == null ? 1 : img.getWidth());
         updatePixelPer();
     }
 
diff --git a/cadastre-fr/src/cadastre_fr/WMSLayer.java 
b/cadastre-fr/src/cadastre_fr/WMSLayer.java
index b6bebaf..dd2f804 100644
--- a/cadastre-fr/src/cadastre_fr/WMSLayer.java
+++ b/cadastre-fr/src/cadastre_fr/WMSLayer.java
@@ -273,9 +273,11 @@ public class WMSLayer extends Layer implements 
ImageObserver {
                 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
             else
                 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
-            for (GeorefImage img : images)
-                img.paint(g, mv, CadastrePlugin.backgroundTransparent,
-                        CadastrePlugin.transparency, 
CadastrePlugin.drawBoundaries);
+            synchronized(this){
+                for (GeorefImage img : images)
+                    img.paint(g, mv, CadastrePlugin.backgroundTransparent,
+                            CadastrePlugin.transparency, 
CadastrePlugin.drawBoundaries);
+            }
             g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
savedInterpolation);
         }
         if (this.isRaster) {
diff --git a/editgpx/build.xml b/editgpx/build.xml
index efb0741..598213d 100644
--- a/editgpx/build.xml
+++ b/editgpx/build.xml
@@ -56,6 +56,7 @@
                                <attribute name="Plugin-Class" 
value="org.openstreetmap.josm.plugins.editgpx.EditGpxPlugin" />
                                <attribute name="Plugin-Date" 
value="${version.entry.commit.date}"/>
                                <attribute name="Plugin-Description" 
value="Allows the user to anonymize timestamps and delete parts of huge GPX 
tracks very fast." />
+                               <attribute name="Plugin-Icon" 
value="images/mapmode/editgpx_mode.png"/>
                                <attribute name="Plugin-Link" 
value="http://wiki.openstreetmap.org/wiki/JOSM/Plugins/EditGpx"; />
                                <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}" />
                                <attribute name="Plugin-Version" 
value="${version.entry.commit.revision}"/>
diff --git a/lakewalker/build.xml b/lakewalker/build.xml
index a17568e..17d82be 100644
--- a/lakewalker/build.xml
+++ b/lakewalker/build.xml
@@ -55,6 +55,7 @@
                                <attribute name="Plugin-Class" 
value="org.openstreetmap.josm.plugins.lakewalker.LakewalkerPlugin" />
                                <attribute name="Plugin-Date" 
value="${version.entry.commit.date}"/>
                                <attribute name="Plugin-Description" 
value="Helps vectorizing WMS images." />
+                               <attribute name="Plugin-Icon" 
value="images/lakewalker-sml.png"/>
                                <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}"/>
                                <attribute name="Plugin-Version" 
value="${version.entry.commit.revision}"/>
                        </manifest>
diff --git a/livegps/build.xml b/livegps/build.xml
index e8a262a..e915efe 100644
--- a/livegps/build.xml
+++ b/livegps/build.xml
@@ -55,6 +55,7 @@
                                <attribute name="Plugin-Class" 
value="livegps.LiveGpsPlugin"/>
                                <attribute name="Plugin-Date" 
value="${version.entry.commit.date}"/>
                                <attribute name="Plugin-Description" 
value="Support live GPS input (moving dot) through a connection to gpsd 
server."/>
+                               <attribute name="Plugin-Icon" 
value="images/dialogs/livegps.png"/>
                                <attribute name="Plugin-Link" 
value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/LiveGPS"/>
                                <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}"/>
                                <attribute name="Plugin-Stage" value="50"/>
diff --git a/measurement/build.xml b/measurement/build.xml
index fe755dc..087f340 100644
--- a/measurement/build.xml
+++ b/measurement/build.xml
@@ -55,6 +55,7 @@
                                <attribute name="Plugin-Class" 
value="org.openstreetmap.josm.plugins.measurement.MeasurementPlugin"/>
                                <attribute name="Plugin-Date" 
value="${version.entry.commit.date}"/>
                                <attribute name="Plugin-Description" 
value="Provide a measurement dialog and a layer to measure length and angle of 
segments, area surrounded by a (simple) closed way and create measurement paths 
(which also can be imported from a gps layer)."/>
+                               <attribute name="Plugin-Icon" 
value="images/dialogs/measure.png"/>
                                <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}"/>
                                <attribute name="Plugin-Version" 
value="${version.entry.commit.revision}"/>
                        </manifest>
diff --git a/openvisible/build.xml b/openvisible/build.xml
index 9bcb609..0672a7c 100644
--- a/openvisible/build.xml
+++ b/openvisible/build.xml
@@ -60,6 +60,7 @@
                                <attribute name="Plugin-Date" 
value="${version.entry.commit.date}"/>
                                <attribute name="Plugin-Dependencies" 
value="jgrapht-jdk1.5"/>
                                <attribute name="Plugin-Description" 
value="Allows opening gpx/osm files that intersect the currently visible screen 
area"/>
+                               <attribute name="Plugin-Icon" 
value="images/openvisible.png"/>
                                <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}"/>
                                <attribute name="Plugin-Stage" value="50"/>
                                <attribute name="Plugin-Version" 
value="${version.entry.commit.revision}"/>
diff --git a/routing/build.xml b/routing/build.xml
index 46eb30d..c21112c 100644
--- a/routing/build.xml
+++ b/routing/build.xml
@@ -72,6 +72,7 @@
                                <attribute name="Plugin-Class" 
value="com.innovant.josm.plugin.routing.RoutingPlugin"/>
                                <attribute name="Plugin-Date" 
value="${version.entry.commit.date}"/>
                                <attribute name="Plugin-Description" 
value="Provides routing capabilities."/>
+                               <attribute name="Plugin-Icon" 
value="images/preferences/routing.png"/>
                                <attribute name="Plugin-Link" 
value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/Routing"/>
                                <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}"/>
                                <attribute name="Plugin-Stage" value="50"/>
diff --git a/slippymap/build.xml b/slippymap/build.xml
index 6727f85..4440051 100644
--- a/slippymap/build.xml
+++ b/slippymap/build.xml
@@ -54,6 +54,7 @@
                                <attribute name="Plugin-Class" 
value="org.openstreetmap.josm.plugins.slippymap.SlippyMapPlugin"/>
                                <attribute name="Plugin-Date" 
value="${version.entry.commit.date}"/>
                                <attribute name="Plugin-Description" 
value="Displays a slippy map grid in JOSM. Can load tiles from slippy map as 
background and request updates."/>
+                               <attribute name="Plugin-Icon" 
value="images/preferences/slippymap.png"/>
                                <attribute name="Plugin-Link" 
value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/SlippyMap"/>
                                <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}"/>
                                <attribute name="Plugin-Version" 
value="${version.entry.commit.revision}"/>
diff --git a/surveyor/build.xml b/surveyor/build.xml
index f91afb4..fee1e4f 100644
--- a/surveyor/build.xml
+++ b/surveyor/build.xml
@@ -71,6 +71,7 @@
                                <attribute name="Plugin-Class" 
value="at.dallermassl.josm.plugin.surveyor.SurveyorPlugin"/>
                                <attribute name="Plugin-Date" 
value="${version.entry.commit.date}"/>
                                <attribute name="Plugin-Description" 
value="Allow adding markers/nodes on current gps positions."/>
+                               <attribute name="Plugin-Icon" 
value="images/surveyormenu.png"/>
                                <attribute name="Plugin-Link" 
value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/Surveyor"/>
                                <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}"/>
                                <attribute name="Plugin-Requires" 
value="livegps"/>
diff --git a/svn-info.xml b/svn-info.xml
index 1d5a2a8..5016e5a 100644
--- a/svn-info.xml
+++ b/svn-info.xml
@@ -3,16 +3,16 @@
 <entry
    kind="dir"
    path="plugins"
-   revision="21666">
+   revision="22363">
 <url>http://svn.openstreetmap.org/applications/editors/josm/plugins</url>
 <repository>
 <root>http://svn.openstreetmap.org</root>
 <uuid>b9d5c4c9-76e1-0310-9c85-f3177eceb1e4</uuid>
 </repository>
 <commit
-   revision="21666">
-<author>bastik</author>
-<date>2010-06-12T07:13:56.296435Z</date>
+   revision="22295">
+<author>nakor</author>
+<date>2010-07-13T00:34:51.532356Z</date>
 </commit>
 </entry>
 </info>
diff --git a/wmsplugin/build.xml b/wmsplugin/build.xml
index 0be9d47..7b811ba 100644
--- a/wmsplugin/build.xml
+++ b/wmsplugin/build.xml
@@ -27,7 +27,7 @@
 <project name="wmsplugin" default="dist" basedir=".">
 
 
-       <property name="commit.message" value="filter control characters that 
are send to the consol and create morse code effect" />
+       <property name="commit.message" value="add commit message" />
        <property name="plugin.main.version" value="2830" />
 
 
@@ -58,6 +58,7 @@
                                <attribute name="Plugin-Class" 
value="wmsplugin.WMSPlugin" />
                                <attribute name="Plugin-Date" 
value="${version.entry.commit.date}" />
                                <attribute name="Plugin-Description" 
value="Display georeferenced images as background in JOSM (WMS servers, Yahoo, 
...)." />
+                               <attribute name="Plugin-Icon" 
value="images/wms.png"/>
                                <attribute name="Plugin-Link" 
value="http://wiki.openstreetmap.org/wiki/JOSM/Plugins/WMSPlugin"; />
                                <attribute name="Plugin-Mainversion" 
value="${plugin.main.version}" />
                                <attribute name="Plugin-Version" 
value="${version.entry.commit.revision}" />
diff --git a/wmsplugin/src/wmsplugin/GeorefImage.java 
b/wmsplugin/src/wmsplugin/GeorefImage.java
index 85440bf..7a41243 100644
--- a/wmsplugin/src/wmsplugin/GeorefImage.java
+++ b/wmsplugin/src/wmsplugin/GeorefImage.java
@@ -24,6 +24,7 @@ public class GeorefImage implements Serializable {
        public EastNorth min, max;
        public boolean downloadingStarted;
        public boolean failed = false;
+       public boolean infotext = false;
 
        public GeorefImage(boolean downloadingStarted) {
                this.downloadingStarted = downloadingStarted;
diff --git a/wmsplugin/src/wmsplugin/Grabber.java 
b/wmsplugin/src/wmsplugin/Grabber.java
index 14e4011..54a30c8 100644
--- a/wmsplugin/src/wmsplugin/Grabber.java
+++ b/wmsplugin/src/wmsplugin/Grabber.java
@@ -88,7 +88,7 @@ abstract public class Grabber extends Thread {
         g.drawString(tr("Not in cache"), 10, height()/2);
         image.image = img;
         image.flushedResizedCachedInstance();
-        image.failed = true;
+        image.infotext = true;
         image.downloadingStarted = false;
         g.setFont(font);
     }
@@ -113,5 +113,5 @@ abstract public class Grabber extends Thread {
         return (int)(Math.random() * ((max+1)-min) ) + min;
     }
 
-    abstract public boolean loadFromCache();
+    abstract public boolean loadFromCache(boolean real);
 }
diff --git a/wmsplugin/src/wmsplugin/WMSGrabber.java 
b/wmsplugin/src/wmsplugin/WMSGrabber.java
index 47529b4..098f494 100644
--- a/wmsplugin/src/wmsplugin/WMSGrabber.java
+++ b/wmsplugin/src/wmsplugin/WMSGrabber.java
@@ -154,7 +154,7 @@ public class WMSGrabber extends Grabber {
     }
 
     @Override
-       public boolean loadFromCache(){
+       public boolean loadFromCache(boolean real){
         URL url = null;
         try{
            url = getURL(
@@ -165,7 +165,7 @@ public class WMSGrabber extends Grabber {
            return false;
         }
         BufferedImage cached = cache.getImg(url.toString());
-        if(!layer.hasAutoDownload() || cached != null){
+        if((!real && !layer.hasAutoDownload()) || cached != null){
            image.min = b.min;
            image.max = b.max;
            if(cached == null){
diff --git a/wmsplugin/src/wmsplugin/WMSLayer.java 
b/wmsplugin/src/wmsplugin/WMSLayer.java
index cd6fe54..1e67263 100644
--- a/wmsplugin/src/wmsplugin/WMSLayer.java
+++ b/wmsplugin/src/wmsplugin/WMSLayer.java
@@ -37,442 +37,459 @@ import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.io.CacheFiles;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
 
 /**
  * This is a layer that grabs the current screen from an WMS server. The data
  * fetched this way is tiled and managed to the disc to reduce server load.
  */
-public class WMSLayer extends Layer {
-       protected static final Icon icon =
-               new 
ImageIcon(Toolkit.getDefaultToolkit().createImage(WMSPlugin.class.getResource("/images/wms_small.png")));
-
-       public int messageNum = 5; //limit for messages per layer
-       protected MapView mv;
-       protected String resolution;
-       protected boolean stopAfterPaint = false;
-       protected int imageSize = 500;
-       protected int dax = 10;
-       protected int day = 10;
-       protected int minZoom = 3;
-       protected double dx = 0.0;
-       protected double dy = 0.0;
-       protected double pixelPerDegree;
-       protected GeorefImage[][] images = new GeorefImage[dax][day];
-       JCheckBoxMenuItem startstop = new JCheckBoxMenuItem(tr("Automatic 
downloading"), true);
-       protected JCheckBoxMenuItem alphaChannel = new JCheckBoxMenuItem(new 
ToggleAlphaAction());
-       protected String baseURL;
-       protected String cookies;
-       protected final int serializeFormatVersion = 5;
-
-       private ExecutorService executor = null;
-
-       /** set to true if this layer uses an invalid base url */
-       private boolean usesInvalidUrl = false;
-       /** set to true if the user confirmed to use an potentially invalid WMS 
base url */
-       private boolean isInvalidUrlConfirmed = false;
-
-       public WMSLayer() {
-               this(tr("Blank Layer"), null, null);
-               initializeImages();
-               mv = Main.map.mapView;
-       }
-
-       public WMSLayer(String name, String baseURL, String cookies) {
-               super(name);
-               
alphaChannel.setSelected(Main.pref.getBoolean("wmsplugin.alpha_channel"));
-               setBackgroundLayer(true); /* set global background variable */
-               initializeImages();
-               this.baseURL = baseURL;
-               this.cookies = cookies;
-               WMSGrabber.getProjection(baseURL, true);
-               mv = Main.map.mapView;
-
-               // quick hack to predefine the PixelDensity to reuse the cache
-               int codeIndex = getName().indexOf("#PPD=");
-               if (codeIndex != -1) {
-                       pixelPerDegree = 
Double.valueOf(getName().substring(codeIndex+5));
-               } else {
-                       pixelPerDegree = getPPD();
-               }
-               resolution = mv.getDist100PixelText();
-
-               executor = Executors.newFixedThreadPool(3);
-               if (baseURL != null && !baseURL.startsWith("html:") && 
!WMSGrabber.isUrlWithPatterns(baseURL)) {
-                       if (!(baseURL.endsWith("&") || baseURL.endsWith("?"))) {
-                               if (!confirmMalformedUrl(baseURL)) {
-                                       System.out.println(tr("Warning: WMS 
layer deactivated because of malformed base url ''{0}''", baseURL));
-                                       usesInvalidUrl = true;
-                                       setName(getName() + 
tr("(deactivated)"));
-                                       return;
-                               } else {
-                                       isInvalidUrlConfirmed = true;
-                               }
-                       }
-               }
-       }
-
-       public boolean hasAutoDownload(){
-               return startstop.isSelected();
-       }
-
-       public double getDx(){
-               return dx;
-       }
-
-       public double getDy(){
-               return dy;
-       }
-
-       @Override
-       public void destroy() {
-               try {
-                       executor.shutdownNow();
-                       // Might not be initialized, so catch NullPointer as 
well
-               } catch(Exception x) {
-                       x.printStackTrace();
-               }
-       }
-
-       public double getPPD(){
-               ProjectionBounds bounds = mv.getProjectionBounds();
-               return mv.getWidth() / (bounds.max.east() - bounds.min.east());
-       }
-
-       public void initializeImages() {
-               images = new GeorefImage[dax][day];
-               for(int x = 0; x<dax; ++x) {
-                       for(int y = 0; y<day; ++y) {
-                               images[x][y]= new GeorefImage(false);
-                       }
-               }
-       }
-
-       @Override public Icon getIcon() {
-               return icon;
-       }
-
-       @Override public String getToolTipText() {
-               if(startstop.isSelected())
-                       return tr("WMS layer ({0}), automatically downloading 
in zoom {1}", getName(), resolution);
-               else
-                       return tr("WMS layer ({0}), downloading in zoom {1}", 
getName(), resolution);
-       }
-
-       @Override public boolean isMergable(Layer other) {
-               return false;
-       }
-
-       @Override public void mergeFrom(Layer from) {
-       }
-
-       private ProjectionBounds XYtoBounds (int x, int y) {
-               return new ProjectionBounds(
-                               new EastNorth(      x * imageSize / 
pixelPerDegree,       y * imageSize / pixelPerDegree),
-                               new EastNorth((x + 1) * imageSize / 
pixelPerDegree, (y + 1) * imageSize / pixelPerDegree));
-       }
-
-       private int modulo (int a, int b) {
-               return a % b >= 0 ? a%b : a%b+b;
-       }
-
-       private boolean zoomIsTooBig() {
-               //don't download when it's too outzoomed
-               return pixelPerDegree / getPPD() > minZoom;
-       }
-
-       @Override public void paint(Graphics2D g, final MapView mv, Bounds 
bounds) {
-               if(baseURL == null) return;
-               if (usesInvalidUrl && !isInvalidUrlConfirmed) return;
-
-               if (zoomIsTooBig()) {
-                       for(int x = 0; x<dax; ++x) {
-                               for(int y = 0; y<day; ++y) {
-                                       
images[modulo(x,dax)][modulo(y,day)].paint(g, mv, dx, dy);
-                               }
-                       }
-               } else {
-                       downloadAndPaintVisible(g, mv);
-               }
-       }
-
-       public void displace(double dx, double dy) {
-               this.dx += dx;
-               this.dy += dy;
-       }
-
-       protected boolean confirmMalformedUrl(String url) {
-               if (isInvalidUrlConfirmed)
-                       return true;
-               String msg  = tr("<html>The base URL<br>"
-                               + "''{0}''<br>"
-                               + "for this WMS layer does neither end with a 
''&'' nor with a ''?''.<br>"
-                               + "This is likely to lead to invalid WMS 
request. You should check your<br>"
-                               + "preference settings.<br>"
-                               + "Do you want to fetch WMS tiles anyway?",
-                               url);
-               String [] options = new String[] {
-                               tr("Yes, fetch images"),
-                               tr("No, abort")
-               };
-               int ret = JOptionPane.showOptionDialog(
-                               Main.parent,
-                               msg,
-                               tr("Invalid URL?"),
-                               JOptionPane.YES_NO_OPTION,
-                               JOptionPane.WARNING_MESSAGE,
-                               null,
-                               options, options[1]
-               );
-               switch(ret) {
-               case JOptionPane.YES_OPTION: return true;
-               default: return false;
-               }
-       }
-
-       protected void downloadAndPaintVisible(Graphics g, final MapView mv){
-               if (usesInvalidUrl)
-                       return;
-
-               ProjectionBounds bounds = mv.getProjectionBounds();
-               int bminx= (int)Math.floor (((bounds.min.east() - dx) * 
pixelPerDegree) / imageSize );
-               int bminy= (int)Math.floor (((bounds.min.north() - dy) * 
pixelPerDegree) / imageSize );
-               int bmaxx= (int)Math.ceil  (((bounds.max.east() - dx) * 
pixelPerDegree) / imageSize );
-               int bmaxy= (int)Math.ceil  (((bounds.max.north() - dy) * 
pixelPerDegree) / imageSize );
-
-               for(int x = bminx; x<bmaxx; ++x) {
-                       for(int y = bminy; y<bmaxy; ++y){
-                               GeorefImage img = 
images[modulo(x,dax)][modulo(y,day)];
-                               g.drawRect(x, y, dax, bminy);
-                               if(!img.paint(g, mv, dx, dy) && 
!img.downloadingStarted){
-                                       img.downloadingStarted = true;
-                                       img.image = null;
-                                       img.flushedResizedCachedInstance();
-                                       Grabber gr = 
WMSPlugin.getGrabber(XYtoBounds(x,y), img, mv, this);
-                                       if(!gr.loadFromCache()){
-                                               gr.setPriority(1);
-                                               executor.submit(gr);
-                                       }
-                               }
-                       }
-               }
-       }
-
-       @Override public void visitBoundingBox(BoundingXYVisitor v) {
-               for(int x = 0; x<dax; ++x) {
-                       for(int y = 0; y<day; ++y)
-                               if(images[x][y].image!=null){
-                                       v.visit(images[x][y].min);
-                                       v.visit(images[x][y].max);
-                               }
-               }
-       }
-
-       @Override public Object getInfoComponent() {
-               return getToolTipText();
-       }
-
-       @Override public Component[] getMenuEntries() {
-               return new Component[]{
-                               new 
JMenuItem(LayerListDialog.getInstance().createActivateLayerAction(this)),
-                               new 
JMenuItem(LayerListDialog.getInstance().createShowHideLayerAction(this)),
-                               new 
JMenuItem(LayerListDialog.getInstance().createDeleteLayerAction(this)),
-                               new JSeparator(),
-                               new JMenuItem(new LoadWmsAction()),
-                               new JMenuItem(new SaveWmsAction()),
-                               new JMenuItem(new BookmarkWmsAction()),
-                               new JSeparator(),
-                               startstop,
-                               alphaChannel,
-                               new JMenuItem(new ChangeResolutionAction()),
-                               new JMenuItem(new ReloadErrorTilesAction()),
-                               new JMenuItem(new DownloadAction()),
-                               new JSeparator(),
-                               new JMenuItem(new 
LayerListPopup.InfoAction(this))
-               };
-       }
-
-       public GeorefImage findImage(EastNorth eastNorth) {
-               for(int x = 0; x<dax; ++x) {
-                       for(int y = 0; y<day; ++y)
-                               if(images[x][y].image!=null && 
images[x][y].min!=null && images[x][y].max!=null)
-                                       if(images[x][y].contains(eastNorth, dx, 
dy))
-                                               return images[x][y];
-               }
-               return null;
-       }
-
-       public class DownloadAction extends AbstractAction {
-               public DownloadAction() {
-                       super(tr("Download visible tiles"));
-               }
-               public void actionPerformed(ActionEvent ev) {
-                       if (zoomIsTooBig()) {
-                               JOptionPane.showMessageDialog(
-                                               Main.parent,
-                                               tr("The requested area is too 
big. Please zoom in a little, or change resolution"),
-                                               tr("Error"),
-                                               JOptionPane.ERROR_MESSAGE
-                               );
-                       } else {
-                               downloadAndPaintVisible(mv.getGraphics(), mv);
-                       }
-               }
-       }
-
-       public class ChangeResolutionAction extends AbstractAction {
-               public ChangeResolutionAction() {
-                       super(tr("Change resolution"));
-               }
-               public void actionPerformed(ActionEvent ev) {
-                       initializeImages();
-                       resolution = mv.getDist100PixelText();
-                       pixelPerDegree = getPPD();
-                       mv.repaint();
-               }
-       }
-
-       public class ReloadErrorTilesAction extends AbstractAction {
-               public ReloadErrorTilesAction() {
-                       super(tr("Reload erroneous tiles"));
-               }
-               public void actionPerformed(ActionEvent ev) {
-                       // Delete small files, because they're probably blank 
tiles.
-                       // See https://josm.openstreetmap.de/ticket/2307
-                       
WMSPlugin.cache.customCleanUp(CacheFiles.CLEAN_SMALL_FILES, 4096);
-
-                       for (int x = 0; x < dax; ++x) {
-                               for (int y = 0; y < day; ++y) {
-                                       GeorefImage img = 
images[modulo(x,dax)][modulo(y,day)];
-                                       if(img.failed){
-                                               img.image = null;
-                                               
img.flushedResizedCachedInstance();
-                                               img.downloadingStarted = false;
-                                               img.failed = false;
-                                               mv.repaint();
-                                       }
-                               }
-                       }
-               }
-       }
-
-       public class ToggleAlphaAction extends AbstractAction {
-               public ToggleAlphaAction() {
-                       super(tr("Alpha channel"));
-               }
-               public void actionPerformed(ActionEvent ev) {
-                       JCheckBoxMenuItem checkbox = (JCheckBoxMenuItem) 
ev.getSource();
-                       boolean alphaChannel = checkbox.isSelected();
-                       Main.pref.put("wmsplugin.alpha_channel", alphaChannel);
-
-                       // clear all resized cached instances and repaint the 
layer
-                       for (int x = 0; x < dax; ++x) {
-                               for (int y = 0; y < day; ++y) {
-                                       GeorefImage img = images[modulo(x, 
dax)][modulo(y, day)];
-                                       img.flushedResizedCachedInstance();
-                               }
-                       }
-                       mv.repaint();
-               }
-       }
-
-       public class SaveWmsAction extends AbstractAction {
-               public SaveWmsAction() {
-                       super(tr("Save WMS layer to file"), 
ImageProvider.get("save"));
-               }
-               public void actionPerformed(ActionEvent ev) {
-                       File f = SaveActionBase.createAndOpenSaveFileChooser(
-                                       tr("Save WMS layer"), ".wms");
-                       try {
-                               if (f != null) {
-                                       ObjectOutputStream oos = new 
ObjectOutputStream(
-                                                       new FileOutputStream(f)
-                                       );
-                                       oos.writeInt(serializeFormatVersion);
-                                       oos.writeInt(dax);
-                                       oos.writeInt(day);
-                                       oos.writeInt(imageSize);
-                                       oos.writeDouble(pixelPerDegree);
-                                       oos.writeObject(getName());
-                                       oos.writeObject(baseURL);
-                                       oos.writeObject(images);
-                                       oos.close();
-                               }
-                       } catch (Exception ex) {
-                               ex.printStackTrace(System.out);
-                       }
-               }
-       }
-
-       public class LoadWmsAction extends AbstractAction {
-               public LoadWmsAction() {
-                       super(tr("Load WMS layer from file"), 
ImageProvider.get("load"));
-               }
-               public void actionPerformed(ActionEvent ev) {
-                       JFileChooser fc = 
DiskAccessAction.createAndOpenFileChooser(true,
-                                       false, tr("Load WMS layer"), "wms");
-                       if(fc == null) return;
-                       File f = fc.getSelectedFile();
-                       if (f == null) return;
-                       try
-                       {
-                               FileInputStream fis = new FileInputStream(f);
-                               ObjectInputStream ois = new 
ObjectInputStream(fis);
-                               int sfv = ois.readInt();
-                               if (sfv != serializeFormatVersion) {
-                                       
JOptionPane.showMessageDialog(Main.parent,
-                                                       tr("Unsupported WMS 
file version; found {0}, expected {1}", sfv, serializeFormatVersion),
-                                                       tr("File Format Error"),
-                                                       
JOptionPane.ERROR_MESSAGE);
-                                       return;
-                               }
-                               startstop.setSelected(false);
-                               dax = ois.readInt();
-                               day = ois.readInt();
-                               imageSize = ois.readInt();
-                               pixelPerDegree = ois.readDouble();
-                               setName((String)ois.readObject());
-                               baseURL = (String) ois.readObject();
-                               images = (GeorefImage[][])ois.readObject();
-                               ois.close();
-                               fis.close();
-                               mv.repaint();
-                       }
-                       catch (Exception ex) {
-                               // FIXME be more specific
-                               ex.printStackTrace(System.out);
-                               JOptionPane.showMessageDialog(Main.parent,
-                                               tr("Error loading file"),
-                                               tr("Error"),
-                                               JOptionPane.ERROR_MESSAGE);
-                               return;
-                       }
-               }
-       }
-       /**
-        * This action will add a WMS layer menu entry with the current WMS 
layer URL and name extended by the current resolution.
-        * When using the menu entry again, the WMS cache will be used properly.
-        */
-       public class BookmarkWmsAction extends AbstractAction {
-               public BookmarkWmsAction() {
-                       super(tr("Set WMS Bookmark"));
-               }
-               public void actionPerformed(ActionEvent ev) {
-                       int i = 0;
-                       while (Main.pref.hasKey("wmsplugin.url."+i+".url")) {
-                               i++;
-                       }
-                       String baseName;
-                       // cut old parameter
-                       int parameterIndex = getName().indexOf("#PPD=");
-                       if (parameterIndex != -1) {
-                               baseName = 
getName().substring(0,parameterIndex);
-                       }
-                       else {
-                               baseName = getName();
-                       }
-                       Main.pref.put("wmsplugin.url."+ i +".url",baseURL );
-                       
Main.pref.put("wmsplugin.url."+String.valueOf(i)+".name", baseName + "#PPD=" + 
pixelPerDegree );
-                       WMSPlugin.refreshMenu();
-               }
-       }
+public class WMSLayer extends Layer implements PreferenceChangedListener {
+    protected static final Icon icon =
+        new 
ImageIcon(Toolkit.getDefaultToolkit().createImage(WMSPlugin.class.getResource("/images/wms_small.png")));
+
+    public int messageNum = 5; //limit for messages per layer
+    protected MapView mv;
+    protected String resolution;
+    protected boolean stopAfterPaint = false;
+    protected int imageSize = 500;
+    protected int dax = 10;
+    protected int day = 10;
+    protected int minZoom = 3;
+    protected double dx = 0.0;
+    protected double dy = 0.0;
+    protected double pixelPerDegree;
+    protected GeorefImage[][] images = new GeorefImage[dax][day];
+    JCheckBoxMenuItem startstop = new JCheckBoxMenuItem(tr("Automatic 
downloading"), true);
+    protected JCheckBoxMenuItem alphaChannel = new JCheckBoxMenuItem(new 
ToggleAlphaAction());
+    protected String baseURL;
+    protected String cookies;
+    protected final int serializeFormatVersion = 5;
+
+    private ExecutorService executor = null;
+
+    /** set to true if this layer uses an invalid base url */
+    private boolean usesInvalidUrl = false;
+    /** set to true if the user confirmed to use an potentially invalid WMS 
base url */
+    private boolean isInvalidUrlConfirmed = false;
+
+    public WMSLayer() {
+        this(tr("Blank Layer"), null, null);
+        initializeImages();
+        mv = Main.map.mapView;
+    }
+
+    public WMSLayer(String name, String baseURL, String cookies) {
+        super(name);
+        
alphaChannel.setSelected(Main.pref.getBoolean("wmsplugin.alpha_channel"));
+        setBackgroundLayer(true); /* set global background variable */
+        initializeImages();
+        this.baseURL = baseURL;
+        this.cookies = cookies;
+        WMSGrabber.getProjection(baseURL, true);
+        mv = Main.map.mapView;
+
+        // quick hack to predefine the PixelDensity to reuse the cache
+        int codeIndex = getName().indexOf("#PPD=");
+        if (codeIndex != -1) {
+            pixelPerDegree = Double.valueOf(getName().substring(codeIndex+5));
+        } else {
+            pixelPerDegree = getPPD();
+        }
+        resolution = mv.getDist100PixelText();
+
+        executor = Executors.newFixedThreadPool(
+            Main.pref.getInteger("wmsplugin.numThreads",
+            WMSPlugin.simultaneousConnections));
+        if (baseURL != null && !baseURL.startsWith("html:") && 
!WMSGrabber.isUrlWithPatterns(baseURL)) {
+            if (!(baseURL.endsWith("&") || baseURL.endsWith("?"))) {
+                if (!confirmMalformedUrl(baseURL)) {
+                    System.out.println(tr("Warning: WMS layer deactivated 
because of malformed base url ''{0}''", baseURL));
+                    usesInvalidUrl = true;
+                    setName(getName() + tr("(deactivated)"));
+                    return;
+                } else {
+                    isInvalidUrlConfirmed = true;
+                }
+            }
+        }
+
+        Main.pref.addPreferenceChangeListener(this);
+    }
+
+    public boolean hasAutoDownload(){
+        return startstop.isSelected();
+    }
+
+    public double getDx(){
+        return dx;
+    }
+
+    public double getDy(){
+        return dy;
+    }
+
+    @Override
+    public void destroy() {
+        try {
+            executor.shutdownNow();
+            // Might not be initialized, so catch NullPointer as well
+        } catch(Exception x) {
+            x.printStackTrace();
+        }
+    }
+
+    public double getPPD(){
+        ProjectionBounds bounds = mv.getProjectionBounds();
+        return mv.getWidth() / (bounds.max.east() - bounds.min.east());
+    }
+
+    public void initializeImages() {
+        images = new GeorefImage[dax][day];
+        for(int x = 0; x<dax; ++x) {
+            for(int y = 0; y<day; ++y) {
+                images[x][y]= new GeorefImage(false);
+            }
+        }
+    }
+
+    @Override public Icon getIcon() {
+        return icon;
+    }
+
+    @Override public String getToolTipText() {
+        if(startstop.isSelected())
+            return tr("WMS layer ({0}), automatically downloading in zoom 
{1}", getName(), resolution);
+        else
+            return tr("WMS layer ({0}), downloading in zoom {1}", getName(), 
resolution);
+    }
+
+    @Override public boolean isMergable(Layer other) {
+        return false;
+    }
+
+    @Override public void mergeFrom(Layer from) {
+    }
+
+    private ProjectionBounds XYtoBounds (int x, int y) {
+        return new ProjectionBounds(
+            new EastNorth(      x * imageSize / pixelPerDegree,       y * 
imageSize / pixelPerDegree),
+            new EastNorth((x + 1) * imageSize / pixelPerDegree, (y + 1) * 
imageSize / pixelPerDegree));
+    }
+
+    private int modulo (int a, int b) {
+        return a % b >= 0 ? a%b : a%b+b;
+    }
+
+    private boolean zoomIsTooBig() {
+        //don't download when it's too outzoomed
+        return pixelPerDegree / getPPD() > minZoom;
+    }
+
+    @Override public void paint(Graphics2D g, final MapView mv, Bounds bounds) 
{
+        if(baseURL == null) return;
+        if (usesInvalidUrl && !isInvalidUrlConfirmed) return;
+
+        if (zoomIsTooBig()) {
+            for(int x = 0; x<dax; ++x) {
+                for(int y = 0; y<day; ++y) {
+                    images[modulo(x,dax)][modulo(y,day)].paint(g, mv, dx, dy);
+                }
+            }
+        } else {
+            downloadAndPaintVisible(g, mv, false);
+        }
+    }
+
+    public void displace(double dx, double dy) {
+        this.dx += dx;
+        this.dy += dy;
+    }
+
+    protected boolean confirmMalformedUrl(String url) {
+        if (isInvalidUrlConfirmed)
+            return true;
+        String msg  = tr("<html>The base URL<br>"
+            + "''{0}''<br>"
+            + "for this WMS layer does neither end with a ''&'' nor with a 
''?''.<br>"
+            + "This is likely to lead to invalid WMS request. You should check 
your<br>"
+            + "preference settings.<br>"
+            + "Do you want to fetch WMS tiles anyway?",
+            url);
+        String [] options = new String[] {
+            tr("Yes, fetch images"),
+            tr("No, abort")
+        };
+        int ret = JOptionPane.showOptionDialog(
+            Main.parent,
+            msg,
+            tr("Invalid URL?"),
+            JOptionPane.YES_NO_OPTION,
+            JOptionPane.WARNING_MESSAGE,
+            null,
+            options, options[1]
+        );
+        switch(ret) {
+        case JOptionPane.YES_OPTION: return true;
+        default: return false;
+        }
+    }
+
+    protected void downloadAndPaintVisible(Graphics g, final MapView mv,
+    boolean real){
+        if (usesInvalidUrl)
+            return;
+
+        ProjectionBounds bounds = mv.getProjectionBounds();
+        int bminx= (int)Math.floor (((bounds.min.east() - dx) * 
pixelPerDegree) / imageSize );
+        int bminy= (int)Math.floor (((bounds.min.north() - dy) * 
pixelPerDegree) / imageSize );
+        int bmaxx= (int)Math.ceil  (((bounds.max.east() - dx) * 
pixelPerDegree) / imageSize );
+        int bmaxy= (int)Math.ceil  (((bounds.max.north() - dy) * 
pixelPerDegree) / imageSize );
+
+        for(int x = bminx; x<bmaxx; ++x) {
+            for(int y = bminy; y<bmaxy; ++y){
+                GeorefImage img = images[modulo(x,dax)][modulo(y,day)];
+                if((!img.paint(g, mv, dx, dy) || img.infotext) && 
!img.downloadingStarted){
+                    img.downloadingStarted = true;
+                    img.image = null;
+                    img.flushedResizedCachedInstance();
+                    Grabber gr = WMSPlugin.getGrabber(XYtoBounds(x,y), img, 
mv, this);
+                    if(!gr.loadFromCache(real)){
+                        gr.setPriority(1);
+                        executor.submit(gr);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override public void visitBoundingBox(BoundingXYVisitor v) {
+        for(int x = 0; x<dax; ++x) {
+            for(int y = 0; y<day; ++y)
+                if(images[x][y].image!=null){
+                    v.visit(images[x][y].min);
+                    v.visit(images[x][y].max);
+                }
+        }
+    }
+
+    @Override public Object getInfoComponent() {
+        return getToolTipText();
+    }
+
+    @Override public Component[] getMenuEntries() {
+        return new Component[]{
+            new 
JMenuItem(LayerListDialog.getInstance().createActivateLayerAction(this)),
+            new 
JMenuItem(LayerListDialog.getInstance().createShowHideLayerAction(this)),
+            new 
JMenuItem(LayerListDialog.getInstance().createDeleteLayerAction(this)),
+            new JSeparator(),
+            new JMenuItem(new LoadWmsAction()),
+            new JMenuItem(new SaveWmsAction()),
+            new JMenuItem(new BookmarkWmsAction()),
+            new JSeparator(),
+            startstop,
+            alphaChannel,
+            new JMenuItem(new ChangeResolutionAction()),
+            new JMenuItem(new ReloadErrorTilesAction()),
+            new JMenuItem(new DownloadAction()),
+            new JSeparator(),
+            new JMenuItem(new LayerListPopup.InfoAction(this))
+        };
+    }
+
+    public GeorefImage findImage(EastNorth eastNorth) {
+        for(int x = 0; x<dax; ++x) {
+            for(int y = 0; y<day; ++y)
+                if(images[x][y].image!=null && images[x][y].min!=null && 
images[x][y].max!=null)
+                    if(images[x][y].contains(eastNorth, dx, dy))
+                        return images[x][y];
+        }
+        return null;
+    }
+
+    public class DownloadAction extends AbstractAction {
+        public DownloadAction() {
+            super(tr("Download visible tiles"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            if (zoomIsTooBig()) {
+                JOptionPane.showMessageDialog(
+                    Main.parent,
+                    tr("The requested area is too big. Please zoom in a 
little, or change resolution"),
+                    tr("Error"),
+                    JOptionPane.ERROR_MESSAGE
+                );
+            } else {
+                downloadAndPaintVisible(mv.getGraphics(), mv, true);
+            }
+        }
+    }
+
+    public class ChangeResolutionAction extends AbstractAction {
+        public ChangeResolutionAction() {
+            super(tr("Change resolution"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            initializeImages();
+            resolution = mv.getDist100PixelText();
+            pixelPerDegree = getPPD();
+            mv.repaint();
+        }
+    }
+
+    public class ReloadErrorTilesAction extends AbstractAction {
+        public ReloadErrorTilesAction() {
+            super(tr("Reload erroneous tiles"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            // Delete small files, because they're probably blank tiles.
+            // See https://josm.openstreetmap.de/ticket/2307
+            WMSPlugin.cache.customCleanUp(CacheFiles.CLEAN_SMALL_FILES, 4096);
+
+            for (int x = 0; x < dax; ++x) {
+                for (int y = 0; y < day; ++y) {
+                    GeorefImage img = images[modulo(x,dax)][modulo(y,day)];
+                    if(img.failed){
+                        img.image = null;
+                        img.flushedResizedCachedInstance();
+                        img.downloadingStarted = false;
+                        img.failed = false;
+                        mv.repaint();
+                    }
+                }
+            }
+        }
+    }
+
+    public class ToggleAlphaAction extends AbstractAction {
+        public ToggleAlphaAction() {
+            super(tr("Alpha channel"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            JCheckBoxMenuItem checkbox = (JCheckBoxMenuItem) ev.getSource();
+            boolean alphaChannel = checkbox.isSelected();
+            Main.pref.put("wmsplugin.alpha_channel", alphaChannel);
+
+            // clear all resized cached instances and repaint the layer
+            for (int x = 0; x < dax; ++x) {
+                for (int y = 0; y < day; ++y) {
+                    GeorefImage img = images[modulo(x, dax)][modulo(y, day)];
+                    img.flushedResizedCachedInstance();
+                }
+            }
+            mv.repaint();
+        }
+    }
+
+    public class SaveWmsAction extends AbstractAction {
+        public SaveWmsAction() {
+            super(tr("Save WMS layer to file"), ImageProvider.get("save"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            File f = SaveActionBase.createAndOpenSaveFileChooser(
+                tr("Save WMS layer"), ".wms");
+            try {
+                if (f != null) {
+                    ObjectOutputStream oos = new ObjectOutputStream(
+                        new FileOutputStream(f)
+                    );
+                    oos.writeInt(serializeFormatVersion);
+                    oos.writeInt(dax);
+                    oos.writeInt(day);
+                    oos.writeInt(imageSize);
+                    oos.writeDouble(pixelPerDegree);
+                    oos.writeObject(getName());
+                    oos.writeObject(baseURL);
+                    oos.writeObject(images);
+                    oos.close();
+                }
+            } catch (Exception ex) {
+                ex.printStackTrace(System.out);
+            }
+        }
+    }
+
+    public class LoadWmsAction extends AbstractAction {
+        public LoadWmsAction() {
+            super(tr("Load WMS layer from file"), ImageProvider.get("load"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            JFileChooser fc = DiskAccessAction.createAndOpenFileChooser(true,
+                false, tr("Load WMS layer"), "wms");
+            if(fc == null) return;
+            File f = fc.getSelectedFile();
+            if (f == null) return;
+            try
+            {
+                FileInputStream fis = new FileInputStream(f);
+                ObjectInputStream ois = new ObjectInputStream(fis);
+                int sfv = ois.readInt();
+                if (sfv != serializeFormatVersion) {
+                    JOptionPane.showMessageDialog(Main.parent,
+                        tr("Unsupported WMS file version; found {0}, expected 
{1}", sfv, serializeFormatVersion),
+                        tr("File Format Error"),
+                        JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                startstop.setSelected(false);
+                dax = ois.readInt();
+                day = ois.readInt();
+                imageSize = ois.readInt();
+                pixelPerDegree = ois.readDouble();
+                setName((String)ois.readObject());
+                baseURL = (String) ois.readObject();
+                images = (GeorefImage[][])ois.readObject();
+                ois.close();
+                fis.close();
+                mv.repaint();
+            }
+            catch (Exception ex) {
+                // FIXME be more specific
+                ex.printStackTrace(System.out);
+                JOptionPane.showMessageDialog(Main.parent,
+                        tr("Error loading file"),
+                        tr("Error"),
+                        JOptionPane.ERROR_MESSAGE);
+                return;
+            }
+        }
+    }
+    /**
+     * This action will add a WMS layer menu entry with the current WMS layer
+     * URL and name extended by the current resolution.
+     * When using the menu entry again, the WMS cache will be used properly.
+     */
+    public class BookmarkWmsAction extends AbstractAction {
+        public BookmarkWmsAction() {
+            super(tr("Set WMS Bookmark"));
+        }
+        public void actionPerformed(ActionEvent ev) {
+            int i = 0;
+            while (Main.pref.hasKey("wmsplugin.url."+i+".url")) {
+                i++;
+            }
+            String baseName;
+            // cut old parameter
+            int parameterIndex = getName().indexOf("#PPD=");
+            if (parameterIndex != -1) {
+                baseName = getName().substring(0,parameterIndex);
+            }
+            else {
+                baseName = getName();
+            }
+            Main.pref.put("wmsplugin.url."+ i +".url",baseURL );
+            Main.pref.put("wmsplugin.url."+String.valueOf(i)+".name",
+                baseName + "#PPD=" + pixelPerDegree );
+            WMSPlugin.refreshMenu();
+        }
+    }
+
+    public void preferenceChanged(PreferenceChangeEvent event) {
+        if (event.getKey().equals("wmsplugin.simultaneousConnections")) {
+            executor.shutdownNow();
+            executor = Executors.newFixedThreadPool(
+                Main.pref.getInteger("wmsplugin.numThreads",
+                WMSPlugin.simultaneousConnections));
+        }
+    }
 }
diff --git a/wmsplugin/src/wmsplugin/WMSPlugin.java 
b/wmsplugin/src/wmsplugin/WMSPlugin.java
index 4a462a2..9672bad 100644
--- a/wmsplugin/src/wmsplugin/WMSPlugin.java
+++ b/wmsplugin/src/wmsplugin/WMSPlugin.java
@@ -52,6 +52,7 @@ public class WMSPlugin extends Plugin {
     static boolean doOverlap = false;
     static int overlapEast = 14;
     static int overlapNorth = 4;
+    static int simultaneousConnections = 3;
 
     // remember state of menu item to restore on changed preferences
     static private boolean menuEnabled = false;
@@ -109,6 +110,11 @@ public class WMSPlugin extends Plugin {
         try {
             overlapNorth = 
Integer.valueOf(prefs.get("wmsplugin.url.overlapNorth"));
         } catch (Exception e) {} // If sth fails, we drop to default settings.
+               
+        // Load the settings for number of simultaneous connections
+        try {
+            simultaneousConnections = 
Integer.valueOf(prefs.get("wmsplugin.simultanousConnections"));
+        } catch (Exception e) {} // If sth fails, we drop to default settings.
 
         // And then the names+urls of WMS servers
         int prefid = 0;
diff --git a/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java 
b/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java
index 42c8b28..2541c17 100644
--- a/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java
+++ b/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java
@@ -38,6 +38,7 @@ public class WMSPreferenceEditor implements PreferenceSetting 
{
     JCheckBox overlapCheckBox;
     JSpinner spinEast;
     JSpinner spinNorth;
+    JSpinner spinSimConn;
 
     public void addGui(final PreferenceTabbedPane gui) {
         JPanel p = gui.createPreferenceTab("wms", tr("WMS Plugin 
Preferences"), tr("Modify list of WMS servers displayed in the WMS plugin 
menu"));
@@ -162,7 +163,6 @@ public class WMSPreferenceEditor implements 
PreferenceSetting {
         p.add(new JLabel(tr("Downloader:")), 
GBC.eol().fill(GridBagConstraints.HORIZONTAL));
         p.add(browser);
 
-
         //Overlap
         p.add(Box.createHorizontalGlue(), 
GBC.eol().fill(GridBagConstraints.HORIZONTAL));
 
@@ -180,6 +180,15 @@ public class WMSPreferenceEditor implements 
PreferenceSetting {
         overlapPanel.add(spinNorth);
 
         p.add(overlapPanel);
+               
+        // Simultaneous connections
+        p.add(Box.createHorizontalGlue(), 
GBC.eol().fill(GridBagConstraints.HORIZONTAL));
+        JLabel labelSimConn = new JLabel(tr("Simultaneous connections"));
+        spinSimConn = new JSpinner(new 
SpinnerNumberModel(WMSPlugin.simultaneousConnections, 1, 30, 1));
+        JPanel overlapPanelSimConn = new JPanel(new FlowLayout());
+        overlapPanelSimConn.add(labelSimConn);
+        overlapPanelSimConn.add(spinSimConn);
+        p.add(overlapPanelSimConn);
     }
 
     public boolean ok() {
@@ -222,12 +231,14 @@ public class WMSPreferenceEditor implements 
PreferenceSetting {
         WMSPlugin.doOverlap = overlapCheckBox.getModel().isSelected();
         WMSPlugin.overlapEast = (Integer) spinEast.getModel().getValue();
         WMSPlugin.overlapNorth = (Integer) spinNorth.getModel().getValue();
+        WMSPlugin.simultaneousConnections = (Integer) 
spinSimConn.getModel().getValue();
 
         Main.pref.put("wmsplugin.url.overlap",    
String.valueOf(WMSPlugin.doOverlap));
         Main.pref.put("wmsplugin.url.overlapEast", 
String.valueOf(WMSPlugin.overlapEast));
         Main.pref.put("wmsplugin.url.overlapNorth", 
String.valueOf(WMSPlugin.overlapNorth));
 
-        Main.pref.put("wmsplugin.browser", 
browser.getEditor().getItem().toString());
+        Main.pref.put("wmsplugin.browser", 
browser.getEditor().getItem().toString()); 
+        Main.pref.put("wmsplugin.simultaneousConnections", 
String.valueOf(WMSPlugin.simultaneousConnections));
         return false;
     }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-grass/josm-plugins.git

_______________________________________________
Pkg-grass-devel mailing list
Pkg-grass-devel@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-grass-devel

Reply via email to