package com.algobase.share.maps; import java.lang.Runnable; import java.io.File; import java.util.Timer; import java.util.TimerTask; import java.util.List; import android.os.Handler; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.Gravity; import android.view.MotionEvent; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.Toast; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Color; import android.location.Location; import com.google.android.maps.MapView; import com.google.android.maps.Overlay; import com.google.android.maps.GeoPoint; import com.google.android.maps.Projection; public class GMapView extends ViewGroup implements IMapView { public void setTitle(String txt) {} public void setText(String txt) {} class GMapOverlay extends Overlay { IMapOverlay mapOverlay; MapView mapView; GMapOverlay(MapView mv, IMapOverlay overlay) { mapView = mv; mapOverlay = overlay; } @Override public void draw(Canvas canvas, MapView mv, boolean shadow) { super.draw(canvas,mv,shadow); mapOverlay.draw(canvas,shadow); } } public boolean touchEventHandler(MotionEvent event) { return false; } private Context context; private MapView mapView; private String tileSource = "Google"; private String tileURL = "Google"; private float rotation = 0; private float heading = 0; private Handler handler = new Handler(); private Matrix rotationMatrix = new Matrix(); private Timer timer = new Timer(); private Runnable animFinish = null; private void init(Context ctxt, String apiKey) { context = ctxt; mapView = new MapView(ctxt, apiKey) { @Override public boolean onTouchEvent(MotionEvent event) { if (touchEventHandler(event)) return true; return super.onTouchEvent(event); } }; setBackgroundColor(Color.rgb(180,180,180)); mapView.setClickable(true); mapView.setSatellite(false); /* mapView.setBuiltInZoomControls(true); */ addView(mapView); } public GMapView(Context ctxt, String apiKey) { super(ctxt); init(ctxt,apiKey); } /* public GMapView(Context ctxt) { super(ctxt); context = ctxt; } public GMapView(Context ctxt, AttributeSet attrs) { super(ctxt, attrs); context = ctxt; } public GMapView(Context ctxt, AttributeSet attrs, int defStyle) { super(ctxt, attrs, defStyle); context = ctxt; } */ void showToast(final String txt) { handler.post(new Runnable() { public void run() { Toast.makeText(context,txt, Toast.LENGTH_SHORT).show(); } }); } @Override public void setHeading(float h) { heading = h; } @Override public float getHeading() { return heading; } @Override public void setAnimFinish(Runnable r) { animFinish = r; } @Override public void setRotation(float phi) { rotation = phi; rotationMatrix.setRotate(phi,getWidth()/2,getHeight()/2); invalidate(); } @Override public float getRotation() { return rotation; } @Override public void setRotationAnim(float phi) { phi = phi % 360.0f; //if (heading_delta == 0) return; synchronized (this) { float delta = phi - rotation; //if (Math.abs(delta) < heading_delta) return; rotation = phi; rotationMatrix.setRotate(phi,getWidth()/2,getHeight()/2); float target = 0; if (delta > +180) target = 360; if (delta < -180) target = -360; Animation anim = new RotateAnimation(delta,target, Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF,0.5f); long duration = Math.abs((long)(8000*delta/360)); if (duration > 2000) duration = 2000; anim.setDuration(duration); View view = (getChildCount() > 0) ? getChildAt(0) : this; view.setAnimation(anim); //mapView.setAnimation(anim); invalidate(); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int width = getWidth(); final int height = getHeight(); final int count = getChildCount(); for (int i = 0; i < count; i++) { View view = getChildAt(i); int child_width = view.getMeasuredWidth(); int child_height = view.getMeasuredHeight(); int child_left = (width - child_width) / 2; int child_top = (height - child_height) / 2; view.layout(child_left, child_top, child_left + child_width, child_top + child_height); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int w = getMeasuredWidth(); int h = getMeasuredHeight(); WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); int wmax = wm.getDefaultDisplay().getWidth(); int hmax = wm.getDefaultDisplay().getHeight(); if (w > wmax || h > hmax) Log.v("sTracks",String.format("onMeasure: w = %d h = %d",w,h)); if (w > wmax) w = wmax; if (h > hmax) h = hmax; int d = (int)Math.hypot(w,h); int sizeSpec = MeasureSpec.makeMeasureSpec(d,MeasureSpec.EXACTLY); for (int i = 0; i < getChildCount(); i++) getChildAt(i).measure(sizeSpec, sizeSpec); } @Override public boolean dispatchTouchEvent(MotionEvent event) { float[] vec = { event.getX(), event.getY() }; rotationMatrix.mapPoints(vec); event.setLocation(vec[0], vec[1]); return super.dispatchTouchEvent(event); } @Override protected void dispatchDraw(Canvas canvas) { canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.rotate(-rotation, getWidth()/2, getHeight()/2); super.dispatchDraw(canvas); canvas.restore(); } public String getTileSource() { return tileSource; } public String getTileURL() { return tileURL; } public View getView() { return this; } public void setUseDataConnection(boolean b) {} public void setTileSource(String src) {} public void setMapDirectory(File dir) {} public void setOverlay(IMapOverlay overlay) { mapView.getOverlays().clear(); if (overlay != null) mapView.getOverlays().add(new GMapOverlay(mapView,overlay)); mapView.invalidate(); } public void getCenter(double coord[]) { GeoPoint p = (GeoPoint)mapView.getMapCenter(); coord[0] = p.getLatitudeE6()/1E6; coord[1] = p.getLongitudeE6()/1E6; } public void setZoomFactor(float f) {} public void setZoom(int z) { if (z < 2) z = 2; if (z == getZoomLevel() + 1) mapView.getController().zoomIn(); else if (z == getZoomLevel() - 1) mapView.getController().zoomOut(); else mapView.getController().setZoom(z); setText(tileSource + " " + getZoomLevel()); } public void setZoom0(int z) { if (z < 2) z = 2; mapView.getController().setZoom(z); setText(tileSource + " " + z); } public void setZoomLevel(int z) { setZoom0(z); } public void animToZoomLevel(int z) { } public void zoomIn() { mapView.getController().zoomIn(); //mapView.getController().setZoom(getZoomLevel()+1); setText(tileSource + " " + getZoomLevel()); } public void zoomOut() { mapView.getController().zoomOut(); //mapView.getController().setZoom(getZoomLevel()-1); setText(tileSource + " " + getZoomLevel()); } public int getMapWidth() { return mapView.getWidth(); } public int getMapHeight() { return mapView.getHeight(); } public int getZoomLevel() { return mapView.getZoomLevel(); } public void zoomToSpan(double lat_span, double lon_span) { if (lat_span < 0.005) lat_span = 0.005; if (lon_span < 0.005) lon_span = 0.005; mapView.getController().zoomToSpan((int)(1E6*lat_span), (int)(1E6*lon_span)); setText(tileSource + " " + getZoomLevel()); } public void zoomToFit(double lat_min, double lon_min, double lat_max, double lon_max) { double lat = (lat_min + lat_max)/2; double lon = (lon_min + lon_max)/2; //animateTo(lat,lon,-1); animateTo(lat,lon,-1,0); zoomToSpan(lat_max-lat_min,lon_max-lon_min); } public void setCenter(double lat, double lon) { GeoPoint gp = new GeoPoint((int)(1E6*lat),(int)(1E6*lon)); mapView.getController().setCenter(gp); } public void setCenter(Location loc) { if (loc != null) setCenter(loc.getLatitude(), loc.getLongitude()); } public void animateTo(double lat, double lon, int z, float heading) { if (z == -1) z = getZoomLevel(); int zoom_d = z - getZoomLevel(); GeoPoint gp = new GeoPoint((int)(1E6*lat),(int)(1E6*lon)); Runnable runnable = animFinish; animFinish = null; mapView.getController().animateTo(gp,runnable); if (heading != rotation) { if (heading > +180) heading -=360; if (heading < -180) heading +=360; setRotationAnim(heading); } setZoom(getZoomLevel()+zoom_d); } public void animateTo(double lat, double lon, int z) { animateTo(lat,lon,z,rotation); } public void animateTo(double lat, double lon) { animateTo(lat,lon,-1); } public void animateTo(Location loc, int z, float heading) { animateTo(loc.getLatitude(), loc.getLongitude(),z,heading); } public void animateTo(Location loc, int z) { animateTo(loc,z,rotation); } public void animateTo(Location loc) { animateTo(loc,-1); } public boolean isSatellite() { return mapView.isSatellite(); } public void setSatellite(boolean b) { mapView.setSatellite(b); } public boolean isStreetView() { return mapView.isStreetView(); } public void setStreetView(boolean b) { mapView.setStreetView(b); } public boolean isTraffic() { return mapView.isTraffic(); } public void setTraffic(boolean b) { mapView.setTraffic(b); } public int getMaxZoomLevel() { return mapView.getMaxZoomLevel(); } public void windowCoords(double[] lat, double[] lon) { int width = mapView.getWidth(); int height = mapView.getHeight(); Projection proj = mapView.getProjection(); GeoPoint top_left = (GeoPoint)proj.fromPixels(0,0); GeoPoint bot_right = (GeoPoint)proj.fromPixels(width-1,height-1); lon[0] = top_left.getLongitudeE6()/1E6; lon[1] = bot_right.getLongitudeE6()/1E6; lat[0] = bot_right.getLatitudeE6()/1E6; lat[1] = top_left.getLatitudeE6()/1E6; } public void toPixels(double lat, double lon, Point p) { mapView.getProjection().toPixels(new GeoPoint((int)(1E6*lat),(int)(1E6*lon)), p); } public void toPixels(Location loc, Point p) { if (loc != null) toPixels(loc.getLatitude(), loc.getLongitude(),p); } public Location fromPixels(int x, int y) { GeoPoint pos = (GeoPoint)mapView.getProjection().fromPixels(x,y); double lat = pos.getLatitudeE6()/1E6; double lon = pos.getLongitudeE6()/1E6; Location loc = new Location("map"); loc.setLatitude(lat); loc.setLongitude(lon); return loc; } public float metersToEquatorPixels(float meter) { return mapView.getProjection().metersToEquatorPixels(meter); } public void invalidate() { mapView.invalidate(); } public void postInvalidate() { mapView.postInvalidate(); } // not implemented public void drawTiles() {} public void downloadTiles(int level, int num) {} public long numberOfTiles() { return 0; } public long numberOfTiles(int minLevel, int maxLevel) { return 0; } public long numberOfExistingTiles() { return 0; } public long numberOfExistingTiles(int minLevel, int maxLevel) { return 0; } }