RubyCocoa is one of the most fascinating tools on OSX. It makes it more than easy to rapidly prototype and try ideas with Cocoa. But unfortunately, out of the box, a RubyCocoa project seems to require an Objective-C shell to start it up. That means firing up XCode for every single prototype you’re playing with.
It only seems that way, though. A quick look behind the scenes reveals that all that shell does is:
- start the ruby environment
- ‘require’ all included ruby scripts
- and runs NSApplicationMain
The first two, I can obviously do on my own. The third provides the main loop for all NSApplications. But you can’t simply call it from Ruby - it requires you to have an Info.plist. Again, too much baggage for quick & dirty prototypes. The goal is to have one ruby file to play around in.
That one is a bit trickier to find out, but after digging around in Apple’s documentation, it turns out there is a decent explanation in the overview for NSApplication
For future reference, this is what it does:
void NSApplicationMain(int argc, char *argv[]) {
[NSApplication sharedApplication];
[NSBundle loadNibNamed:@"myMain" owner:NSApp];
[NSApp run];
}
Now we’re getting somewhere. This can actually be completely duplicated in Ruby. Since I might want to quit my application, I’ve thrown in a window that shuts down the application when closed.
require ‘OSX/cocoa’
class CloseDelegate < OSX::NSObject
def windowWillClose( sender )
OSX::NSApp.terminate_ sender
end
end
# Instantiate the shared App
OSX::NSApplication.sharedApplication
window = OSX::NSWindow.alloc
window.initWithContentRect_styleMask_backing_defer_(
OSX::NSMakeRect(50,50,200,400),
OSX::NSTitledWindowMask
+ OSX::NSClosableWindowMask,
OSX::NSBackingStoreBuffered, true)
window.setDelegate CloseDelegate.alloc.init
window.makeKeyAndOrderFront nil
# run the main loop
OSX::NSApplication.sharedApplication.run
Or just download standalone.rb