Added NSNotification support to HotCocoa
I added the ability to easily support notification posting and subscribing in HotCocoa: You can subscribe to notifications with the on_notification method. on_notification :sent_by => object, :named => "SomeName" do | notification| #...do something end This method is available on the HotCocoa module and on individual objects. When its used globally you can specify the sent_by object and/or the named option. When its called on a particular object, the sent_by is that object and you don't have to specify it. require 'hotcocoa' include HotCocoa #here sent_by will be nil...so you will receive all NSWindowDidResizeNotification notifications on_notification :named => 'NSWindowDidResizeNotification' do | notification| puts "A window resized!" end application do window :size => [300, 100] do |win| #here :sent_by => win win.on_notification do |notification| puts "Received notification of #{notification.name} on my window" end tb = toolbar :default => [:show_fonts], :size => :small, :display => :icon_and_label win.toolbar = tb end end You can also pass in :distributed => true and subscribe to the distributed notification center. When you do that the option of :when_suspended can be supplied (which defaults to :coalese) and map as: DistributedBehaviors = { :drop => NSNotificationSuspensionBehaviorDrop, :coalesce => NSNotificationSuspensionBehaviorCoalesce, :hold => NSNotificationSuspensionBehaviorHold, :deliver_immediately => NSNotificationSuspensionBehaviorDeliverImmediately } You can see the Cocoa docs on what these mean. The object returned from on_notification is a NotificationListener instance that you can then use to stop receiving notifications by calling #stop_notifications on the instance: listener = win.on_notification do |notification| puts "Received first notification of #{notification.name} on my window and now stopping!" listener.stop_notifications end To post notifications you can do: notification :name => "SomeName", :object => some_object, :info => {:key => 'value'} If you do that it will post immediately, if you don't want it to post you can do: notification ...options..., :post => false You can also supply :distributed => true and it will post a distributed notification. Best, Rich
On Sep 19, 2008, at 6:22 AM, Richard Kilmer wrote:
I added the ability to easily support notification posting and subscribing in HotCocoa:
[...] Great! $ cat t2.rb require 'hotcocoa' include HotCocoa application do on_notification :distributed => true do |note| puts note.description end end $ ./miniruby -I./lib t2.rb NSConcreteNotification 0x185f9b0 {name = O3EngineChanged; object = brte*04271800; userInfo = { DisplayID = 69670912; EngineType = 1651668069; }} [...] NSConcreteNotification 0x16cb8e0 {name = com.apple.iTunes.playerInfo; object = com.apple.iTunes.player; userInfo = { Album = Damnation; Artist = Opeth; Genre = "Death Metal"; Location = "file://localhost/Volumes/Data/music/Opeth/Damnation/03%20Death%20whispered%20a%20lullaby.mp3 "; Name = "Death whispered a lullaby"; "Player State" = Playing; "Store URL" = "itms://itunes.com/link?n=Death%20whispered%20a%20lullaby&an=Opeth&pn=Damnation "; "Total Time" = 349805; "Track Count" = 8; "Track Number" = 3; Year = 2003; }} [...] I also checked that posting a distributed notification works. $ cat t3.rb require 'hotcocoa' include HotCocoa application do notification :name => ARGV.first, :info => {'123' => '456'}, :distributed => true end Note, I had to apply the following patch before. Index: lib/hotcocoa/mappings/notification.rb =================================================================== --- lib/hotcocoa/mappings/notification.rb (revision 608) +++ lib/hotcocoa/mappings/notification.rb (working copy) @@ -5,12 +5,12 @@ def alloc_with_options(options) if options.delete(:post) if options.delete(:distributed) - NSDistributedNotificationCenter.defaultCenter.postNotificationWithName options.delete(:name), object:options.delete(:object), userInfo:options.delete(:info), deliverImmediately: (options.delete(:immediately) == true) + NSDistributedNotificationCenter.defaultCenter.postNotificationName options.delete(:name), object:options.delete(:object), userInfo:options.delete(:info), deliverImmediately: (options.delete(:immediately) == true) else - NSNotificationCenter.defaultCenter.postNotificationWithName options.delete(:name), object:options.delete(:object), userInfo:options.delete(:info) + NSNotificationCenter.defaultCenter.postNotificationName options.delete(:name), object:options.delete(:object), userInfo:options.delete(:info) end else - NSNotification.notificationWithName options.delete(:name), object:options.delete(:object), userInfo:options.delete(:info) + NSNotification.notificationName options.delete(:name), object:options.delete(:object), userInfo:options.delete(:info) end end Great work! Laurent
On Sep 19, 2008, at 6:22 AM, Richard Kilmer wrote:
I added the ability to easily support notification posting and subscribing in HotCocoa:
Nice! Very nice! This makes me wonder though... Since we're now into the area of inter-application messaging, how might the ScriptingBridge APIs look once suitably "HotCocoa'd"? More concise than RubyOSA, I'd imagine, and perhaps capable of recapturing some of the ease-of-use we lost when transitioning from RubyOSA to ScriptingBridge... Just a random thought, and aimed mostly at Laurent. :) - Jordan
On Sep 19, 2008, at 11:47 AM, Jordan K. Hubbard wrote:
On Sep 19, 2008, at 6:22 AM, Richard Kilmer wrote:
I added the ability to easily support notification posting and subscribing in HotCocoa:
Nice! Very nice!
This makes me wonder though... Since we're now into the area of inter-application messaging, how might the ScriptingBridge APIs look once suitably "HotCocoa'd"? More concise than RubyOSA, I'd imagine, and perhaps capable of recapturing some of the ease-of-use we lost when transitioning from RubyOSA to ScriptingBridge... Just a random thought, and aimed mostly at Laurent. :)
ScriptingBridge works as it is under MacRuby. Off the top of my mind, the main advantages compared to RubyOSA are 1) objects returned by SB do not need to be boxed (since they are native!) 2) unicode strings! As an example, here is a script that lists all songs in iTunes. I have quite a few songs with Japanese titles and they show up perfectly in the terminal. framework 'ScriptingBridge' itunes = SBApplication.applicationWithBundleIdentifier('com.apple.itunes') itunes.sources[0].playlists[0].tracks.each do |t| puts t.name, t.artist, '---' end Obviously one could write some HotCocoa mappings for ScriptingBridge. For example, the [SBApplication applicationWithBundleIdentifier:] incantation is just too verbose, compared to RubyOSA's app('iTunes'). It would be a nice idea, though I'm not sure if we would be able to offer the same user experience than RubyOSA, given that all the scriptable APIs are generated on the fly and RubyOSA takes care of creating Ruby-like methods. Also, it is still impossible to access enumerations via ScriptingBridge, because it does not expose them. I would actually prefer to work on making MacRuby a real OSA language and bundling an OSA bridge similar to RubyOSA in the core. Laurent
participants (3)
-
Jordan K. Hubbard
-
Laurent Sansonetti
-
Richard Kilmer