NSInvocation *invocation = [NSInvocation invocationWithTarget:object selector:listener];
if (doRetain) [invocation retainArguments];
+ if (eventType == nil) eventType = @"";
+
// When an event listener is added or removed, a new NSArray object is created, instead of
// changing the array. The reason for this is that we can avoid creating a copy of the NSArray
// in the "dispatchEvent"-method, which is called far more often than
NSArray *listeners = [mEventListeners objectForKey:eventType];
if (!listeners)
{
- listeners = [[NSArray alloc] initWithObjects:invocation, nil];
- [mEventListeners setObject:listeners forKey:eventType];
- [listeners release];
+ listeners = [NSArray arrayWithObject:invocation];
}
else
{
listeners = [listeners arrayByAddingObject:invocation];
- [mEventListeners setObject:listeners forKey:eventType];
- }
+ }
+ [mEventListeners setObject:listeners forKey:eventType];
+
}
- (void)addEventListener:(SEL)listener atObject:(id)object forType:(NSString*)eventType
- (void)removeEventListener:(SEL)listener atObject:(id)object forType:(NSString*)eventType
{
+ if (eventType == nil) eventType = @"";
+
NSArray *listeners = [mEventListeners objectForKey:eventType];
if (listeners)
{
- (BOOL)hasEventListenerForType:(NSString*)eventType
{
+ if (eventType == nil) eventType = @"";
return [mEventListeners objectForKey:eventType] != nil;
}
- (void)dispatchEvent:(SPEvent*)event
{
- NSMutableArray *listeners = [mEventListeners objectForKey:event.type];
- if (!event.bubbles && !listeners) return; // no need to do anything.
+ NSArray *listenersOfType = [mEventListeners objectForKey:event.type];
+ NSArray *listenersOfAllEvents = [mEventListeners objectForKey:@""];
+ if (!event.bubbles && !(listenersOfType || listenersOfAllEvents)) return; // no need to do anything.
// if the event already has a current target, it was re-dispatched by user -> we change the
// target to 'self' for now, but undo that later on (instead of creating a copy, which could
[self retain]; // the event listener could release 'self', so we have to make sure that it
// stays valid while we're here.
- BOOL stopImmediatPropagation = NO;
- if (listeners.count != 0)
- {
- // we can enumerate directly over the array, since "add"- and "removeEventListener" won't
- // change it, but instead always create a new array.
- [listeners retain];
- for (NSInvocation *inv in listeners)
- {
- [inv setArgument:&event atIndex:2];
- [inv invoke];
- if (event.stopsImmediatePropagation)
+ BOOL stopImmediatPropagation = NO;
+ NSArray *listeners = listenersOfType;
+ while (listeners) {
+ if (listeners.count != 0) {
+ // we can enumerate directly over the array, since "add"- and "removeEventListener" won't
+ // change it, but instead always create a new array.
+ [listeners retain];
+ for (NSInvocation *inv in listeners)
{
- stopImmediatPropagation = YES;
- break;
+ [inv setArgument:&event atIndex:2];
+ [inv invoke];
+ if (event.stopsImmediatePropagation)
+ {
+ stopImmediatPropagation = YES;
+ break;
+ }
}
+ [listeners release];
}
- [listeners release];
+ listeners = (listeners != listenersOfAllEvents ? listenersOfAllEvents : nil);
}
if (!stopImmediatPropagation)