d921fd1023bc5d8653cd43ad63a9c6d39f7ae2b7
[fw/altos] / altoslib / AltosMapTile.java
1 /*
2  * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 package org.altusmetrum.altoslib_10;
19
20 import java.io.*;
21 import java.util.*;
22
23 public class AltosMapTile implements AltosFontListener, AltosMapStoreListener {
24         LinkedList<AltosMapTileListener>        listeners = new LinkedList<AltosMapTileListener>();
25         public AltosLatLon      upper_left, center;
26         public int              px_size;
27         int             zoom;
28         int             maptype;
29         int             scale;
30         private AltosMapCache   cache;
31         public AltosMapStore    store;
32         public int      status;
33
34         static public final int loaded = 0;     /* loaded from file */
35         static public final int fetched = 1;    /* downloaded to file */
36         static public final int fetching = 2;   /* downloading from net */
37         static public final int failed = 3;     /* loading from file failed */
38         static public final int bad_request = 4;/* downloading failed */
39         static public final int forbidden = 5;  /* downloading failed */
40
41         private File map_file() {
42                 double lat = center.lat;
43                 double lon = center.lon;
44                 char chlat = lat < 0 ? 'S' : 'N';
45                 char chlon = lon < 0 ? 'W' : 'E';
46
47                 if (lat < 0) lat = -lat;
48                 if (lon < 0) lon = -lon;
49                 String maptype_string = String.format("%s-", AltosMap.maptype_names[maptype]);
50                 String format_string;
51                 if (maptype == AltosMap.maptype_hybrid || maptype == AltosMap.maptype_satellite || maptype == AltosMap.maptype_terrain)
52                         format_string = "jpg";
53                 else
54                         format_string = "png";
55                 return new File(AltosPreferences.mapdir(),
56                                 String.format("map-%c%.6f,%c%.6f-%s%d%s.%s",
57                                               chlat, lat, chlon, lon, maptype_string, zoom, scale == 1 ? "" : String.format("-%d", scale), format_string));
58         }
59
60         private String map_url() {
61                 String format_string;
62                 int z = zoom;
63
64                 if (maptype == AltosMap.maptype_hybrid || maptype == AltosMap.maptype_satellite || maptype == AltosMap.maptype_terrain)
65                         format_string = "jpg";
66                 else
67                         format_string = "png32";
68
69                 for (int s = 1; s < scale; s <<= 1)
70                         z--;
71
72                 if (AltosVersion.has_google_maps_api_key())
73                         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",
74                                              center.lat, center.lon, z, px_size/scale, px_size/scale, scale, AltosMap.maptype_names[maptype], format_string, AltosVersion.google_maps_api_key);
75                 else
76                         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",
77                                              center.lat, center.lon, z, px_size/scale, px_size/scale, AltosMap.maptype_names[maptype], format_string);
78         }
79
80         public void font_size_changed(int font_size) {
81         }
82
83         private synchronized void notify_listeners(int status) {
84                 this.status = status;
85                 for (AltosMapTileListener listener : listeners)
86                         listener.notify_tile(this, status);
87         }
88
89         public void notify_store(AltosMapStore store, int status) {
90                 notify_listeners(status);
91         }
92
93         public void notify_image(AltosImage image) {
94                 if (image == null)
95                         status = failed;
96                 else
97                         status = loaded;
98                 notify_listeners(status);
99         }
100
101         public void paint(AltosMapTransform t) {
102         }
103
104         public AltosImage get_image() {
105                 if (cache == null)
106                         return null;
107                 return cache.get(this);
108         }
109
110         public synchronized void add_listener(AltosMapTileListener listener) {
111                 if (!listeners.contains(listener))
112                         listeners.add(listener);
113                 listener.notify_tile(this, status);
114         }
115
116         public synchronized void remove_listener(AltosMapTileListener listener) {
117                 listeners.remove(listener);
118         }
119
120         public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
121                 this.cache = cache;
122                 this.upper_left = upper_left;
123
124                 while (center.lon < -180.0)
125                         center.lon += 360.0;
126                 while (center.lon > 180.0)
127                         center.lon -= 360.0;
128
129                 this.center = center;
130                 this.zoom = zoom;
131                 this.maptype = maptype;
132                 this.px_size = px_size;
133                 this.scale = scale;
134
135                 store = AltosMapStore.get(map_url(), map_file());
136                 store.add_listener(this);
137         }
138
139         public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
140                 this(cache, upper_left, center, zoom, maptype, px_size, 1);
141         }
142 }