/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* 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.map;
import java.util.AbstractList;
import java.util.concurrent.CopyOnWriteArrayList;
import org.oscim.event.Gesture;
import org.oscim.event.GestureListener;
import org.oscim.event.MotionEvent;
import org.oscim.layers.Layer;
import org.oscim.map.Map.InputListener;
import org.oscim.map.Map.UpdateListener;
import org.oscim.renderer.LayerRenderer;
public final class Layers extends AbstractList<Layer> {
private final CopyOnWriteArrayList<Layer> mLayerList;
private final Map mMap;
private boolean mDirtyLayers;
private LayerRenderer[] mLayerRenderer;
private Layer[] mLayers;
Layers(Map map) {
mMap = map;
mLayerList = new CopyOnWriteArrayList<Layer>();
}
@Override
public synchronized Layer get(int index) {
return mLayerList.get(index);
}
@Override
public synchronized int size() {
return mLayerList.size();
}
@Override
public synchronized void add(int index, Layer layer) {
if (mLayerList.contains(layer))
throw new IllegalArgumentException("layer added twice");
if (layer instanceof UpdateListener)
mMap.events.bind((UpdateListener) layer);
if (layer instanceof InputListener)
mMap.input.bind((InputListener) layer);
mLayerList.add(index, layer);
mDirtyLayers = true;
}
@Override
public synchronized Layer remove(int index) {
mDirtyLayers = true;
Layer remove = mLayerList.remove(index);
if (remove instanceof UpdateListener)
mMap.events.unbind((UpdateListener) remove);
if (remove instanceof InputListener)
mMap.input.unbind((InputListener) remove);
return remove;
}
@Override
public synchronized Layer set(int index, Layer layer) {
if (mLayerList.contains(layer))
throw new IllegalArgumentException("layer added twice");
mDirtyLayers = true;
Layer remove = mLayerList.set(index, layer);
// unbind replaced layer
if (remove instanceof UpdateListener)
mMap.events.unbind((UpdateListener) remove);
if (remove instanceof InputListener)
mMap.input.unbind((InputListener) remove);
return remove;
}
/**
* Should only be used by MapRenderer.
*
* @return the current LayerRenderer as array.
* */
public LayerRenderer[] getLayerRenderer() {
if (mDirtyLayers)
updateLayers();
return mLayerRenderer;
}
void destroy() {
if (mDirtyLayers)
updateLayers();
for (Layer o : mLayers)
o.onDetach();
}
boolean handleGesture(Gesture g, MotionEvent e) {
if (mDirtyLayers)
updateLayers();
for (Layer o : mLayers)
if (o instanceof GestureListener)
if (((GestureListener) o).onGesture(g, e))
return true;
return false;
}
private synchronized void updateLayers() {
mLayers = new Layer[mLayerList.size()];
int numRenderLayers = 0;
for (int i = 0, n = mLayerList.size(); i < n; i++) {
Layer o = mLayerList.get(i);
if (o.getRenderer() != null)
numRenderLayers++;
mLayers[n - i - 1] = o;
}
mLayerRenderer = new LayerRenderer[numRenderLayers];
for (int i = 0, cnt = 0, n = mLayerList.size(); i < n; i++) {
Layer o = mLayerList.get(i);
LayerRenderer l = o.getRenderer();
if (l != null)
mLayerRenderer[cnt++] = l;
}
mDirtyLayers = false;
}
}