andymatuschak.org: Square Signals

This article was published on Friday, September 12th, 2008 at 8:13 pm.

Some book shops, libraries, bathrooms, cinemas, doctors' free polyphonic ringtone creator and places of worship prohibit their use, so that other patrons will not be disturbed by conversations.The first content sold to mobile free msg ringtones was the ringing tone, first launched in 1998 in Finland.mike oldfield ringtones

HotCocoa Is Pretty Damn Hot

A few days ago, MacRuby 0.3 was released. If you haven’t heard about it before, MacRuby is an implementation of Ruby 1.9 running directly on top of the Objective-C runtime and CoreFoundation. So when you type [4, 5, 6], you get an NSArray. And you can make calls to Cocoa like "/Users/andym/Desktop".pathComponents. Sweet.

Version 0.3 is a huge improvement: it provides Interface Builder support; it makes Ruby calls with the Obj-C message dispatcher (a huge speed boost); and it supports RubyGems. But most interestingly, it includes a new layer called HotCocoa.

HotCocoa is a layer of mappings on top of common Cocoa classes to make them simpler and to put them in line with idiomatic Ruby.

Showing Off

Alright, what does that mean? Say you want to make an NSColor for #f4b263.

In Obj-C:

[NSColor colorWithRed:0.9569 green:0.6980 blue:0.3882]

In MacRuby 0.2:

NSColor.colorWithRed 0.9569, green:0.6980, blue:0.3882

In MacRuby 0.3:

color :red => 0.9569, :green => 0.6980, :blue => 0.3882

MacRuby 0.3, with extra sugar:

color :rgb => 0xf4b263

That doesn’t look like a huge change, but you can see how the implementation using MacRuby 0.3 is much more idiomatic than 0.2. The syntax is much more at home in Ruby.

What else might you be able to do? Well, there are mappings for many common views:

slider :frame => [100, 150, 200, 24] do |s|
  s.min = 0
  s.max = 100
  s.on_action do |sender|
    puts "Changed to #{sender.doubleValue}!"
  end
end

In fact, HotCocoa is in large part designed to make it easy to set up interfaces through Ruby alone. So you could create your whole Cocoa app, window, and UI through a few lines of beautiful Ruby (adapted from Laurent’s original blog post):

require 'hotcocoa'
include HotCocoa
application do |app|
  window :size => [100, 50] do |win|
    b = button :title => 'Hello'
    b.on_action { puts 'World!' }
    win << b # Sugar for adding a subview.
    win.will_close { puts 'Goodbye!'; exit } # Delegate method--implemented!
  end
end

Note that HotCocoa provided sensible defaults for many NSWindow parameters typically required in the initializer—Obj-C is not very good at optional parameters, but Ruby is.

Normally, one of the biggest problems with defining views programmatically is layout: you spend forever specifying how each view resizes and saying “this one should be 15px to the right of this one, and this field should align with this label…”

HotCocoa helps with that, too:

window :size => [150, 50] do |win|
  win.view = layout_view :mode => :horizontal do |layout|
    layout.spacing = 10
    layout << button(:title => 'Hi!', :layout => {:align => :center})
    layout << label(:text => "<- A button.",
                    :layout => {:align => :center, :bottom_padding => 3})
  end
end

Example Window with button and label

Playing with HotCocoa

The documentation for HotCocoa is still quite spare at the time of writing, so you’ll have to do some spelunking to figure out how things work.

Start by taking a look at the example applications installed at /Developer/Examples/Ruby/MacRuby/HotCocoa; that’ll explain a lot of the basics, and you’ll get to see some more realistic examples than the idealistic ones I’ve shown here.

Once you’ve looked through those, you can browse the mappings HotCocoa makes available to you at /Library/Frameworks/MacRuby.framework/Versions/
0.3/usr/lib/ruby/1.9.0/hotcocoa/mappings
.

It might also help to look at HotCocoa’s implementation (in the parent directory of that path), to figure out exactly what black magic is going on for a particular call.

macirb is an indispensable tool for playing around with HotCocoa; just fire it up and fire off the following to start playing with mappings:

>> require 'hotcocoa'
=> true
>> include HotCocoa
=> NSObject

The Requisite Moral Judgment

So HotCocoa is really cool.

But Cappuccino is also really cool, and it scares the bejeezus out of me.

When working with MacRuby, I spend a lot of time thinking “man, this is really clunky-looking in Ruby.” That’s mainly because Obj-C is clunky. It’s verbose. It’s C-y. But we know Objective-C; we know Cocoa. That’s why there’s a bridge at all.

Take a look at this code:

Shoes.app {
  @push = button "Push me"
  @note = para "Nothing pushed so far"
 
  @push.click {
    @note.replace "Aha! Click!"
  }
}

It looks pretty similar to the HotCocoa code I’ve been quoting in this post. It’s actually some Ruby code using Shoes, a cross-platform UI framework. I guess I’m wondering: if we’re going to hide all the Cocoa away, why not just use something like this?

I’m a little concerned that if we go about redefining large swaths of the Cocoa API to make it pretty and idiomatic in Ruby, we’ll end up even more confused and spending even more time on documentation. After all, not all of the API is being redefined, and so I fear I’ll always be asking “can I do this thing Ruby-style, or do I need camel-case?”

Nervous kerfludgery aside, I’m having a hell of a time playing with HotCocoa, and I’m already totally sure it’ll make quick one-off tools faster. I think that with a little time spent learning this wrapper around the technologies we already know so well, one could rapidly become a super-fast, Cocoa-coding, city-terrorizing machine!

Congrats to Laurent Sansonetti and Rich Kilmer for their great work on this release!

The Conversation {14 comments}

  1. Michael Gorbach 13 September, 08 @ 12:46 am

    Why not Shoes?
    Because HotCocoa looks like it will allow people to “grow into” a full UI framework like Cocoa, gradually. Make the simple things easy and complex things possible. In the case of Shoes and other simplified frameworks, complex things may not be possible at all, so in building new features into an app I could hit a “wall”. In the case of HotCocoa I could easily shift to using the full weight of the cocoa frameworks, as well as any other bridged ObjC or C apis. I think this ability to actually attack more difficult problems when needed makes a big difference.

  2. Andy Matuschak 13 September, 08 @ 6:22 am

    Well put, Michael.

  3. Brian Mitchell 13 September, 08 @ 7:54 am

    Doesn’t the parser MacRuby is based on allow the much nicer syntax?

    color rgb:0xf4b263

    Even better now IMO:

    window size: [150, 50] do |win|
    win.view = layout_view mode: :horizontal do |layout|
    layout.spacing = 10
    layout

  4. Brian Mitchell 13 September, 08 @ 7:55 am

    GO figure…. I wish blogs would note what they comment system supported so I wouldn’t have to guess about escaping. I’m sure everyone can guess the rest.

  5. Jordan Hubbard 13 September, 08 @ 5:14 pm

    Let me just echo Michael’s sentiments: HotCocoa is not Yet Another UI Wrapping Layer which achieves its magic by, and I’ll be blunt, dumbing-down Cocoa or shaving off all the bits that don’t conform to some cross-platform model that can be implemented on top of other UI toolkits. It’s not really even an additional abstraction layer - it’s more akin a set of pre-processor macros that simplify calls to an existing layer. That gives you simplicity without subtracting any flexibility - a rare thing, I’d say!

  6. Andy Matuschak 13 September, 08 @ 6:56 pm

    Sorry for the trouble on the comment syntax.

    You’re right—that’s a correct alternative way to write it. I guess I’m just use to Rails and its =>-y style.

  7. _why 13 September, 08 @ 7:31 pm

    If I may, just if I could interject… I think the argument about simplicity hitting the wall doesn’t really hold up. (Well, except, I mean, it *may* hold up in Shoes’ case, because I could have designed it wrong.)

    But as for the concept of simplicity breaking down at a certain point, I would argue the contrary. Look at HTML. You have very few elements but people are able to build wildly complex things that wxWidgets or QT could never dream of. Yet HTML is far, far simpler than those. You have fewer things on hand to paint with. But it is less rigid, really. And that pays off hugely.

    Maybe these other layers on top of HTML like SproutCore and — oh, there are others I’m sure — maybe those prove that HTML is too limited. One thing about Shoes though is that I think it could prove to be more extensible and easier to layer than HTML because Shoes uses methods where HTML would use tags. And you can’t just add tags to HTML, right?

    I’m not arguing against HotCocoa at all. We’re all just out here feeling around for answers. Besides, Shoes is just for fun. But I still find myself wondering if there is a “wall”. I have heard tell of a “wall” and the wizards speculate that a “wall” may one day come down and keep the Shoesers from moving beyond it into the meadows, an obstacle with a very “wall”-like manner will descend… but, myself, I haven’t seen a wall at all!!

    Idea: maybe it is an underground wall?

  8. Rich Kilmer 13 September, 08 @ 8:09 pm

    Andy. First, great piece and I am glad you are digging HotCocoa. As you can see it IS early in its lifetime and we still have lots to hash out.
    I added some documentation tonight on the HotCocoa mappings:

    http://www.macruby.org/trac/wiki/HotCocoaMappings

    Regarding your concern about remapping all of Cocoa’s API to idiomatic Ruby…that is not my goal. I want to map things where they make sense. When I started I began mapping any method I used to underscore from camelCase but I stopped doing that, and will likely revert mappings that simply do that. Laurent may come up with some magic switch to underscore all camelCased methods…but for now I am adding custom methods only where they actually make things more clear in the API.

    As Jordan indicated HotCocoa is an attempt to mainly simplify the configuration of these classes, not create an abstraction layer to call through. In this way it is very unlike Shoes. Each HotCocoa method returns an instance of an Objective-C class #window => NSWindow, etc.

    _why…I think the wall people are talking about, in things like WxWidgets, is when you want to take advantage of the complete API of a particular control on OS X, but Wx limits you to a subset which is cross-platform. These widget libraries go very deep, as you know, and although most of the time the shallows are perfect every once in a while you need to jump off the high-dive and in shallow water that’s quite a wall to hit.

  9. Andy Matuschak 14 September, 08 @ 12:47 pm

    _why, thanks for weighing in! You make an excellent point with respect to HTML. Though many would indeed say that the rise of Javascript—the Little Lost Language doing all kinds of things it wasn’t meant to do—indicates limitation, I’d point to the CSS Zen Garden’s many examples and say they take web design as far as it needs to go, thankyouverymuch.

    However! When it comes to interactive layouts and designs, there are whole new dimensions of complexity possible on top of static designs. Is HTML/JS/Flash enough for that? I’d say no—280 Slides is damn impressive, but it still does only a fraction of what Keynote does, and it does that through a (seriously impressive) series of hacks that cap its performance at, again, a fraction of its desktop counterpart.

    That’s not to say it’s impossible to take some beautiful syntax and API and to fulfill the holy grail of “simple things simple; complex things possible.” I think Shoes has done a simply spectacular job of that for games. And while it can’t design a three-pane OS X interface with a toolbar and CoreAnimation and CoreWiggyWow, it’s not trying to!

    Of course, HotCocoa is, and I think that might be a much harder challenge! Thanks for clarifying things, Rich—I think you’ve done great work here, and I think you’re on track to something truly awesome.

    HotCocoa aims to simplify the simple things in Cocoa, but you can still drill down to the full Cocoa toolkit at any time. This is great. I think the only thing you’ve really got to be careful about is that confusion of “can I do this thing ruby-ishly?” A CamelCase -> under_scored converter would be truly sweet. Now that I examine HotCocoa more thoroughly, I see the vast majority of what it’s doing right now is constructors, so you’re in way better shape than you would be if you were trying to redefine large swaths of API.

    Mostly, I wanted to bring up some Controversy to get a conversation going—and I’m glad that one has! For the record, I’d like to note that I think both Shoes and HotCocoa are The Bee’s Knees.

  10. OMouse 14 September, 08 @ 3:56 pm

    _why, you’re talking about composability. You can take a look at Morphic in the Squeak Smalltalk system to see how well it works, though HTML isn’t a bad example.

    Rich, I get what you mean by reaching down the layers into the OS. Perhaps a good layer allows its guts to show when needed so that you can redefine the layer?

  11. OMouse 14 September, 08 @ 4:03 pm

    Shit, I forgot to say that the Ruby syntax with the keywords looks almost like Smalltalk and you might as well be using a Smalltalk! :P

    I just Googled and found F-Script which is based on Smalltalk and apparently integrates very well with Objective C and Cocoa: http://www.fscript.org/

    Etoile is also available and it looks like it’s a Smalltalk/Objective C bridge to GNUStep/NEXTStep: http://etoileos.com/etoile/

  12. Jonno 14 September, 08 @ 11:33 pm

    How hard is it to distribute a macruby/hotcocoa app to a .app bundle?

  13. Laurent Sansonetti 15 September, 08 @ 2:17 pm

    Jonno: if you create a HotCocoa project using the hotcocoa command line tool, all you need to do is to type “macrake” and it will generate a .app bundle for you in the same directory.

  14. JulesLt 20 October, 08 @ 2:45 pm

    I have to say that I love the look of this - along with NodeBox (a differently aimed wrapper atop PyObjC) and Etoile’s Smalltalk-as-first-class-language intention, because we’re at the point in the curve where barely anyone should be coding GUI apps in c-like languages these days, unless they have really good reason too.

    Credit where it’s due, Microsoft’s CLR is a similar idea (many programming languages, one runtime / API library) but unfortunately they never got to do the cleansing operation that Cocoa offered. Well sort of, seeing as we have Carbon.

    I’ve also been wondering about what would a new NextStep look like - i.e. NextStep/Obj-C/Interface Builder were state of the art in the early 90s, but in a lot of areas have been surpassed since, and of course some of the decisions were pragmatic (like C++, Obj-C was an answer to the problem of slow Smalltalk performance at the time, but VM technology has moved on a lot since then).

    What would you get if you set out with the same intentions today?? (i.e. setting out to create an environment that made it easy to create desktop applications???).
    I’m pretty certain you’d start with a current dynamic language rather than a C legacy.

    The interesting point will come when / if we get new ‘Cocoa’ libraries implemented in languages other than ObjC - with toll-free bridging that starts to become possible.

Leave a Comment

Currently you have JavaScript disabled. In order to post comments, please make sure JavaScript and Cookies are enabled, and reload the page.

You can follow any responses to this entry via its RSS comments feed. You can also leave a trackback if the inclination is there.

If you're looking for something specific then give the search form below a try:

RSS Wordpress Grady (theme) Return to the Top ↑