package com.robert.maps.applib.overlays; import java.util.ArrayList; import java.util.Iterator; import java.util.Locale; import org.andnav.osm.util.GeoPoint; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Path; import android.graphics.Point; import android.graphics.Rect; import android.preference.PreferenceManager; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.RelativeLayout.LayoutParams; import android.widget.TextView; import com.robert.maps.applib.R; import com.robert.maps.applib.utils.CoordFormatter; import com.robert.maps.applib.utils.DistanceFormatter; import com.robert.maps.applib.view.TileView; import com.robert.maps.applib.view.TileViewOverlay; public class MeasureOverlay extends TileViewOverlay { private Paint mPaint = new Paint(); private Paint mPaintText; private ArrayList<DistPoint> points = new ArrayList<DistPoint>(); private Bitmap mCornerMarker = null; private float mDistance = 0; private TextView mT; private LinearLayout msgbox = null; private DistanceFormatter mDf; private CoordFormatter mCf; private DistPoint mLocation; private CharSequence mDescr; private final String LAT; private final String LON; private final String DIST_START; private final String DIST_END; private final String DIST_PREV; private final String AZI; private boolean mShowInfoBubble; private boolean mShowLineInfo; static private final String DIV = ": "; public MeasureOverlay(Context ctx, View bottomView) { super(); mPaint.setColor(ctx.getResources().getColor(R.color.chart_graph_0)); mPaint.setStyle(Style.STROKE); mPaint.setStrokeWidth(3); mPaint.setAntiAlias(true); mPaint.setAlpha(180); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setShadowLayer(10.0f, 0, 0, ctx.getResources().getColor(R.color.chart_graph_0)); mPaintText = new Paint(); mPaintText.setAntiAlias(true); mPaintText.setAlpha(10); mPaintText.setColor(ctx.getResources().getColor(android.R.color.black)); mPaintText.setShadowLayer(4.0f, 0, 0, ctx.getResources().getColor(android.R.color.white)); mPaintText.setTextAlign(Paint.Align.CENTER); mPaintText.setTextSize(ctx.getResources().getDimensionPixelSize(R.dimen.measuretool_label_size)); mDf = new DistanceFormatter(ctx); mCf = new CoordFormatter(ctx); msgbox = (LinearLayout) LayoutInflater.from(ctx).inflate(R.layout.measure_info_box, (ViewGroup) bottomView); msgbox.setVisibility(View.VISIBLE); this.mT = (TextView) LayoutInflater.from(ctx).inflate(R.layout.search_bubble, null); this.mT.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); LAT = ctx.getResources().getString(R.string.PoiLat); LON = ctx.getResources().getString(R.string.PoiLon); DIST_START = ctx.getResources().getString(R.string.tostart); DIST_END = ctx.getResources().getString(R.string.toend); DIST_PREV = ctx.getResources().getString(R.string.toprev); AZI = ctx.getResources().getString(R.string.azimuth); final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(ctx); mShowLineInfo = pref.getBoolean("pref_show_measure_line_info", true); mShowInfoBubble = pref.getBoolean("pref_show_measure_info", true); ShowDistance(); } private Bitmap getPic(TileView tileView) { if(mCornerMarker == null) mCornerMarker = BitmapFactory.decodeResource(tileView.getContext().getResources(), R.drawable.r_mark); return mCornerMarker; } private void ShowDistance() { ((TextView) msgbox.findViewById(R.id.value)).setText(mDf.formatDistance(mDistance)); } @Override protected void onDraw(Canvas c, TileView tileView) { final com.robert.maps.applib.view.TileView.OpenStreetMapViewProjection pj = tileView.getProjection(); final Bitmap pic = getPic(tileView); if(points.size() > 0) { Point p0 = null; DistPoint pt = null; final Path path = new Path(); Iterator<DistPoint> it = points.iterator(); while(it.hasNext()) { pt = it.next(); final Point p1 = pj.toPixels(pt.Point, null); if(p0 != null) { c.drawLine(p0.x, p0.y, p1.x, p1.y, mPaint); path.reset(); if(p0.x < p1.x) { path.moveTo(p0.x, p0.y); path.lineTo(p1.x, p1.y); } else { path.moveTo(p1.x, p1.y); path.lineTo(p0.x, p0.y); } if(mShowLineInfo) { c.drawTextOnPath(mDf.formatDistance(pt.Dist2Prev), path, 0, -5, mPaintText); c.drawTextOnPath(String.format(Locale.UK, "%.1f�", pt.Bearing), path, 0, mPaintText.getTextSize(), mPaintText); } c.drawBitmap(pic, p0.x - (int)(pic.getWidth()/2), p0.y - (int)(pic.getHeight() / 2), mPaint); } p0 = p1; } c.drawBitmap(pic, p0.x - (int)(pic.getWidth()/2), p0.y - (int)(pic.getHeight() / 2), mPaint); } if(this.mLocation != null){ mT.setText(mDescr); mT.measure(0, 0); mT.layout(0, 0, mT.getMeasuredWidth(), mT.getMeasuredHeight()); final Point screenCoords = new Point(); pj.toPixels(this.mLocation.Point, screenCoords); c.save(); c.rotate(tileView.getBearing(), screenCoords.x, screenCoords.y); c.translate(screenCoords.x - mT.getMeasuredWidth() / 2, screenCoords.y - mT.getMeasuredHeight() + 2); mT.draw(c); c.restore(); c.drawBitmap(pic, screenCoords.x - (int)(pic.getWidth()/2), screenCoords.y - (int)(pic.getHeight() / 2), mPaint); } } @Override protected void onDrawFinished(Canvas c, TileView tileView) { } @Override public boolean onSingleTapUp(MotionEvent e, TileView tileView) { final com.robert.maps.applib.view.TileView.OpenStreetMapViewProjection pj = tileView.getProjection(); DistPoint pt = null; Point px = new Point(); Rect rect = new Rect(); final int bounds = 12; Iterator<DistPoint> it = points.iterator(); while(it.hasNext()) { pt = it.next(); px = pj.toPixels(pt.Point, tileView.getBearing(), px); rect.set(px.x - bounds, px.y - bounds, px.x + bounds, px.y + bounds); if(rect.contains((int)e.getX(), (int)e.getY())) { if(mLocation != null && mLocation.Point.equals(pt.Point)) mLocation = null; else mLocation = pt; setDescr(); return true; } } addPoint(e.getX(), e.getY(), tileView); return true; } private void addPoint(float x, float y, TileView tileView) { final com.robert.maps.applib.view.TileView.OpenStreetMapViewProjection pj = tileView.getProjection(); DistPoint pt = null; pt = new DistPoint(pj.fromPixels(x, y, tileView.getBearing())); pt.Dist2Prev = points.size() > 0 ? points.get(points.size() - 1).Point.distanceTo(pt.Point) : 0; pt.Dist2Start = mDistance + pt.Dist2Prev; pt.Bearing = points.size() > 0 ? points.get(points.size() - 1).Point.bearingTo360(pt.Point) : 0; if(mShowInfoBubble) mLocation = pt; if(points.size() > 0) { mDistance += pt.Dist2Prev; } points.add(pt); setDescr(); ShowDistance(); } private class DistPoint { double Dist2Start; double Dist2Prev; double Bearing; GeoPoint Point; DistPoint(GeoPoint point) { Point = point; } } private void setDescr() { if(mLocation != null) mDescr = new StringBuilder() .append(LAT).append(DIV).append(mCf.convertLat(mLocation.Point.getLatitude())) .append("\n").append(LON).append(DIV).append(mCf.convertLon(mLocation.Point.getLongitude())) .append("\n").append(DIST_PREV).append(DIV).append(mDf.formatDistance(mLocation.Dist2Prev)) .append("\n").append(DIST_START).append(DIV).append(mDf.formatDistance(mLocation.Dist2Start)) .append("\n").append(DIST_END).append(DIV).append(mDf.formatDistance(mDistance - mLocation.Dist2Start)) .append("\n").append(AZI).append(DIV).append(String.format(Locale.UK, "%.1f�", mLocation.Bearing)) .toString(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event, TileView mapView) { if (keyCode == KeyEvent.KEYCODE_BACK) { Undo(); mapView.invalidate(); return true; } return super.onKeyDown(keyCode, event, mapView); } public void Clear() { points.clear(); mDistance = 0; mLocation = null; ShowDistance(); } public void Undo() { if(points.size() > 2) { mDistance -= points.get(points.size() - 1).Point.distanceTo(points.get(points.size() - 2).Point); points.remove(points.size() - 1); } else if(points.size() > 0) { mDistance = 0; points.remove(points.size() - 1); } if(points.size() > 0) { mLocation = points.get(points.size() - 1); setDescr(); } else { mLocation = null; } ShowDistance(); } public void setShowInfoBubble(boolean showInfo) { mShowInfoBubble = showInfo; if(!showInfo) mLocation = null; } public void setShowLineInfo(boolean showInfo) { mShowLineInfo = showInfo; } public void addPointOnCenter(TileView tileView) { addPoint(tileView.getWidth() / 2, tileView.getHeight() / 2, tileView); } }