package net.osmand.plus.views;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import net.osmand.data.FavouritePoint;
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.FavouritesDbHelper;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.base.FavoriteImageDrawable;
import net.osmand.plus.views.ContextMenuLayer.ApplyMovedObjectCallback;
import net.osmand.plus.views.MapTextLayer.MapTextProvider;
import java.util.ArrayList;
import java.util.List;
public class FavouritesLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider,
ContextMenuLayer.IMoveObjectProvider, MapTextProvider<FavouritePoint> {
protected int startZoom = 6;
protected OsmandMapTileView view;
private Paint paint;
private FavouritesDbHelper favorites;
protected List<FavouritePoint> cache = new ArrayList<>();
private MapTextLayer textLayer;
private Paint paintIcon;
private Bitmap pointSmall;
private int defaultColor;
private OsmandSettings settings;
private ContextMenuLayer contextMenuLayer;
protected String getObjName() {
return view.getContext().getString(R.string.favorite);
}
protected List<? extends FavouritePoint> getPoints() {
return favorites.getFavouritePoints();
}
@Override
public void initLayer(OsmandMapTileView view) {
this.view = view;
paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
settings = view.getApplication().getSettings();
favorites = view.getApplication().getFavorites();
textLayer = view.getLayerByClass(MapTextLayer.class);
paintIcon = new Paint();
pointSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_white_shield_small);
defaultColor = ContextCompat.getColor(view.getContext(), R.color.color_favorite);
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
}
private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) {
return (Math.abs(objx - ex) <= radius * 2 && Math.abs(objy - ey) <= radius * 2) ;
// return Math.abs(objx - ex) <= radius && (ey - objy) <= radius / 2 && (objy - ey) <= 3 * radius ;
//return Math.abs(objx - ex) <= radius && (ey - objy) <= radius / 2 && (objy - ey) <= 3 * radius ;
}
@Override
public void destroyLayer() {
}
@Override
public boolean drawInScreenPixels() {
return true;
}
@Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (contextMenuLayer.getMoveableObject() instanceof FavouritePoint) {
FavouritePoint objectInMotion = (FavouritePoint) contextMenuLayer.getMoveableObject();
FavoriteImageDrawable fid = FavoriteImageDrawable.getOrCreate(view.getContext(),
objectInMotion.getColor(), true);
PointF pf = contextMenuLayer.getMovableCenterPoint(tileBox);
fid.drawBitmapInCenter(canvas, pf.x, pf.y);
}
}
@Override
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
cache.clear();
if (this.settings.SHOW_FAVORITES.get()) {
if (tileBox.getZoom() >= startZoom) {
float iconSize = FavoriteImageDrawable.getOrCreate(view.getContext(), 0,
true).getIntrinsicWidth() * 3 / 2.5f;
QuadTree<QuadRect> boundIntersections = initBoundIntersections(tileBox);
// request to load
final QuadRect latLonBounds = tileBox.getLatLonBounds();
List<FavouritePoint> fullObjects = new ArrayList<>();
List<LatLon> fullObjectsLatLon = new ArrayList<>();
List<LatLon> smallObjectsLatLon = new ArrayList<>();
for (FavouritePoint o : getPoints()) {
if (!o.isVisible()) {
continue;
}
float x = tileBox.getPixXFromLatLon(o.getLatitude(), o.getLongitude());
float y = tileBox.getPixYFromLatLon(o.getLatitude(), o.getLongitude());
if (intersects(boundIntersections, x, y, iconSize, iconSize)) {
@ColorInt
int col = o.getColor() == 0 || o.getColor() == Color.BLACK ? defaultColor : o.getColor();
paintIcon.setColorFilter(new PorterDuffColorFilter(col, PorterDuff.Mode.MULTIPLY));
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 (FavouritePoint o : fullObjects) {
if (o != contextMenuLayer.getMoveableObject()) {
drawPoint(canvas, tileBox, latLonBounds, o);
}
}
this.fullObjectsLatLon = fullObjectsLatLon;
this.smallObjectsLatLon = smallObjectsLatLon;
}
}
if(textLayer.isVisible()) {
textLayer.putData(this, cache);
}
}
private void drawPoint(Canvas canvas, RotatedTileBox tileBox, final QuadRect latLonBounds, FavouritePoint o) {
if (o.isVisible() && o.getLatitude() >= latLonBounds.bottom && o.getLatitude() <= latLonBounds.top && o.getLongitude() >= latLonBounds.left
&& o.getLongitude() <= latLonBounds.right ) {
cache.add(o);
int x = (int) tileBox.getPixXFromLatLon(o.getLatitude(), o.getLongitude());
int y = (int) tileBox.getPixYFromLatLon(o.getLatitude(), o.getLongitude());
FavoriteImageDrawable fid = FavoriteImageDrawable.getOrCreate(view.getContext(), o.getColor(), true);
fid.drawBitmapInCenter(canvas, x, y);
}
}
@Override
public boolean onLongPressEvent(PointF point, RotatedTileBox tileBox) {
return false;
}
public void getFavoriteFromPoint(RotatedTileBox tb, PointF point, List<? super FavouritePoint> res) {
int r = (int) (15 * tb.getDensity());
int ex = (int) point.x;
int ey = (int) point.y;
for (FavouritePoint n : getPoints()) {
getFavFromPoint(tb, res, r, ex, ey, n);
}
}
private void getFavFromPoint(RotatedTileBox tb, List<? super FavouritePoint> res, int r, int ex, int ey,
FavouritePoint n) {
if (n.isVisible()) {
int x = (int) tb.getPixXFromLatLon(n.getLatitude(), n.getLongitude());
int y = (int) tb.getPixYFromLatLon(n.getLatitude(), n.getLongitude());
if (calculateBelongs(ex, ey, x, y, r)) {
res.add(n);
}
}
}
@Override
public PointDescription getObjectName(Object o) {
if(o instanceof FavouritePoint){
return ((FavouritePoint) o).getPointDescription(view.getContext()); //$NON-NLS-1$
}
return null;
}
@Override
public boolean disableSingleTap() {
return false;
}
@Override
public boolean disableLongPressOnMap() {
return false;
}
@Override
public boolean isObjectClickable(Object o) {
return o instanceof FavouritePoint && o != contextMenuLayer.getMoveableObject();
}
@Override
public void collectObjectsFromPoint(PointF point, RotatedTileBox tileBox, List<Object> res) {
if (this.settings.SHOW_FAVORITES.get() && tileBox.getZoom() >= startZoom) {
getFavoriteFromPoint(tileBox, point, res);
}
}
@Override
public LatLon getObjectLocation(Object o) {
if(o instanceof FavouritePoint){
return new LatLon(((FavouritePoint)o).getLatitude(), ((FavouritePoint)o).getLongitude());
}
return null;
}
@Override
public LatLon getTextLocation(FavouritePoint o) {
return new LatLon(o.getLatitude(), o.getLongitude());
}
@Override
public int getTextShift(FavouritePoint o, RotatedTileBox rb) {
return (int) (16 * rb.getDensity());
}
@Override
public String getText(FavouritePoint o) {
return PointDescription.getSimpleName(o, view.getContext());
}
@Override
public boolean isObjectMovable(Object o) {
return o instanceof FavouritePoint;
}
@Override
public void applyNewObjectPosition(@NonNull Object o,
@NonNull LatLon position,
@Nullable ApplyMovedObjectCallback callback) {
boolean result = false;
if (o instanceof FavouritePoint) {
favorites.editFavourite((FavouritePoint) o, position.getLatitude(), position.getLongitude());
result = true;
}
if (callback != null) {
callback.onApplyMovedObject(result, o);
}
}
}