package net.osmand.plus.views; import java.util.ArrayList; import java.util.List; import net.osmand.LogUtil; import net.osmand.OsmAndFormatter; import net.osmand.data.Amenity; import net.osmand.osm.LatLon; import net.osmand.plus.OsmandSettings; import net.osmand.plus.PoiFilter; import net.osmand.plus.R; import net.osmand.plus.ResourceManager; import net.osmand.plus.activities.EditingPOIActivity; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.DialogInterface.OnClickListener; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.RectF; import android.graphics.Paint.Style; import android.net.Uri; import android.util.DisplayMetrics; import android.view.WindowManager; import android.widget.Toast; public class POIMapLayer implements OsmandMapLayer, ContextMenuLayer.IContextMenuProvider { private static final int startZoom = 10; public static final int LIMIT_POI = 200; public static final org.apache.commons.logging.Log log = LogUtil.getLog(POIMapLayer.class); private Paint pointAltUI; private Paint point; private OsmandMapTileView view; private List<Amenity> objects = new ArrayList<Amenity>(); private ResourceManager resourceManager; private PoiFilter filter; private DisplayMetrics dm; @Override public boolean onLongPressEvent(PointF point) { return false; } public PoiFilter getFilter() { return filter; } public void setFilter(PoiFilter filter) { this.filter = filter; } public Amenity getAmenityFromPoint(PointF point){ Amenity result = null; if (objects != null) { int ex = (int) point.x; int ey = (int) point.y; int radius = getRadiusPoi(view.getZoom()) * 3 / 2; try { for (int i = 0; i < objects.size(); i++) { Amenity n = objects.get(i); int x = view.getRotatedMapXForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude()); int y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude()); if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) { radius = Math.max(Math.abs(x - ex), Math.abs(y - ey)); result = n; } } } catch (IndexOutOfBoundsException e) { // that's really rare case, but is much efficient than introduce synchronized block } } return result; } @Override public boolean onTouchEvent(PointF point) { Amenity n = getAmenityFromPoint(point); if(n != null){ String format = OsmAndFormatter.getPoiSimpleFormat(n, view.getContext(), OsmandSettings.usingEnglishNames(view.getSettings())); if(n.getOpeningHours() != null){ format += "\n" + view.getContext().getString(R.string.opening_hours) +" : "+ n.getOpeningHours(); //$NON-NLS-1$ //$NON-NLS-2$ } if(n.getPhone() != null){ format += "\n" + view.getContext().getString(R.string.phone) +" : "+ n.getPhone(); //$NON-NLS-1$ //$NON-NLS-2$ } if(n.getSite() != null){ format += "\n" + view.getContext().getString(R.string.website) +" : "+ n.getSite(); //$NON-NLS-1$ //$NON-NLS-2$ } Toast.makeText(view.getContext(), format, Toast.LENGTH_SHORT).show(); return true; } return false; } @Override public void initLayer(OsmandMapTileView view) { this.view = view; dm = new DisplayMetrics(); WindowManager wmgr = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE); wmgr.getDefaultDisplay().getMetrics(dm); pointAltUI = new Paint(); pointAltUI.setColor(Color.rgb(255, 128, 0)); pointAltUI.setAlpha(160); pointAltUI.setStyle(Style.FILL); point = new Paint(); point.setColor(Color.GRAY); point.setAntiAlias(true); point.setStyle(Style.STROKE); resourceManager = view.getApplication().getResourceManager(); } public int getRadiusPoi(int zoom){ int r = 0; if(zoom < startZoom){ r = 0; } else if(zoom <= 15){ r = 10; } else if(zoom == 16){ r = 14; } else if(zoom == 17){ r = 16; } else { r = 18; } return (int) (r * dm.density); } @Override public void onDraw(Canvas canvas, RectF latLonBounds, boolean nightMode) { if (view.getZoom() >= startZoom) { objects.clear(); resourceManager.searchAmenitiesAsync(latLonBounds.top, latLonBounds.left, latLonBounds.bottom, latLonBounds.right, view.getZoom(), filter, objects); int r = getRadiusPoi(view.getZoom()); for (Amenity o : objects) { int x = view.getMapXForPoint(o.getLocation().getLongitude()); int y = view.getMapYForPoint(o.getLocation().getLatitude()); canvas.drawCircle(x, y, r, pointAltUI); canvas.drawCircle(x, y, r, point); } } } @Override public void destroyLayer() { } @Override public boolean drawInScreenPixels() { return false; } @Override public OnClickListener getActionListener(List<String> actionsList, Object o) { final Amenity a = (Amenity) o; actionsList.add(this.view.getResources().getString(R.string.poi_context_menu_modify)); actionsList.add(this.view.getResources().getString(R.string.poi_context_menu_delete)); int ind = 2; final int phoneIndex = a.getPhone() != null ? ind++ : -1; final int siteIndex = a.getSite() != null ? ind++ : -1; if(a.getPhone() != null){ actionsList.add(this.view.getResources().getString(R.string.poi_context_menu_call)); } if(a.getSite() != null){ actionsList.add(this.view.getResources().getString(R.string.poi_context_menu_website)); } final EditingPOIActivity edit = new EditingPOIActivity(view.getContext(), view.getApplication(), view); return new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { if (which == 0) { edit.showEditDialog(a); } else if(which == 1) { edit.showDeleteDialog(a); } else if (which == phoneIndex) { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("tel:"+a.getPhone())); //$NON-NLS-1$ view.getContext().startActivity(intent); } catch (RuntimeException e) { log.error("Failed to invoke call", e); //$NON-NLS-1$ Toast.makeText(view.getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); } } else if (which == siteIndex) { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(a.getSite())); view.getContext().startActivity(intent); } catch (RuntimeException e) { log.error("Failed to invoke call", e); //$NON-NLS-1$ Toast.makeText(view.getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); } } else { } } }; } @Override public String getObjectDescription(Object o) { if(o instanceof Amenity){ return OsmAndFormatter.getPoiSimpleFormat((Amenity) o, view.getContext(), OsmandSettings.usingEnglishNames(view.getSettings())); } return null; } @Override public Object getPointObject(PointF point) { return getAmenityFromPoint(point); } @Override public LatLon getObjectLocation(Object o) { if(o instanceof Amenity){ return ((Amenity)o).getLocation(); } return null; } }