From 1d6bdcb0f270bee99ac7e51996b3763ca616bee8 Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Fri, 1 Nov 2013 17:58:37 +0100
Subject: [PATCH] simplify map listener handling

---
 .../src/org/oscim/android/MapView.java        |   2 +-
 .../android/input/AndroidMotionEvent.java     |   9 --
 vtm-gdx/src/org/oscim/gdx/GdxMotionEvent.java |   6 -
 vtm/src/org/oscim/event/Dispatcher.java       |  19 ---
 vtm/src/org/oscim/event/EventDispatcher.java  |   8 --
 vtm/src/org/oscim/event/EventListener.java    |   5 -
 vtm/src/org/oscim/event/IListener.java        |   5 -
 vtm/src/org/oscim/event/KeyEvent.java         |  25 ----
 vtm/src/org/oscim/event/MapEvent.java         |  12 --
 vtm/src/org/oscim/event/MotionEvent.java      |   8 +-
 vtm/src/org/oscim/layers/MapEventLayer.java   |  20 +---
 .../tile/vector/labeling/LabelLayer.java      |  36 +++---
 vtm/src/org/oscim/map/Map.java                | 108 +++++++++---------
 13 files changed, 73 insertions(+), 190 deletions(-)
 delete mode 100644 vtm/src/org/oscim/event/Dispatcher.java
 delete mode 100644 vtm/src/org/oscim/event/EventDispatcher.java
 delete mode 100644 vtm/src/org/oscim/event/EventListener.java
 delete mode 100644 vtm/src/org/oscim/event/IListener.java
 delete mode 100644 vtm/src/org/oscim/event/KeyEvent.java
 delete mode 100644 vtm/src/org/oscim/event/MapEvent.java

diff --git a/vtm-android/src/org/oscim/android/MapView.java b/vtm-android/src/org/oscim/android/MapView.java
index 980da33a..a77a5871 100644
--- a/vtm-android/src/org/oscim/android/MapView.java
+++ b/vtm-android/src/org/oscim/android/MapView.java
@@ -218,7 +218,7 @@ public class MapView extends RelativeLayout {
 		mPausing = false;
 	}
 
-	AndroidMotionEvent mMotionEvent = new AndroidMotionEvent(this);
+	AndroidMotionEvent mMotionEvent = new AndroidMotionEvent();
 
 	@Override
 	public boolean onTouchEvent(android.view.MotionEvent motionEvent) {
diff --git a/vtm-android/src/org/oscim/android/input/AndroidMotionEvent.java b/vtm-android/src/org/oscim/android/input/AndroidMotionEvent.java
index 8ad606bf..c26fffe4 100644
--- a/vtm-android/src/org/oscim/android/input/AndroidMotionEvent.java
+++ b/vtm-android/src/org/oscim/android/input/AndroidMotionEvent.java
@@ -18,15 +18,6 @@ import org.oscim.event.MotionEvent;
 
 public class AndroidMotionEvent extends MotionEvent {
 
-	/**
-	 *
-	 */
-	private static final long serialVersionUID = 1L;
-
-	public AndroidMotionEvent(Object source) {
-		super(source);
-	}
-
 	android.view.MotionEvent mEvent;
 
 	public void wrap(android.view.MotionEvent e) {
diff --git a/vtm-gdx/src/org/oscim/gdx/GdxMotionEvent.java b/vtm-gdx/src/org/oscim/gdx/GdxMotionEvent.java
index 7bd878e2..b7a82911 100644
--- a/vtm-gdx/src/org/oscim/gdx/GdxMotionEvent.java
+++ b/vtm-gdx/src/org/oscim/gdx/GdxMotionEvent.java
@@ -6,12 +6,6 @@ import com.badlogic.gdx.InputProcessor;
 
 public class GdxMotionEvent extends MotionEvent implements InputProcessor {
 
-	private static final long serialVersionUID = 1L;
-
-	public GdxMotionEvent(Object source) {
-		super(source);
-	}
-
 	@Override
 	public int getAction() {
 		return 0;
diff --git a/vtm/src/org/oscim/event/Dispatcher.java b/vtm/src/org/oscim/event/Dispatcher.java
deleted file mode 100644
index 7fc5012f..00000000
--- a/vtm/src/org/oscim/event/Dispatcher.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.oscim.event;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class Dispatcher<T> {
-	protected List<T> listeners = new ArrayList<T>();
-
-	public void addListener(T l) {
-		if (!listeners.contains(l))
-			listeners.add(l);
-	}
-
-	public void removeListener(T l) {
-		listeners.remove(l);
-	}
-
-	public abstract void dispatch();
-}
diff --git a/vtm/src/org/oscim/event/EventDispatcher.java b/vtm/src/org/oscim/event/EventDispatcher.java
deleted file mode 100644
index 8c8ee368..00000000
--- a/vtm/src/org/oscim/event/EventDispatcher.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.oscim.event;
-
-public interface EventDispatcher {
-
-	public void addListener(String type, EventListener listener);
-
-	public void removeListener(String type, EventListener listener);
-}
diff --git a/vtm/src/org/oscim/event/EventListener.java b/vtm/src/org/oscim/event/EventListener.java
deleted file mode 100644
index fda4d0b6..00000000
--- a/vtm/src/org/oscim/event/EventListener.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.oscim.event;
-
-public interface EventListener {
-	public void handleEvent(MapEvent event);
-}
diff --git a/vtm/src/org/oscim/event/IListener.java b/vtm/src/org/oscim/event/IListener.java
deleted file mode 100644
index 55b6ffd7..00000000
--- a/vtm/src/org/oscim/event/IListener.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.oscim.event;
-
-public interface IListener {
-
-}
diff --git a/vtm/src/org/oscim/event/KeyEvent.java b/vtm/src/org/oscim/event/KeyEvent.java
deleted file mode 100644
index a59ce9a9..00000000
--- a/vtm/src/org/oscim/event/KeyEvent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2013
- *
- * 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.event;
-
-public class KeyEvent extends MapEvent {
-
-	private static final long serialVersionUID = 1L;
-
-	public KeyEvent(Object source) {
-		super(source);
-	}
-
-}
diff --git a/vtm/src/org/oscim/event/MapEvent.java b/vtm/src/org/oscim/event/MapEvent.java
deleted file mode 100644
index ab3be154..00000000
--- a/vtm/src/org/oscim/event/MapEvent.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.oscim.event;
-
-import java.util.EventObject;
-
-public class MapEvent extends EventObject {
-
-	private static final long serialVersionUID = 1L;
-
-	public MapEvent(Object source) {
-		super(source);
-	}
-}
diff --git a/vtm/src/org/oscim/event/MotionEvent.java b/vtm/src/org/oscim/event/MotionEvent.java
index bba5762b..612388b1 100644
--- a/vtm/src/org/oscim/event/MotionEvent.java
+++ b/vtm/src/org/oscim/event/MotionEvent.java
@@ -14,16 +14,10 @@
  */
 package org.oscim.event;
 
-public abstract class MotionEvent extends MapEvent {
-
-	private static final long serialVersionUID = 1L;
+public abstract class MotionEvent {
 
 	public static final String TYPE = "MotionEvent";
 
-	public MotionEvent(Object source) {
-		super(source);
-	}
-
 	public static final int ACTION_DOWN = 0;
 	public static final int ACTION_UP = 1;
 	public static final int ACTION_MOVE = 2;
diff --git a/vtm/src/org/oscim/layers/MapEventLayer.java b/vtm/src/org/oscim/layers/MapEventLayer.java
index 2c4384eb..83298217 100644
--- a/vtm/src/org/oscim/layers/MapEventLayer.java
+++ b/vtm/src/org/oscim/layers/MapEventLayer.java
@@ -15,8 +15,6 @@
 package org.oscim.layers;
 
 import org.oscim.core.Tile;
-import org.oscim.event.EventListener;
-import org.oscim.event.MapEvent;
 import org.oscim.event.MotionEvent;
 import org.oscim.map.Map;
 import org.oscim.map.Viewport;
@@ -33,7 +31,7 @@ import org.slf4j.LoggerFactory;
  *        http://en.wikipedia.org/wiki/Viterbi_algorithm
  */
 
-public class MapEventLayer extends Layer implements EventListener {
+public class MapEventLayer extends Layer implements Map.InputListener {
 	private static final boolean debug = false;
 	static final Logger log = LoggerFactory.getLogger(MapEventLayer.class);
 
@@ -68,24 +66,15 @@ public class MapEventLayer extends Layer implements EventListener {
 
 	public MapEventLayer(Map map) {
 		super(map);
-		map.addListener(MotionEvent.TYPE, this);
 		mMapPosition = map.getViewport();
 		mTracker = new VelocityTracker();
 	}
 
 	@Override
-	public void onDetach() {
-		mMap.removeListener(MotionEvent.TYPE, this);
+	public void onMotionEvent(MotionEvent event) {
+		onTouchEvent(event);
 	}
 
-	@Override
-	public void handleEvent(MapEvent event) {
-		if (event instanceof MotionEvent)
-			onTouchEvent((MotionEvent) event);
-	}
-
-	//private long mPrevTime;
-
 	private boolean mEnableRotation = true;
 	private boolean mEnableTilt = true;
 	private boolean mEnableMove = true;
@@ -111,11 +100,8 @@ public class MapEventLayer extends Layer implements EventListener {
 		mEnableZoom = enable;
 	}
 
-	//@Override
 	public boolean onTouchEvent(MotionEvent e) {
 
-		//mPrevTime = e.getTime();
-
 		int action = getAction(e);
 
 		if (action == MotionEvent.ACTION_DOWN) {
diff --git a/vtm/src/org/oscim/layers/tile/vector/labeling/LabelLayer.java b/vtm/src/org/oscim/layers/tile/vector/labeling/LabelLayer.java
index cd153dca..7b1e9524 100644
--- a/vtm/src/org/oscim/layers/tile/vector/labeling/LabelLayer.java
+++ b/vtm/src/org/oscim/layers/tile/vector/labeling/LabelLayer.java
@@ -15,8 +15,6 @@
 package org.oscim.layers.tile.vector.labeling;
 
 import org.oscim.core.MapPosition;
-import org.oscim.event.EventListener;
-import org.oscim.event.MapEvent;
 import org.oscim.event.MotionEvent;
 import org.oscim.layers.Layer;
 import org.oscim.map.Map;
@@ -24,7 +22,7 @@ import org.oscim.tiling.TileRenderer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class LabelLayer extends Layer implements EventListener, Map.UpdateListener {
+public class LabelLayer extends Layer implements Map.InputListener, Map.UpdateListener {
 	static final Logger log = LoggerFactory.getLogger(LabelLayer.class);
 	private final TextRenderer mTextRenderer;
 
@@ -33,8 +31,6 @@ public class LabelLayer extends Layer implements EventListener, Map.UpdateListen
 	public LabelLayer(Map map, TileRenderer tileRenderLayer) {
 		super(map);
 
-		map.addListener(MotionEvent.TYPE, this);
-
 		//mTextLayer = new org.oscim.renderer.layers.TextRenderLayer(map, tileRenderLayer);
 		mTextRenderer = new TextRenderer(map, tileRenderLayer);
 		mRenderer = mTextRenderer;
@@ -42,8 +38,6 @@ public class LabelLayer extends Layer implements EventListener, Map.UpdateListen
 
 	@Override
 	public void onDetach() {
-		mMap.removeListener(MotionEvent.TYPE, this);
-
 		// TODO stop and clear labeling thread
 		log.debug("DETACH");
 		mTextRenderer.clearLabels();
@@ -52,23 +46,19 @@ public class LabelLayer extends Layer implements EventListener, Map.UpdateListen
 	}
 
 	@Override
-	public void handleEvent(MapEvent event) {
-		if (event instanceof MotionEvent) {
-			MotionEvent e = (MotionEvent) event;
-
-			int action = e.getAction() & MotionEvent.ACTION_MASK;
-			if (action == MotionEvent.ACTION_POINTER_DOWN) {
-				multi++;
-				mTextRenderer.hold(true);
-			} else if (action == MotionEvent.ACTION_POINTER_UP) {
-				multi--;
-				if (multi == 0)
-					mTextRenderer.hold(false);
-			} else if (action == MotionEvent.ACTION_CANCEL) {
-				multi = 0;
-				log.debug("cancel " + multi);
+	public void onMotionEvent(MotionEvent e) {
+		int action = e.getAction() & MotionEvent.ACTION_MASK;
+		if (action == MotionEvent.ACTION_POINTER_DOWN) {
+			multi++;
+			mTextRenderer.hold(true);
+		} else if (action == MotionEvent.ACTION_POINTER_UP) {
+			multi--;
+			if (multi == 0)
 				mTextRenderer.hold(false);
-			}
+		} else if (action == MotionEvent.ACTION_CANCEL) {
+			multi = 0;
+			log.debug("cancel " + multi);
+			mTextRenderer.hold(false);
 		}
 	}
 
diff --git a/vtm/src/org/oscim/map/Map.java b/vtm/src/org/oscim/map/Map.java
index fd6ab1f5..677a52a0 100644
--- a/vtm/src/org/oscim/map/Map.java
+++ b/vtm/src/org/oscim/map/Map.java
@@ -15,15 +15,12 @@
 package org.oscim.map;
 
 import java.util.AbstractList;
-import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.oscim.core.BoundingBox;
 import org.oscim.core.MapPosition;
-import org.oscim.event.Dispatcher;
-import org.oscim.event.EventDispatcher;
-import org.oscim.event.EventListener;
-import org.oscim.event.IListener;
 import org.oscim.event.MotionEvent;
 import org.oscim.layers.Layer;
 import org.oscim.layers.MapEventLayer;
@@ -39,10 +36,30 @@ import org.oscim.utils.async.AsyncExecutor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public abstract class Map implements EventDispatcher {
+public abstract class Map {
 
 	static final Logger log = LoggerFactory.getLogger(Map.class);
 
+	/**
+	 * Listener interface for map update notifications.
+	 * Layers implementing this interface they will be automatically
+	 * regiseter when the layer is added to the map and unregistered when
+	 * the layer is removed.
+	 */
+	public interface UpdateListener {
+		void onMapUpdate(MapPosition mapPosition, boolean positionChanged, boolean clear);
+	}
+
+	/**
+	 * Listener interface for input events.
+	 * Layers implementing this interface they will be automatically
+	 * regiseter when the layer is added to the map and unregistered when
+	 * the layer is removed.
+	 */
+	public interface InputListener {
+		void onMotionEvent(MotionEvent e);
+	}
+
 	public static final boolean debugTheme = false;
 
 	private final Layers mLayers;
@@ -57,6 +74,9 @@ public abstract class Map implements EventDispatcher {
 
 	private VectorTileLayer mBaseLayer;
 
+	private Set<InputListener> mMotionListeners = new LinkedHashSet<InputListener>();
+	private Set<UpdateListener> mUpdateListeners = new LinkedHashSet<UpdateListener>();
+
 	public Map() {
 
 		mViewport = new Viewport(this);
@@ -183,7 +203,15 @@ public abstract class Map implements EventDispatcher {
 	 * Caution: Do not call directly!
 	 */
 	protected void updateLayers() {
-		mUpdateDispatcher.dispatch();
+		boolean changed = false;
+
+		// get the current MapPosition
+		changed |= mViewport.getMapPosition(mMapPosition);
+
+		for (UpdateListener l : mUpdateListeners)
+			l.onMapUpdate(mMapPosition, changed, mClearMap);
+
+		mClearMap = false;
 	}
 
 	/**
@@ -236,64 +264,31 @@ public abstract class Map implements EventDispatcher {
 		return mAnimator;
 	}
 
-	ArrayList<EventListener> mMotionListeners = new ArrayList<EventListener>();
-
-	@Override
-	public void addListener(String type, EventListener listener) {
-		if (type == MotionEvent.TYPE)
-			mMotionListeners.add(listener);
+	public void bind(InputListener listener) {
+		mMotionListeners.add(listener);
 	}
 
-	@Override
-	public void removeListener(String type, EventListener listener) {
-		if (type == MotionEvent.TYPE)
-			mMotionListeners.remove(listener);
+	public void unbind(InputListener listener) {
+		mMotionListeners.remove(listener);
 	}
 
 	public void handleMotionEvent(MotionEvent e) {
-		for (EventListener l : mMotionListeners)
-			l.handleEvent(e);
+		for (InputListener l : mMotionListeners)
+			l.onMotionEvent(e);
 	}
 
-	/**
-	 * Listener interface for map update notifications.
-	 * NOTE: Layers implementing this interface they will be automatically
-	 * registered when the layer is added to the map and unresitered when
-	 * the layer is removed.
-	 */
-	public interface UpdateListener extends IListener {
-		void onMapUpdate(MapPosition mapPosition, boolean positionChanged, boolean clear);
-	}
-
-	private class UpdateDispatcher extends Dispatcher<UpdateListener> {
-		@Override
-		public void dispatch() {
-			boolean changed = false;
-
-			// get the current MapPosition
-			changed |= mViewport.getMapPosition(mMapPosition);
-
-			for (UpdateListener l : listeners)
-				l.onMapUpdate(mMapPosition, changed, mClearMap);
-
-			mClearMap = false;
-		}
-	}
-
-	private final UpdateDispatcher mUpdateDispatcher = new UpdateDispatcher();
-
 	/**
 	 * Register UpdateListener
 	 */
-	public void addUpdateListener(UpdateListener l) {
-		mUpdateDispatcher.addListener(l);
+	public void bind(UpdateListener l) {
+		mUpdateListeners.add(l);
 	}
 
 	/**
 	 * Unregister UpdateListener
 	 */
-	public void removeUpdateListener(UpdateListener l) {
-		mUpdateDispatcher.removeListener(l);
+	public void unbind(UpdateListener l) {
+		mUpdateListeners.remove(l);
 	}
 
 	public final class Layers extends AbstractList<Layer> {
@@ -320,7 +315,9 @@ public abstract class Map implements EventDispatcher {
 				throw new IllegalArgumentException("layer added twice");
 
 			if (layer instanceof UpdateListener)
-				addUpdateListener((UpdateListener) layer);
+				bind((UpdateListener) layer);
+			if (layer instanceof InputListener)
+				bind((InputListener) layer);
 
 			mLayerList.add(index, layer);
 			mDirtyLayers = true;
@@ -333,7 +330,9 @@ public abstract class Map implements EventDispatcher {
 			Layer remove = mLayerList.remove(index);
 
 			if (remove instanceof UpdateListener)
-				removeUpdateListener((UpdateListener) remove);
+				unbind((UpdateListener) remove);
+			if (remove instanceof InputListener)
+				unbind((InputListener) remove);
 
 			return remove;
 		}
@@ -346,8 +345,11 @@ public abstract class Map implements EventDispatcher {
 			mDirtyLayers = true;
 			Layer remove = mLayerList.set(index, layer);
 
+			// unbind replaced layer
 			if (remove instanceof UpdateListener)
-				removeUpdateListener((UpdateListener) remove);
+				unbind((UpdateListener) remove);
+			if (remove instanceof InputListener)
+				unbind((InputListener) remove);
 
 			return remove;
 		}