diff --git a/OsmAnd/src/net/osmand/AndroidUtils.java b/OsmAnd/src/net/osmand/AndroidUtils.java index 0433e097c8..038392d1c1 100644 --- a/OsmAnd/src/net/osmand/AndroidUtils.java +++ b/OsmAnd/src/net/osmand/AndroidUtils.java @@ -6,6 +6,7 @@ import android.app.Activity; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.graphics.PointF; import android.os.Build; import android.os.IBinder; import android.text.TextUtils; @@ -24,6 +25,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.Date; +import java.util.List; import static android.util.TypedValue.COMPLEX_UNIT_DIP; @@ -184,4 +186,14 @@ public class AndroidUtils { return null; } } + + public static PointF centroidForPoly(PointF[] points) { + float centroidX = 0, centroidY = 0; + + for (PointF point : points) { + centroidX += point.x / points.length; + centroidY += point.y / points.length; + } + return new PointF(centroidX, centroidY); + } } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuController.java index 37fb67486b..6e0fe6faa6 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuController.java @@ -6,6 +6,8 @@ import java.util.LinkedList; import java.util.List; import net.osmand.IndexConstants; +import net.osmand.NativeLibrary; +import net.osmand.NativeLibrary.RenderedObject; import net.osmand.binary.BinaryMapDataObject; import net.osmand.binary.RouteDataObject; import net.osmand.data.Amenity; @@ -38,6 +40,7 @@ import net.osmand.plus.mapcontextmenu.controllers.MapDataMenuController; import net.osmand.plus.mapcontextmenu.controllers.MapMarkerMenuController; import net.osmand.plus.mapcontextmenu.controllers.MyLocationMenuController; import net.osmand.plus.mapcontextmenu.controllers.PointDescriptionMenuController; +import net.osmand.plus.mapcontextmenu.controllers.RenderedObjectMenuController; import net.osmand.plus.mapcontextmenu.controllers.TargetPointMenuController; import net.osmand.plus.mapcontextmenu.controllers.TransportRouteController; import net.osmand.plus.mapcontextmenu.controllers.TransportStopController; @@ -152,8 +155,9 @@ public abstract class MenuController extends BaseMenuController { menuController = new MyLocationMenuController(app, mapActivity, pointDescription); } } else if (object instanceof RouteDataObject) { - menuController = new ImpassibleRoadsMenuController(app, mapActivity, - pointDescription, (RouteDataObject) object); + menuController = new ImpassibleRoadsMenuController(app, mapActivity, pointDescription, (RouteDataObject) object); + } else if (object instanceof RenderedObject) { + menuController = new RenderedObjectMenuController(app, mapActivity, pointDescription, (RenderedObject) object); } } if (menuController == null) { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/RenderedObjectMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/RenderedObjectMenuController.java new file mode 100644 index 0000000000..be024ed767 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/RenderedObjectMenuController.java @@ -0,0 +1,84 @@ +package net.osmand.plus.mapcontextmenu.controllers; + +import net.osmand.NativeLibrary.RenderedObject; +import net.osmand.data.PointDescription; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.mapcontextmenu.MenuBuilder; +import net.osmand.plus.mapcontextmenu.MenuController; +import net.osmand.plus.render.RenderingIcons; +import net.osmand.util.Algorithms; + +public class RenderedObjectMenuController extends MenuController { + + private RenderedObject renderedObject; + + public RenderedObjectMenuController(OsmandApplication app, MapActivity mapActivity, PointDescription pointDescription, final RenderedObject renderedObject) { + super(new MenuBuilder(app), pointDescription, mapActivity); + this.renderedObject = renderedObject; + } + + @Override + protected void setObject(Object object) { + if (object instanceof RenderedObject) { + this.renderedObject = (RenderedObject) object; + } + } + + @Override + protected Object getObject() { + return renderedObject; + } + + @Override + protected int getSupportedMenuStatesPortrait() { + return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN | MenuState.FULL_SCREEN; + } + + @Override + public boolean displayStreetNameInTitle() { + return Algorithms.isEmpty(getNameStr()); + } + + @Override + public boolean displayDistanceDirection() { + return true; + } + + @Override + public int getLeftIconId() { + if (renderedObject.getIconRes() != null && RenderingIcons.containsBigIcon(renderedObject.getIconRes())) { + return RenderingIcons.getBigIconResourceId(renderedObject.getIconRes()); + } else { + return R.drawable.ic_type_address; + } + } + + @Override + public String getNameStr() { + if (!Algorithms.isEmpty(renderedObject.getName())) { + return renderedObject.getName(); + } else if (renderedObject.getTags().size() > 0) { + String lang = getMapActivity().getMyApplication().getSettings().MAP_PREFERRED_LOCALE.get().toLowerCase(); + String name; + if (!Algorithms.isEmpty(lang)) { + name = renderedObject.getTags().get("name:" + lang); + } else { + name = renderedObject.getTags().get("name"); + } + return name; + } + return ""; + } + + @Override + public String getCommonTypeStr() { + return getMapActivity().getString(R.string.shared_string_location); + } + + @Override + public boolean needStreetName() { + return !getPointDescription().isAddress(); + } +} diff --git a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java index 95305b01d1..886c7da5ca 100644 --- a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java @@ -21,15 +21,18 @@ import android.widget.ArrayAdapter; import android.widget.FrameLayout.LayoutParams; import android.widget.ImageView; +import net.osmand.AndroidUtils; import net.osmand.CallbackWithObject; import net.osmand.NativeLibrary.RenderedObject; import net.osmand.RenderingContext; +import net.osmand.ResultMatcher; import net.osmand.binary.BinaryMapIndexReader; import net.osmand.data.Amenity; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.data.QuadRect; import net.osmand.data.RotatedTileBox; +import net.osmand.data.TransportStop; import net.osmand.osm.PoiCategory; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuItem; @@ -39,7 +42,6 @@ import net.osmand.plus.mapcontextmenu.MapContextMenu; import net.osmand.plus.mapcontextmenu.other.MapMultiSelectionMenu; import net.osmand.plus.render.MapRenderRepositories; import net.osmand.plus.render.NativeOsmandLibrary; -import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; import java.util.ArrayList; @@ -350,6 +352,11 @@ public class ContextMenuLayer extends OsmandMapLayer { selectedObjectContextMenuProvider = provider; hideVisibleMenues(); activity.getMapViewTrackingUtilities().setMapLinkedToLocation(false); + if (!activity.getMapView().getCurrentRotatedTileBox().containsLatLon(latLon)) { + menu.setMapCenter(latLon); + menu.setMapPosition(activity.getMapView().getMapPosition()); + menu.setCenterMarker(true); + } menu.show(latLon, pointDescription, object); return true; } @@ -386,6 +393,27 @@ public class ContextMenuLayer extends OsmandMapLayer { return false; } + private boolean showContextMenu(LatLon latLon, Map selectedObjects) { + if (selectedObjects.size() == 1) { + Object selectedObj = selectedObjects.keySet().iterator().next(); + PointDescription pointDescription = null; + final IContextMenuProvider provider = selectedObjects.get(selectedObj); + if (provider != null) { + latLon = provider.getObjectLocation(selectedObj); + pointDescription = provider.getObjectName(selectedObj); + } + showContextMenu(latLon, pointDescription, selectedObj, provider); + return true; + + } else if (selectedObjects.size() > 1) { + selectedObjectContextMenuProvider = null; + showContextMenuForSelectedObjects(latLon, selectedObjects); + return true; + } + + return false; + } + @NonNull private LatLon getLatLon(PointF point, RotatedTileBox tileBox) { LatLon latLon; @@ -522,31 +550,53 @@ public class ContextMenuLayer extends OsmandMapLayer { renderedObjects = nativeLib.searchRenderedObjectsFromContext(rc, (int)( point.x - x), (int)( point.y- y)); } if (renderedObjects != null) { + Map selectedObjects = new HashMap<>(); + IContextMenuProvider poiMenuProvider = activity.getMapLayers().getPoiMapLayer(); + IContextMenuProvider transportStopMenuProvider = activity.getMapLayers().getTransportStopsLayer(); Log.e("111", "found " + renderedObjects.length + " object(s) at x=" + point.x + " y=" + point.y); + LatLon latLon = null; for (RenderedObject renderedObject : renderedObjects) { Log.e("111", "++++ object=" + renderedObject.getName()); for (Entry entry : renderedObject.getTags().entrySet()) { Log.e("111", "tag=" + entry.getKey() + " value=" + entry.getValue()); } - LatLon latLon = tileBox.getLatLonFromPixel(point.x, point.y); - boolean objectFound = false; - String name = renderedObject.getTags().get("name"); - if (!Algorithms.isEmpty(name)) { - Amenity amenity = findAmenity(name, latLon.getLatitude(), latLon.getLongitude()); - if (amenity != null) { - PointDescription pointDescription = new PointDescription(PointDescription.POINT_TYPE_POI, - amenity.getName(activity.getMyApplication().getSettings().MAP_PREFERRED_LOCALE.get())); - activity.getContextMenu().show(amenity.getLocation(), pointDescription, amenity); - objectFound = true; - } - } - if (!objectFound) { - activity.getContextMenu().show(latLon, null, null); + if (renderedObject.getX() != null && renderedObject.getX().size() == 1 + && renderedObject.getY() != null && renderedObject.getY().size() == 1) { + latLon = new LatLon(MapUtils.get31LatitudeY(renderedObject.getY().get(0)), + MapUtils.get31LongitudeX(renderedObject.getX().get(0))); } else { - break; + latLon = tileBox.getLatLonFromPixel(point.x, point.y); + } + if (renderedObject.getId() != null) { + TransportStop transportStop = findTransportStop(renderedObject.getId() >> 6, latLon.getLatitude(), latLon.getLongitude()); + if (transportStop != null) { + selectedObjects.put(transportStop, transportStopMenuProvider); + continue; + } + Amenity amenity = findAmenity(renderedObject.getId() >> 6, latLon.getLatitude(), latLon.getLongitude()); + if (amenity != null) { + selectedObjects.put(amenity, poiMenuProvider); + continue; + } + if (renderedObject.getX() != null && renderedObject.getX().size() > 1 + && renderedObject.getY() != null && renderedObject.getY().size() > 1) { + + PointF[] points = new PointF[renderedObject.getX().size()]; + for (int i = 0; i < points.length; i++) { + points[i] = new PointF(renderedObject.getX().get(i), renderedObject.getY().get(i)); + } + PointF center = AndroidUtils.centroidForPoly(points); + latLon = new LatLon(MapUtils.get31LatitudeY((int)center.y), + MapUtils.get31LongitudeX((int)center.x)); + } + selectedObjects.put(renderedObject, null); } Log.e("111", "------------------"); } + if (selectedObjects.size() > 0 && latLon != null) { + showContextMenu(latLon, selectedObjects); + return true; + } } else { Log.e("111", "objects not found at x=" + point.x + " y=" + point.y); } @@ -559,7 +609,7 @@ public class ContextMenuLayer extends OsmandMapLayer { return false; } - private Amenity findAmenity(String name, double lat, double lon) { + private Amenity findAmenity(long id, double lat, double lon) { QuadRect rect = MapUtils.calculateLatLonBbox(lat, lon, 150); List amenities = activity.getMyApplication().getResourceManager().searchAmenities( new BinaryMapIndexReader.SearchPoiTypeFilter() { @@ -575,10 +625,50 @@ public class ContextMenuLayer extends OsmandMapLayer { }, rect.top, rect.left, rect.bottom, rect.right, -1, null); for (Amenity amenity : amenities) { - if (amenity.getName().equals(name)) { + Long amenityId = amenity.getId(); + if (amenityId != null && amenityId == id) { return amenity; } } + for (Amenity amenity : amenities) { + Long amenityId = amenity.getId(); + if (amenityId != null && Math.abs(amenityId - id) < 2) { + return amenity; + } + } + return null; + } + + private TransportStop findTransportStop(long id, double lat, double lon) { + + QuadRect rect = MapUtils.calculateLatLonBbox(lat, lon, 150); + List res = activity.getMyApplication().getResourceManager() + .searchTransportSync(rect.top, rect.left, rect.bottom, rect.right, + new ResultMatcher() { + + @Override + public boolean publish(TransportStop object) { + return true; + } + + @Override + public boolean isCancelled() { + return false; + } + }); + + for (TransportStop stop : res) { + Long stopId = stop.getId(); + if (stopId != null && stopId == id) { + return stop; + } + } + for (TransportStop stop : res) { + Long stopId = stop.getId(); + if (stopId != null && Math.abs(stopId - id) < 2) { + return stop; + } + } return null; }