/*********************************************************************************
* TotalCross Software Development Kit *
* Copyright (C) 2000-2012 SuperWaba Ltda. *
* All Rights Reserved *
* *
* This library and virtual machine is distributed in the hope that it will *
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
*********************************************************************************/
package totalcross.android;
import android.graphics.*;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.os.*;
import android.view.*;
import com.google.android.maps.*;
import java.util.*;
import totalcross.*;
public class MapViewer extends MapActivity
{
private int ilatMin=Integer.MAX_VALUE,ilatMax=Integer.MIN_VALUE;
private int ilonMin=Integer.MAX_VALUE,ilonMax=Integer.MIN_VALUE;
private int mRadius;
private void computeBounds(int ilat, int ilon)
{
if (ilat < ilatMin) ilatMin = ilat;
if (ilat > ilatMax) ilatMax = ilat;
if (ilon < ilonMin) ilonMin = ilon;
if (ilon > ilonMax) ilonMax = ilon;
}
private abstract class MapItem
{
public abstract void draw(Canvas canvas, Projection projection);
}
private class Circle extends MapItem
{
GeoPoint geo;
double rad;
boolean filled;
int color;
Circle(String s)
{
String[] ss = s.split(",");
int i = 1;
int lat = Integer.valueOf(ss[i++]);
int lon = Integer.valueOf(ss[i++]);
geo = new GeoPoint(lat,lon);
computeBounds(lat,lon);
rad = Double.valueOf(ss[i++]);
filled = ss[i++].equals("true");
color = Integer.valueOf(ss[i++]); if ((color & 0xFF000000) == 0) color |= 0xFF000000;
}
public void draw(Canvas canvas, Projection projection)
{
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(color);
paint.setStyle(filled ? Paint.Style.FILL_AND_STROKE : Paint.Style.STROKE);
RectF oval;
if (rad > 0) // in meters?
{
Point point = new Point();
projection.toPixels(geo, point);
float frad = projection.metersToEquatorPixels((float)rad);
oval = new RectF(point.x - frad, point.y - frad, point.x + frad, point.y + frad);
}
else // in coords delta
{
double r = -rad;
float la = fromCoord(geo.getLatitudeE6()), lo = fromCoord(geo.getLongitudeE6());
Point p1 = projection.toPixels(new GeoPoint(toCoord(la-r),toCoord(lo-r)), null);
Point p2 = projection.toPixels(new GeoPoint(toCoord(la+r),toCoord(lo+r)), null);
AndroidUtils.debug(p1+" - "+p2);
oval = new RectF(p1.x,p1.y,p2.x,p2.y);
}
canvas.drawOval(oval, paint);
}
}
private class Shape extends MapItem
{
GeoPoint []geos;
boolean filled;
int color;
Shape(String s)
{
String[] ss = s.split(",");
int i = 1;
int n = Integer.valueOf(ss[i++]);
geos = new GeoPoint[n];
for (int j = 0; j < n; j++)
{
int lat = Integer.valueOf(ss[i++]);
int lon = Integer.valueOf(ss[i++]);
geos[j] = new GeoPoint(lat,lon);
computeBounds(lat,lon);
}
filled = ss[i++].equals("true");
color = Integer.valueOf(ss[i++]); if ((color & 0xFF000000) == 0) color |= 0xFF000000;
}
public void draw(Canvas canvas, Projection projection)
{
Point point = new Point();
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(color);
paint.setStyle(filled ? Paint.Style.FILL_AND_STROKE : Paint.Style.STROKE);
Path path = new Path();
for (int i = 0; i < geos.length; i++)
{
projection.toPixels(geos[i], point);
if (i == 0)
path.moveTo(point.x, point.y); // used for first point
else
path.lineTo(point.x, point.y);
}
canvas.drawPath(path, paint);
}
}
private class Place extends MapItem
{
GeoPoint geo;
String caption, details[];
int backColor, capColor, detColor, pinColor;
int fontPerc;
Place(String s)
{
// *P*,"aaa","bbb",22.0,-22.1,0,1,2,3,150
String[] ss = s.split("\"");
caption = ss[1]; if (caption.equals("null")) caption = null;
details = ss[3].split("\n");
ss = ss[4].split(",");
int lat = Integer.valueOf(ss[1]);
int lon = Integer.valueOf(ss[2]);
geo = new GeoPoint(lat,lon);
computeBounds(lat,lon);
backColor= Integer.valueOf(ss[3]); if ((backColor & 0xFF000000) == 0) backColor |= 0xFF000000;
capColor = Integer.valueOf(ss[4]); if ((capColor & 0xFF000000) == 0) capColor |= 0xFF000000;
detColor = Integer.valueOf(ss[5]); if ((detColor & 0xFF000000) == 0) detColor |= 0xFF000000;
pinColor = Integer.valueOf(ss[6]); if ((pinColor & 0xFF000000) == 0) pinColor |= 0xFF000000;
fontPerc = Integer.valueOf(ss[7]);
}
private void drawBaloon(Canvas canvas, Projection projection) // above
{
Paint paint2= new Paint();
float frad = mRadius * fontPerc / 100;//projection.metersToEquatorPixels((float)mRadius);
Point point = new Point();
projection.toPixels(geo, point);
point.y -= frad * 4; // shift above pin
float textH = frad*2;
paint2.setTextSize(textH); //set text size
// compute max text width
FontMetrics fm = new FontMetrics();
paint2.setTextAlign(Paint.Align.CENTER);
paint2.getFontMetrics(fm);
paint2.setFakeBoldText(true);
boolean hasCap = caption != null;
float ww = hasCap ? paint2.measureText(caption) : 0;
paint2.setFakeBoldText(false);
for (int i = 0; i < details.length; i++)
ww = Math.max(ww, paint2.measureText(details[i]));
float yy = point.y - frad*2*((hasCap?1:0)+details.length+1)-frad;
ww += textH; // give some extra space
// draw baloon
//canvas.drawRect(point.x - ww/2, yy, point.x + ww/2, point.y-frad, mpaint);
Paint mpaint= new Paint();
mpaint.setStyle(Style.FILL);
Path path = new Path();
path.addRoundRect(new RectF(point.x - ww/2, yy, point.x + ww/2, point.y-frad-frad), textH/2,textH/2, Path.Direction.CCW);
path.moveTo(point.x-frad,point.y-frad-frad);
path.lineTo(point.x,point.y-frad/2);
path.lineTo(point.x+frad,point.y-frad-frad);
float delta = frad/4;
mpaint.setColor(darker(backColor));
path.offset(delta,delta);
canvas.drawPath(path, mpaint);
mpaint.setColor(backColor);
path.offset(-delta,-delta);
canvas.drawPath(path, mpaint);
// draw text
yy += textH; // text's anchor is at bottom
if (hasCap)
{
paint2.setFakeBoldText(true);
paint2.setColor(capColor);
canvas.drawText(caption, point.x, yy, paint2); // title
yy += textH;
}
paint2.setFakeBoldText(false);
paint2.setColor(detColor);
for (int i = 0; i < details.length; i++, yy += textH)
canvas.drawText(details[i], point.x, yy, paint2);
}
private int darker(int c)
{
int a = (c >> 24) & 0xFF;
int r = (c >> 16) & 0xFF;
int g = (c >> 8) & 0xFF;
int b = c & 0xFF;
r -= 64; if (r < 0) r = 0;
g -= 64; if (g < 0) g = 0;
b -= 64; if (b < 0) b = 0;
return (a << 24) | (r << 16) | (g << 8) | b;
}
private void drawPin(Canvas canvas, Projection projection) // below
{
Paint paint = new Paint();
paint.setAntiAlias(true);
float frad = mRadius * fontPerc / 100;//projection.metersToEquatorPixels((float)mRadius);
Point point = new Point();
projection.toPixels(geo, point);
point.y -= frad * 3;
paint.setColor(pinColor);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
Path path = new Path();
RectF oval = new RectF(point.x - frad, point.y - frad, point.x + frad, point.y + frad);
path.addArc(oval, 150,240);
path.lineTo(point.x,point.y+frad*3);
canvas.drawPath(path, paint);
}
public void draw(Canvas canvas, Projection projection)
{
drawPin(canvas,projection);
drawBaloon(canvas,projection);
}
}
public MapItem[] getItems(String s0)
{
String[] ss = s0.split("\\|");
MapItem[] items = new MapItem[ss.length];
for (int i = 0; i < ss.length; i++)
{
String s = ss[i];
if (s.startsWith("*S*"))
items[i] = new Shape(s);
else
if (s.startsWith("*C*"))
items[i] = new Circle(s);
else
if (s.startsWith("*P*"))
items[i] = new Place(s);
}
return items;
}
/** Called when the activity is first created. */
private class MyOverLay extends Overlay
{
private GeoPoint gp1;
public MyOverLay(GeoPoint gp1) // GeoPoint is a int. (6E)
{
this.gp1 = gp1;
}
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when)
{
Projection projection = mapView.getProjection();
if (!shadow)
{
Paint paint = new Paint();
paint.setAntiAlias(true);
Point point = new Point();
projection.toPixels(gp1, point);
paint.setColor(Color.BLUE);
RectF oval = new RectF(point.x - mRadius, point.y - mRadius, point.x + mRadius, point.y + mRadius);
canvas.drawOval(oval, paint);
}
return super.draw(canvas, mapView, shadow, when);
}
}
private class MyItemsOverLay extends Overlay
{
MapItem[] items;
public MyItemsOverLay(MapItem[] items) // GeoPoint is a int. (6E)
{
this.items = items;
}
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when)
{
Projection projection = mapView.getProjection();
if (!shadow)
{
for (int i = 0; i < items.length; i++)
items[i].draw(canvas, projection);
}
return super.draw(canvas, mapView, shadow, when);
}
}
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setup the viewe
MapView mapview = new MapView(this,"0FcAyehwXTAXpaMaXoVn7kGJVJdRSuSI2RsqELQ");
mapview.setBuiltInZoomControls(true);
mapview.setClickable(true);
mapview.setStreetView(true);
setContentView(mapview);
if (Loader.isFullScreen)
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
// get passed parameters
Bundle extras = getIntent().getExtras();
mapview.setSatellite(extras.getBoolean("sat"));
mRadius = Launcher4A.deviceFontHeight/2;
List<Overlay> overs = mapview.getOverlays();
String items = extras.getString("items");
if (items != null)
overs.add(new MyItemsOverLay(getItems(items)));
else
{
double lat = extras.getDouble("lat");
double lon = extras.getDouble("lon");
int ilat = toCoord(lat);
int ilon = toCoord(lon);
computeBounds(ilat,ilon);
overs.add(new MyOverLay(new GeoPoint(ilat,ilon)));
}
// move the map to the given point
MapController mc = mapview.getController();
int clat = (ilatMin + ilatMax) / 2;
int clon = (ilonMin + ilonMax) / 2;
mc.setCenter(new GeoPoint(clat,clon));
if (ilatMax == ilatMin || ilonMax == ilonMin)
mc.setZoom(21);
else
mc.zoomToSpan(ilatMax-ilatMin,ilonMax-ilonMin);
}
private static int toCoord(double v)
{
return (int)(v * 1e6);
}
private static float fromCoord(int i)
{
return (float)i / 1e6f;
}
protected boolean isRouteDisplayed()
{
return false;
}
}