altoslib: Fix map preloading callbacks, run in separate thread
[fw/altos] / altoslib / AltosMapTile.java
index b5dee7a4ae660dcb211a76375b019b8928ad2ce6..fdc8ff65995ab0752843e88ad3f58b62afd52049 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_6;
+package org.altusmetrum.altoslib_10;
 
 import java.io.*;
 import java.util.*;
 
-public class AltosMapTile implements AltosFontListener {
-       AltosMapTileListener    listener;
-       AltosLatLon     upper_left, center;
-       int             px_size;
+public abstract class AltosMapTile implements AltosFontListener, AltosMapStoreListener {
+       LinkedList<AltosMapTileListener>        listeners = new LinkedList<AltosMapTileListener>();
+       public AltosLatLon      upper_left, center;
+       public int              px_size;
        int             zoom;
        int             maptype;
-       AltosMapStore   store;
-       AltosMapCache   cache;
-       int             status;
-
-       static public final int success = 0;
-       static public final int loading = 1;
-       static public final int failed = 2;
-       static public final int bad_request = 3;
-       static public final int forbidden = 4;
+       int             scale;
+       private AltosMapCache   cache;
+       public AltosMapStore    store;
+       public int      status;
+
+       static public final int loaded = 0;     /* loaded from file */
+       static public final int fetched = 1;    /* downloaded to file */
+       static public final int fetching = 2;   /* downloading from net */
+       static public final int failed = 3;     /* loading from file failed */
+       static public final int bad_request = 4;/* downloading failed */
+       static public final int forbidden = 5;  /* downloading failed */
 
        private File map_file() {
                double lat = center.lat;
@@ -51,51 +53,72 @@ public class AltosMapTile implements AltosFontListener {
                else
                        format_string = "png";
                return new File(AltosPreferences.mapdir(),
-                               String.format("map-%c%.6f,%c%.6f-%s%d.%s",
-                                             chlat, lat, chlon, lon, maptype_string, zoom, format_string));
+                               String.format("map-%c%.6f,%c%.6f-%s%d%s.%s",
+                                             chlat, lat, chlon, lon, maptype_string, zoom, scale == 1 ? "" : String.format("-%d", scale), format_string));
        }
 
        private String map_url() {
                String format_string;
+               int z = zoom;
+
                if (maptype == AltosMap.maptype_hybrid || maptype == AltosMap.maptype_satellite || maptype == AltosMap.maptype_terrain)
                        format_string = "jpg";
                else
                        format_string = "png32";
 
+               for (int s = 1; s < scale; s <<= 1)
+                       z--;
+
                if (AltosVersion.has_google_maps_api_key())
-                       return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s&key=%s",
-                                            center.lat, center.lon, zoom, px_size, px_size, AltosMap.maptype_names[maptype], format_string, AltosVersion.google_maps_api_key);
+                       return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&scale=%d&sensor=false&maptype=%s&format=%s&key=%s",
+                                            center.lat, center.lon, z, px_size/scale, px_size/scale, scale, AltosMap.maptype_names[maptype], format_string, AltosVersion.google_maps_api_key);
                else
-                       return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s",
-                                            center.lat, center.lon, zoom, px_size, px_size, AltosMap.maptype_names[maptype], format_string);
+                       return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&scale=%d&sensor=false&maptype=%s&format=%s",
+                                            center.lat, center.lon, z, px_size/scale, px_size/scale, AltosMap.maptype_names[maptype], format_string);
        }
 
        public void font_size_changed(int font_size) {
        }
 
-       public void set_status(int status) {
+       private synchronized void notify_listeners(int status) {
                this.status = status;
-               listener.notify_tile(this, status);
+               for (AltosMapTileListener listener : listeners)
+                       listener.notify_tile(this, status);
+       }
+
+       public void notify_store(AltosMapStore store, int status) {
+//             System.out.printf("AltosMapTile.notify_store %d\n", status);
+               notify_listeners(status);
        }
 
        public void notify_image(AltosImage image) {
-               listener.notify_tile(this, status);
+               if (image == null)
+                       status = failed;
+               else
+                       status = loaded;
+               notify_listeners(status);
        }
 
-       public int store_status() {
-               return store.status();
+       public abstract void paint(AltosMapTransform t);
+
+       public AltosImage get_image() {
+               if (cache == null)
+                       return null;
+               return cache.get(this);
        }
 
-       public void add_store_listener(AltosMapStoreListener listener) {
-               store.add_listener(listener);
+       public synchronized void add_listener(AltosMapTileListener listener) {
+               if (!listeners.contains(listener))
+                       listeners.add(listener);
+               listener.notify_tile(this, status);
        }
 
-       public void remove_store_listener(AltosMapStoreListener listener) {
-               store.remove_listener(listener);
+       public synchronized void remove_listener(AltosMapTileListener listener) {
+               listeners.remove(listener);
        }
 
-       public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
-               this.listener = listener;
+       public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
+               this.cache = cache;
                this.upper_left = upper_left;
 
                while (center.lon < -180.0)
@@ -107,8 +130,13 @@ public class AltosMapTile implements AltosFontListener {
                this.zoom = zoom;
                this.maptype = maptype;
                this.px_size = px_size;
+               this.scale = scale;
 
-               status = AltosMapTile.loading;
                store = AltosMapStore.get(map_url(), map_file());
+               store.add_listener(this);
+       }
+
+       public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+               this(cache, upper_left, center, zoom, maptype, px_size, 1);
        }
 }