vtm/vtm/src/org/oscim/view/Layers.java
2013-10-09 02:38:00 +02:00

497 lines
12 KiB
Java

/*
* Copyright 2012 osmdroid authors
* Copyright 2013 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.view;
import java.util.AbstractList;
import java.util.concurrent.CopyOnWriteArrayList;
import org.oscim.backend.Log;
import org.oscim.backend.input.KeyEvent;
import org.oscim.backend.input.MotionEvent;
import org.oscim.core.MapPosition;
import org.oscim.core.PointF;
import org.oscim.layers.InputLayer;
import org.oscim.layers.Layer;
import org.oscim.layers.overlay.Overlay.Snappable;
import org.oscim.renderer.RenderLayer;
public class Layers extends AbstractList<Layer> {
private final static String TAG = Layers.class.getName();
private final static boolean debugInput = false;
private final CopyOnWriteArrayList<Layer> mLayerList;
Layers() {
mLayerList = new CopyOnWriteArrayList<Layer>();
}
@Override
public synchronized Layer get(final int pIndex) {
return mLayerList.get(pIndex);
}
@Override
public synchronized int size() {
return mLayerList.size();
}
@Override
public synchronized void add(final int pIndex, final Layer pElement) {
mLayerList.add(pIndex, pElement);
mDirtyLayers = true;
}
@Override
public synchronized Layer remove(final int pIndex) {
mDirtyLayers = true;
return mLayerList.remove(pIndex);
}
@Override
public synchronized Layer set(final int pIndex, final Layer pElement) {
mDirtyLayers = true;
return mLayerList.set(pIndex, pElement);
}
private boolean mDirtyLayers;
private RenderLayer[] mDrawLayers;
public RenderLayer[] getRenderLayers() {
if (mDirtyLayers)
updateLayers();
return mDrawLayers;
}
public void onDetach() {
if (mDirtyLayers)
updateLayers();
for (Layer o : mLayers)
o.onDetach();
}
public void onUpdate(MapPosition mapPosition, boolean changed, boolean clear) {
if (mDirtyLayers)
updateLayers();
for (Layer l : mLayers)
l.onUpdate(mapPosition, changed, clear);
}
public void destroy() {
if (mDirtyLayers)
updateLayers();
for (Layer l : mLayers) {
l.destroy();
}
}
Layer[] mLayers;
InputLayer[] mInputLayer;
private synchronized void updateLayers() {
if (!mDirtyLayers)
return;
mLayers = new Layer[mLayerList.size()];
int numRenderLayers = 0;
int numInputLayers = 0;
//Log.d(TAG, "update layers:");
for (int i = 0, n = mLayerList.size(); i < n; i++) {
Layer o = mLayerList.get(i);
//Log.d(TAG, "\t" + o.getClass().getName());
if (o.getLayer() != null)
numRenderLayers++;
if (o instanceof InputLayer)
numInputLayers++;
mLayers[i] = o;
}
mDrawLayers = new RenderLayer[numRenderLayers];
mInputLayer = new InputLayer[numInputLayers];
for (int i = 0, cntR = 0, cntI = 1, n = mLayerList.size(); i < n; i++) {
Layer o = mLayerList.get(i);
RenderLayer l = o.getLayer();
if (l != null)
mDrawLayers[cntR++] = l;
if (o instanceof InputLayer) {
// sort from top to bottom, so that highest layers
// process event first.
mInputLayer[numInputLayers - cntI] = (InputLayer) o;
cntI++;
}
}
mDirtyLayers = false;
}
private boolean mCancelGesture;
public boolean handleMotionEvent(MotionEvent e) {
boolean handleGesture = true;
if (mCancelGesture) {
int action = e.getAction();
handleGesture = (action == MotionEvent.ACTION_CANCEL ||
action == MotionEvent.ACTION_UP);
}
// if (handleGesture) {
// if (mGestureDetector.onTouchEvent(e))
// return true;
//
// mCancelGesture = false;
// }
if (onTouchEvent(e))
return true;
return false;
}
/**
* Call this to not foward events to generic GestureDetector until
* next ACTION_UP or ACTION_CANCEL event. - Use with care for the
* case that an InputLayer recognized the start of its gesture and
* does further processing in only onTouch callback.
*/
public void cancelGesture() {
mCancelGesture = true;
}
public boolean onTouchEvent(final MotionEvent event) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer) {
if (o.onTouchEvent(event)) {
if (debugInput)
Log.d(TAG, "onTouch\t\t" + o.getClass());
return true;
}
}
return false;
}
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer)
if (o.onKeyDown(keyCode, event))
return true;
return false;
}
public boolean onKeyUp(final int keyCode, final KeyEvent event) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer)
if (o.onKeyUp(keyCode, event))
return true;
return false;
}
public boolean onTrackballEvent(final MotionEvent event) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer)
if (o.onTrackballEvent(event))
return true;
return false;
}
public boolean onSnapToItem(final int x, final int y, final PointF snapPoint) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer)
if (o instanceof Snappable)
if (((Snappable) o).onSnapToItem(x, y, snapPoint))
return true;
return false;
}
/* GestureDetector.OnDoubleTapListener */
public boolean onDoubleTap(final MotionEvent e) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer) {
if (o.onDoubleTap(e)) {
if (debugInput)
Log.d(TAG, "onDoubleTap\t" + o.getClass());
return true;
}
}
return false;
}
public boolean onDoubleTapEvent(final MotionEvent e) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer) {
if (o.onDoubleTapEvent(e)) {
if (debugInput)
Log.d(TAG, "onDoubleTapEvent\t" + o.getClass());
return true;
}
}
return false;
}
public boolean onSingleTapConfirmed(final MotionEvent e) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer) {
if (o.onSingleTapConfirmed(e)) {
if (debugInput)
Log.d(TAG, "onSingleTapConfirmed\tt" + o.getClass());
return true;
}
}
return false;
}
/* OnGestureListener */
public boolean onDown(final MotionEvent pEvent) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer) {
if (o.onDown(pEvent)) {
if (debugInput)
Log.d(TAG, "onDown\t" + o.getClass());
return true;
}
}
return false;
}
////@Override
//public boolean onFling(final MotionEvent pEvent1, final MotionEvent pEvent2,
// final float pVelocityX, final float pVelocityY) {
// if (mDirtyLayers)
// updateLayers();
//
// for (InputLayer o : mInputLayer) {
// if (o.onFling(pEvent1, pEvent2, pVelocityX, pVelocityY)) {
// if (debugInput)
// Log.d(TAG, "onFling\t" + o.getClass());
// return true;
// }
// }
// return false;
//}
public void onLongPress(final MotionEvent pEvent) {
if (mCancelGesture)
return;
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer)
if (o.onLongPress(pEvent))
return;
}
public boolean onScroll(final MotionEvent pEvent1, final MotionEvent pEvent2,
final float pDistanceX, final float pDistanceY) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer) {
if (o.onScroll(pEvent1, pEvent2, pDistanceX, pDistanceY)) {
if (debugInput)
Log.d(TAG, "onScroll\t" + o.getClass());
return true;
}
}
return false;
}
public void onShowPress(final MotionEvent pEvent) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer)
o.onShowPress(pEvent);
}
public boolean onSingleTapUp(final MotionEvent pEvent) {
if (mDirtyLayers)
updateLayers();
for (InputLayer o : mInputLayer) {
if (o.onSingleTapUp(pEvent)) {
if (debugInput)
Log.d(TAG, "onSingleTapUp\t" + o.getClass());
return true;
}
}
return false;
}
// /**
// * Gets the optional TilesLayer class.
// *
// * @return the tilesLayer
// */
// public TilesLayer getTilesLayer() {
// return mTilesLayer;
// }
//
// /**
// * Sets the optional TilesLayer class. If set, this overlay will be
// drawn before all other
// * overlays and will not be included in the editable list of overlays and
// can't be cleared
// * except by a subsequent call to setTilesLayer().
// *
// * @param tilesLayer
// * the tilesLayer to set
// */
// public void setTilesLayer(final TilesLayer tilesLayer) {
// mTilesLayer = tilesLayer;
// }
// public void onDraw(final Canvas c, final MapView pMapView) {
// // if ((mTilesLayer != null) && mTilesLayer.isEnabled()) {
// // mTilesLayer.draw(c, pMapView, true);
// // }
// //
// // if ((mTilesLayer != null) && mTilesLayer.isEnabled()) {
// // mTilesLayer.draw(c, pMapView, false);
// // }
//
// for (final Layer overlay : mLayerList) {
// if (overlay.isEnabled()) {
// overlay.draw(c, pMapView, true);
// }
// }
//
// for (final Layer overlay : mLayerList) {
// if (overlay.isEnabled()) {
// overlay.draw(c, pMapView, false);
// }
// }
//
// }
// ** Options Menu **//
// public void setOptionsMenusEnabled(final boolean pEnabled) {
// for (final Layer overlay : mLayerList) {
// if ((overlay instanceof ILayerMenuProvider)
// && ((ILayerMenuProvider) overlay).isOptionsMenuEnabled()) {
// ((ILayerMenuProvider) overlay).setOptionsMenuEnabled(pEnabled);
// }
// }
// }
//
// public boolean onCreateOptionsMenu(final Menu pMenu, final int
// menuIdOffset,
// final MapView map) {
// boolean result = true;
// for (final Layer overlay : this.overlaysReversed()) {
// if ((overlay instanceof ILayerMenuProvider)
// && ((ILayerMenuProvider) overlay).isOptionsMenuEnabled()) {
// result &= ((ILayerMenuProvider) overlay).onCreateOptionsMenu(pMenu,
// menuIdOffset,
// map);
// }
// }
//
// if ((mTilesLayer != null) && (mTilesLayer instanceof
// ILayerMenuProvider)
// && ((ILayerMenuProvider) mTilesLayer).isOptionsMenuEnabled()) {
// result &= mTilesLayer.onCreateOptionsMenu(pMenu, menuIdOffset,
// map);
// }
//
// return result;
// }
//
// public boolean onPrepareOptionsMenu(final Menu pMenu, final int
// menuIdOffset,
// final MapView map) {
// for (final Layer overlay : this.overlaysReversed()) {
// if ((overlay instanceof ILayerMenuProvider)
// && ((ILayerMenuProvider) overlay).isOptionsMenuEnabled()) {
// ((ILayerMenuProvider) overlay).onPrepareOptionsMenu(pMenu,
// menuIdOffset, map);
// }
// }
//
// if ((mTilesLayer != null) && (mTilesLayer instanceof
// ILayerMenuProvider)
// && ((ILayerMenuProvider) mTilesLayer).isOptionsMenuEnabled()) {
// mTilesLayer.onPrepareOptionsMenu(pMenu, menuIdOffset, map);
// }
//
// return true;
// }
//
// public boolean onOptionsItemSelected(final MenuItem item, final int
// menuIdOffset,
// final MapView map) {
// for (final Layer overlay : this.overlaysReversed()) {
// if ((overlay instanceof ILayerMenuProvider)
// && ((ILayerMenuProvider) overlay).isOptionsMenuEnabled()
// && ((ILayerMenuProvider) overlay).onOptionsItemSelected(item,
// menuIdOffset,
// map)) {
// return true;
// }
// }
//
// if ((mTilesLayer != null)
// && (mTilesLayer instanceof ILayerMenuProvider)
// && ((ILayerMenuProvider) mTilesLayer).isOptionsMenuEnabled()
// && ((ILayerMenuProvider) mTilesLayer).onOptionsItemSelected(item,
// menuIdOffset,
// map)) {
// return true;
// }
//
// return false;
// }
}