home *** CD-ROM | disk | FTP | other *** search
- #import <objc/HashTable.h>
- #import <objc/Storage.h>
- #import <strings.h>
-
- #import "ObserveDispatch.h"
-
- @implementation ObserveDispatch
-
- - init
- {
- [super init];
-
- // Create the observers list
- // The key will be the name of the method
- observerTable = [[HashTable alloc] initKeyDesc:"*" valueDesc:"@"];
-
- return self;
- }
-
- /*
- ** Method: initObserver:
- **
- ** Purpose: Initialize an observer record that can then be added to the
- ** List of observers for an action. This is a good method for sub-classes
- ** to overwrite if they want to accept shorthand action names and turn
- ** them into something more appropriate.
- */
-
- - initObserver:(observerrec *)anObserver withObject:(id)anObject
- forAction:(char *)anAction withFilter:(char *)aFilter
- {
- anObserver->active = YES;
- anObserver->anObject = anObject;
- anObserver->action = NXCopyStringBuffer(anAction);
- anObserver->filter = NXCopyStringBuffer(aFilter);
-
- return self;
- }
-
- /*
- Method: observerListForAction:
- Returns a list of the observers that are watching for the given
- action.
-
- Return Value:
- Returns the list of observers if there is one or nil otherwise
- */
-
- - observerListForAction:(char *)anAction
- {
- id aList = nil;
-
- aList = (id)[observerTable valueForKey:anAction];
-
- return aList;
- }
-
- /*
- Method: addObserver:forAction:withFilter:
- This method is the primary interface for adding an observer to
- a watch list for a given action.
-
- Parameters:
- id anObject The object that is the observer
- char *actionList A comma separated list of the actions the observer
- wants to watch for.
- char *aFilter additional information (unused)
-
- Return Value:
- Always returns 0
- */
-
- - (int)addObserver:(id)anObject
- forAction:(char *)actionList
- withFilter:(char *)aFilter
- {
- id aList = nil;
- observerrec newobserver;
-
- #if DBG_ADDSERVER
- printf("ObserveD - addObserver:forAction: %s\n",actionList);
- #endif DBG_ADDSERVER
-
- if (!actionList || !*actionList)
- return -1;
-
- // Create an observer record
- [self initObserver:&newobserver withObject:anObject
- forAction:actionList withFilter:aFilter];
-
- // Add it to the hash table
- // Look for the list this belongs to
- aList = [self observerListForAction:newobserver.action];
-
- // If not found create it
- if (!aList)
- {
- aList = [[Storage allocFromZone:[self zone]]
- initCount:0
- elementSize:sizeof(observerrec)
- description:"{i@**}"];
-
- // Add the new list to the table of lists
- [observerTable insertKey:NXCopyStringBuffer(newobserver.action)
- value:aList];
- }
-
- // Add the observer to the list
- [aList addElement:&newobserver];
-
- return NO;
- }
-
- /*
- Method: addObserver:forAction:
- Same as addObserver:forAction:withFilter:, but passes a blank filter
- by default.
-
- Return Value:
- returns whatever addObserver:forAction:withFilter: returns
- */
- - (int)addObserver:(id)anObject
- forAction:(char *)actionList
- {
- return [self addObserver:anObject forAction:actionList withFilter:""];
- }
-
- /*
- Method: forward::
-
- Return Value:
- always returns self
- */
-
- - forward:(SEL)aSelector :(marg_list)argFrame
- {
- id aList = nil;
- char *selectorName = sel_getName(aSelector);
-
- // Find the list of observers for this method
- // Send the message to each member of the list;
-
- // Dispatch the message to all observers
- aList = [observerTable valueForKey:selectorName];
- if (aList)
- {
- observerrec *anObserver;
- int numObservers = [aList count];
- int counter = 0;
-
- // Now we have the list of observers
- // For each one of them
- for (counter = 0; counter < numObservers; counter++)
- {
- // send out the same message
- anObserver = [aList elementAt:counter];
- [anObserver->anObject performv:aSelector :argFrame];
- }
- }
-
- return self;
- }
-
-
- @end