From e15163bb089a418a7018153604e8c49686332667 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Fri, 14 Feb 2014 14:50:19 +0100 Subject: [PATCH] use EventDispatcher for Input- and Map-Events --- .../src/org/oscim/android/MapScaleBar.java | 9 +- .../src/org/oscim/android/MapView.java | 3 +- vtm/src/org/oscim/event/Event.java | 9 ++ vtm/src/org/oscim/event/EventDispatcher.java | 60 ++------- vtm/src/org/oscim/event/EventListener.java | 8 ++ .../org/oscim/layers/CustomRenderLayer.java | 3 +- vtm/src/org/oscim/layers/MapEventLayer.java | 9 +- .../oscim/layers/tile/BitmapTileLayer.java | 8 +- vtm/src/org/oscim/layers/tile/TileLayer.java | 16 ++- .../tile/vector/labeling/LabelLayer.java | 48 ++++---- vtm/src/org/oscim/map/Layers.java | 13 +- vtm/src/org/oscim/map/Map.java | 114 ++++++++---------- vtm/src/org/oscim/tiling/TileManager.java | 21 +++- 13 files changed, 153 insertions(+), 168 deletions(-) create mode 100644 vtm/src/org/oscim/event/Event.java create mode 100644 vtm/src/org/oscim/event/EventListener.java diff --git a/vtm-android/src/org/oscim/android/MapScaleBar.java b/vtm-android/src/org/oscim/android/MapScaleBar.java index 9af443f0..64e6cc7e 100644 --- a/vtm-android/src/org/oscim/android/MapScaleBar.java +++ b/vtm-android/src/org/oscim/android/MapScaleBar.java @@ -17,12 +17,13 @@ package org.oscim.android; */ import java.util.HashMap; -import java.util.Map; import org.oscim.android.canvas.AndroidBitmap; import org.oscim.core.MapPosition; import org.oscim.core.MercatorProjection; +import org.oscim.event.Event; import org.oscim.layers.Layer; +import org.oscim.map.Map; import org.oscim.map.Map.UpdateListener; import org.oscim.renderer.BitmapRenderer; @@ -71,7 +72,7 @@ public class MapScaleBar extends Layer implements UpdateListener { private boolean mRedrawNeeded; private double mPrevLatitude = -1; private final double mPrevScale = -1; - private final Map mTextFields; + private final HashMap mTextFields; private final Bitmap mBitmap; // passed to BitmapRenderer - need to sync on this object. @@ -102,7 +103,9 @@ public class MapScaleBar extends Layer implements UpdateListener { } @Override - public void onMapUpdate(MapPosition mapPosition, boolean changed, boolean clear) { + public void onMapEvent(Event e, MapPosition mapPosition) { + if (e == Map.UPDATE_EVENT) + return; double latitude = MercatorProjection.toLatitude(mapPosition.y); diff --git a/vtm-android/src/org/oscim/android/MapView.java b/vtm-android/src/org/oscim/android/MapView.java index b6b97b09..a5097542 100644 --- a/vtm-android/src/org/oscim/android/MapView.java +++ b/vtm-android/src/org/oscim/android/MapView.java @@ -152,8 +152,7 @@ public class MapView extends RelativeLayout { if (mGestureDetector.onTouchEvent(motionEvent)) return true; - mMap.handleMotionEvent(mMotionEvent.wrap(motionEvent)); - + mMap.input.fire(null, mMotionEvent.wrap(motionEvent)); return true; } diff --git a/vtm/src/org/oscim/event/Event.java b/vtm/src/org/oscim/event/Event.java new file mode 100644 index 00000000..4c1ad029 --- /dev/null +++ b/vtm/src/org/oscim/event/Event.java @@ -0,0 +1,9 @@ +package org.oscim.event; + +/** + * The Class Event to be sub-classed by event-producers. Should be used + * to distinguish the type of event when more than one is produced. + */ +public class Event { + +} diff --git a/vtm/src/org/oscim/event/EventDispatcher.java b/vtm/src/org/oscim/event/EventDispatcher.java index 87605920..6d471255 100644 --- a/vtm/src/org/oscim/event/EventDispatcher.java +++ b/vtm/src/org/oscim/event/EventDispatcher.java @@ -5,70 +5,32 @@ import org.oscim.utils.pool.LList; /** * The Class EventDispatcher. * - * Events MUST be dispached from main-loop! To add events from other + * Events MUST be dispatched from main-loop! To add events from other * threads use: * Map.post(new Runnable(){ public void run(tell(event,data);)};); * * @param the event source type * @param the event 'data' type */ -public class EventDispatcher { - - /** - * Generic event-listener interface. - * - * @param the type of event 'data' - */ - public interface Listener { - - /** - * The onEvent handler to be implemented by Listeners. - * - * @param source the event source - * @param event the event object/type - * @param data some object involved in this event - */ - public void onEvent(Object source, Event event, E data); - } - - /** - * The Class Event to be subclassed by event-producers. Should be used - * to distinguish the type of event when more than one is produced. - */ - public static class Event { - // nothing here - } - - /** The event source object. */ - protected final T mSource; +public abstract class EventDispatcher { /** The list of listeners. */ - protected LList> mListeners; - - /** - * Instantiates a new event dispatcher. - * - * @param source the event-source - */ - public EventDispatcher(T source) { - mSource = source; - } + protected LList mListeners; /** * Bind listener for event notifications. */ - public void bind(Listener listener) { + public void bind(E listener) { if (LList.find(mListeners, listener) != null) { - // throw some poo? return; } - mListeners = LList.push(mListeners, new LList>(listener)); + mListeners = LList.push(mListeners, new LList(listener)); } /** - * Unbind listener. + * Remove listener. */ - public void unbind(Listener listener) { + public void unbind(E listener) { mListeners = LList.remove(mListeners, listener); } @@ -78,9 +40,11 @@ public class EventDispatcher { * @param event the event * @param data the data */ - public void tell(Event event, E data) { - for (LList> l = mListeners; l != null; l = l.next) { - l.data.onEvent(mSource, event, data); + public abstract void tell(E listener, Event event, T data); + + public void fire(Event event, T data) { + for (LList l = mListeners; l != null; l = l.next) { + tell(l.data, event, data); } } } diff --git a/vtm/src/org/oscim/event/EventListener.java b/vtm/src/org/oscim/event/EventListener.java new file mode 100644 index 00000000..142954f0 --- /dev/null +++ b/vtm/src/org/oscim/event/EventListener.java @@ -0,0 +1,8 @@ +package org.oscim.event; + +/** + * Event-listener interface. + */ +public interface EventListener { + +} diff --git a/vtm/src/org/oscim/layers/CustomRenderLayer.java b/vtm/src/org/oscim/layers/CustomRenderLayer.java index 6e9931df..4dd06f8d 100644 --- a/vtm/src/org/oscim/layers/CustomRenderLayer.java +++ b/vtm/src/org/oscim/layers/CustomRenderLayer.java @@ -17,6 +17,7 @@ package org.oscim.layers; import org.oscim.core.MapPosition; +import org.oscim.event.Event; import org.oscim.map.Map; import org.oscim.map.Map.UpdateListener; import org.oscim.renderer.GLViewport; @@ -61,7 +62,7 @@ public class CustomRenderLayer extends Layer implements UpdateListener { private int someConccurentVariable; @Override - public void onMapUpdate(MapPosition mapPosition, boolean changed, boolean clear) { + public void onMapEvent(Event e, MapPosition mapPosition) { synchronized (mRenderer) { someConccurentVariable++; diff --git a/vtm/src/org/oscim/layers/MapEventLayer.java b/vtm/src/org/oscim/layers/MapEventLayer.java index e5733129..5bd27032 100644 --- a/vtm/src/org/oscim/layers/MapEventLayer.java +++ b/vtm/src/org/oscim/layers/MapEventLayer.java @@ -18,10 +18,12 @@ package org.oscim.layers; import org.oscim.backend.CanvasAdapter; import org.oscim.core.Tile; +import org.oscim.event.Event; import org.oscim.event.Gesture; import org.oscim.event.GestureListener; import org.oscim.event.MotionEvent; import org.oscim.map.Map; +import org.oscim.map.Map.InputListener; import org.oscim.map.ViewController; import org.oscim.utils.FastMath; import org.slf4j.Logger; @@ -30,7 +32,7 @@ import org.slf4j.LoggerFactory; /** * Changes Viewport by handling move, fling, scale, rotation and tilt gestures. */ -public class MapEventLayer extends Layer implements Map.InputListener, GestureListener { +public class MapEventLayer extends Layer implements InputListener, GestureListener { static final Logger log = LoggerFactory.getLogger(MapEventLayer.class); @@ -84,8 +86,8 @@ public class MapEventLayer extends Layer implements Map.InputListener, GestureLi } @Override - public void onMotionEvent(MotionEvent event) { - onTouchEvent(event); + public void onInputEvent(Event e, MotionEvent motionEvent) { + onTouchEvent(motionEvent); } public void enableRotation(boolean enable) { @@ -496,4 +498,5 @@ public class MapEventLayer extends Layer implements Map.InputListener, GestureLi // return sum; //} } + } diff --git a/vtm/src/org/oscim/layers/tile/BitmapTileLayer.java b/vtm/src/org/oscim/layers/tile/BitmapTileLayer.java index 1793a963..bab4ba6d 100644 --- a/vtm/src/org/oscim/layers/tile/BitmapTileLayer.java +++ b/vtm/src/org/oscim/layers/tile/BitmapTileLayer.java @@ -24,6 +24,7 @@ import org.oscim.backend.canvas.Bitmap; import org.oscim.core.MapElement; import org.oscim.core.MapPosition; import org.oscim.core.Tile; +import org.oscim.event.Event; import org.oscim.map.Map; import org.oscim.renderer.elements.BitmapLayer; import org.oscim.renderer.elements.ElementLayers; @@ -71,8 +72,11 @@ public class BitmapTileLayer extends TileLayer { } @Override - public void onMapUpdate(MapPosition pos, boolean changed, boolean clear) { - super.onMapUpdate(pos, changed, clear); + public void onMapEvent(Event event, MapPosition pos) { + super.onMapEvent(event, pos); + + if (event != Map.POSITION_EVENT) + return; FadeStep[] fade = mTileSource.getFadeSteps(); diff --git a/vtm/src/org/oscim/layers/tile/TileLayer.java b/vtm/src/org/oscim/layers/tile/TileLayer.java index a68a55ad..52d86feb 100644 --- a/vtm/src/org/oscim/layers/tile/TileLayer.java +++ b/vtm/src/org/oscim/layers/tile/TileLayer.java @@ -17,6 +17,7 @@ package org.oscim.layers.tile; import org.oscim.core.MapPosition; +import org.oscim.event.Event; import org.oscim.layers.Layer; import org.oscim.map.Map; import org.oscim.map.Map.UpdateListener; @@ -69,19 +70,22 @@ public abstract class TileLayer extends Layer implements UpdateListener { } @Override - public void onMapUpdate(MapPosition mapPosition, boolean changed, boolean clear) { - if (clear) { + public void onMapEvent(Event event, MapPosition mapPosition) { + + if (event == Map.CLEAR_EVENT) { // sync with TileRenderer synchronized (mRenderer) { tileRenderer().clearTiles(); mTileManager.init(); } - changed = true; - } + if (mTileManager.update(mapPosition)) + notifyLoaders(); - if (changed && mTileManager.update(mapPosition)) - notifyLoaders(); + } else if (event == Map.POSITION_EVENT) { + if (mTileManager.update(mapPosition)) + notifyLoaders(); + } } @Override 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 f8f4c4fe..b4b98b6f 100644 --- a/vtm/src/org/oscim/layers/tile/vector/labeling/LabelLayer.java +++ b/vtm/src/org/oscim/layers/tile/vector/labeling/LabelLayer.java @@ -17,9 +17,7 @@ package org.oscim.layers.tile.vector.labeling; import org.oscim.core.MapPosition; -import org.oscim.event.EventDispatcher.Event; -import org.oscim.event.EventDispatcher.Listener; -import org.oscim.event.MotionEvent; +import org.oscim.event.Event; import org.oscim.layers.Layer; import org.oscim.layers.tile.vector.VectorTileLayer; import org.oscim.map.Map; @@ -29,8 +27,7 @@ import org.oscim.utils.async.SimpleWorker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class LabelLayer extends Layer implements Map.InputListener, Map.UpdateListener, - Listener { +public class LabelLayer extends Layer implements Map.UpdateListener, TileManager.Listener { static final Logger log = LoggerFactory.getLogger(LabelLayer.class); @@ -94,33 +91,34 @@ public class LabelLayer extends Layer implements Map.InputListener, Map.UpdateLi } @Override - public void onMapUpdate(MapPosition mapPosition, boolean changed, boolean clear) { - if (clear) + public void onMapEvent(Event event, MapPosition mapPosition) { + + if (event == Map.CLEAR_EVENT) mWorker.cancel(true); - if (changed || clear) + if (event == Map.POSITION_EVENT) mWorker.submit(MAX_RELABEL_DELAY); } - @Override - 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); - // } - } + // @Override + // 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); + // // } + // } @Override - public void onEvent(Object source, Event e, MapTile tile) { + public void onTileManagerEvent(Event e, MapTile tile) { if (e == TileManager.TILE_LOADED) { if (tile.isVisible) mWorker.submit(MAX_RELABEL_DELAY / 4); diff --git a/vtm/src/org/oscim/map/Layers.java b/vtm/src/org/oscim/map/Layers.java index 18db4742..753ec6e9 100644 --- a/vtm/src/org/oscim/map/Layers.java +++ b/vtm/src/org/oscim/map/Layers.java @@ -57,9 +57,10 @@ public final class Layers extends AbstractList { throw new IllegalArgumentException("layer added twice"); if (layer instanceof UpdateListener) - mMap.bind((UpdateListener) layer); + mMap.events.bind((UpdateListener) layer); + if (layer instanceof InputListener) - mMap.bind((InputListener) layer); + mMap.input.bind((InputListener) layer); mLayerList.add(index, layer); mDirtyLayers = true; @@ -72,9 +73,9 @@ public final class Layers extends AbstractList { Layer remove = mLayerList.remove(index); if (remove instanceof UpdateListener) - mMap.unbind((UpdateListener) remove); + mMap.events.unbind((UpdateListener) remove); if (remove instanceof InputListener) - mMap.unbind((InputListener) remove); + mMap.input.unbind((InputListener) remove); return remove; } @@ -89,9 +90,9 @@ public final class Layers extends AbstractList { // unbind replaced layer if (remove instanceof UpdateListener) - mMap.unbind((UpdateListener) remove); + mMap.events.unbind((UpdateListener) remove); if (remove instanceof InputListener) - mMap.unbind((InputListener) remove); + mMap.input.unbind((InputListener) remove); return remove; } diff --git a/vtm/src/org/oscim/map/Map.java b/vtm/src/org/oscim/map/Map.java index b5512eeb..5fd3f9f9 100644 --- a/vtm/src/org/oscim/map/Map.java +++ b/vtm/src/org/oscim/map/Map.java @@ -16,10 +16,10 @@ */ package org.oscim.map; -import java.util.LinkedHashSet; -import java.util.Set; - import org.oscim.core.MapPosition; +import org.oscim.event.Event; +import org.oscim.event.EventDispatcher; +import org.oscim.event.EventListener; import org.oscim.event.Gesture; import org.oscim.event.GestureDetector; import org.oscim.event.MotionEvent; @@ -45,8 +45,8 @@ public abstract class Map { * register 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); + public interface UpdateListener extends EventListener { + void onMapEvent(Event e, MapPosition mapPosition); } /** @@ -55,41 +55,67 @@ public abstract class Map { * register when the layer is added to the map and unregistered when * the layer is removed. */ - public interface InputListener { - void onMotionEvent(MotionEvent e); + + public interface InputListener extends EventListener { + void onInputEvent(Event e, MotionEvent motionEvent); } + /***/ + public static Event UPDATE_EVENT = new Event(); + /** + * Map state has changed in a way that all layers should clear their state + * e.g. the theme or the TilesSource has changed + */ + public static Event CLEAR_EVENT = new Event(); + public static Event POSITION_EVENT = new Event(); + + public final EventDispatcher input; + public final EventDispatcher events; + private final Layers mLayers; private final ViewController mViewport; private final Animator mAnimator; - private final MapPosition mMapPosition; private final AsyncExecutor mAsyncExecutor; protected final MapEventLayer mEventLayer; protected GestureDetector mGestureDetector; - + /** + * Listener interface for map update notifications. + * Layers implementing this interface they will be automatically + * register when the layer is added to the map and unregistered when + * the layer is removed. + */ private VectorTileLayer mBaseLayer; - private Set mInputListenerSet = new LinkedHashSet(); - private InputListener[] mInputListeners; - - private Set mUpdateListenerSet = new LinkedHashSet(); - private UpdateListener[] mUpdateListeners; - protected boolean mClearMap = true; public Map() { mViewport = new ViewController(); mAnimator = new Animator(this); - mLayers = new Layers(this); + input = new EventDispatcher() { + + @Override + public void tell(InputListener l, Event e, MotionEvent d) { + l.onInputEvent(e, d); + } + }; + events = new EventDispatcher() { + + @Override + public void tell(UpdateListener l, Event e, MapPosition d) { + l.onMapEvent(e, d); + } + }; + mAsyncExecutor = new AsyncExecutor(2); mMapPosition = new MapPosition(); mEventLayer = new MapEventLayer(this); mLayers.add(0, mEventLayer); + } public MapEventLayer getEventLayer() { @@ -248,22 +274,6 @@ public abstract class Map { return mAnimator; } - /** - * Register UpdateListener - */ - public void bind(UpdateListener l) { - if (mUpdateListenerSet.add(l)) - mUpdateListeners = null; - } - - /** - * Unregister UpdateListener - */ - public void unbind(UpdateListener l) { - if (mUpdateListenerSet.remove(l)) - mUpdateListeners = null; - } - /** * This function is run on main-loop before rendering a frame. * Caution: Do not call directly! @@ -274,44 +284,16 @@ public abstract class Map { changed |= mViewport.getMapPosition(pos); - if (mUpdateListeners == null) { - mUpdateListeners = new UpdateListener[mUpdateListenerSet.size()]; - mUpdateListenerSet.toArray(mUpdateListeners); - } - - for (UpdateListener l : mUpdateListeners) - l.onMapUpdate(pos, changed, mClearMap); + if (mClearMap) + events.fire(CLEAR_EVENT, pos); + else if (changed) + events.fire(POSITION_EVENT, pos); + else + events.fire(UPDATE_EVENT, pos); mClearMap = false; } - /** - * Register InputListener - */ - public void bind(InputListener listener) { - if (mInputListenerSet.add(listener)) - mInputListeners = null; - } - - /** - * Unregister InputListener - */ - public void unbind(InputListener listener) { - if (mInputListenerSet.remove(listener)) - mInputListeners = null; - } - - public void handleMotionEvent(MotionEvent e) { - - if (mInputListeners == null) { - mInputListeners = new InputListener[mInputListenerSet.size()]; - mInputListenerSet.toArray(mInputListeners); - } - - for (InputListener l : mInputListeners) - l.onMotionEvent(e); - } - public boolean handleGesture(Gesture g, MotionEvent e) { return mLayers.handleGesture(g, e); } diff --git a/vtm/src/org/oscim/tiling/TileManager.java b/vtm/src/org/oscim/tiling/TileManager.java index 408d7e28..31599755 100644 --- a/vtm/src/org/oscim/tiling/TileManager.java +++ b/vtm/src/org/oscim/tiling/TileManager.java @@ -28,8 +28,9 @@ import java.util.Arrays; import org.oscim.core.MapPosition; import org.oscim.core.Tile; +import org.oscim.event.Event; import org.oscim.event.EventDispatcher; -import org.oscim.event.EventDispatcher.Event; +import org.oscim.event.EventListener; import org.oscim.map.Map; import org.oscim.map.Viewport; import org.oscim.renderer.BufferObject; @@ -46,7 +47,17 @@ public class TileManager { public final static Event TILE_LOADED = new Event(); public final static Event TILE_REMOVED = new Event(); - public final EventDispatcher events; + public final EventDispatcher events = new EventDispatcher() { + + @Override + public void tell(Listener l, Event event, MapTile tile) { + l.onTileManagerEvent(event, tile); + } + }; + + public interface Listener extends EventListener { + void onTileManagerEvent(Event event, MapTile tile); + }; private int mCacheLimit; private int mCacheReduce; @@ -139,8 +150,6 @@ public class TileManager { mTilesSize = 0; mTilesForUpload = 0; mUpdateSerial = 0; - - events = new EventDispatcher(this); } private int[] mZoomTable; @@ -392,7 +401,7 @@ public class TileManager { private void removeFromCache(MapTile t) { if (t.state == NEW_DATA || t.state == READY) - events.tell(TILE_REMOVED, t); + events.fire(TILE_REMOVED, t); synchronized (t) { /* still belongs to TileLoader thread, defer clearing to @@ -518,7 +527,7 @@ public class TileManager { } tile.state = NEW_DATA; - events.tell(TILE_LOADED, tile); + events.fire(TILE_LOADED, tile); mTilesForUpload += 1;