dynamic Dock menus, HotCocoa version
Here’s a simpler version of that last post using Rich Kilmer’s HotCocoa library. I also use the approach I suggested at the end of the last post: Build a menu each time it’s requested, instead of trying to keep one at the ready.
Starting again from the end of the ADC MacRuby/Cocoa tutorial, we first need to make HotCocoa available to our program. At the top of Controller.rb:
require 'hotcocoa'
That defines the HotCocoa module; now, to make its methods available to our class:
class Controller include HotCocoa ... end
And here’s the method to build and return a new Dock menu on request:
def applicationDockMenu(sender) menu do |dock| @friends.each do |friend| dock.item(:remove_friend, :title => "Remove #{friend.first_name} #{friend.last_name}", :action => 'removeFriend:', :representedObject => friend ) end end end
(The :remove_friend symbol is sort of superfluous in this application. It’s used to generate default values for the menu item’s title ("Remove Friend") and action ("on_remove_friend:"), but because we’re generating a different menu item for each friend, and they’re all implemented with the same action, those defaults won’t do. The symbol can also be used to look up a menu item by name, for example to delete it from the menu, but we’re not doing that.)
Oh yes, and that remove_friend action - the same as last time, only we don’t delete the menu item:
def removeFriend(sender) friend = sender.representedObject @friends.delete(friend) @friendsTableView.reloadData end
Now all we have to do is tell Cocoa that Controller is our application delegate, which we do the same way as last time: In Interface Builder, control-drag from File’s Owner to Controller, and then select the delegate outlet.
As I said in the previous post, I don’t know whether building a menu each time and then hoping someone else throws it away is really kosher. For now, I’m hoping that even if it is a memory leak, menus are small enough resources, and Dock menus are used rarely enough, that it won’t be a serious problem. But somebody should look into that.