2 * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
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.
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.
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.
18 package org.altusmetrum.altosuilib_3;
21 import java.awt.image.*;
23 import javax.imageio.*;
24 import java.awt.geom.*;
27 import java.awt.RenderingHints.*;
28 import org.altusmetrum.altoslib_5.*;
30 public class AltosUIMapTile {
31 AltosUIMapTileListener listener;
32 AltosUILatLon upper_left, center;
36 AltosUIMapStore store;
37 AltosUIMapCache cache;
40 private File map_file() {
41 double lat = center.lat;
42 double lon = center.lon;
43 char chlat = lat < 0 ? 'S' : 'N';
44 char chlon = lon < 0 ? 'W' : 'E';
46 if (lat < 0) lat = -lat;
47 if (lon < 0) lon = -lon;
48 String maptype_string = String.format("%s-", AltosUIMap.maptype_names[maptype]);
50 if (maptype == AltosUIMap.maptype_hybrid || maptype == AltosUIMap.maptype_satellite || maptype == AltosUIMap.maptype_terrain)
51 format_string = "jpg";
53 format_string = "png";
54 return new File(AltosUIPreferences.mapdir(),
55 String.format("map-%c%.6f,%c%.6f-%s%d.%s",
56 chlat, lat, chlon, lon, maptype_string, zoom, format_string));
59 private String map_url() {
61 if (maptype == AltosUIMap.maptype_hybrid || maptype == AltosUIMap.maptype_satellite || maptype == AltosUIMap.maptype_terrain)
62 format_string = "jpg";
64 format_string = "png32";
66 if (AltosUIVersion.has_google_maps_api_key())
67 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",
68 center.lat, center.lon, zoom, px_size, px_size, AltosUIMap.maptype_names[maptype], format_string, AltosUIVersion.google_maps_api_key);
70 return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=%s&format=%s",
71 center.lat, center.lon, zoom, px_size, px_size, AltosUIMap.maptype_names[maptype], format_string);
73 private Font font = null;
75 public void set_font(Font font) {
84 public void paint_graphics(Graphics2D g2d, AltosUIMapTransform t, int serial) {
85 if (serial < painted_serial)
88 Point2D.Double point_double = t.screen(upper_left);
89 Point point = new Point((int) (point_double.x + 0.5),
90 (int) (point_double.y + 0.5));
92 painted_serial = serial;
94 if (!g2d.hitClip(point.x, point.y, px_size, px_size))
98 g2d.drawImage(image, point.x, point.y, null);
101 g2d.setColor(Color.GRAY);
102 g2d.fillRect(point.x, point.y, px_size, px_size);
104 if (t.has_location()) {
105 String message = null;
107 case AltosUIMapCache.loading:
108 message = "Loading...";
110 case AltosUIMapCache.bad_request:
111 message = "Internal error";
113 case AltosUIMapCache.failed:
114 message = "Network error, check connection";
116 case AltosUIMapCache.forbidden:
117 message = "Too many requests, try later";
120 if (message != null && font != null) {
122 g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
123 Rectangle2D bounds = font.getStringBounds(message, g2d.getFontRenderContext());
125 float x = px_size / 2.0f;
126 float y = px_size / 2.0f;
127 x = x - (float) bounds.getWidth() / 2.0f;
128 y = y + (float) bounds.getHeight() / 2.0f;
129 g2d.setColor(Color.BLACK);
130 g2d.drawString(message, (float) point_double.x + x, (float) point_double.y + y);
136 public void set_status(int status) {
137 this.status = status;
138 listener.notify_tile(this, status);
141 public void notify_image(Image image) {
142 listener.notify_tile(this, status);
145 public void paint(Graphics g, AltosUIMapTransform t) {
146 Graphics2D g2d = (Graphics2D) g;
147 boolean queued = false;
149 Point2D.Double point = t.screen(upper_left);
151 if (!g.hitClip((int) (point.x + 0.5), (int) (point.y + 0.5), px_size, px_size))
156 if (image == null && t.has_location())
157 image = cache.get(this, store, px_size, px_size);
159 paint_graphics(g2d, t, painting_serial);
162 public int store_status() {
163 return store.status();
166 public void add_store_listener(AltosUIMapStoreListener listener) {
167 store.add_listener(listener);
170 public void remove_store_listener(AltosUIMapStoreListener listener) {
171 store.remove_listener(listener);
174 public AltosUIMapTile(AltosUIMapTileListener listener, AltosUILatLon upper_left, AltosUILatLon center, int zoom, int maptype, int px_size, Font font) {
175 this.listener = listener;
176 this.upper_left = upper_left;
177 cache = listener.cache();
179 while (center.lon < -180.0)
181 while (center.lon > 180.0)
184 this.center = center;
186 this.maptype = maptype;
187 this.px_size = px_size;
189 status = AltosUIMapCache.loading;
190 store = AltosUIMapStore.get(map_url(), map_file());