SimpleEventBus<H> class
Basic implementation of EventBus.
class SimpleEventBus<H> extends EventBus<H> {
static _EmptySource _emptySource = new _EmptySource();
/**
* Map of event type to map of event source to list of their handlers.
*/
Map<EventType, Map<Object, List>> map = new Map<EventType, Map<Object, List>>();
int _firingDepth = 0;
/**
* Add and remove operations received during dispatch.
*/
List<Command> _deferredDeltas;
/**
* Allows creation of an instance that fires its handlers in the reverse of
* the order in which they were added, although filtered handlers all fire
* before unfiltered handlers.
*/
SimpleEventBus();
/**
* @deprecated required by legacy features in GWT's old HandlerManager
*/
//@Deprecated
bool isEventHandled(EventType<H> type) {
return map.containsKey(type);
}
/**
* Adds an unfiltered [handler] to receive events of this [type] from all sources.
*
* It is rare to call this method directly. More typically an [Event]
* subclass will provide a static <code>register</code> method, or a widget
* will accept handlers directly.
*
* @param <H> The type of handler
* @param type the event type associated with this handler
* @param handler the handler
* @return the handler registration, can be stored in order to remove the
* handler later
*/
HandlerRegistration addHandler(EventType<H> type, H handler) {
return _doAdd(type, _emptySource, handler);
}
/**
* Adds a [handler] to receive events of this [type] from the given [source].
*
* It is rare to call this method directly. More typically a [Event]
* subclass will provide a static <code>register</code> method, or a widget
* will accept handlers directly.
*
* @param <H> The type of handler
* @param type the event type associated with this handler
* @param source the source associated with this handler
* @param handler the handler
* @return the handler registration, can be stored in order to remove the
* handler later
*/
HandlerRegistration addHandlerToSource(EventType<H> type, Object source, H handler) {
assert(source != null);
//
return _doAdd(type, source, handler);
}
HandlerRegistration _doAdd(EventType<H> type, Object source, H handler) {
assert(type != null);
assert(handler != null);
//
if (_firingDepth > 0) {
_enqueueAdd(type, source, handler);
} else {
_doAddNow(type, source, handler);
}
return new _HandlerRegistration(this, type, source, handler);
}
void _doAddNow(EventType<H> type, Object source, H handler) {
List<H> l = ensureHandlerList(type, source);
l.add(handler);
}
List<H> ensureHandlerList(EventType<H> type, Object source) {
Map<Object, List> sourceMap;
if (map.containsKey(type)) {
sourceMap = map[type];
} else {
sourceMap = new Map<Object, List>();
map[type] = sourceMap;
}
// safe, we control the puts.
List<H> handlers;
if (sourceMap.containsKey(source)) {
handlers = sourceMap[source];
} else {
handlers = new List<H>();
sourceMap[source] = handlers;
}
return handlers;
}
void _doRemove(EventType<H> type, Object source, H handler) {
if (_firingDepth > 0) {
_enqueueRemove(type, source, handler);
} else {
_doRemoveNow(type, source, handler);
}
}
void _doRemoveNow(EventType<H> type, Object source, H handler) {
List<H> l = getHandlerList(type, source);
int indx = l.indexOf(handler);
if (indx != -1) {
l.removeAt(indx);
if (l.isEmpty) {
prune(type, source);
}
}
}
void prune(EventType type, Object source) {
if (map.containsKey(type)) {
Map<Object, List> sourceMap = map[type];
List pruned = sourceMap.remove(source);
assert (pruned != null); // : "Can't prune what wasn't there";
assert (pruned.isEmpty); // : "Pruned unempty list!";
if (sourceMap.isEmpty) {
map.remove(type);
}
}
}
//********
// COMMAND
//********
void _defer(Command command) {
if (_deferredDeltas == null) {
_deferredDeltas = new List<Command>();
}
_deferredDeltas.add(command);
}
void _handleQueuedAddsAndRemoves() {
if (_deferredDeltas != null) {
try {
for (Command c in _deferredDeltas) {
c.execute();
}
} finally {
_deferredDeltas = null;
}
}
}
void _enqueueRemove(EventType<H> type, Object source, H handler) {
_defer(new _RemoveCommand(this, type, source, handler));
}
void _enqueueAdd(EventType<H> type, Object source, H handler) {
_defer(new _AddCommand(this, type, source, handler));
}
//*******
// FIRING
//*******
/**
* Fires the event from no source. Only unfiltered handlers will receive it.
*
* Any exceptions thrown by handlers will be bundled into a
* [UmbrellaException] and then re-thrown after all handlers have
* completed. An exception thrown by a handler will not prevent other handlers
* from executing.
*
* @throws UmbrellaException wrapping exceptions thrown by handlers
*
* @param event the event to fire
*/
void fireEvent(IEvent event) {
_doFire(event, null);
}
/**
* Fires the given event to the handlers listening to the event's type.
*
* Any exceptions thrown by handlers will be bundled into a
* [UmbrellaException] and then re-thrown after all handlers have
* completed. An exception thrown by a handler will not prevent other handlers
* from executing.
*
* @throws UmbrellaException wrapping exceptions thrown by handlers
*
* @param event the event to fire
*/
void fireEventFromSource(IEvent event, Object source) {
assert(source != null);
_doFire(event, source);
}
void _doFire(IEvent event, Object source) {
assert(event != null);
try {
_firingDepth++;
if (source != null) {
event.setSource(source);
}
List<H> handlers = getDispatchList(event.getAssociatedType(), source);
Set<Exception> causes = null;
for (int i = 0; i < handlers.length; i++) {
H handler = handlers[i];
// for (Iterator<H> it = handlers.iterator; it.moveNext();) {
// H handler = it.current;
try {
EventBus.dispatchEvent(event, handler);
} on Exception catch (e) {
if (causes == null) {
causes = new Set<Exception>();
}
causes.add(e);
}
}
if (causes != null) {
throw new UmbrellaException(causes);
}
} finally {
_firingDepth--;
if (_firingDepth == 0) {
_handleQueuedAddsAndRemoves();
}
}
}
List<H> getDispatchList(EventType<H> type, Object source) {
List<H> directHandlers = getHandlerList(type, source);
if (source == null) {
return directHandlers;
}
List<H> globalHandlers = getHandlerList(type, _emptySource);
List<H> rtn = new List<H>.from(directHandlers);
if (globalHandlers.length > 0) {
rtn.addAll(globalHandlers);
}
return rtn;
}
List<H> getHandlerList(EventType<H> type, Object source) {
if (map.containsKey(type)) {
Map<Object, List> sourceMap = map[type];
//
if (source == null) {
source = _emptySource;
}
if (source != null && sourceMap.containsKey(source)) {
return sourceMap[source];
}
}
return new List<H>();
}
}
Extends
EventBus<H> > SimpleEventBus<H>
Constructors
new SimpleEventBus() #
Allows creation of an instance that fires its handlers in the reverse of the order in which they were added, although filtered handlers all fire before unfiltered handlers.
SimpleEventBus();
Properties
Methods
HandlerRegistration addHandler(EventType<H> type, H handler) #
Adds an unfiltered handler to receive events of this type from all sources.
It is rare to call this method directly. More typically an Event
subclass will provide a static <code>register</code> method, or a widget
will accept handlers directly.
@param <H> The type of handler @param type the event type associated with this handler @param handler the handler @return the handler registration, can be stored in order to remove the
handler later
HandlerRegistration addHandler(EventType<H> type, H handler) {
return _doAdd(type, _emptySource, handler);
}
HandlerRegistration addHandlerToSource(EventType<H> type, Object source, H handler) #
Adds a handler to receive events of this type from the given source.
It is rare to call this method directly. More typically a Event
subclass will provide a static <code>register</code> method, or a widget
will accept handlers directly.
@param <H> The type of handler @param type the event type associated with this handler @param source the source associated with this handler @param handler the handler @return the handler registration, can be stored in order to remove the
handler later
HandlerRegistration addHandlerToSource(EventType<H> type, Object source, H handler) {
assert(source != null);
//
return _doAdd(type, source, handler);
}
List<H> ensureHandlerList(EventType<H> type, Object source) #
List<H> ensureHandlerList(EventType<H> type, Object source) {
Map<Object, List> sourceMap;
if (map.containsKey(type)) {
sourceMap = map[type];
} else {
sourceMap = new Map<Object, List>();
map[type] = sourceMap;
}
// safe, we control the puts.
List<H> handlers;
if (sourceMap.containsKey(source)) {
handlers = sourceMap[source];
} else {
handlers = new List<H>();
sourceMap[source] = handlers;
}
return handlers;
}
void fireEvent(IEvent event) #
Fires the event from no source. Only unfiltered handlers will receive it.
Any exceptions thrown by handlers will be bundled into a UmbrellaException and then re-thrown after all handlers have completed. An exception thrown by a handler will not prevent other handlers from executing.
@throws UmbrellaException wrapping exceptions thrown by handlers
@param event the event to fire
void fireEvent(IEvent event) {
_doFire(event, null);
}
void fireEventFromSource(IEvent event, Object source) #
Fires the given event to the handlers listening to the event's type.
Any exceptions thrown by handlers will be bundled into a UmbrellaException and then re-thrown after all handlers have completed. An exception thrown by a handler will not prevent other handlers from executing.
@throws UmbrellaException wrapping exceptions thrown by handlers
@param event the event to fire
void fireEventFromSource(IEvent event, Object source) {
assert(source != null);
_doFire(event, source);
}
List<H> getDispatchList(EventType<H> type, Object source) #
List<H> getDispatchList(EventType<H> type, Object source) {
List<H> directHandlers = getHandlerList(type, source);
if (source == null) {
return directHandlers;
}
List<H> globalHandlers = getHandlerList(type, _emptySource);
List<H> rtn = new List<H>.from(directHandlers);
if (globalHandlers.length > 0) {
rtn.addAll(globalHandlers);
}
return rtn;
}
List<H> getHandlerList(EventType<H> type, Object source) #
List<H> getHandlerList(EventType<H> type, Object source) {
if (map.containsKey(type)) {
Map<Object, List> sourceMap = map[type];
//
if (source == null) {
source = _emptySource;
}
if (source != null && sourceMap.containsKey(source)) {
return sourceMap[source];
}
}
return new List<H>();
}
bool isEventHandled(EventType<H> type) #
@deprecated required by legacy features in GWT's old HandlerManager
bool isEventHandled(EventType<H> type) {
return map.containsKey(type);
}
void prune(EventType type, Object source) #
void prune(EventType type, Object source) {
if (map.containsKey(type)) {
Map<Object, List> sourceMap = map[type];
List pruned = sourceMap.remove(source);
assert (pruned != null); // : "Can't prune what wasn't there";
assert (pruned.isEmpty); // : "Pruned unempty list!";
if (sourceMap.isEmpty) {
map.remove(type);
}
}
}