| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 | 
							- Smalltalk createPackage: 'Kernel-Announcements'!
 
- Object subclass: #AnnouncementSubscription
 
- 	instanceVariableNames: 'valuable announcementClass'
 
- 	package: 'Kernel-Announcements'!
 
- !AnnouncementSubscription commentStamp!
 
- I am a single entry in a subscription registry of an `Announcer`.
 
- Several subscriptions by the same object is possible.!
 
- !AnnouncementSubscription methodsFor: 'accessing'!
 
- announcementClass
 
- 	^ announcementClass
 
- !
 
- announcementClass: aClass
 
- 	announcementClass := aClass
 
- !
 
- block
 
- 	"Use #valuable instead"
 
- 	
 
- 	self deprecatedAPI.
 
- 	^ self valuable
 
- !
 
- block: aValuable
 
- 	"Use #valuable instead"
 
- 	
 
- 	self deprecatedAPI.
 
- 	self valuable: aValuable
 
- !
 
- receiver
 
- 	^ self valuable receiver
 
- !
 
- valuable
 
- 	^ valuable
 
- !
 
- valuable: aValuable
 
- 	valuable := aValuable
 
- ! !
 
- !AnnouncementSubscription methodsFor: 'announcing'!
 
- deliver: anAnnouncement
 
- 	(self handlesAnnouncement: anAnnouncement)
 
- 		ifTrue: [ self valuable value: anAnnouncement ]
 
- !
 
- handlesAnnouncement: anAnnouncement
 
- 	"anAnnouncement might be announced from within another Amber environment"
 
- 	
 
- 	^ (Smalltalk globals at: self announcementClass name)
 
- 		ifNil: [ ^ false ]
 
- 		ifNotNil: [ :class |
 
- 		(Smalltalk globals at: anAnnouncement class theNonMetaClass name) includesBehavior: class ]
 
- ! !
 
- Object subclass: #Announcer
 
- 	instanceVariableNames: 'registry subscriptions'
 
- 	package: 'Kernel-Announcements'!
 
- !Announcer commentStamp!
 
- I hold annoncement subscriptions (instances of `AnnouncementSubscription`) in a private registry.
 
- I announce (trigger) announces, which are then dispatched to all subscriptions.
 
- The code is based on the announcements as [described by Vassili Bykov](http://www.cincomsmalltalk.com/userblogs/vbykov/blogView?searchCategory=Announcements%20Framework).
 
- ## API
 
- Use `#announce:` to trigger an announcement.
 
- Use `#on:do:` or `#on:send:to:` to register subscriptions.
 
- When using `#on:send:to:`, unregistration can be done with `#unregister:`.
 
- ## Usage example:
 
-     SystemAnnouncer current
 
-         on: ClassAdded
 
-         do: [ :ann | window alert: ann theClass name, ' added' ].!
 
- !Announcer methodsFor: 'announcing'!
 
- announce: anAnnouncement
 
- 	subscriptions do: [ :each |
 
- 		each deliver: anAnnouncement ]
 
- ! !
 
- !Announcer methodsFor: 'initialization'!
 
- initialize
 
- 	super initialize.
 
- 	subscriptions := OrderedCollection new
 
- ! !
 
- !Announcer methodsFor: 'subscribing'!
 
- on: aClass do: aBlock
 
- 	subscriptions add: (AnnouncementSubscription new
 
- 		valuable: aBlock;
 
- 		announcementClass: aClass;
 
- 		yourself)
 
- !
 
- on: aClass doOnce: aBlock
 
- 	| subscription |
 
- 	
 
- 	subscription := AnnouncementSubscription new
 
- 		announcementClass: aClass;
 
- 		yourself.
 
- 	subscription valuable: [ :ann |
 
- 		subscriptions remove: subscription.
 
- 		aBlock value: ann ].
 
- 	subscriptions add: subscription
 
- !
 
- on: aClass send: aSelector to: anObject
 
- 	subscriptions add: (AnnouncementSubscription new
 
- 		valuable: (MessageSend new
 
- 			receiver: anObject;
 
- 			selector: aSelector;
 
- 			yourself);
 
- 		announcementClass: aClass;
 
- 		yourself)
 
- !
 
- unsubscribe: anObject
 
- 	subscriptions := subscriptions reject: [ :each |
 
- 		each receiver = anObject ]
 
- ! !
 
- Announcer subclass: #SystemAnnouncer
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !SystemAnnouncer commentStamp!
 
- My unique instance is the global announcer handling all Amber system-related announces.
 
- ## API
 
- Access to the unique instance is done via `#current`!
 
- SystemAnnouncer class instanceVariableNames: 'current'!
 
- !SystemAnnouncer class methodsFor: 'accessing'!
 
- current
 
- 	^ current ifNil: [ current := super new ]
 
- ! !
 
- !SystemAnnouncer class methodsFor: 'instance creation'!
 
- new
 
- 	self shouldNotImplement
 
- ! !
 
- Object subclass: #SystemAnnouncement
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !SystemAnnouncement commentStamp!
 
- I am the superclass of all system announcements!
 
- !SystemAnnouncement class methodsFor: 'helios'!
 
- heliosClass
 
- 	^ 'announcement'
 
- ! !
 
- SystemAnnouncement subclass: #ClassAnnouncement
 
- 	instanceVariableNames: 'theClass'
 
- 	package: 'Kernel-Announcements'!
 
- !ClassAnnouncement commentStamp!
 
- I am the abstract superclass of class-related announcements.!
 
- !ClassAnnouncement methodsFor: 'accessing'!
 
- theClass
 
- 	^ theClass
 
- !
 
- theClass: aClass
 
- 	theClass := aClass
 
- ! !
 
- ClassAnnouncement subclass: #ClassAdded
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !ClassAdded commentStamp!
 
- I am emitted when a class is added to the system.
 
- See ClassBuilder >> #addSubclassOf:... methods!
 
- ClassAnnouncement subclass: #ClassCommentChanged
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !ClassCommentChanged commentStamp!
 
- I am emitted when the comment of a class changes. (Behavior >> #comment)!
 
- ClassAnnouncement subclass: #ClassDefinitionChanged
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !ClassDefinitionChanged commentStamp!
 
- I am emitted when the definition of a class changes.
 
- See ClassBuilder >> #class:instanceVariableNames:!
 
- ClassAnnouncement subclass: #ClassMigrated
 
- 	instanceVariableNames: 'oldClass'
 
- 	package: 'Kernel-Announcements'!
 
- !ClassMigrated commentStamp!
 
- I am emitted when a class is migrated.!
 
- !ClassMigrated methodsFor: 'accessing'!
 
- oldClass
 
- 	^ oldClass
 
- !
 
- oldClass: aClass
 
- 	oldClass := aClass
 
- ! !
 
- ClassAnnouncement subclass: #ClassMoved
 
- 	instanceVariableNames: 'oldPackage'
 
- 	package: 'Kernel-Announcements'!
 
- !ClassMoved commentStamp!
 
- I am emitted when a class is moved from one package to another.!
 
- !ClassMoved methodsFor: 'accessing'!
 
- oldPackage
 
- 	^ oldPackage
 
- !
 
- oldPackage: aPackage
 
- 	oldPackage := aPackage
 
- ! !
 
- ClassAnnouncement subclass: #ClassRemoved
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !ClassRemoved commentStamp!
 
- I am emitted when a class is removed.
 
- See Smalltalk >> #removeClass:!
 
- ClassAnnouncement subclass: #ClassRenamed
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !ClassRenamed commentStamp!
 
- I am emitted when a class is renamed.
 
- See ClassBuilder >> #renameClass:to:!
 
- SystemAnnouncement subclass: #MethodAnnouncement
 
- 	instanceVariableNames: 'method'
 
- 	package: 'Kernel-Announcements'!
 
- !MethodAnnouncement commentStamp!
 
- I am the abstract superclass of method-related announcements.!
 
- !MethodAnnouncement methodsFor: 'accessing'!
 
- method
 
- 	^ method
 
- !
 
- method: aCompiledMethod
 
- 	method := aCompiledMethod
 
- ! !
 
- MethodAnnouncement subclass: #MethodAdded
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !MethodAdded commentStamp!
 
- I am emitted when a `CompiledMethod` is added to a class.!
 
- MethodAnnouncement subclass: #MethodModified
 
- 	instanceVariableNames: 'oldMethod'
 
- 	package: 'Kernel-Announcements'!
 
- !MethodModified commentStamp!
 
- I am emitted when a `CompiledMethod` is modified (a new method is installed). I hold a reference to the old method being replaced.!
 
- !MethodModified methodsFor: 'accessing'!
 
- oldMethod
 
- 	^ oldMethod
 
- !
 
- oldMethod: aMethod
 
- 	oldMethod := aMethod
 
- ! !
 
- MethodAnnouncement subclass: #MethodMoved
 
- 	instanceVariableNames: 'oldProtocol'
 
- 	package: 'Kernel-Announcements'!
 
- !MethodMoved commentStamp!
 
- I am emitted when a `CompiledMethod` is moved to another protocol. I hold a refernce to the old protocol of the method.!
 
- !MethodMoved methodsFor: 'accessing'!
 
- oldProtocol
 
- 	^ oldProtocol
 
- !
 
- oldProtocol: aString
 
- 	oldProtocol := aString
 
- ! !
 
- MethodAnnouncement subclass: #MethodRemoved
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !MethodRemoved commentStamp!
 
- I am emitted when a `CompiledMethod` is removed from a class.!
 
- SystemAnnouncement subclass: #PackageAnnouncement
 
- 	instanceVariableNames: 'package'
 
- 	package: 'Kernel-Announcements'!
 
- !PackageAnnouncement commentStamp!
 
- I am the abstract superclass of package-related announcements.!
 
- !PackageAnnouncement methodsFor: 'accessing'!
 
- package
 
- 	^ package
 
- !
 
- package: aPackage
 
- 	package := aPackage
 
- ! !
 
- PackageAnnouncement subclass: #PackageAdded
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !PackageAdded commentStamp!
 
- I am emitted when a `Package` is added to the system.!
 
- PackageAnnouncement subclass: #PackageRemoved
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !PackageRemoved commentStamp!
 
- I am emitted when a `Package` is removed from the system.!
 
- SystemAnnouncement subclass: #ProtocolAnnouncement
 
- 	instanceVariableNames: 'theClass protocol'
 
- 	package: 'Kernel-Announcements'!
 
- !ProtocolAnnouncement commentStamp!
 
- I am the abstract superclass of protocol-related announcements.!
 
- !ProtocolAnnouncement methodsFor: 'accessing'!
 
- protocol
 
- 	^ protocol
 
- !
 
- protocol: aString
 
- 	protocol := aString
 
- !
 
- theClass
 
- 	^ theClass
 
- !
 
- theClass: aClass
 
- 	theClass := aClass
 
- ! !
 
- ProtocolAnnouncement subclass: #ProtocolAdded
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !ProtocolAdded commentStamp!
 
- I am emitted when a protocol is added to a class.!
 
- ProtocolAnnouncement subclass: #ProtocolRemoved
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Announcements'!
 
- !ProtocolRemoved commentStamp!
 
- I am emitted when a protocol is removed from a class.!
 
 
  |