altosuilib: Add google maps API key, configured with -with-google-key
[fw/altos] / altosuilib / AltosSiteMap.java
index f4143fe2433d84fbdcfeb072daee35f19772381e..d9ea564ce1c6dde2d34e510009f8920cddba6856 100644 (file)
@@ -22,7 +22,7 @@ import java.awt.event.*;
 import javax.swing.*;
 import java.io.*;
 import java.lang.Math;
-import java.awt.geom.Point2D;
+import java.awt.geom.*;
 import java.util.*;
 import java.util.concurrent.*;
 import org.altusmetrum.altoslib_4.*;
@@ -50,7 +50,7 @@ class MapPoint {
        }
 }
 
-public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
+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
@@ -160,6 +160,10 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
        }
        */
 
+       private LatLng latlng(Point pt) {
+               return latlng(new Point2D.Double(pt.x, pt.y), scale_x, scale_y);
+       }
+
        ConcurrentHashMap<Point,AltosSiteMapTile> mapTiles = new ConcurrentHashMap<Point,AltosSiteMapTile>();
        Point2D.Double centre;
 
@@ -209,11 +213,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
                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);
@@ -255,8 +263,6 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
                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++) {
@@ -294,7 +300,11 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
                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();
@@ -307,16 +317,13 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
                base_location_set = false;
                circle_set = false;
                points = new LinkedList<MapPoint>();
-               for (AltosSiteMapTile tile : mapTiles.values())
-                       tile.clearMap();
+               line_start = line_end = null;
        }
 
        public void setBaseLocation(double lat, double lng) {
                this.lat = lat;
                this.lon = lng;
                base_location_set = true;
-               for (AltosSiteMapTile tile : mapTiles.values())
-                       tile.clearMap();
 
                centre = getBaseLocation(lat, lng);
                scrollRocketToVisible(pt(lat,lng));
@@ -325,6 +332,10 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
        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())
@@ -358,8 +369,13 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
                        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;
@@ -376,7 +392,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
        JLabel  zoom_label;
 
        public void set_zoom_label() {
-               zoom_label.setText(String.format("- %d -", zoom - default_zoom));
+               zoom_label.setText(String.format("Zoom %d", zoom - default_zoom));
        }
 
        public void set_zoom(int zoom) {
@@ -442,6 +458,8 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
                }
                if (circle_set)
                        draw_circle(circle_lat, circle_lon);
+               if (line_start != null)
+                       set_line();
        }
 
        public void show(final AltosState state, final AltosListenerState listener_state) {
@@ -519,15 +537,6 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
                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++) {
@@ -598,14 +607,112 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay {
                }
        }
 
-       JComponent comp = new JComponent() { };
+       JComponent comp;
+
        private GridBagLayout layout = new GridBagLayout();
 
+       LatLng  line_start, line_end;
+
+       private void set_line() {
+               if (line_start != null && line_end != null) {
+                       Point2D.Double  start = pt(line_start.lat, line_start.lng);
+                       Point2D.Double  end = pt(line_end.lat, line_end.lng);
+                       AltosGreatCircle        g = new AltosGreatCircle(line_start.lat, line_start.lng,
+                                                                        line_end.lat, line_end.lng);
+
+                       for (Point offset : mapTiles.keySet()) {
+                               AltosSiteMapTile tile = mapTiles.get(offset);
+                               Point2D.Double s, e;
+                               s = translatePoint(start, tileCoordOffset(offset));
+                               e = translatePoint(end, tileCoordOffset(offset));
+                               tile.set_line(new Line2D.Double(s.x, s.y, e.x, e.y), g.distance);
+                       }
+               } else {
+                       for (AltosSiteMapTile tile : mapTiles.values())
+                               tile.set_line(null, 0);
+               }
+       }
+
+       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;
+
+               Rectangle       zerozero = mapTiles.get(new Point(0, 0)).getBounds();
+
+               return latlng(-centre.x + e.getPoint().x - zerozero.x, -centre.y + e.getPoint().y - zerozero.y);
+       }
+
+       /* MouseMotionListener methods */
+       public void mouseDragged(MouseEvent e) {
+               if (!GrabNDrag.grab_n_drag(e)) {
+                       LatLng  loc = latlng(e);
+                       line_end = loc;
+                       set_line();
+               }
+       }
+
+       public void mouseMoved(MouseEvent e) {
+       }
+
+       /* MouseListener methods */
+       public void mouseClicked(MouseEvent e) {
+       }
+
+       public void mouseEntered(MouseEvent e) {
+       }
+
+       public void mouseExited(MouseEvent e) {
+       }
+
+       public void mousePressed(MouseEvent e) {
+               if (!GrabNDrag.grab_n_drag(e)) {
+                       LatLng  loc = latlng(e);
+                       line_start = loc;
+                       line_end = null;
+                       set_line();
+               }
+       }
+
+       public void mouseReleased(MouseEvent e) {
+       }
+
+       public 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();
 
        public AltosSiteMap(int in_radius) {
                radius = in_radius;
 
+               comp = new JComponent() { };
+
+               comp.addMouseMotionListener(this);
+               comp.addMouseListener(this);
+               comp.addHierarchyBoundsListener(this);
+
                GrabNDrag scroller = new GrabNDrag(comp);
 
                comp.setLayout(layout);