package cgeo.geocaching.maps.mapsforge.v6; import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.location.Viewport; import cgeo.geocaching.maps.MapMode; import cgeo.geocaching.maps.interfaces.OnMapDragListener; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; import android.annotation.SuppressLint; import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; import org.mapsforge.core.model.LatLong; import org.mapsforge.core.model.Point; import org.mapsforge.core.util.MercatorProjection; import org.mapsforge.map.android.view.MapView; public class MfMapView extends MapView { private final GestureDetector gestureDetector; private OnMapDragListener onDragListener; public MfMapView(final Context context, final AttributeSet attributeSet) { super(context, attributeSet); gestureDetector = new GestureDetector(context, new GestureListener()); } public Viewport getViewport() { final LatLong center = getModel().mapViewPosition.getCenter(); return new Viewport(new Geopoint(center.latitude, center.longitude), getLatitudeSpan(), getLongitudeSpan()); } public double getLatitudeSpan() { double span = 0; final long mapSize = MercatorProjection.getMapSize(getModel().mapViewPosition.getZoomLevel(), getModel().displayModel.getTileSize()); final Point center = MercatorProjection.getPixelAbsolute(getModel().mapViewPosition.getCenter(), mapSize); if (getHeight() > 0) { try { final LatLong low = MercatorProjection.fromPixels(center.x, center.y - getHeight() / 2, mapSize); final LatLong high = MercatorProjection.fromPixels(center.x, center.y + getHeight() / 2, mapSize); span = Math.abs(high.latitude - low.latitude); } catch (final IllegalArgumentException ex) { Log.w("Exception when calculating latitude span", ex); } } return span; } public double getLongitudeSpan() { double span = 0; final long mapSize = MercatorProjection.getMapSize(getModel().mapViewPosition.getZoomLevel(), getModel().displayModel.getTileSize()); final Point center = MercatorProjection.getPixelAbsolute(getModel().mapViewPosition.getCenter(), mapSize); if (getWidth() > 0) { try { final LatLong low = MercatorProjection.fromPixels(center.x - getWidth() / 2, center.y, mapSize); final LatLong high = MercatorProjection.fromPixels(center.x + getWidth() / 2, center.y, mapSize); span = Math.abs(high.longitude - low.longitude); } catch (final IllegalArgumentException ex) { Log.w("Exception when calculating longitude span", ex); } } return span; } public int getMapZoomLevel() { return getModel().mapViewPosition.getZoomLevel() + 3; } public void setMapZoomLevel(final int zoomLevel) { getModel().mapViewPosition.setZoomLevel((byte) (zoomLevel - 3)); } public void zoomToViewport(final Viewport viewport) { if (viewport.bottomLeft.equals(viewport.topRight)) { setMapZoomLevel(Settings.getMapZoom(MapMode.SINGLE)); } else { final int tileSize = getModel().displayModel.getTileSize(); final long mapSize = MercatorProjection.getMapSize((byte) 0, tileSize); final double dxMax = MercatorProjection.longitudeToPixelX(viewport.getLongitudeMax(), mapSize) / tileSize; final double dxMin = MercatorProjection.longitudeToPixelX(viewport.getLongitudeMin(), mapSize) / tileSize; final double zoomX = Math.floor(-Math.log(3.8) * Math.log(Math.abs(dxMax - dxMin)) + getWidth() / tileSize); final double dyMax = MercatorProjection.longitudeToPixelX(viewport.getLatitudeMax(), mapSize) / tileSize; final double dyMin = MercatorProjection.longitudeToPixelX(viewport.getLatitudeMin(), mapSize) / tileSize; final double zoomY = Math.floor(-Math.log(3.8) * Math.log(Math.abs(dyMax - dyMin)) + getHeight() / tileSize); final byte newZoom = (byte) Math.min(zoomX, zoomY); getModel().mapViewPosition.setZoomLevel(newZoom); } getModel().mapViewPosition.setCenter(new LatLong(viewport.getCenter().getLatitude(), viewport.getCenter().getLongitude())); } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(final MotionEvent ev) { gestureDetector.onTouchEvent(ev); return super.onTouchEvent(ev); } private class GestureListener extends SimpleOnGestureListener { @Override public boolean onDoubleTap(final MotionEvent e) { if (onDragListener != null) { onDragListener.onDrag(); } return true; } @Override public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX, final float distanceY) { if (onDragListener != null) { onDragListener.onDrag(); } return super.onScroll(e1, e2, distanceX, distanceY); } } public void setOnMapDragListener(final OnMapDragListener onDragListener) { this.onDragListener = onDragListener; } }