package org.osmdroid.views.overlay;
import java.util.AbstractList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.CopyOnWriteArrayList;
import org.osmdroid.api.IMapView;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.Overlay.Snappable;
import android.graphics.Canvas;
import android.graphics.Point;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
public class DefaultOverlayManager extends AbstractList<Overlay> implements OverlayManager {
private TilesOverlay mTilesOverlay;
private final CopyOnWriteArrayList<Overlay> mOverlayList;
public DefaultOverlayManager(final TilesOverlay tilesOverlay) {
setTilesOverlay(tilesOverlay);
mOverlayList = new CopyOnWriteArrayList<Overlay>();
}
@Override
public Overlay get(final int pIndex) {
return mOverlayList.get(pIndex);
}
@Override
public int size() {
return mOverlayList.size();
}
@Override
public void add(final int pIndex, final Overlay pElement) {
if (pElement==null){
//#396 fix, null check
Exception ex = new Exception();
Log.e(IMapView.LOGTAG, "Attempt to add a null overlay to the collection. This is probably a bug and should be reported!",ex);
} else {
mOverlayList.add(pIndex, pElement);
}
}
@Override
public Overlay remove(final int pIndex) {
return mOverlayList.remove(pIndex);
}
@Override
public Overlay set(final int pIndex, final Overlay pElement) {
//#396 fix, null check
if (pElement==null){
Exception ex = new Exception();
Log.e(IMapView.LOGTAG, "Attempt to set a null overlay to the collection. This is probably a bug and should be reported!",ex);
return null;
} else {
Overlay overlay = mOverlayList.set(pIndex, pElement);
return overlay;
}
}
@Override
public TilesOverlay getTilesOverlay() {
return mTilesOverlay;
}
@Override
public void setTilesOverlay(final TilesOverlay tilesOverlay) {
mTilesOverlay = tilesOverlay;
}
@Override
public Iterable<Overlay> overlaysReversed() {
return new Iterable<Overlay>() {
@Override
public Iterator<Overlay> iterator() {
final ListIterator<Overlay> i = mOverlayList.listIterator(mOverlayList.size());
return new Iterator<Overlay>() {
@Override
public boolean hasNext() {
return i.hasPrevious();
}
@Override
public Overlay next() {
return i.previous();
}
@Override
public void remove() {
i.remove();
}
};
}
};
}
@Override
public List<Overlay> overlays() {
return mOverlayList;
}
@Override
public void onDraw(final Canvas c, final MapView pMapView) {
//always pass false, the shadow parameter will be removed in a later version of osmdroid, this change should result in the on draw being called twice
if (mTilesOverlay != null && mTilesOverlay.isEnabled()) {
mTilesOverlay.draw(c, pMapView, false);
}
//always pass false, the shadow parameter will be removed in a later version of osmdroid, this change should result in the on draw being called twice
for (final Overlay overlay : mOverlayList) {
//#396 fix, null check
if (overlay!=null && overlay.isEnabled()) {
overlay.draw(c, pMapView, false);
}
}
//potential fix for #52 pMapView.invalidate();
}
@Override
public void onDetach(final MapView pMapView) {
if (mTilesOverlay != null) {
mTilesOverlay.onDetach(pMapView);
}
for (final Overlay overlay : this.overlaysReversed()) {
overlay.onDetach(pMapView);
}
this.clear();
}
@Override
public boolean onKeyDown(final int keyCode, final KeyEvent event, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onKeyDown(keyCode, event, pMapView)) {
return true;
}
}
return false;
}
@Override
public boolean onKeyUp(final int keyCode, final KeyEvent event, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onKeyUp(keyCode, event, pMapView)) {
return true;
}
}
return false;
}
@Override
public boolean onTouchEvent(final MotionEvent event, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onTouchEvent(event, pMapView)) {
return true;
}
}
return false;
}
@Override
public boolean onTrackballEvent(final MotionEvent event, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onTrackballEvent(event, pMapView)) {
return true;
}
}
return false;
}
@Override
public boolean onSnapToItem(final int x, final int y, final Point snapPoint, final IMapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay instanceof Snappable) {
if (((Snappable) overlay).onSnapToItem(x, y, snapPoint, pMapView)) {
return true;
}
}
}
return false;
}
/* GestureDetector.OnDoubleTapListener */
@Override
public boolean onDoubleTap(final MotionEvent e, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onDoubleTap(e, pMapView)) {
return true;
}
}
return false;
}
@Override
public boolean onDoubleTapEvent(final MotionEvent e, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onDoubleTapEvent(e, pMapView)) {
return true;
}
}
return false;
}
@Override
public boolean onSingleTapConfirmed(final MotionEvent e, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onSingleTapConfirmed(e, pMapView)) {
return true;
}
}
return false;
}
/* OnGestureListener */
@Override
public boolean onDown(final MotionEvent pEvent, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onDown(pEvent, pMapView)) {
return true;
}
}
return false;
}
@Override
public boolean onFling(final MotionEvent pEvent1, final MotionEvent pEvent2,
final float pVelocityX, final float pVelocityY, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onFling(pEvent1, pEvent2, pVelocityX, pVelocityY, pMapView)) {
return true;
}
}
return false;
}
@Override
public boolean onLongPress(final MotionEvent pEvent, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onLongPress(pEvent, pMapView)) {
return true;
}
}
return false;
}
@Override
public boolean onScroll(final MotionEvent pEvent1, final MotionEvent pEvent2,
final float pDistanceX, final float pDistanceY, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onScroll(pEvent1, pEvent2, pDistanceX, pDistanceY, pMapView)) {
return true;
}
}
return false;
}
@Override
public void onShowPress(final MotionEvent pEvent, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
overlay.onShowPress(pEvent, pMapView);
}
}
@Override
public boolean onSingleTapUp(final MotionEvent pEvent, final MapView pMapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay.onSingleTapUp(pEvent, pMapView)) {
return true;
}
}
return false;
}
// ** Options Menu **//
@Override
public void setOptionsMenusEnabled(final boolean pEnabled) {
for (final Overlay overlay : mOverlayList) {
if ((overlay instanceof IOverlayMenuProvider)
&& ((IOverlayMenuProvider) overlay).isOptionsMenuEnabled()) {
((IOverlayMenuProvider) overlay).setOptionsMenuEnabled(pEnabled);
}
}
}
@Override
public boolean onCreateOptionsMenu(final Menu pMenu, final int menuIdOffset, final MapView mapView) {
boolean result = true;
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay instanceof IOverlayMenuProvider) {
final IOverlayMenuProvider overlayMenuProvider = (IOverlayMenuProvider) overlay;
if (overlayMenuProvider.isOptionsMenuEnabled()) {
result &= overlayMenuProvider.onCreateOptionsMenu(pMenu, menuIdOffset, mapView);
}
}
}
if (mTilesOverlay != null && mTilesOverlay.isOptionsMenuEnabled()) {
result &= mTilesOverlay.onCreateOptionsMenu(pMenu, menuIdOffset, mapView);
}
return result;
}
@Override
public boolean onPrepareOptionsMenu(final Menu pMenu, final int menuIdOffset, final MapView mapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay instanceof IOverlayMenuProvider) {
final IOverlayMenuProvider overlayMenuProvider = (IOverlayMenuProvider) overlay;
if (overlayMenuProvider.isOptionsMenuEnabled()) {
overlayMenuProvider.onPrepareOptionsMenu(pMenu, menuIdOffset, mapView);
}
}
}
if (mTilesOverlay != null && mTilesOverlay.isOptionsMenuEnabled()) {
mTilesOverlay.onPrepareOptionsMenu(pMenu, menuIdOffset, mapView);
}
return true;
}
@Override
public boolean onOptionsItemSelected(final MenuItem item, final int menuIdOffset, final MapView mapView) {
for (final Overlay overlay : this.overlaysReversed()) {
if (overlay instanceof IOverlayMenuProvider) {
final IOverlayMenuProvider overlayMenuProvider = (IOverlayMenuProvider) overlay;
if (overlayMenuProvider.isOptionsMenuEnabled() &&
overlayMenuProvider.onOptionsItemSelected(item, menuIdOffset, mapView)) {
return true;
}
}
}
if (mTilesOverlay != null &&
mTilesOverlay.isOptionsMenuEnabled() &&
mTilesOverlay.onOptionsItemSelected(item, menuIdOffset, mapView)) {
return true;
}
return false;
}
}