/*
* Copyright (c) 2015 Daimler AG / Moovel GmbH
*
* All rights reserved
*/
package com.car2go.maps.osm;
import android.content.Context;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import com.car2go.maps.AnyMap;
import com.car2go.maps.CameraUpdate;
import com.car2go.maps.Projection;
import com.car2go.maps.UiSettings;
import com.car2go.maps.model.CameraPosition;
import com.car2go.maps.model.Circle;
import com.car2go.maps.model.CircleOptions;
import com.car2go.maps.model.LatLng;
import com.car2go.maps.model.LatLngBounds;
import com.car2go.maps.model.Marker;
import com.car2go.maps.model.MarkerOptions;
import com.car2go.maps.model.Polygon;
import com.car2go.maps.model.PolygonOptions;
import com.car2go.maps.model.Polyline;
import com.car2go.maps.model.PolylineOptions;
import com.car2go.maps.model.VisibleRegion;
import com.car2go.maps.osm.drawable.DrawableComponentFactory;
import org.osmdroid.api.IGeoPoint;
import org.osmdroid.events.MapListener;
import org.osmdroid.events.ScrollEvent;
import org.osmdroid.events.ZoomEvent;
import org.osmdroid.views.MapView;
import static com.car2go.maps.osm.util.OsmUtils.toLatLng;
/**
* Implementation of {@link AnyMap} which works with Open Street Maps
*/
class OsmMap implements AnyMap {
private final org.osmdroid.views.MapView map;
private final CameraUpdateHandler cameraUpdateHandler;
private final MyLocationHandler myLocationHandler;
private final DrawableComponentFactory drawableComponentFactory;
private final UiSettings uiSettings;
private OnMapClickListener onMapClickListener = OnMapClickListener.NULL;
private OnMapLongClickListener onMapLongClickListener = OnMapLongClickListener.NULL;
private boolean mapEnabled = true;
OsmMap(MapView map) {
this.map = map;
cameraUpdateHandler = new CameraUpdateHandler(map);
myLocationHandler = new MyLocationHandler(map);
drawableComponentFactory = new DrawableComponentFactory(map);
uiSettings = new OsmUiSettings();
map.setOnTouchListener(new MapTouchListener(map.getContext()));
}
@Override
public void moveCamera(CameraUpdate cameraUpdate) {
cameraUpdateHandler.moveCamera(cameraUpdate);
}
@Override
public void animateCamera(CameraUpdate cameraUpdate) {
cameraUpdateHandler.animateCamera(cameraUpdate);
}
@Override
public void animateCamera(CameraUpdate cameraUpdate, CancelableCallback callback) {
cameraUpdateHandler.animateCamera(cameraUpdate, callback);
}
@Override
public void animateCamera(CameraUpdate cameraUpdate, int duration, CancelableCallback callback) {
cameraUpdateHandler.animateCamera(cameraUpdate, duration, callback);
}
@Override
public CameraPosition getCameraPosition() {
return currentCameraPosition();
}
@Override
public Projection getProjection() {
org.osmdroid.views.Projection projection = map.getProjection();
return new OsmProjection(
new VisibleRegion(
new LatLngBounds(
new LatLng(
projection.getSouthWest().getLatitude(),
projection.getSouthWest().getLongitude()
),
new LatLng(
projection.getNorthEast().getLatitude(),
projection.getNorthEast().getLongitude()
)
)
)
);
}
@Override
public Marker addMarker(MarkerOptions options) {
return drawableComponentFactory.addMarker(options);
}
@Override
public Circle addCircle(CircleOptions options) {
return drawableComponentFactory.addCircle(options);
}
@Override
public Polygon addPolygon(PolygonOptions options) {
return drawableComponentFactory.addPolygon(options);
}
@Override
public Polyline addPolyline(PolylineOptions options) {
return drawableComponentFactory.addPolyline(options);
}
@Override
public UiSettings getUiSettings() {
return uiSettings;
}
@Override
public void setOnMapClickListener(OnMapClickListener listener) {
onMapClickListener = (listener == null)
? OnMapClickListener.NULL
: listener;
}
@Override
public void setOnMapLongClickListener(OnMapLongClickListener listener) {
onMapLongClickListener = (listener == null)
? OnMapLongClickListener.NULL
: listener;
}
@Override
public void setOnCameraChangeListener(OnCameraChangeListener listener) {
map.setMapListener(new OsmMapListener(listener));
}
@Override
public void setOnMarkerClickListener(OnMarkerClickListener listener) {
drawableComponentFactory.setOnMarkerClickListener(listener);
}
@Override
public void setInfoWindowAdapter(InfoWindowAdapter adapter) {
// Do nothing
}
@Override
public void setTrafficEnabled(boolean enabled) {
// Do nothing
}
@Override
public void setMyLocationEnabled(boolean enabled) {
myLocationHandler.setMyLocationEnabled(enabled);
}
@Override
public void setMapType(Type type) {
// Do nothing
}
@Override
public void setPadding(int left, int top, int right, int bottom) {
map.setTranslationY((top - bottom) / 2f);
map.setTranslationX((left - right) / 2f);
}
@Override
public void onUserLocationChanged(LatLng location, float accuracy) {
//Do nothing
}
private CameraPosition currentCameraPosition() {
final IGeoPoint center = map.getMapCenter();
final int zoomLevel = map.getZoomLevel();
return new CameraPosition(
new LatLng(center.getLatitude(), center.getLongitude()),
zoomLevel
);
}
/**
* Detects clicks and long-clicks on map
*/
private class MapTouchListener implements View.OnTouchListener, GestureDetector.OnGestureListener {
private GestureDetector gestureDetector;
public MapTouchListener(Context context) {
gestureDetector = new GestureDetector(context, this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (!mapEnabled) {
return true;
}
gestureDetector.onTouchEvent(event);
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
onMapClickListener.onMapClick(touchPoint(e));
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
onMapLongClickListener.onMapLongClick(touchPoint(e));
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
private LatLng touchPoint(MotionEvent e) {
IGeoPoint geoPoint = map.getProjection().fromPixels(
(int) e.getX(),
(int) e.getY()
);
return toLatLng(geoPoint);
}
}
/**
* Listens for map position changes and delegates them
* to {@link com.car2go.maps.AnyMap.OnCameraChangeListener}
*/
private class OsmMapListener implements MapListener {
private final OnCameraChangeListener listener;
private OsmMapListener(OnCameraChangeListener listener) {
this.listener = listener;
}
@Override
public boolean onScroll(ScrollEvent event) {
notifyListener();
return false;
}
@Override
public boolean onZoom(ZoomEvent event) {
notifyListener();
return false;
}
private void notifyListener() {
listener.onCameraChange(
currentCameraPosition()
);
}
}
/**
* UI settings for OpenStreetMap
*/
private class OsmUiSettings implements UiSettings {
@Override
public void setAllGesturesEnabled(final boolean enabled) {
mapEnabled = enabled;
}
@Override
public void setMyLocationButtonEnabled(boolean enabled) {
// Do nothing
}
@Override
public void setMapToolbarEnabled(boolean enabled) {
// Do nothing
}
}
}