home *** CD-ROM | disk | FTP | other *** search
- // EOObserver.h
- // Copyright (c) 1995, NeXT Software, Inc. All rights reserved.
- //
- // The EOObserver provides an efficient specialized notification mechanism
- // for an observing object to find out when another object is about to change
- // its state.
- // "Observable" objects (typically all business objects) are reponsible for calling
- // [self willChange] prior to altering their state (in a set method, for instance).
- // Observers, such as the EOEditingContext, add themselves as observers to the objects
- // they care about in the EOObserverCenter, and receive objectWillChange: notification
- // whenever an observed object sends [self willChange].
- // Application objects interested in notification of object change are usually better
- // of listening for aggregate change notification from the EOEditingContext rather than
- // observing the objects directly.
- #import <Foundation/Foundation.h>
-
- @interface NSObject (EOObserver)
- - (void)willChange;
- // Called by a subject to message all of its observers.
- // Convenience for [EOObserverCenter notifyObserversObjectWillChange:self]
- @end
-
- @protocol EOObserving <NSObject>
- - (void)objectWillChange:(id)subject;
- // called when object being observed is about to change
- @end
-
- @interface EOObserverCenter : NSObject
- + (void)addObserver:(id <EOObserving>)observer forObject:(id)object;
- // Registers the given observer to receive objectWillChange:
- // notification when the given object calls [self willChange];
- // Multiple calls with same observer and same object are coalesced.
-
- + (void)removeObserver:(id <EOObserving>)observer forObject:(id)object;
- // Unregisters the given observer from observing the given object.
- // Observers are responsible for removing themselves from every subject
- // they observe (perhaps in dealloc)
-
- + (void)notifyObserversObjectWillChange:(id)object;
- // Notifies all observers of this object that it will change.
- // This is called by [NSObject willChange];
- // As an optimization, multiple consecutive willChange notifications for
- // the same object are automatically suppressed. If an observer wants to
- // ensure that it receives notification the next time the last object
- // to change changes again, it should call
- // [EOObserverCenter notifyObserversObjectWillChange:nil]
-
- + (NSArray *)observersForObject:(id)object;
- // Returns a list of all objects currently observing the given object.
-
- + (id)observerForObject:(id)object ofClass:(Class)targetClass;
- // returns an observer of the given object (if any) of the target class.
- // If many such observers exist, just one is returned.
-
- + (void)suppressObserverNotification;
- + (void)enableObserverNotification;
- // Turn on and off listening to object change notifications.
- // Supressed notifications are lost forever.
- // These calls nest.
- + (unsigned)observerNotificationSuppressCount;
-
- + (void)addOmniscientObserver:(id <EOObserving>)observer;
- + (void)removeOmniscientObserver:(id <EOObserving>)observer;
- // The observer will see ALL [self willChange] notifications
- // on all objects. Use with care!
- @end
-
-
- // EODelayedObservers are observers that receive asynchronous notification
- // of changes to observed objects. EOAssociations, for examples are
- // asynchronous observers of their EODisplayGroups. The EODelayedObserverQueue
- // supports the asynchronous notfication of EODelayedObservers.
- // Multiple notifications to the same observer are coalesced.
- // DelayedObservers have a static priority and are notified in priority order.
- @class EODelayedObserverQueue;
-
- typedef enum {
- EOObserverPriorityImmediate, // Synchronous delivery, not delayed
- EOObserverPriorityFirst, //
- EOObserverPrioritySecond, // Master EODetailAssociation delivery
- EOObserverPriorityThird, // Default EOAssociation priority
- EOObserverPriorityFourth, //
- EOObserverPriorityFifth, //
- EOObserverPrioritySixth, // EODisplayGroup clears didChange state
- EOObserverPriorityLater //
- } EOObserverPriority;
- #define EOObserverNumberOfPriorities ((unsigned)EOObserverPriorityLater + 1)
-
-
- @interface EODelayedObserver : NSObject <EOObserving> {
- @public // Public only to the observer queue. do not use.
- EODelayedObserver *_next; // linked list. Nil if not on list.
- }
- - (void)objectWillChange:(id)subject;
- // overridden by EODelayedObserver to put observer on queue
-
- - (EOObserverPriority)priority;
- // the observer should return its notification priority (order)
- // default is EOObserverPriorityThird
- - (EODelayedObserverQueue *)observerQueue;
- // allows observer to determine the queue it waits on.
- // default is [EODelayedObserverQueue defaultQueue]
-
- // Must be implemented by subclasses
- - (void)subjectChanged;
- // called by the delayed observer queue to let observer take
- // appropriate action. The observer may have been "watching"
- // more than one subject, and any change notifications from these
- // subjects are coalesced into a single subjectChanged call.
- // Therefore, the observer is responsible for keeping track of
- // the set of of subjects it is observing, and checking with them
- // upon receiving the subjectChanged message
-
- - (void)discardPendingNotification;
- // if this observer is currently enqueued for delayed notification,
- // removes it from the queue. It may be appropriate to call this when
- // a DelayedObserver is dealloced.
- @end
-
- // used with NSRunLoop's performSelector:target:argument:order:modes:
- enum {
- EOFlushDelayedObserversRunLoopOrdering = 400000
- };
-
-
- @interface EODelayedObserverQueue : NSObject
- {
- EODelayedObserver *_queue[EOObserverNumberOfPriorities]; // lists for each priority
- unsigned _highestNonEmptyQueue;
- BOOL _haveEntryInNotificationQueue;
- NSArray *_modes;
- }
- + (EODelayedObserverQueue *)defaultObserverQueue;
-
- - (void)enqueueObserver:(EODelayedObserver *)observer;
- // Called by EODelayedObserver objectWillChange: to enqueue the object for
- // asynchronous notification. Already enqueued observers are not enqueued again.
- - (void)dequeueObserver:(EODelayedObserver *)observer;
- // remove an observer from the queue.
- - (void)notifyObserversUpToPriority:(EOObserverPriority)lastPriority;
- // Do the updating of all observers with priority no lower than lastPriority.
- // The first time an observer is added to the queue, the queue registers for
- // ASAP notification from the NSNotificationQueue. When this notification is
- // received, the queue calls [self notifyObserversUpToPriority:EOObserverPrioritySixth];
-
- - (void)setRunLoopModes:(NSArray *)modes;
- - (NSArray *)runLoopModes;
- // Set the modes passed to the notificationQueue to determine
- // when DelayedObservers are notified.
- @end
-
-
- // Observer that passes on notification to its target. When proxy receives
- // subjectChanged it send its target its action passing itself as the argument.
- // This is useful for objects that want to be asynchronous observers, but cannot
- // subclass from EODelayedObserver.
- @interface EOObserverProxy : EODelayedObserver {
- id _target;
- SEL _action;
- EOObserverPriority _priority;
- }
- - initWithTarget:(id)target action:(SEL)action priority:(EOObserverPriority)priority;
- @end
-