package org.wheelmap.android.osmdroid; import org.osmdroid.api.IMapView; import org.osmdroid.util.GeoPoint; import org.osmdroid.views.MapView; import org.osmdroid.views.Projection; import org.osmdroid.views.overlay.ItemizedOverlay; import org.osmdroid.views.overlay.OverlayItem; import org.wheelmap.android.app.WheelmapApp; import org.wheelmap.android.manager.SupportManager; import org.wheelmap.android.model.POIHelper; import org.wheelmap.android.model.WheelchairFilterState; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.DatabaseUtils; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.ScaleDrawable; import android.os.Handler; import android.text.TextUtils; import android.view.Gravity; import android.view.MotionEvent; import android.widget.Toast; import de.akquinet.android.androlog.Log; import roboguice.event.Observes; public class POIsCursorOsmdroidOverlay extends ItemizedOverlay<OverlayItem> { private final static String TAG = POIsCursorOsmdroidOverlay.class .getSimpleName(); private static final int NO_HIT = -1; private Context mContext; private Cursor mCursor; private Handler mHandler; private OnTapListener mListener; private final Point mCurScreenCoords = new Point(); private final Point mTouchScreenPoint = new Point(); private final Point mItemPoint = new Point(); private Matrix mTempMatrix = new Matrix(); public POIsCursorOsmdroidOverlay(Context context, OnTapListener listener) { super(context, WheelmapApp.getSupportManager().getDefaultOverlayDrawable()); mContext = context; mHandler = new Handler(); mListener = listener; } public synchronized void setCursor(Cursor cursor) { if (cursor == mCursor) { return; } if (cursor == null) { return; } mCursor = cursor; if (mCursor == null) { return; } populate(); } @Override public synchronized int size() { if (mCursor == null) { return 0; } return mCursor.getCount(); } @Override protected synchronized OverlayItem createItem(int i) { if (mCursor == null || mCursor.isClosed()) { return null; } int count = mCursor.getCount(); if (count == 0 || i >= count) { return null; } mCursor.moveToPosition(i); OverlayItem item = getFromCursor(mContext, mCursor); return item; } public static OverlayItem getFromCursor(Context context, Cursor cursor) { long id = POIHelper.getId(cursor); String name = POIHelper.getName(cursor); SupportManager manager = WheelmapApp.getSupportManager(); WheelchairFilterState state = POIHelper.getWheelchair(cursor); double lat = POIHelper.getLatitude(cursor); double lng = POIHelper.getLongitude(cursor); int nodeTypeId = POIHelper.getNodeTypeId(cursor); Drawable marker = null; if (nodeTypeId != 0) { marker = manager.lookupNodeType(nodeTypeId).getStateDrawable(state); } if (marker == null) { return null; } float density = context.getResources().getDisplayMetrics().density; int markerHeight = marker.getIntrinsicHeight(); int markerWidth = marker.getIntrinsicWidth(); float heightToWidth = (float) markerWidth / markerHeight; int halfDestinationDensity = (int) (16 * density); //show marker (centered && above) the declared position marker.setBounds( (int) (-halfDestinationDensity * heightToWidth), -2 * halfDestinationDensity, (int) (halfDestinationDensity * heightToWidth), 0); GeoPoint geo = new GeoPoint(lat, lng); OverlayItem item = new OverlayItem(String.valueOf(id), name, name, geo); item.setMarker(marker); return item; } protected boolean executeOnTap(int index) { if (mCursor == null) { return false; } int count = mCursor.getCount(); if (count == 0 || index >= count) { return false; } mCursor.moveToPosition(index); long poiId = POIHelper.getId(mCursor); Log.d(TAG, "onTap index = " + index + " id = " + poiId); ContentValues values = new ContentValues(); DatabaseUtils.cursorRowToContentValues(mCursor, values); if (mListener != null) { mListener.onTap(createItem(index), values); } return true; } protected boolean executeLongPress(int index) { if (mCursor == null) { return false; } int count = mCursor.getCount(); if (count == 0 || index >= count) { return false; } mCursor.moveToPosition(index); long poiId = POIHelper.getId(mCursor); String name = POIHelper.getName(mCursor); int nodeTypeId = POIHelper.getNodeTypeId(mCursor); String nodeTypeName = WheelmapApp.getSupportManager().lookupNodeType( nodeTypeId).localizedName; String address = POIHelper.getAddress(mCursor); StringBuilder builder = new StringBuilder(); if (!TextUtils.isEmpty(name)) { builder.append(name); } else { builder.append(nodeTypeName); } if (!TextUtils.isEmpty(address)) { builder.append(", "); builder.append(address); } final String outputText = builder.toString(); Log.d(TAG, Long.toString(poiId) + " " + outputText); mHandler.post(new Runnable() { @Override public void run() { Toast.makeText(mContext, outputText, Toast.LENGTH_SHORT).show(); } }); return true; } @Override public boolean onSnapToItem(int x, int y, Point snapPoint, IMapView mapView) { return false; //To change body of implemented methods use File | Settings | File Templates. } @Override protected void draw(Canvas canvas, MapView mapView, boolean shadow) { if (shadow) { return; } final Projection pj = mapView.getProjection(); final int size = size() - 1; Matrix canvasMatrix = canvas.getMatrix(); /* Draw in backward cycle, so the items with the least index are on the front. */ for (int i = size; i >= 0; i--) { final OverlayItem item = getItem(i); pj.toPixels(item.getPoint(), mCurScreenCoords); onDrawItem(canvas, item, mCurScreenCoords, canvasMatrix); } canvas.setMatrix(canvasMatrix); //Restore old matrix } protected void onDrawItem(Canvas canvas, OverlayItem item, Point curScreenCoords, Matrix canvasMatrix) { Drawable pin = item.getDrawable(); mTempMatrix.set(canvasMatrix); mTempMatrix.preTranslate(curScreenCoords.x, curScreenCoords.y); canvas.setMatrix(mTempMatrix); pin.draw(canvas); } @Override public boolean onLongPress(final MotionEvent event, final MapView mapView) { int hitIndex = checkForItemHit(event, mapView); Log.d(TAG, "onLongPress: hitIndex = " + hitIndex); if (hitIndex == NO_HIT) { return super.onLongPress(event, mapView); } return executeLongPress(hitIndex); } @Override protected boolean onTap(int index) { return executeOnTap(index); } private int checkForItemHit(final MotionEvent event, final MapView mapView) { //avoid NullPointerException if (mCursor == null || mapView == null || event == null || mapView.getProjection() == null) { return NO_HIT; } final Projection pj = mapView.getProjection(); final int eventX = (int) event.getX(); final int eventY = (int) event.getY(); Point p = new Point(eventX, eventY); pj.toPixelsFromProjected(p, mTouchScreenPoint); mCursor.moveToFirst(); while (!mCursor.isAfterLast()) { final double lat = POIHelper.getLatitude(mCursor); final double lon = POIHelper.getLongitude(mCursor); final Drawable marker = this.mDefaultMarker; GeoPoint geoPoint = new GeoPoint(lat, lon); pj.toPixels(geoPoint, mItemPoint); if (marker.getBounds().contains(mTouchScreenPoint.x - mItemPoint.x, mTouchScreenPoint.y - mItemPoint.y)) { return mCursor.getPosition(); } mCursor.moveToNext(); } return NO_HIT; } }