This is IKAnnouncer.m in view mode; [Download] [Up]
/* File IKAnnouncer.m Release 1.2, 7 June 1994 Copyright (C) 1994 by H. Scott Roy This code is part of IconKit, a general toolbox for drag-and-drop applications. IconKit is free for noncommercial use, but costs money for a commercial license. You should have received a copy of the license agreement with this file. If not, a copy of the license and the complete source of IconKit can be obtained from the author: H. Scott Roy 2573 Stowe Ct. Northbrook, IL 60062-8103 iconkit@cs.stanford.edu For your editing convenience, this file is best viewed using an editor that automatically wraps long lines, in a fixed point font at 80 columns, with tabs every 4 spaces. */ /* ========================================================================== */ /* The IKAnnouncer class is the basic class that IconKit uses to conform to the IKDependency protocol. It provides a simple announcement service to notify users and listeners of changes to an object. There are two ways to incorporate an IKAnnouncer in a new class. One can either inherit from it directly, or one can keep an IKAnnouncer as an instance variable. The IconKit classes have adopted this second approach as it seems conceptually clearer. */ #import <appkit/appkit.h> #import "iconkit.h" @implementation IKAnnouncer /* ========================================================================== */ /* Here is the initialization method. The owner of an IKAnnouncer will be given as the first argument in any announce messages. */ - initOwner: theOwner { if ((self = [super init]) != nil) { owner = theOwner; usersAndListeners = [[List alloc] init]; numUsers = 0; sendAnnouncements = YES; } return self; } - free { [usersAndListeners free]; return self = [super free]; } - usersAndListeners { return usersAndListeners; } - (int) numUsers { return numUsers; } - (BOOL) sendAnnouncements { return sendAnnouncements; } - setSendAnnouncements: (BOOL) flag; { sendAnnouncements = flag; return self; } /* ========================================================================== */ /* Here are the methods to add and remove users and listeners. They all return the IKAnnouncer owner. It's important to permit objects to add themselves multiple times, so that all the add and remove calls correctly balance. */ - addUser: who { IKdprintf ("adding user: %-17s (%p) for: %s (%p)\n", [who name], who, [owner name], owner); [usersAndListeners addObject: who]; numUsers++; return owner; } - addListener: who { IKdprintf ("adding listener: %-17s (%p) for: %s (%p)\n", [who name], who, [owner name], owner); [usersAndListeners addObject: who]; return owner; } - removeUser: who { IKdprintf ("removing user: %-17s (%p) for: %s (%p)\n", [who name], who, [owner name], owner); [usersAndListeners removeObject: who]; numUsers--; return owner; } - removeListener: who { IKdprintf ("removing listener: %-17s (%p) for: %s (%p)\n", [who name], who, [owner name], owner); [usersAndListeners removeObject: who]; return owner; } /* ========================================================================== */ /* Here are the methods to send out notification messages to all users and listeners. The methods try to be safe in case objects try to add or delete themselves from the user list during an announcement, but keep in mind that it's probably a bad idea to muck too much with an object during an announcement. There's a fair amount of overhead to these announcement messages. A more performance minded implementation is certainly possible. Users and listeners only receive the messages to which they can actually respond. Notification messages should all take forms like, didChange: sender didChange: sender info: arg */ - announce: (SEL) message { id recipients, who; int i = [usersAndListeners count]; if (i > 0 && sendAnnouncements) { recipients = [usersAndListeners copy]; while (i--) if ([who = [recipients objectAt: i] respondsTo: message]) [who perform: message with: owner]; [recipients free]; } return owner; } - announce: (SEL) message with: arg { id recipients, who; int i = [usersAndListeners count]; if (i > 0 && sendAnnouncements) { recipients = [usersAndListeners copy]; while (i--) if ([who = [recipients objectAt: i] respondsTo: message]) [who perform: message with: owner with: arg]; [recipients free]; } return owner; } /* ========================================================================== */ /* Here are the methods to poll the users of an object for approval before performing an operation. The result is a logical AND of all the responses. Both methods return as soon as any user responds NO. Some users might therefore never see a polling message. */ - (BOOL) poll: (SEL) message { id recipients, who; int i = [usersAndListeners count]; if (i > 0) { recipients = [usersAndListeners copy]; while (i--) if ( [who = [recipients objectAt: i] respondsTo: message] && [who perform: message with: owner] == NO) break; [recipients free]; return (i < 0) ? YES : NO; } else return YES; } - (BOOL) poll: (SEL) message with: arg { id recipients, who; int i = [usersAndListeners count]; if (i > 0) { recipients = [usersAndListeners copy]; while (i--) if ( [who = [recipients objectAt: i] respondsTo: message] && [who perform: message with: owner with: arg] == NO) break; [recipients free]; return (i < 0) ? YES : NO; } else return YES; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.