package de.bloxel.core.events;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* core of the event system {@link EventListener} can subscribe specific event types (or all (eventType="ALL") and will called when an event of the
* subscribed type is triggered.
*
* @since 0.1.0
* @author dorer
* @author Klaus Hauschild
*/
public class EventManager {
private final Map<String, Set<EventListener>> eventListeners = new HashMap<String, Set<EventListener>>();
@SuppressWarnings("unchecked")
private final List<Event>[] eventQueue = new List[2];
private int index;
public EventManager() {
eventQueue[0]=new ArrayList<Event>();
eventQueue[1]=new ArrayList<Event>();
}
/**
* subscribes an eventListener to a specific eventType use "ALL" as eventType to receive all events.
*
* @param type
* the event type which should be subscribed
* @param listener
* the {@link EventListener} who should be notified
*/
public void subscribeEvent(final String type, final EventListener listener) {
if (eventListeners.containsKey(type)) {
eventListeners.get(type).add(listener);
} else {
final Set<EventListener> listenerSet=new HashSet<EventListener>();
listenerSet.add(listener);
eventListeners.put(type, listenerSet);
}
}
/**
* unsubscribe a listener for a specific event type.
*
* @param type
* the event type
* @param listener
* the listener
*/
public void unsubscribeEvent(final String type, final EventListener listener) {
if (eventListeners.containsKey(type) && eventListeners.get(type).contains(listener)) {
eventListeners.get(type).remove(listener);
}
}
/**
* removes all event subscriptions for a {@link EventListener}.
*
* @param listener
* the listener
*/
public void unsubscribeAll(final EventListener listener) {
for(final Set<EventListener> s:eventListeners.values()) {
if (s.contains(listener)) {
s.remove(listener);
}
}
}
/**
* queues an event for processing.
*
* @param event
* the event
*/
public void queueEvent(final Event event) {
eventQueue[index].add(event);
}
/**
* processes all event in the current queue two event queues are used to avoid an endless loop if an {@link EventListener} triggers another event.
*/
public void doEvents() {
final int current=index;
//switch to other event queue for new events
index=(index+1)%2;
while(!eventQueue[current].isEmpty()) {
final Event currentEvent=eventQueue[current].remove(0);
//send events to listeners listening for all events
if (eventListeners.containsKey("ALL")) {
for(final EventListener listener:eventListeners.get("ALL")) {
listener.handleEvent(currentEvent);
}
}
//send events to subscribed listeners
if (eventListeners.containsKey(currentEvent.getType())) {
for(final EventListener listener: eventListeners.get(currentEvent.getType())) {
if (listener.handleEvent(currentEvent)) {
break;
}
}
}
}
}
}
|