Index: /applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/GrabThread.java
===================================================================
--- /applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/GrabThread.java	(revision 25032)
+++ /applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/GrabThread.java	(revision 25033)
@@ -22,5 +22,5 @@
     private WMSLayer wmsLayer;
 
-    private Lock lock = new ReentrantLock();
+    private Lock lockImagesToGrag = new ReentrantLock();
 
     private ArrayList<EastNorthBound> imagesToGrab = new ArrayList<EastNorthBound>();
@@ -30,18 +30,27 @@
     private EastNorthBound currentGrabImage;
 
+    private Lock lockCurrentGrabImage = new ReentrantLock();
+
+    /**
+     * Call directly grabber for raster images or prepare thread for vector images 
+     * @param moreImages
+     */
     public void addImages(ArrayList<EastNorthBound> moreImages) {
-        lock.lock();
+        lockImagesToGrag.lock();
         imagesToGrab.addAll(moreImages);
-        lock.unlock();
+        lockImagesToGrag.unlock();
         synchronized(this) {
             this.notify();
         }
         System.out.println("Added " + moreImages.size() + " to the grab thread");
+        if (wmsLayer.isRaster()) {
+            waitNotification();
+        }
     }
 
     public int getImagesToGrabSize() {
-        lock.lock();
+        lockImagesToGrag.lock();
         int size = imagesToGrab.size();
-        lock.unlock();
+        lockImagesToGrag.unlock();
         return size;
     }
@@ -49,17 +58,17 @@
     public ArrayList<EastNorthBound> getImagesToGrabCopy() {
         ArrayList<EastNorthBound> copyList = new ArrayList<EastNorthBound>(); 
-        lock.lock();
+        lockImagesToGrag.lock();
         for (EastNorthBound img : imagesToGrab) {
             EastNorthBound imgCpy = new EastNorthBound(img.min, img.max);
             copyList.add(imgCpy);
         }
-        lock.unlock();
+        lockImagesToGrag.unlock();
         return copyList;
     }
     
     public void clearImagesToGrab() {        
-        lock.lock();
+        lockImagesToGrag.lock();
         imagesToGrab.clear();
-        lock.unlock();
+        lockImagesToGrag.unlock();
     }
     
@@ -68,8 +77,10 @@
         for (;;) {
             while (getImagesToGrabSize() > 0) {
-                lock.lock();
+                lockImagesToGrag.lock();
+                lockCurrentGrabImage.lock();
                 currentGrabImage = imagesToGrab.get(0);
+                lockCurrentGrabImage.unlock();
                 imagesToGrab.remove(0);
-                lock.unlock();
+                lockImagesToGrag.unlock();
                 if (cancelled) {
                     break;
@@ -77,4 +88,5 @@
                     GeorefImage newImage;
                     try {
+                        Main.map.repaint(); // paint the current grab box
                         newImage = grabber.grab(wmsLayer, currentGrabImage.min, currentGrabImage.max);
                     } catch (IOException e) {
@@ -93,4 +105,5 @@
                         break;
                     }
+                    try {
                     if (CadastrePlugin.backgroundTransparent) {
                         wmsLayer.imagesLock.lock();
@@ -109,20 +122,22 @@
                     Main.map.mapView.repaint();
                     saveToCache(newImage);
+                    } catch (NullPointerException e) {
+                        System.out.println("Layer destroyed. Cancel grab thread");
+                        setCancelled(true);
+                    }
                 }
             }
             System.out.println("grab thread list empty");
+            lockCurrentGrabImage.lock();
             currentGrabImage = null;
+            lockCurrentGrabImage.unlock();
             if (cancelled) {
                 clearImagesToGrab();
                 cancelled = false;
             }
-            synchronized(this) {
-                try {
-                    wait();
-                } catch (InterruptedException e) {
-                    e.printStackTrace(System.out);
-                }
-            }
-        }
+            if (wmsLayer.isRaster()) {
+                notifyWaiter();
+            }
+            waitNotification();        }
     }
 
@@ -165,11 +180,15 @@
 
     public void paintBoxesToGrab(Graphics g, MapView mv) {
-        ArrayList<EastNorthBound> imagesToGrab = getImagesToGrabCopy();
-        for (EastNorthBound img : imagesToGrab) {
-            paintBox(g, mv, img, Color.red);
-        }
+        if (getImagesToGrabSize() > 0) {
+            ArrayList<EastNorthBound> imagesToGrab = getImagesToGrabCopy();
+            for (EastNorthBound img : imagesToGrab) {
+                paintBox(g, mv, img, Color.red);
+            }
+        }
+        lockCurrentGrabImage.lock();
         if (currentGrabImage != null) {
             paintBox(g, mv, currentGrabImage, Color.orange);
         }
+        lockCurrentGrabImage.unlock();
     }
     
@@ -203,3 +222,15 @@
     }
 
+    private synchronized void notifyWaiter() {
+        this.notify();
+    }
+
+    private synchronized void waitNotification() {
+        try {
+            wait();
+        } catch (InterruptedException e) {
+            e.printStackTrace(System.out);
+        }
+    }
+
 }
Index: /applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSLayer.java
===================================================================
--- /applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSLayer.java	(revision 25032)
+++ /applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSLayer.java	(revision 25033)
@@ -108,4 +108,5 @@
         // if the layer is currently saving the images in the cache, wait until it's finished
         grabThread.cancel();
+        grabThread = null;
         super.destroy();
         images = null;
@@ -141,11 +142,9 @@
                 divideBbox(b, Integer.parseInt(Main.pref.get("cadastrewms.scale", Scale.X1.toString())));
         }
-
         grabThread.addImages(dividedBbox);
-        Main.map.repaint();
-    }
-
-    /**
-     * Divides the bounding box in smaller polygons.
+    }
+
+    /**
+     * Divides the bounding box in smaller squares. Their size (and quantity) is configurable in Preferences.
      * 
      * @param b      the original bbox, usually the current bbox on screen
@@ -172,12 +171,52 @@
         } else {
             // divide to fixed size squares
-            int cSquare = Integer.parseInt(Main.pref.get("cadastrewms.squareSize", "100"));
-            minEast = minEast - minEast % cSquare;
-            minNorth = minNorth - minNorth % cSquare;
-            for (int xEast = (int)minEast; xEast < lambertMax.east(); xEast+=cSquare)
-                for (int xNorth = (int)minNorth; xNorth < lambertMax.north(); xNorth+=cSquare) {
-                    dividedBbox.add(new EastNorthBound(new EastNorth(xEast, xNorth),
-                                new EastNorth(xEast + cSquare, xNorth + cSquare)));
-            }
+            // grab all square in a spiral starting from the center (usually the most interesting place)
+            int c = Integer.parseInt(Main.pref.get("cadastrewms.squareSize", "100"));
+            lambertMin = lambertMin.add(- minEast%c, - minNorth%c);
+            lambertMax = lambertMax.add(c - lambertMax.east()%c, c - lambertMax.north()%c);
+            EastNorth mid = lambertMax.getCenter(lambertMin);
+            mid = mid.add(-1, 1); // in case the boxes side is a pair, select the one one top,left to follow the rotation
+            mid = mid.add(- mid.east()%c, - mid.north()%c);
+            int x = (int)(lambertMax.east() - lambertMin.east())/100;
+            int y = (int)(lambertMax.north() - lambertMin.north())/100;
+            int dx[] = {+1, 0,-1, 0};
+            int dy[] = {0,-1, 0,+1};
+            int currDir = -1, lDir = 1, i = 1, j = 0, k = -1;
+            if (x == 1)
+                currDir = 0;
+            dividedBbox.add(new EastNorthBound(mid, new EastNorth(mid.east()+c, mid.north()+c)));
+            while (i < (x*y)) {
+                i++;
+                j++;
+                if (j >= lDir) {
+                    k++;
+                    if (k > 1) {
+                        lDir++;
+                        k = 0;
+                    }
+                    j = 0;
+                    currDir = (currDir+1)%4;
+                } else if (currDir >= 0 && j >= (currDir == 0 || currDir == 2 ? x-1 : y-1)) {
+                    // the overall is a rectangle, not a square. Jump to the other side to grab next square.
+                    k++;
+                    if (k > 1) {
+                        lDir++;
+                        k = 0;
+                    }
+                    j = lDir-1;
+                    currDir = (currDir+1)%4;
+                    mid = new EastNorth(mid.east() + dx[currDir]*c*(lDir-1), mid.north() + dy[currDir]*c*(lDir-1));
+                }
+                mid = new EastNorth(mid.east() + dx[currDir]*c, mid.north() + dy[currDir]*c);
+                dividedBbox.add(new EastNorthBound(mid, new EastNorth(mid.east()+c, mid.north()+c)));
+            }
+//            // simple algorithm to grab all squares
+//            minEast = minEast - minEast % cSquare;
+//            minNorth = minNorth - minNorth % cSquare;
+//            for (int xEast = (int)minEast; xEast < lambertMax.east(); xEast+=cSquare)
+//                for (int xNorth = (int)minNorth; xNorth < lambertMax.north(); xNorth+=cSquare) {
+//                    dividedBbox.add(new EastNorthBound(new EastNorth(xEast, xNorth),
+//                                new EastNorth(xEast + cSquare, xNorth + cSquare)));
+//            }
         }
     }
@@ -231,7 +270,5 @@
             paintCrosspieces(g, mv);
         }
-        //        if (grabThread.getImagesToGrabSize() > 0) {
-            grabThread.paintBoxesToGrab(g, mv);
-            //        }
+        grabThread.paintBoxesToGrab(g, mv);
         if (this.adjustModeEnabled) {
             WMSAdjustAction.paintAdjustFrames(g, mv);
@@ -379,5 +416,4 @@
      */
     public void write(ObjectOutputStream oos) throws IOException {
-        // Set currentFormat to the serializeFormatVersion
         currentFormat = this.serializeFormatVersion;
         oos.writeInt(this.serializeFormatVersion);
