package gpslogger;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.net.MalformedURLException;
import java.net.URL;
import java.awt.Toolkit;
public class GoogleTileCanvas extends ImageCanvas {
static final int TILE_SIZE = 256;
static final int FRAME_WIDTH = 308;
static final int FRAME_HEIGHT = 210;
private Graphics g;
private boolean fetcherror;
private int x;
private int y;
private int heading;
private Toolkit tk;
private Image tiles[][] = new Image[3][3];
public GoogleTileCanvas() {
//System.err.println("GoogleTileCanvas: GoogleTileCanvas: Constructor called");
this.x = FRAME_WIDTH/2;
this.y = FRAME_HEIGHT/2;
this.heading = 0;
tk = Toolkit.getDefaultToolkit();
fetcherror = false;
}
/**
* Overloads setImage in ImageCanvas to accept a GoogleTile object instead
* of an Image. a GoogleTile object has enough information in it to infer the
* positions of other tiles, so a full-frame map can be constructed. Calls repaint()
* before returning so image updates are always immediate.
*
* @param centerTile a GoogleTile object to construct the map around (GPS position is always centered)
*/
public void setImage(GoogleTile centerTile) {
Point centerTilePixelOffset = GoogleTileUtils.getPixelOffsetInTile(centerTile.getTileLatLong().getX(),
centerTile.getTileLatLong().getY(), centerTile.getZoom());
Point centerTileCoord = GoogleTileUtils.toTileXY(centerTile.getTileLatLong().getX(),
centerTile.getTileLatLong().getY(), centerTile.getZoom());
this.x = centerTilePixelOffset.x;
this.y = centerTilePixelOffset.y;
try {
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
tiles[i][j] = tk.getImage(new URL(GoogleTileURL.url(centerTileCoord.x+(i-1), centerTileCoord.y+(j-1), centerTile.getZoom())));
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
this.repaint();
}
/**
* constructs the final display image out of the tiles in the buffer
*/
private void buildImage() {
//System.err.println("GoogleTileCanvas: buildImage: starting");
g = image.getGraphics();
// build up our image for display here
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
g.drawImage(tiles[i][j], TILE_SIZE*i, TILE_SIZE*j, this);
}
}
g.dispose();
}
/**
* Renders and displays the image
*/
public void paint(Graphics gc) {
//System.err.println("GoogleTileCanvas: paint: starting");
if (image == null) {
image = createImage(FRAME_WIDTH*3, FRAME_HEIGHT*3);
}
if ((image != null) && (fetcherror != true)) {
buildImage();
gc.drawImage(image, (FRAME_WIDTH/2)-x-TILE_SIZE, (FRAME_HEIGHT/2)-y-TILE_SIZE, null);
// gc.drawString("X", FRAME_WIDTH/2, FRAME_HEIGHT/2);
gc.setColor(java.awt.Color.red);
gc.fillArc(FRAME_WIDTH/2 - 15, FRAME_HEIGHT/2 - 15, 30, 30, (heading + 180)-22, 44);
}
if (fetcherror == true) {
gc.drawString("Error loading images", 0, 10);
}
}
public void setHeading(int heading) {
this.heading = heading;
this.heading -= 90;
if (this.heading < 0)
this.heading += 360;
this.heading = 360 - this.heading;
}
/** imageUpdate gets called when the status of an image we've expressed interest in
* changes. When an image is image is finished, repaint gets called to render
* and display it. This is the "poor man's" way to make sure each image has finished
* loading before attempting to display. Check out java.awt.MediaTracker for
* a better way.
*/
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
if ((infoflags & ERROR) != 0) {
System.err.println("GoogleTileCanvas: imageUpdate: Error loading image " + img.toString());
fetcherror = true;
}
if ((infoflags & ALLBITS) != 0) {
System.err.println("GoogleTileCanvas: imageUpdate: Finished loading image " + img.toString());
}
boolean done = ((infoflags & (ALLBITS | ERROR)) != 0);
if (done)
this.repaint(0);
return !done;
}
}