altosuilib: Publish AltosSiteMap.centre. Add prefetchMaps with old API
[fw/altos] / altosuilib / AltosSiteMap.java
index f22d9531848acd4d87be60ae4b5ed06946e7d155..7f0e1844b264d3efe5508e8719ff2626f46eef1e 100644 (file)
@@ -50,7 +50,7 @@ class MapPoint {
        }
 }
 
-public class AltosSiteMap extends JComponent implements AltosFlightDisplay, MouseMotionListener, MouseListener {
+public class AltosSiteMap extends JComponent implements AltosFlightDisplay, MouseMotionListener, MouseListener, HierarchyBoundsListener {
        // preferred vertical step in a tile in naut. miles
        // will actually choose a step size between x and 2x, where this
        // is 1.5x
@@ -74,7 +74,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                "terrain"
        };
 
-       static final String[] maptype_labels = {
+       public static final String[] maptype_labels = {
                "Hybrid",
                "Roadmap",
                "Satellite",
@@ -213,11 +213,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                tile.set_status(AltosSiteMapCache.loading);
                int status = AltosSiteMapCache.fetch_map(pngfile, pngurl);
                if (status == AltosSiteMapCache.success) {
-                       SwingUtilities.invokeLater(new Runnable() {
-                                       public void run() {
-                                               tile.load_map(pngfile);
-                                       }
-                               });
+                       if (SwingUtilities.isEventDispatchThread())
+                               tile.load_map(pngfile);
+                       else {
+                               SwingUtilities.invokeLater(new Runnable() {
+                                               public void run() {
+                                                       tile.load_map(pngfile);
+                                               }
+                                       });
+                       }
                } else {
                        tile.set_status(status);
                        System.out.printf("# Failed to fetch file %s (status %d)\n", pngfile, status);
@@ -236,7 +240,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                String  pngurl;
        }
 
-       public AltosSiteMapPrefetch prefetchMap(int x, int y) {
+       private AltosSiteMapPrefetch prefetchMap(int x, int y) {
                AltosSiteMapPrefetch    prefetch = new AltosSiteMapPrefetch();
                LatLng map_latlng = latlng(
                        -centre.x + x*px_size + px_size/2,
@@ -253,35 +257,43 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                return prefetch;
        }
 
-       public static void prefetchMaps(double lat, double lng) {
-               int w = AltosSiteMapPreload.width;
-               int h = AltosSiteMapPreload.height;
+       public static void prefetchMaps(double lat, double lng, int radius, int maptypes, int min_zoom, int max_zoom) {
                AltosSiteMap asm = new AltosSiteMap(true);
-               asm.centre = asm.getBaseLocation(lat, lng);
-
-               //Point2D.Double p = new Point2D.Double();
-               //Point2D.Double p2;
-               int dx = -w/2, dy = -h/2;
-               for (int y = dy; y < h+dy; y++) {
-                       for (int x = dx; x < w+dx; x++) {
-                               AltosSiteMapPrefetch prefetch = asm.prefetchMap(x, y);
-                               switch (prefetch.result) {
-                               case 1:
-                                       System.out.printf("Already have %s\n", prefetch.pngfile);
-                                       break;
-                               case 0:
-                                       System.out.printf("Fetched map %s\n", prefetch.pngfile);
-                                       break;
-                               case -1:
-                                       System.out.printf("# Failed to fetch file %s\n", prefetch.pngfile);
-                                       System.out.printf(" wget -O '%s' ''\n",
-                                                         prefetch.pngfile, prefetch.pngurl);
-                                       break;
+
+               for (int z = min_zoom; z <= max_zoom; z++) {
+                       asm.zoom = z;
+                       asm.set_radius(radius);
+                       asm.centre = asm.getBaseLocation(lat, lng);
+                       for (int t = maptype_hybrid; t <= maptype_terrain; t++) {
+                               if ((maptypes & (1 << t)) !=0) {
+                                       asm.maptype = t;
+                                       for (int y = -radius; y <= radius; y++) {
+                                               for (int x = -radius; x <= radius; x++) {
+                                                       AltosSiteMapPrefetch prefetch = asm.prefetchMap(x, y);
+                                                       switch (prefetch.result) {
+                                                       case 1:
+                                                               System.out.printf("Already have %s\n", prefetch.pngfile);
+                                                               break;
+                                                       case 0:
+                                                               System.out.printf("Fetched map %s\n", prefetch.pngfile);
+                                                               break;
+                                                       case -1:
+                                                               System.out.printf("# Failed to fetch file %s\n", prefetch.pngfile);
+                                                               System.out.printf(" wget -O '%s' ''\n",
+                                                                                 prefetch.pngfile, prefetch.pngurl);
+                                                               break;
+                                                       }
+                                               }
+                                       }
                                }
                        }
                }
        }
 
+       public static void prefetchMaps(double lat, double lon) {
+               prefetchMaps(lat, lon, 2, 1 << maptype_hybrid, 0, 0);
+       }
+
        public File init_map(Point offset, int load_mode) {
                AltosSiteMapTile tile = mapTiles.get(offset);
                Point2D.Double coord = tileCoordOffset(offset);
@@ -294,11 +306,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                return pngfile;
        }
 
-       public void initAndFinishMapAsync (final AltosSiteMapTile tile, final Point offset) {
+       private void initAndFinishMapAsync (final AltosSiteMapTile tile, final Point offset) {
                Thread thread = new Thread() {
                                public void run() {
                                        init_map(offset, load_mode_cached|load_mode_uncached);
-                                       finishTileLater(tile, offset);
+                                       SwingUtilities.invokeLater( new Runnable() {
+                                                       public void run() {
+                                                               addTileAt(tile, offset);
+                                                       }
+                                               } );
                                }
                        };
                thread.start();
@@ -312,11 +328,13 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                circle_set = false;
                points = new LinkedList<MapPoint>();
                line_start = line_end = null;
+               for (AltosSiteMapTile tile : mapTiles.values()) {
+                       tile.clearMap();
+                       tile.set_status(AltosSiteMapCache.loading);
+               }
        }
 
        public void setBaseLocation(double lat, double lng) {
-               for (AltosSiteMapTile tile : mapTiles.values())
-                       tile.clearMap();
                this.lat = lat;
                this.lon = lng;
                base_location_set = true;
@@ -328,6 +346,10 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
        private void initMaps(double lat, double lng) {
                setBaseLocation(lat, lng);
 
+               for (AltosSiteMapTile tile : mapTiles.values()) {
+                       tile.clearMap();
+                       tile.set_status(AltosSiteMapCache.loading);
+               }
                Thread thread = new Thread() {
                                public void run() {
                                        for (Point k : mapTiles.keySet())
@@ -361,15 +383,20 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                        format_string = "jpg";
                else
                        format_string = "png32";
-               return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s",
-                                    lat, lng, zoom, px_size, px_size, maptype_names[maptype], format_string);
+
+               if (AltosUIVersion.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",
+                                            lat, lng, zoom, px_size, px_size, maptype_names[maptype], format_string, AltosUIVersion.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",
+                                            lat, lng, zoom, px_size, px_size, maptype_names[maptype], format_string);
        }
 
        boolean initialised = false;
        MapPoint last_point = null;
        int last_state = -1;
 
-       public void show(double lat, double lon) {
+       private void show(double lat, double lon) {
                System.out.printf ("show %g %g\n", lat, lon);
                return;
 //             initMaps(lat, lon);
@@ -378,15 +405,17 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
 
        JLabel  zoom_label;
 
-       public void set_zoom_label() {
-               zoom_label.setText(String.format("- %d -", zoom - default_zoom));
+       private void set_zoom_label() {
+               zoom_label.setText(String.format("Zoom %d", zoom - default_zoom));
        }
 
        public void set_zoom(int zoom) {
                if (min_zoom <= zoom && zoom <= max_zoom) {
                        this.zoom = zoom;
-                       if (base_location_set)
+                       if (base_location_set) {
+                               set_tiles();
                                initMaps(lat, lon);
+                       }
                        redraw();
                        set_zoom_label();
                }
@@ -396,7 +425,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                return zoom;
        }
 
-       public void draw(MapPoint last_point, MapPoint point) {
+       public void set_maptype(int type) {
+               maptype = type;
+               maptype_combo.setSelectedIndex(type);
+               if (base_location_set)
+                       initMaps(lat, lon);
+               redraw();
+       }
+
+       private void draw(MapPoint last_point, MapPoint point) {
                boolean force_ensure = false;
                if (last_point == null) {
                        force_ensure = true;
@@ -436,7 +473,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                }
        }
 
-       public void redraw() {
+       private void redraw() {
                MapPoint        last_point = null;
 
                for (MapPoint point : points) {
@@ -524,15 +561,6 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                mapTiles.put(offset, tile);
                return tile;
        }
-       private void finishTileLater(final AltosSiteMapTile tile,
-                                    final Point offset)
-       {
-               SwingUtilities.invokeLater( new Runnable() {
-                       public void run() {
-                               addTileAt(tile, offset);
-                       }
-               } );
-       }
 
        private void ensureTilesAround(Point base_offset) {
                for (int x = -radius; x <= radius; x++) {
@@ -546,6 +574,32 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                }
        }
 
+       private void set_tiles() {
+               for (int x = -radius; x <= radius; x++) {
+                       for (int y = -radius; y <= radius; y++) {
+                               Point offset = new Point(x, y);
+                               if (mapTiles.containsKey(offset))
+                                       continue;
+                               AltosSiteMapTile t = createTile(offset);
+                               addTileAt(t, offset);
+                       }
+               }
+               for (Point offset : mapTiles.keySet()) {
+                       if (offset.x < -radius || offset.x > radius ||
+                           offset.y < -radius || offset.y > radius)
+                       {
+                               removeTileAt(offset);
+                       }
+               }
+       }
+
+       public void set_radius(int radius) {
+               if (radius != this.radius) {
+                       this.radius = radius;
+                       set_tiles();
+               }
+       }
+
        private Point topleft = new Point(0,0);
        private void scrollRocketToVisible(Point2D.Double pt) {
                Rectangle r = comp.getVisibleRect();
@@ -569,18 +623,11 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                        return;
                }
 
-               boolean review = false;
-               Rectangle r = comp.getVisibleRect();
-               if (offset.x < topleft.x) {
-                       r.x += (topleft.x - offset.x) * px_size;
+               if (offset.x < topleft.x)
                        topleft.x = offset.x;
-                       review = true;
-               }
-               if (offset.y < topleft.y) {
-                       r.y += (topleft.y - offset.y) * px_size;
+               if (offset.y < topleft.y)
                        topleft.y = offset.y;
-                       review = true;
-               }
+
                GridBagConstraints c = new GridBagConstraints();
                c.anchor = GridBagConstraints.CENTER;
                c.fill = GridBagConstraints.BOTH;
@@ -592,9 +639,6 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                layout.setConstraints(tile, c);
 
                comp.add(tile);
-//             if (review) {
-//                     comp.scrollRectToVisible(r);
-//             }
        }
 
        private AltosSiteMap(boolean knowWhatYouAreDoing) {
@@ -603,6 +647,21 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                }
        }
 
+       private void removeTileAt(Point offset) {
+               AltosSiteMapTile        tile = mapTiles.get(offset);
+
+               mapTiles.remove(offset);
+               comp.remove(tile);
+
+               topleft = new Point(MAX_TILE_DELTA, MAX_TILE_DELTA);
+               for (Point o : mapTiles.keySet()) {
+                       if (o.x < topleft.x)
+                               topleft.x = o.x;
+                       if (o.y < topleft.y)
+                               topleft.y = o.y;
+               }
+       }
+
        JComponent comp;
 
        private GridBagLayout layout = new GridBagLayout();
@@ -629,6 +688,16 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                }
        }
 
+       static void debug_component(Component who, String where) {
+/*
+               Rectangle       r = who.getBounds();
+               int             x = r.x / px_size;
+               int             y = r.y / px_size;
+
+               System.out.printf ("%3d, %3d: %s\n", x, y, where);
+*/
+       }
+
        LatLng latlng(MouseEvent e) {
                if (!base_location_set)
                        return null;
@@ -672,8 +741,28 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
        public void mouseReleased(MouseEvent e) {
        }
 
+       private void set_cache_size() {
+               Rectangle       r = comp.getVisibleRect();
+
+               int     width_tiles = (r.width + 2*px_size) / px_size;
+               int     height_tiles = (r.height + 2*px_size) / px_size;
+               int     tiles = width_tiles * height_tiles;
+               AltosSiteMapCache.set_cache_size(tiles);
+       }
+
+       /* HierarchyBoundsListener methods */
+       public void ancestorMoved(HierarchyEvent e) {
+               set_cache_size();
+       }
+
+       public void ancestorResized(HierarchyEvent e) {
+               set_cache_size();
+       }
+
        JScrollPane     pane = new JScrollPane();
 
+       JComboBox<String>       maptype_combo;
+
        public AltosSiteMap(int in_radius) {
                radius = in_radius;
 
@@ -681,18 +770,14 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
 
                comp.addMouseMotionListener(this);
                comp.addMouseListener(this);
+               comp.addHierarchyBoundsListener(this);
 
                GrabNDrag scroller = new GrabNDrag(comp);
 
                comp.setLayout(layout);
 
-               for (int x = -radius; x <= radius; x++) {
-                       for (int y = -radius; y <= radius; y++) {
-                               Point offset = new Point(x, y);
-                               AltosSiteMapTile t = createTile(offset);
-                               addTileAt(t, offset);
-                       }
-               }
+               set_tiles();
+
                pane.setViewportView(comp);
                pane.setPreferredSize(new Dimension(500,500));
                pane.setVisible(true);
@@ -774,7 +859,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay, Mous
                c.weighty = 0;
                add(zoom_out, c);
 
-               final JComboBox<String> maptype_combo = new JComboBox<String>(maptype_labels);
+               maptype_combo = new JComboBox<String>(maptype_labels);
 
                maptype_combo.setEditable(false);
                maptype_combo.setMaximumRowCount(maptype_combo.getItemCount());