1 package net.kazhik.android.tokyorunners;
\r
3 import java.util.ArrayList;
\r
4 import java.util.Iterator;
\r
5 import java.util.List;
\r
7 import android.app.AlertDialog;
\r
8 import android.app.Dialog;
\r
9 import android.content.BroadcastReceiver;
\r
10 import android.content.Context;
\r
11 import android.content.DialogInterface;
\r
12 import android.content.Intent;
\r
13 import android.content.IntentFilter;
\r
14 import android.graphics.Canvas;
\r
15 import android.graphics.Color;
\r
16 import android.graphics.Paint;
\r
17 import android.graphics.Path;
\r
18 import android.graphics.Point;
\r
19 import android.graphics.PointF;
\r
20 import android.graphics.RectF;
\r
21 import android.graphics.Paint.FontMetrics;
\r
22 import android.graphics.drawable.ShapeDrawable;
\r
23 import android.graphics.drawable.shapes.PathShape;
\r
24 import android.location.Location;
\r
25 import android.location.LocationManager;
\r
26 import android.os.Bundle;
\r
27 import android.os.Debug;
\r
28 import android.view.KeyEvent;
\r
29 import android.view.Menu;
\r
30 import android.view.MenuItem;
\r
32 import com.google.android.maps.GeoPoint;
\r
33 import com.google.android.maps.MapActivity;
\r
34 import com.google.android.maps.MapController;
\r
35 import com.google.android.maps.MapView;
\r
36 import com.google.android.maps.MyLocationOverlay;
\r
37 import com.google.android.maps.Overlay;
\r
38 import com.google.android.maps.Projection;
\r
40 // TODO: Auto-generated Javadoc
\r
42 * The Class MapMode.
\r
44 public class MapMode extends MapActivity {
\r
46 /** The m_controller. */
\r
47 private MapController m_controller;
\r
49 /** The m_map overlays. */
\r
50 private List<Overlay> m_mapOverlays;
\r
52 /** The m_start time. */
\r
53 private long m_startTime = 0;
\r
55 /** The m_route paint. */
\r
56 private static Paint m_routePaint;
\r
58 /** The m_text paint. */
\r
59 private static Paint m_textPaint;
\r
61 /** The m_info paint. */
\r
62 private static Paint m_infoPaint;
\r
64 private RunningRoute m_route;
\r
67 m_routePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
\r
68 m_routePaint.setStyle(Paint.Style.STROKE);
\r
69 m_routePaint.setAntiAlias(true);
\r
70 m_routePaint.setStrokeWidth(3);
\r
71 m_routePaint.setColor(Color.YELLOW);
\r
73 m_textPaint = new Paint();
\r
74 m_textPaint.setColor(Color.BLACK);
\r
76 m_infoPaint = new Paint();
\r
77 m_infoPaint.setTextSize(20);
\r
78 m_infoPaint.setAntiAlias(true);
\r
79 m_infoPaint.setFakeBoldText(true);
\r
80 m_infoPaint.setColor(Color.LTGRAY);
\r
85 * The Class RunningRoute.
\r
87 public class RunningRoute extends Overlay {
\r
89 private ArrayList<GeoPoint> m_pointList = new ArrayList<GeoPoint>();
\r
91 public RunningRoute() {
\r
95 public void addPoint(GeoPoint pt) {
\r
96 m_pointList.add(pt);
\r
102 * @see com.google.android.maps.Overlay#draw(android.graphics.Canvas,
\r
103 * com.google.android.maps.MapView, boolean)
\r
106 public void draw(Canvas canvas, MapView mapView, boolean shadow) {
\r
107 super.draw(canvas, mapView, shadow);
\r
110 Projection projection = mapView.getProjection();
\r
111 Point pxStart = null;
\r
112 Point pxEnd = null;
\r
113 GeoPoint gpCenter = mapView.getMapCenter();
\r
114 int latFrom = gpCenter.getLatitudeE6()
\r
115 - (mapView.getLatitudeSpan() / 2);
\r
116 int latTo = gpCenter.getLatitudeE6()
\r
117 + (mapView.getLatitudeSpan() / 2);
\r
118 int lonFrom = gpCenter.getLongitudeE6()
\r
119 - (mapView.getLongitudeSpan() / 2);
\r
120 int lonTo = gpCenter.getLongitudeE6()
\r
121 + (mapView.getLongitudeSpan() / 2);
\r
122 for (Iterator<GeoPoint> it = m_pointList.iterator(); it
\r
124 GeoPoint gp = it.next();
\r
126 int lat = gp.getLatitudeE6();
\r
127 int lon = gp.getLongitudeE6();
\r
129 if (lat < latFrom || lat > latTo || lon < lonFrom
\r
134 pxEnd = projection.toPixels(gp, null);
\r
135 if (pxStart != null) {
\r
137 canvas.drawLine(pxStart.x, pxStart.y, pxEnd.x, pxEnd.y,
\r
148 * The Class TextOverlay.
\r
150 public class TextOverlay extends Overlay {
\r
153 private String m_text;
\r
155 /** The m_point. */
\r
156 private GeoPoint m_point;
\r
159 * Instantiates a new text overlay.
\r
166 public TextOverlay(GeoPoint point, String text) {
\r
174 * @see com.google.android.maps.Overlay#draw(android.graphics.Canvas,
\r
175 * com.google.android.maps.MapView, boolean)
\r
178 public void draw(Canvas canvas, MapView mapView, boolean shadow) {
\r
179 super.draw(canvas, mapView, shadow);
\r
182 Projection projection = mapView.getProjection();
\r
183 Point pt = projection.toPixels(m_point, null);
\r
185 drawBalloon(canvas, pt);
\r
197 private void drawBalloon(Canvas canvas, Point pt) {
\r
198 FontMetrics fontMetrics = m_textPaint.getFontMetrics();
\r
199 float textWidth = m_textPaint.measureText(m_text);
\r
200 float textHeight = Math.abs(fontMetrics.top) + fontMetrics.bottom;
\r
202 float triangleHeight = textHeight;
\r
203 float triangleWidth = triangleHeight;
\r
205 final float margin = 5;
\r
206 float textX = pt.x - textWidth / 2;
\r
208 float textY = pt.y - margin - triangleHeight;
\r
210 RectF infoRect = new RectF(textX - margin, pt.y - textHeight
\r
211 - (margin * 2) - triangleHeight,
\r
212 textX + textWidth + margin, pt.y - triangleHeight);
\r
214 final float radius = 5;
\r
216 canvas.drawRoundRect(infoRect, radius, radius, m_infoPaint);
\r
220 PointF[] cornerPoint = new PointF[3];
\r
221 PointF point = new PointF(infoRect.centerX() - triangleWidth / 2,
\r
223 cornerPoint[0] = new PointF(0, 0);
\r
224 cornerPoint[1] = new PointF(triangleWidth, 0);
\r
225 cornerPoint[2] = new PointF(triangleWidth / 2, triangleHeight);
\r
227 drawShape(canvas, point, cornerPoint, m_infoPaint.getColor());
\r
230 canvas.drawText(m_text, textX, textY, m_textPaint);
\r
246 private void drawShape(Canvas canvas, PointF point, PointF[] corners,
\r
248 float maxWidth = 0;
\r
249 float maxHeight = 0;
\r
252 Path path = new Path();
\r
253 for (int cornerCnt = 0; cornerCnt < corners.length; cornerCnt++) {
\r
254 float x = corners[cornerCnt].x;
\r
255 float y = corners[cornerCnt].y;
\r
257 if (cornerCnt == 0) {
\r
263 if (maxWidth < x) {
\r
266 if (maxHeight < y) {
\r
273 ShapeDrawable drawable = new ShapeDrawable(new PathShape(path,
\r
274 maxWidth, maxHeight));
\r
275 drawable.getPaint().setColor(color);
\r
276 drawable.setBounds((int) point.x, (int) point.y, (int) point.x
\r
277 + (int) maxWidth, (int) point.y + (int) maxHeight);
\r
278 drawable.draw(canvas);
\r
282 /** The m_running record receiver. */
\r
283 private BroadcastReceiver m_runningRecordReceiver = new BroadcastReceiver() {
\r
285 public void onReceive(Context context, Intent intent) {
\r
286 String action = intent.getAction();
\r
287 if (action.equals("NewRunningRecord")) {
\r
288 long recordDate = intent.getLongExtra("RunningRecord", 0);
\r
290 Record rec = TokyoRunners.getRecord(recordDate);
\r
293 ExLog.put("No record: " + recordDate);
\r
297 GeoPoint gp = new GeoPoint(rec.getLatitudeE6(), rec
\r
298 .getLongitudeE6());
\r
299 m_controller.animateTo(gp);
\r
301 m_route.addPoint(gp);
\r
303 if (rec.getName().length() > 0) {
\r
304 TextOverlay textOverlay = new TextOverlay(gp, rec.getName());
\r
305 m_mapOverlays.add(textOverlay);
\r
315 * @see com.google.android.maps.MapActivity#isRouteDisplayed()
\r
318 protected boolean isRouteDisplayed() {
\r
325 * @see com.google.android.maps.MapActivity#onResume()
\r
328 public void onResume() {
\r
330 IntentFilter filter = new IntentFilter();
\r
331 filter.addAction("NewRunningRecord");
\r
333 registerReceiver(m_runningRecordReceiver, filter);
\r
336 Record rec = TokyoRunners.getRecord(m_startTime);
\r
338 MapView mapView = (MapView) findViewById(R.id.mapview);
\r
339 drawOverlays(mapView);
\r
347 * @see com.google.android.maps.MapActivity#onPause()
\r
350 public void onPause() {
\r
353 unregisterReceiver(m_runningRecordReceiver);
\r
359 * @see com.google.android.maps.MapActivity#onCreate(android.os.Bundle)
\r
362 public void onCreate(Bundle savedInstanceState) {
\r
363 super.onCreate(savedInstanceState);
\r
365 setContentView(R.layout.map);
\r
367 MapView mapView = (MapView) findViewById(R.id.mapview);
\r
368 mapView.setBuiltInZoomControls(true);
\r
370 m_controller = mapView.getController();
\r
371 m_controller.setZoom(16);
\r
373 m_mapOverlays = mapView.getOverlays();
\r
375 m_route = new RunningRoute();
\r
376 m_mapOverlays.add(m_route);
\r
378 drawOverlays(mapView);
\r
387 private void drawOverlays(MapView mapView) {
\r
389 m_mapOverlays.clear();
\r
391 MyLocationOverlay myLocationOverlay = new MyLocationOverlay(this,
\r
393 myLocationOverlay.enableMyLocation();
\r
395 m_mapOverlays.add(myLocationOverlay);
\r
397 Iterator<Record> it = TokyoRunners.getRecordIterator();
\r
398 GeoPoint gp = null;
\r
399 RunningRoute route = new RunningRoute();
\r
400 while (it.hasNext()) {
\r
401 Record rec = it.next();
\r
402 if (rec.hasLocation()) {
\r
403 gp = new GeoPoint(rec.getLatitudeE6(), rec.getLongitudeE6());
\r
404 route.addPoint(gp);
\r
406 if (rec.getName().length() > 0) {
\r
407 TextOverlay textOverlay = new TextOverlay(gp, rec.getName());
\r
408 m_mapOverlays.add(textOverlay);
\r
409 // drawSplitPoint(gp, rec.getName(), rec.getDate());
\r
412 if (m_startTime == 0) {
\r
413 m_startTime = rec.getDate().getTime();
\r
416 m_mapOverlays.add(route);
\r
418 m_controller.setCenter(gp);
\r
426 * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
\r
428 public boolean onKeyDown(int keyCode, KeyEvent event) {
\r
429 if (keyCode == KeyEvent.KEYCODE_BACK) {
\r
430 showDialog(Constants.DIALOG_EXIT_ID);
\r
434 return super.onKeyDown(keyCode, event);
\r
441 * @see android.app.Activity#onCreateDialog(int)
\r
444 public Dialog onCreateDialog(int id) {
\r
446 AlertDialog.Builder builder = new AlertDialog.Builder(this);
\r
448 case Constants.DIALOG_EXIT_ID:
\r
449 builder.setTitle(R.string.dialog_exit_title);
\r
450 builder.setMessage(R.string.dialog_exit_message);
\r
451 builder.setPositiveButton(R.string.dialog_yes,
\r
452 new DialogInterface.OnClickListener() {
\r
454 public void onClick(DialogInterface dialog, int which) {
\r
455 Debug.stopMethodTracing();
\r
460 builder.setNegativeButton(R.string.dialog_no,
\r
461 new DialogInterface.OnClickListener() {
\r
463 public void onClick(DialogInterface dialog, int which) {
\r
474 AlertDialog alertDialog = builder.create();
\r
475 return alertDialog;
\r
481 * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
\r
484 public boolean onCreateOptionsMenu(Menu menu) {
\r
485 menu.add(Menu.NONE, Constants.MENU_HERE, Menu.NONE, R.string.menu_here)
\r
486 .setIcon(android.R.drawable.ic_menu_mylocation);
\r
487 return super.onCreateOptionsMenu(menu);
\r
493 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
\r
496 public boolean onOptionsItemSelected(MenuItem item) {
\r
498 switch (item.getItemId()) {
\r
499 case Constants.MENU_SETTING:
\r
500 intent = new Intent(this, Config.class);
\r
501 intent.setAction(Intent.ACTION_VIEW);
\r
502 startActivity(intent);
\r
504 case Constants.MENU_HERE:
\r
505 LocationManager locMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
\r
506 Location loc = locMgr
\r
507 .getLastKnownLocation(LocationManager.GPS_PROVIDER);
\r
509 GeoPoint gp = new GeoPoint((int) (loc.getLatitude() * 1E6),
\r
510 (int) (loc.getLongitude() * 1E6));
\r
511 m_controller.animateTo(gp);
\r