Adds support to Sparrow's SPEventDispatcher to subscribe to all events using SP_EVENT...
authordsc <david.schoonover@gmail.com>
Sat, 4 Jun 2011 09:40:12 +0000 (02:40 -0700)
committerdsc <david.schoonover@gmail.com>
Sat, 4 Jun 2011 09:40:12 +0000 (02:40 -0700)
libs/sparrow/src/Classes/SPEvent.h
libs/sparrow/src/Classes/SPEventDispatcher.h
libs/sparrow/src/Classes/SPEventDispatcher.m

index a4c2a90..6553cdb 100644 (file)
@@ -11,6 +11,7 @@
 
 #import <Foundation/Foundation.h>
 
+#define SP_EVENT_TYPE_ANY @""
 #define SP_EVENT_TYPE_ADDED @"added"
 #define SP_EVENT_TYPE_ADDED_TO_STAGE @"addedToStage"
 #define SP_EVENT_TYPE_REMOVED @"removed"
index 264e9da..f3b2c08 100644 (file)
 {
   @private
     NSMutableDictionary *mEventListeners;
+    NSArray* mAnyEventListeners;
 }
 
 /// -------------
 /// @name Methods
 /// -------------
 
-/// Registers an event listener at a certain object. 
+/// Registers an event listener at a certain object. Passing the empty string or nil will register for all events.
 - (void)addEventListener:(SEL)listener atObject:(id)object forType:(NSString*)eventType 
             retainObject:(BOOL)retain;
 
index 9721b9d..b4e1ce1 100644 (file)
@@ -26,6 +26,8 @@
     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
@@ -52,6 +53,8 @@
 
 - (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)