March 25, 2009

MacRuby CSS Based Charts

I spiked around a while ago searching for the best solution to create charts under MacRuby for Pomodori. There are wonderful Ruby library for charting and 2D drawing in general, but the problem is to see if they are MacRuby compatible. In theory, everything can work under MacRuby as it runs under MRI but the macgem mechanism is still immature and even installing by hand doesn’t guarantee that the gem doesn’t bomb with impossible-to-read core dumps. I also searched for a non-native drawing solution (so all rmagick libs are out of discussion) because I don’t want to force the user to install a dependency which requires compilation.

A promising pure 100% Ruby library for the task is SVG::Graph. I jumped into it to find out that REXML gives a strange exception under MacRuby 0.4 which is already a major open ticket. I wasted some time to understand if I could fix it but I really wanted to have something done quickly. So I searched for something else.

While searching for options I also found this hidden gem inside the MacRuby installation: HotCocoa::Graphics. This is the Ruby bridge to the powerful Cocoa 2D graphics capabilities and can draw wonders. Probably this is the future core for a native charting library that unfortunately doesn’t exist yet. I had a quick look to realize how much work would require to use those low level primitives to create a bar chart. Again, too much work.

CSS charting was a very promising option from the start. I had a look at the many Geoffrey Grosenbach’s wonderful charting libraries with no luck. That’s because either Rails based or requiring rmagick. So I was left with javascript charting or CSS charting, two solutions requiring a web engine to work. Of the two I picked CSS charting because it’s dead simple and plenty of examples around.

The trick to make it works under MacRuby is just to open a web_view (I’m using HotCocoa to wrap Cocoa objects) and point the view to a local HTML file containing the data and using a CSS file to render them as charts. And you see the following as expected

That’s just a matter of:

where resources/all_tags_report.html is local to the application. The HTML file can then import all the necessary CSS always from localhost. Notice how the local reference is loaded with NSURL.alloc.initFileURLWithPath. There is some trickyness though: the reload method on WebView doesn’t work for local pages so to refresh the chart you actually need to produce another HTML file with different data and point the web_view to it.

The next piece of implementation to consider is how to make the static HTML page dynamic so that when it’s loaded it populates with the latest data available. I started looking around for template engines like Radius. No problem running a Radius parsing like this one under MacRuby:

except for the fact that the to_s isn’t working! The Proc returned after the parse isn’t evaluated for some reason and returned as is.

> macruby radius_test.rb
[##-<:parsetag:0x8005d84e0 block="#<Proc:0x8005d87a0@csscharts/radius/lib/radius.rb:422">>]
> ruby radius_test.rb
A small example: Hello world!

Damn another MacRuby incompatibility! Also in this case I decided not to try to fix it myself, also because a simple gsub on the HTML file should do the trick. The last thing I want to try for this is semr: I can create a small html-ish grammar with loop support to help me creating the small template engine I need.

Even though not perfect, I find the CSS web view based solution very simple and flexible at the same time. I’m pretty sure that when MacRuby will be shipped with Mac Os X nothing of this work would be useful because all the standard pure Ruby graphic library will be supported out of the box. But for now…

Comments (View)
blog comments powered by Disqus