package net.osmand.plus.audionotes; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.PointF; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import net.osmand.data.DataTileManager; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.data.QuadRect; import net.osmand.data.QuadTree; import net.osmand.data.RotatedTileBox; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.audionotes.AudioVideoNotesPlugin.Recording; import net.osmand.plus.views.ContextMenuLayer; import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider; import net.osmand.plus.views.OsmandMapLayer; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.util.Algorithms; import java.util.ArrayList; import java.util.List; public class AudioNotesLayer extends OsmandMapLayer implements IContextMenuProvider, ContextMenuLayer.IMoveObjectProvider { private static final int startZoom = 10; private MapActivity activity; private AudioVideoNotesPlugin plugin; private Paint pointAltUI; private Paint paintIcon; private OsmandMapTileView view; private Bitmap audio; private Bitmap video; private Bitmap photo; private Bitmap pointSmall; private ContextMenuLayer contextMenuLayer; public AudioNotesLayer(MapActivity activity, AudioVideoNotesPlugin plugin) { this.activity = activity; this.plugin = plugin; } @Override public void initLayer(OsmandMapTileView view) { this.view = view; pointAltUI = new Paint(); pointAltUI.setColor(0xa0FF3344); pointAltUI.setStyle(Style.FILL); audio = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_audio); video = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_video); photo = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_photo); pointSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_small); paintIcon = new Paint(); Paint point = new Paint(); point.setColor(Color.GRAY); point.setAntiAlias(true); point.setStyle(Style.STROKE); contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class); } public int getRadiusPoi(RotatedTileBox tb) { int r = 0; if (tb.getZoom() < startZoom) { r = 0; } else { r = 15; } return (int) (r * tb.getDensity()); } @Override public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { if (contextMenuLayer.getMoveableObject() instanceof Recording) { Recording objectInMotion = (Recording) contextMenuLayer.getMoveableObject(); PointF pf = contextMenuLayer.getMovableCenterPoint(tileBox); drawRecording(canvas, objectInMotion, pf.x, pf.y); } } @Override public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { if (tileBox.getZoom() >= startZoom) { float iconSize = audio.getWidth() * 3 / 2.5f; QuadTree<QuadRect> boundIntersections = initBoundIntersections(tileBox); DataTileManager<Recording> recs = plugin.getRecordings(); final QuadRect latlon = tileBox.getLatLonBounds(); List<Recording> objects = recs.getObjects(latlon.top, latlon.left, latlon.bottom, latlon.right); List<Recording> fullObjects = new ArrayList<>(); List<LatLon> fullObjectsLatLon = new ArrayList<>(); List<LatLon> smallObjectsLatLon = new ArrayList<>(); for (Recording o : objects) { if (o != contextMenuLayer.getMoveableObject()) { float x = tileBox.getPixXFromLatLon(o.getLatitude(), o.getLongitude()); float y = tileBox.getPixYFromLatLon(o.getLatitude(), o.getLongitude()); if (intersects(boundIntersections, x, y, iconSize, iconSize)) { canvas.drawBitmap(pointSmall, x - pointSmall.getWidth() / 2, y - pointSmall.getHeight() / 2, paintIcon); smallObjectsLatLon.add(new LatLon(o.getLatitude(), o.getLongitude())); } else { fullObjects.add(o); fullObjectsLatLon.add(new LatLon(o.getLatitude(), o.getLongitude())); } } } for (Recording o : fullObjects) { float x = tileBox.getPixXFromLatLon(o.getLatitude(), o.getLongitude()); float y = tileBox.getPixYFromLatLon(o.getLatitude(), o.getLongitude()); drawRecording(canvas, o, x, y); } this.fullObjectsLatLon = fullObjectsLatLon; this.smallObjectsLatLon = smallObjectsLatLon; } } private void drawRecording(Canvas canvas, Recording o, float x, float y) { Bitmap b; if (o.isPhoto()) { b = photo; } else if (o.isAudio()) { b = audio; } else { b = video; } canvas.drawBitmap(b, x - b.getWidth() / 2, y - b.getHeight() / 2, paintIcon); } @Override public void destroyLayer() { } @Override public boolean drawInScreenPixels() { return true; } @Override public PointDescription getObjectName(Object o) { if (o instanceof Recording) { Recording rec = (Recording) o; if (rec.getFile().exists()) { String recName = rec.getName(activity, true); if (Algorithms.isEmpty(recName)) { return new PointDescription(rec.getSearchHistoryType(), view.getResources().getString(R.string.recording_default_name)); } return new PointDescription(rec.getSearchHistoryType(), recName); } else { plugin.deleteRecording(rec, true); } } return null; } @Override public boolean disableSingleTap() { return false; } @Override public boolean disableLongPressOnMap() { return false; } @Override public boolean isObjectClickable(Object o) { return o instanceof Recording; } @Override public void collectObjectsFromPoint(PointF point, RotatedTileBox tileBox, List<Object> objects) { if (tileBox.getZoom() >= startZoom) { getRecordingsFromPoint(point, tileBox, objects); } } public void getRecordingsFromPoint(PointF point, RotatedTileBox tileBox, List<? super Recording> am) { int ex = (int) point.x; int ey = (int) point.y; int compare = getRadiusPoi(tileBox); int radius = compare * 3 / 2; for (Recording n : plugin.getAllRecordings()) { int x = (int) tileBox.getPixXFromLatLon(n.getLatitude(), n.getLongitude()); int y = (int) tileBox.getPixYFromLatLon(n.getLatitude(), n.getLongitude()); if (calculateBelongs(ex, ey, x, y, compare)) { compare = radius; am.add(n); } } } private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) { return Math.abs(objx - ex) <= radius && (ey - objy) <= radius / 2 && (objy - ey) <= 3 * radius; } @Override public LatLon getObjectLocation(Object o) { if (o instanceof Recording) { return new LatLon(((Recording) o).getLatitude(), ((Recording) o).getLongitude()); } return null; } @Override public boolean isObjectMovable(Object o) { return o instanceof Recording; } @Override public void applyNewObjectPosition(@NonNull Object o, @NonNull LatLon position, @Nullable ContextMenuLayer.ApplyMovedObjectCallback callback) { boolean result = false; if (o instanceof Recording) { result = ((Recording) o).setLocation(position); } if (callback != null) { callback.onApplyMovedObject(result, o); } } }