package net.osmand.plus.views;
import android.Manifest;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Vibrator;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresPermission;
import android.support.v4.content.ContextCompat;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
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.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.osm.PoiCategory;
import net.osmand.osm.PoiFilter;
import net.osmand.osm.PoiType;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
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;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import gnu.trove.list.array.TIntArrayList;
public class ContextMenuLayer extends OsmandMapLayer {
//private static final Log LOG = PlatformUtil.getLog(ContextMenuLayer.class);
public static final int VIBRATE_SHORT = 100;
private OsmandMapTileView view;
private final MapActivity activity;
private MapContextMenu menu;
private MapMultiSelectionMenu multiSelectionMenu;
private CallbackWithObject<LatLon> selectOnMap = null;
private MapQuickActionLayer mapQuickActionLayer;
private ImageView contextMarker;
private Paint paint;
private Paint outlinePaint;
private Bitmap pressedBitmap;
private Bitmap pressedBitmapSmall;
private List<LatLon> pressedLatLonFull = new ArrayList<>();
private List<LatLon> pressedLatLonSmall = new ArrayList<>();
private GestureDetector movementListener;
private final MoveMarkerBottomSheetHelper mMoveMarkerBottomSheetHelper;
private boolean mInChangeMarkerPositionMode;
private IContextMenuProvider selectedObjectContextMenuProvider;
private boolean cancelApplyingNewMarkerPosition;
private LatLon applyingMarkerLatLon;
private boolean wasCollapseButtonVisible;
private boolean mInGpxDetailsMode;
private List<String> publicTransportTypes;
private Object selectedObject;
public ContextMenuLayer(MapActivity activity) {
this.activity = activity;
menu = activity.getContextMenu();
multiSelectionMenu = menu.getMultiSelectionMenu();
movementListener = new GestureDetector(activity, new MenuLayerOnGestureListener());
mMoveMarkerBottomSheetHelper = new MoveMarkerBottomSheetHelper(activity, this);
}
@Override
public void destroyLayer() {
}
@Override
public void initLayer(OsmandMapTileView view) {
this.view = view;
Context context = view.getContext();
contextMarker = new ImageView(context);
contextMarker.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
contextMarker.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.map_pin_context_menu));
contextMarker.setClickable(true);
int minw = contextMarker.getDrawable().getMinimumWidth();
int minh = contextMarker.getDrawable().getMinimumHeight();
contextMarker.layout(0, 0, minw, minh);
paint = new Paint();
pressedBitmap = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_shield_tap);
pressedBitmapSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_shield_tap_small);
outlinePaint = new Paint();
outlinePaint.setStyle(Paint.Style.STROKE);
outlinePaint.setAntiAlias(true);
outlinePaint.setStrokeWidth(AndroidUtils.dpToPx(activity, 2f));
outlinePaint.setStrokeCap(Paint.Cap.ROUND);
outlinePaint.setColor(activity.getResources().getColor(R.color.osmand_orange));
}
public boolean isVisible() {
return menu.isActive();
}
public Object getSelectedObject() {
return selectedObject;
}
public void setSelectedObject(Object selectedObject) {
this.selectedObject = selectedObject;
}
private List<String> getPublicTransportTypes() {
if (publicTransportTypes == null) {
publicTransportTypes = new ArrayList<>();
List<PoiFilter> filters = activity.getMyApplication().getPoiTypes().getPoiCategoryByName("transportation").getPoiFilters();
for (PoiFilter poiFilter : filters) {
if (poiFilter.getKeyName().equals("public_transport")) {
for (PoiType poiType : poiFilter.getPoiTypes()) {
publicTransportTypes.add(poiType.getKeyName());
for (PoiType poiAdditionalType : poiType.getPoiAdditionals()) {
publicTransportTypes.add(poiAdditionalType.getKeyName());
}
}
}
}
}
return publicTransportTypes;
}
@Override
public void onDraw(Canvas canvas, RotatedTileBox box, DrawSettings nightMode) {
if (selectedObject != null) {
TIntArrayList x = null;
TIntArrayList y = null;
if (selectedObject instanceof Amenity) {
Amenity a = (Amenity) selectedObject;
x = a.getX();
y = a.getY();
} else if (selectedObject instanceof RenderedObject) {
RenderedObject r = (RenderedObject) selectedObject;
x = r.getX();
y = r.getY();
}
if (x != null && y != null && x.size() > 2) {
double lat = MapUtils.get31LatitudeY(y.get(0));
double lon = MapUtils.get31LongitudeX(x.get(0));
int px,py, prevX, prevY;
prevX = (int) box.getPixXFromLatLon(lat, lon);
prevY = (int) box.getPixYFromLatLon(lat, lon);
for (int i = 1; i < x.size(); i++) {
lat = MapUtils.get31LatitudeY(y.get(i));
lon = MapUtils.get31LongitudeX(x.get(i));
px = (int) box.getPixXFromLatLon(lat, lon);
py = (int) box.getPixYFromLatLon(lat, lon);
canvas.drawLine(prevX, prevY, px, py, outlinePaint);
prevX = px;
prevY = py;
}
}
}
for (LatLon latLon : pressedLatLonSmall) {
int x = (int) box.getPixXFromLatLon(latLon.getLatitude(), latLon.getLongitude());
int y = (int) box.getPixYFromLatLon(latLon.getLatitude(), latLon.getLongitude());
canvas.drawBitmap(pressedBitmapSmall, x - pressedBitmapSmall.getWidth() / 2, y - pressedBitmapSmall.getHeight() / 2, paint);
}
for (LatLon latLon : pressedLatLonFull) {
int x = (int) box.getPixXFromLatLon(latLon.getLatitude(), latLon.getLongitude());
int y = (int) box.getPixYFromLatLon(latLon.getLatitude(), latLon.getLongitude());
canvas.drawBitmap(pressedBitmap, x - pressedBitmap.getWidth() / 2, y - pressedBitmap.getHeight() / 2, paint);
}
if (mapQuickActionLayer!= null && mapQuickActionLayer.isInChangeMarkerPositionMode())
return;
if (mInChangeMarkerPositionMode) {
if (menu.getObject() == null) {
canvas.translate(box.getPixWidth() / 2 - contextMarker.getWidth() / 2, box.getPixHeight() / 2 - contextMarker.getHeight());
contextMarker.draw(canvas);
}
mMoveMarkerBottomSheetHelper.onDraw(box);
} else if (menu.isActive()) {
LatLon latLon = menu.getLatLon();
int x = (int) box.getPixXFromLatLon(latLon.getLatitude(), latLon.getLongitude());
int y = (int) box.getPixYFromLatLon(latLon.getLatitude(), latLon.getLongitude());
canvas.translate(x - contextMarker.getWidth() / 2, y - contextMarker.getHeight());
contextMarker.draw(canvas);
}
}
public void setSelectOnMap(CallbackWithObject<LatLon> selectOnMap) {
this.selectOnMap = selectOnMap;
}
@Override
public void populateObjectContextMenu(LatLon latLon, Object o, ContextMenuAdapter adapter, MapActivity mapActivity) {
if (menu.hasHiddenBottomInfo()) {
ContextMenuAdapter.ItemClickListener listener = new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked) {
menu.openMenuFullScreen();
return true;
}
};
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.shared_string_show_description, activity)
.setIcon(R.drawable.ic_action_note_dark)
.setListener(listener)
.createItem());
}
if (isObjectMoveable(o)) {
ContextMenuAdapter.ItemClickListener listener = new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked) {
RotatedTileBox tileBox = activity.getMapView().getCurrentRotatedTileBox();
enterMovingMode(tileBox);
return true;
}
};
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.change_markers_position, activity)
.setIcon(R.drawable.ic_show_on_map)
.setListener(listener)
.createItem());
}
}
@Override
@RequiresPermission(Manifest.permission.VIBRATE)
public boolean onLongPressEvent(PointF point, RotatedTileBox tileBox) {
if (disableLongPressOnMap()) {
return false;
}
if (pressedContextMarker(tileBox, point.x, point.y)) {
Object obj = menu.getObject();
if (isObjectMoveable(obj)) {
enterMovingMode(tileBox);
return true;
}
return false;
}
showContextMenu(point, tileBox, true);
view.refreshMap();
return true;
}
public PointF getMovableCenterPoint(RotatedTileBox tb) {
if (applyingMarkerLatLon != null) {
float x = tb.getPixXFromLatLon(applyingMarkerLatLon.getLatitude(), applyingMarkerLatLon.getLongitude());
float y = tb.getPixYFromLatLon(applyingMarkerLatLon.getLatitude(), applyingMarkerLatLon.getLongitude());
return new PointF(x, y);
} else {
return new PointF(tb.getPixWidth() / 2, tb.getPixHeight() / 2);
}
}
public Object getMoveableObject() {
return mInChangeMarkerPositionMode ? menu.getObject() : null;
}
public boolean isInChangeMarkerPositionMode() {
return mInChangeMarkerPositionMode;
}
public boolean isInGpxDetailsMode() {
return mInGpxDetailsMode;
}
public boolean isObjectMoveable(Object o) {
if (o == null) {
return true;
} else if (selectedObjectContextMenuProvider != null
&& selectedObjectContextMenuProvider instanceof ContextMenuLayer.IMoveObjectProvider) {
final IMoveObjectProvider l = (ContextMenuLayer.IMoveObjectProvider) selectedObjectContextMenuProvider;
if (l.isObjectMovable(o)) {
return true;
}
}
return false;
}
public void applyMovedObject(Object o, LatLon position, ApplyMovedObjectCallback callback) {
if (selectedObjectContextMenuProvider != null) {
if (selectedObjectContextMenuProvider instanceof IMoveObjectProvider) {
final IMoveObjectProvider l = (IMoveObjectProvider) selectedObjectContextMenuProvider;
if (l.isObjectMovable(o)) {
l.applyNewObjectPosition(o, position, callback);
}
}
} else if (mInChangeMarkerPositionMode) {
callback.onApplyMovedObject(true, null);
}
}
public void applyNewMarkerPosition() {
if (!mInChangeMarkerPositionMode) {
throw new IllegalStateException("Not in change marker position mode");
}
RotatedTileBox tileBox = activity.getMapView().getCurrentRotatedTileBox();
PointF newMarkerPosition = getMovableCenterPoint(tileBox);
final LatLon ll = tileBox.getLatLonFromPixel(newMarkerPosition.x, newMarkerPosition.y);
applyingMarkerLatLon = ll;
Object obj = getMoveableObject();
cancelApplyingNewMarkerPosition = false;
mMoveMarkerBottomSheetHelper.enterApplyPositionMode();
applyMovedObject(obj, ll, new ApplyMovedObjectCallback() {
@Override
public void onApplyMovedObject(boolean success, @Nullable Object newObject) {
mMoveMarkerBottomSheetHelper.exitApplyPositionMode();
if (success && !cancelApplyingNewMarkerPosition) {
mMoveMarkerBottomSheetHelper.hide();
quitMovingMarker();
PointDescription pointDescription = null;
if (selectedObjectContextMenuProvider != null) {
pointDescription = selectedObjectContextMenuProvider.getObjectName(newObject);
}
menu.show(ll, pointDescription, newObject);
view.refreshMap();
}
selectedObjectContextMenuProvider = null;
applyingMarkerLatLon = null;
}
@Override
public boolean isCancelled() {
return cancelApplyingNewMarkerPosition;
}
});
}
public void enterGpxDetailsMode() {
menu.updateMapCenter(null);
menu.hide();
mInGpxDetailsMode = true;
activity.disableDrawer();
mark(View.INVISIBLE, R.id.map_ruler_layout,
R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info);
View collapseButton = activity.findViewById(R.id.map_collapse_button);
if (collapseButton != null && collapseButton.getVisibility() == View.VISIBLE) {
wasCollapseButtonVisible = true;
collapseButton.setVisibility(View.INVISIBLE);
} else {
wasCollapseButtonVisible = false;
}
}
public void exitGpxDetailsMode() {
mInGpxDetailsMode = false;
activity.enableDrawer();
mark(View.VISIBLE, R.id.map_ruler_layout,
R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info);
View collapseButton = activity.findViewById(R.id.map_collapse_button);
if (collapseButton != null && wasCollapseButtonVisible) {
collapseButton.setVisibility(View.VISIBLE);
}
}
private void quitMovingMarker() {
mInChangeMarkerPositionMode = false;
mark(View.VISIBLE, R.id.map_ruler_layout,
R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info);
View collapseButton = activity.findViewById(R.id.map_collapse_button);
if (collapseButton != null && wasCollapseButtonVisible) {
collapseButton.setVisibility(View.VISIBLE);
}
}
private void enterMovingMode(RotatedTileBox tileBox) {
Vibrator vibrator = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(VIBRATE_SHORT);
menu.updateMapCenter(null);
menu.hide();
LatLon ll = menu.getLatLon();
RotatedTileBox rb = new RotatedTileBox(tileBox);
rb.setCenterLocation(0.5f, 0.5f);
rb.setLatLonCenter(ll.getLatitude(), ll.getLongitude());
double lat = rb.getLatFromPixel(tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
double lon = rb.getLonFromPixel(tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
view.setLatLon(lat, lon);
mInChangeMarkerPositionMode = true;
mMoveMarkerBottomSheetHelper.show(menu.getLeftIcon());
mark(View.INVISIBLE, R.id.map_ruler_layout,
R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info);
View collapseButton = activity.findViewById(R.id.map_collapse_button);
if (collapseButton != null && collapseButton.getVisibility() == View.VISIBLE) {
wasCollapseButtonVisible = true;
collapseButton.setVisibility(View.INVISIBLE);
} else {
wasCollapseButtonVisible = false;
}
view.refreshMap();
}
private void mark(int status, int... widgets) {
for (int widget : widgets) {
View v = activity.findViewById(widget);
if (v != null) {
v.setVisibility(status);
}
}
}
public void cancelMovingMarker() {
cancelApplyingNewMarkerPosition = true;
quitMovingMarker();
activity.getContextMenu().show();
applyingMarkerLatLon = null;
}
public boolean showContextMenu(double latitude, double longitude, boolean showUnknownLocation) {
RotatedTileBox cp = activity.getMapView().getCurrentRotatedTileBox();
float x = cp.getPixXFromLatLon(latitude, longitude);
float y = cp.getPixYFromLatLon(latitude, longitude);
return showContextMenu(new PointF(x, y), activity.getMapView().getCurrentRotatedTileBox(), showUnknownLocation);
}
public boolean showContextMenu(@NonNull LatLon latLon,
@Nullable PointDescription pointDescription,
@Nullable Object object,
@Nullable IContextMenuProvider provider) {
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;
}
private boolean showContextMenu(PointF point, RotatedTileBox tileBox, boolean showUnknownLocation) {
LatLon objectLatLon = null;
Map<Object, IContextMenuProvider> selectedObjects = selectObjectsForContextMenu(tileBox, point, false);
NativeOsmandLibrary nativeLib = NativeOsmandLibrary.getLoadedLibrary();
if (nativeLib != null) {
MapRenderRepositories maps = activity.getMyApplication().getResourceManager().getRenderer();
RenderingContext rc = maps.getVisibleRenderingContext();
RenderedObject[] renderedObjects = null;
if (rc != null && rc.zoom == tileBox.getZoom()) {
double lat = MapUtils.get31LatitudeY((int) (rc.topY * rc.tileDivisor));
double lon = MapUtils.get31LongitudeX((int) (rc.leftX * rc.tileDivisor));
float x = tileBox.getPixXFromLatLon(lat, lon);
float y = tileBox.getPixYFromLatLon(lat, lon);
renderedObjects = nativeLib.searchRenderedObjectsFromContext(rc, (int) (point.x - x), (int) (point.y - y));
}
if (renderedObjects != null) {
// double tx = c.first/ (rc->tileDivisor);
// double ty = c.second / (rc->tileDivisor);
// float dTileX = tx - rc->getLeft();
// float dTileY = ty - rc->getTop();
// rc->calcX = rc->cosRotateTileSize * dTileX - rc->sinRotateTileSize * dTileY;
// rc->calcY = rc->sinRotateTileSize * dTileX + rc->cosRotateTileSize * dTileY;
int TILE_SIZE = 256;
double cosRotateTileSize = Math.cos(Math.toRadians(rc.rotate)) * TILE_SIZE;
double sinRotateTileSize = Math.sin(Math.toRadians(rc.rotate)) * TILE_SIZE;
for(RenderedObject r : renderedObjects) {
double cx = r.getBbox().centerX();
double cy = r.getBbox().centerY();
double dTileX = (cx * cosRotateTileSize + cy * sinRotateTileSize) / (TILE_SIZE * TILE_SIZE);
double dTileY = (cy * cosRotateTileSize - cx * sinRotateTileSize) / (TILE_SIZE * TILE_SIZE);
int x31 = (int) ((dTileX + rc.leftX) * rc.tileDivisor);
int y31 = (int) ((dTileY + rc.topY) * rc.tileDivisor);
double lat = MapUtils.get31LatitudeY(y31);
double lon = MapUtils.get31LongitudeX(x31);
r.setLabelLatLon(new LatLon(lat, lon));
}
IContextMenuProvider poiMenuProvider = activity.getMapLayers().getPoiMapLayer();
for (RenderedObject renderedObject : renderedObjects) {
if (renderedObject.getX() != null && renderedObject.getX().size() == 1
&& renderedObject.getY() != null && renderedObject.getY().size() == 1) {
objectLatLon = new LatLon(MapUtils.get31LatitudeY(renderedObject.getY().get(0)),
MapUtils.get31LongitudeX(renderedObject.getX().get(0)));
} else if (renderedObject.getLabelLatLon() != null) {
objectLatLon = renderedObject.getLabelLatLon();
}
if (renderedObject.getId() != null) {
List<String> names = new ArrayList<>();
if (!Algorithms.isEmpty(renderedObject.getName())) {
names.add(renderedObject.getName());
}
for (Entry<String, String> entry : renderedObject.getTags().entrySet()) {
if (entry.getKey().startsWith("name:") && !entry.getValue().equals("")) {
names.add(entry.getValue());
}
}
LatLon searchLatLon = objectLatLon;
if (searchLatLon == null) {
searchLatLon = tileBox.getLatLonFromPixel(point.x, point.y);
}
Amenity amenity = findAmenity(renderedObject.getId() >> 7, names, searchLatLon);
if (amenity != null) {
if (renderedObject.getX() != null && renderedObject.getX().size() > 1
&& renderedObject.getY() != null && renderedObject.getY().size() > 1) {
amenity.getX().addAll(renderedObject.getX());
amenity.getY().addAll(renderedObject.getY());
}
selectedObjects.put(amenity, poiMenuProvider);
continue;
}
selectedObjects.put(renderedObject, null);
}
}
}
}
if (selectedObjects.size() == 1) {
Object selectedObj = selectedObjects.keySet().iterator().next();
LatLon latLon = null;
PointDescription pointDescription = null;
final IContextMenuProvider provider = selectedObjects.get(selectedObj);
if (provider != null) {
latLon = provider.getObjectLocation(selectedObj);
pointDescription = provider.getObjectName(selectedObj);
}
if (latLon == null) {
latLon = objectLatLon;
}
if (latLon == null) {
latLon = getLatLon(point, tileBox);
}
showContextMenu(latLon, pointDescription, selectedObj, provider);
return true;
} else if (selectedObjects.size() > 1) {
selectedObjectContextMenuProvider = null;
showContextMenuForSelectedObjects(getLatLon(point, tileBox), selectedObjects);
return true;
} else if (showUnknownLocation) {
hideVisibleMenues();
selectedObjectContextMenuProvider = null;
LatLon latLon = getLatLon(point, tileBox);
activity.getMapViewTrackingUtilities().setMapLinkedToLocation(false);
menu.show(latLon, null, null);
return true;
}
return false;
}
@NonNull
private LatLon getLatLon(PointF point, RotatedTileBox tileBox) {
LatLon latLon;
final double lat = tileBox.getLatFromPixel((int) point.x, (int) point.y);
final double lon = tileBox.getLonFromPixel((int) point.x, (int) point.y);
latLon = new LatLon(lat, lon);
return latLon;
}
public boolean disableSingleTap() {
boolean res = false;
for (OsmandMapLayer lt : view.getLayers()) {
if (lt instanceof ContextMenuLayer.IContextMenuProvider) {
if (((IContextMenuProvider) lt).disableSingleTap()) {
res = true;
break;
}
}
}
return res;
}
public boolean disableLongPressOnMap() {
if (mInChangeMarkerPositionMode || mInGpxDetailsMode) {
return true;
}
boolean res = false;
for (OsmandMapLayer lt : view.getLayers()) {
if (lt instanceof ContextMenuLayer.IContextMenuProvider) {
if (((IContextMenuProvider) lt).disableLongPressOnMap()) {
res = true;
break;
}
}
}
return res;
}
private Map<Object, IContextMenuProvider> selectObjectsForContextMenu(RotatedTileBox tileBox,
PointF point, boolean acquireObjLatLon) {
List<LatLon> pressedLatLonFull = new ArrayList<>();
List<LatLon> pressedLatLonSmall = new ArrayList<>();
Map<Object, IContextMenuProvider> selectedObjects = new HashMap<>();
List<Object> s = new ArrayList<>();
for (OsmandMapLayer lt : view.getLayers()) {
if (lt instanceof ContextMenuLayer.IContextMenuProvider) {
s.clear();
final IContextMenuProvider l = (ContextMenuLayer.IContextMenuProvider) lt;
l.collectObjectsFromPoint(point, tileBox, s);
for (Object o : s) {
selectedObjects.put(o, l);
if (acquireObjLatLon && l.isObjectClickable(o)) {
LatLon latLon = l.getObjectLocation(o);
if (lt.isPresentInFullObjects(latLon) && !pressedLatLonFull.contains(latLon)) {
pressedLatLonFull.add(latLon);
} else if (lt.isPresentInSmallObjects(latLon) && !pressedLatLonSmall.contains(latLon)) {
pressedLatLonSmall.add(latLon);
}
}
}
}
}
if (acquireObjLatLon) {
this.pressedLatLonFull = pressedLatLonFull;
this.pressedLatLonSmall = pressedLatLonSmall;
}
return selectedObjects;
}
@Override
public boolean drawInScreenPixels() {
return true;
}
public boolean pressedContextMarker(RotatedTileBox tb, float px, float py) {
float markerX;
float markerY;
if (mInChangeMarkerPositionMode) {
markerX = tb.getCenterPixelX();
markerY = tb.getCenterPixelY();
} else if (menu.isActive()) {
LatLon latLon = menu.getLatLon();
markerX = tb.getPixXFromLatLon(latLon.getLatitude(), latLon.getLongitude());
markerY = tb.getPixYFromLatLon(latLon.getLatitude(), latLon.getLongitude());
} else {
return false;
}
Rect bs = contextMarker.getDrawable().getBounds();
int dx = (int) (px - markerX);
int dy = (int) (py - markerY);
int bx = dx + bs.width() / 2;
int by = dy + bs.height();
return (bs.contains(bx, by));
}
@Override
public boolean onSingleTap(PointF point, RotatedTileBox tileBox) {
if (mInChangeMarkerPositionMode || mInGpxDetailsMode) {
return true;
}
if (pressedContextMarker(tileBox, point.x, point.y)) {
hideVisibleMenues();
menu.show();
return true;
}
if (selectOnMap != null) {
LatLon latlon = tileBox.getLatLonFromPixel(point.x, point.y);
CallbackWithObject<LatLon> cb = selectOnMap;
cb.processResult(latlon);
menu.init(latlon, null, null);
selectOnMap = null;
return true;
}
if (!disableSingleTap()) {
boolean res = showContextMenu(point, tileBox, false);
if (res) {
return true;
}
}
hideVisibleMenues();
menu.onSingleTapOnMap();
return false;
}
private Amenity findAmenity(long id, List<String> names, LatLon latLon) {
QuadRect rect = MapUtils.calculateLatLonBbox(latLon.getLatitude(), latLon.getLongitude(), 50);
List<Amenity> amenities = activity.getMyApplication().getResourceManager().searchAmenities(
new BinaryMapIndexReader.SearchPoiTypeFilter() {
@Override
public boolean accept(PoiCategory type, String subcategory) {
return true;
}
@Override
public boolean isEmpty() {
return false;
}
}, rect.top, rect.left, rect.bottom, rect.right, -1, null);
Amenity res = null;
for (Amenity amenity : amenities) {
Long amenityId = amenity.getId() >> 1;
if (amenityId == id) {
res = amenity;
break;
}
}
if (res == null && names != null && names.size() > 0) {
for (Amenity amenity : amenities) {
for (String name : names) {
if (name.equals(amenity.getName())) {
res = amenity;
break;
}
}
if (res != null) {
break;
}
}
}
return res;
}
private void hideVisibleMenues() {
if (multiSelectionMenu.isVisible()) {
multiSelectionMenu.hide();
}
}
private void showContextMenuForSelectedObjects(final LatLon latLon, final Map<Object, IContextMenuProvider> selectedObjects) {
multiSelectionMenu.show(latLon, selectedObjects);
}
public void setMapQuickActionLayer(MapQuickActionLayer mapQuickActionLayer) {
this.mapQuickActionLayer = mapQuickActionLayer;
}
@Override
public boolean onTouchEvent(MotionEvent event, RotatedTileBox tileBox) {
if (movementListener.onTouchEvent(event)) {
if (menu.isVisible()) {
menu.hide();
}
if (multiSelectionMenu.isVisible()) {
multiSelectionMenu.hide();
}
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!mInChangeMarkerPositionMode && !mInGpxDetailsMode) {
selectObjectsForContextMenu(tileBox, new PointF(event.getX(), event.getY()), true);
if (pressedLatLonFull.size() > 0 || pressedLatLonSmall.size() > 0) {
view.refreshMap();
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
pressedLatLonFull.clear();
pressedLatLonSmall.clear();
view.refreshMap();
break;
}
return false;
}
public interface IContextMenuProvider {
void collectObjectsFromPoint(PointF point, RotatedTileBox tileBox, List<Object> o);
LatLon getObjectLocation(Object o);
PointDescription getObjectName(Object o);
boolean disableSingleTap();
boolean disableLongPressOnMap();
boolean isObjectClickable(Object o);
}
public interface IMoveObjectProvider {
boolean isObjectMovable(Object o);
void applyNewObjectPosition(@NonNull Object o,
@NonNull LatLon position,
@Nullable ApplyMovedObjectCallback callback);
}
public interface ApplyMovedObjectCallback {
void onApplyMovedObject(boolean success, @Nullable Object newObject);
boolean isCancelled();
}
public interface IContextMenuProviderSelection {
int getOrder(Object o);
void setSelectedObject(Object o);
void clearSelectedObject();
}
private class MenuLayerOnGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return true;
}
}
}