the blog
Back to -Blog

IronRuby Developments - the Visual Designer

We’ll soon release the alpha of our IronRuby environment...
by Huw Collingbourne
Tuesday 12 February 2008.

Microsoft’s IronRuby project - an implementation of Ruby running in the Dynamic Language Runtime (DLR) for .NET - is making good progress. When I first did some demos of our IronRuby form designer back in October of last year, I to work hard to find things that IronRuby could do (there were a great many things it couldn’t do). When I use IronRuby today I can pretty much dive right in and write reasonably complicated programs.

This is the current alpha version of Ruby In Steel for IronRuby. Still in the early stages of development, it already has extensive colour coding, basic IntelliSense and a drag-and-drop form designer with ‘code behind’ form definitions in the Solution Explorer and the ability to set properties using the Property panel.

There are still some things it can’t do but there are increasingly few and far between. To put it to the test, I decided to convert the simple adventure game framework which I’ve been writing about in Bitwise Magazine. This was written for ‘standard Ruby’ (the 1.8.6 Ruby interpreter) with commands entered at a prompt. I wanted to convert it to IronRuby with a form-based interface: commands would (initially, anyway) be ‘attached’ to buttons and the output would be displayed in a RichEdit box.

The user interface of my original ‘standard Ruby’ adventure game has hardly changed since its 1970s predecessors - just a command line and a prompt...

My IronRuby adventure game has a more modern form-based user interface with buttons and a RichEdit area to display output.

The conversion took me about half an hour. That’s pretty good, I reckon. Most of the game required no translation at all. The hierarchy of classes defining the game objects - the Rooms, Actors, Treasures and various ancestor classes - just worked ‘as is’, well, with just one small exception: I had to change a sneaky line of code that used the send method with a symbol as an argument. This has the effect of calling a method with the same name as the symbol. Here is my original code:

exit =[anActor.position].send(aDirection)

The idea here is that when aDirection has the value of a symbol such as :n, then a method named n() will be called. This is an example of Ruby’s ‘metaprogramming’ (using data as code) and is not yet implemented by IronRuby. I got around this by calling methods explicitly like this:

case( aDir )
        when :n : exit =[anActor.position].n
        when :s : exit =[anActor.position].s
        when :w : exit =[anActor.position].w
        when :e : exit =[anActor.position].e
return exit

Another problem I had relates to delegation to event handlers. Currently our form designer generates code that tries to ‘wire up’ events such as a Click on a button called button3 to a named event-handler such as button3_Click. It does this by attaching a block to the control.event and calling a named method inside that block like this:

self.button3.Click do |sender, e| button3_Click(sender, e) end

Frustratingly, when there are multiple controls specifying multiple named event-handlers, only one event-handler is ever called. In my own project, for example, even though button3.Click calls the button3_Click method, when I run the code it actually calls the button1_Click method - as do all the other buttons on my form. This is a known issue with the current release of IronRuby. We understand that the IronRuby team are working on this and I’ll report back later on their progress.

In spite of the wrong event-handler method being called by controls, the correct sender argument is passed to it. The sender argument refers to the control that was clicked. This gives me the ability to determine within their shared Click event handler which control received the original click. In my code, I have labelled the four ‘movement’ buttons with the four directions: n, s, e and w. My event-handler can now use this information (the buttons’ Text properties) to retrieve a string, ‘n’, ‘s’, ‘e’ or ‘w’ and send this to a method named processInput which, in my original commandline adventure game, initiated the movement of the player based on simple text input.

Here I hit another problem. This turns out not to be a deficiency of IronRuby but a technical solution to a problem of which I was not aware. This was my original version of button1_Click:

def button1_Click(sender, e)
        processInput( sender.Text )

This code works but it doesn’t produce the results I was expecting. My processInput method tries uses strings as ‘keys’ (the first item in sets of key-value pairs) into a Hash (or ‘Dictionary’). When a key is matched the corresponding value (a symbol) is returned. Again, this was all based on my original program’s expectation of string input from a command prompt and I’ll probably rewrite it to optimize it for a form-based design at a later stage. At any rate, in this version, when no key is matched, the message "Sorry, I don't understand '#{input}'!" is shown. With the code shown above, every button I clicked always ended up displaying that message! For a while I couldn’t figure this out. When I explicitly displayed the string passed to processInput, it was always exactly what I expected - a single character such as ‘n’. Even so, this never matched the key ‘n’ in my Hash:

{ 'n' => :n, 's' => :s, 'e' => :e, 'w' => :w }

My first suspicion was that there might be some extra whitespace - a carriage return, maybe? - lurking at the end of the string. I decided to remove this using Ruby’s chomp method. To my surprise, chomp didn’t work (it caused an exception) but .NET’s Trim method did.

That was when the penny finally dropped. The Text property of a control is a .NET string (a ‘ClrString’). A .NET string may look like a Ruby string but it isn’t. This is obvious when you think about it. A .NET string forms part of the .NET class hierarchy whereas a Ruby string forms part of the Ruby class hierarchy and they each have different, incompatible, sets of methods. The solution to this problem is to convert a .NET string to a Ruby string using the to_s method. My rewritten event-handler now works correctly:

def button1_Click(sender, e)       
        processInput( sender.Text.to_s )

The problems of making the two class libraries work in cahoots is a tricky one. I am not entirely certain how IronRuby will deal with all those ‘competing’ classes - all the very many data types and structures that exist both in the Ruby and the .NET class hierarchies. I’ll look into this further and write some more in another blog entry later on.

Anyway, in spite of one or two glitches, mentioned above, my experience with IronRuby this time around has been much more pleasant than it was when I wrote about it a few months ago. In fact, I am greatly encouraged by the developments the Microsoft team has made. I honestly didn’t think I would get my adventure game up and running at all. In fact, I did so with just a few very small changes to my code. By combining it with our form designer, I have had the very pleasurable experience of doing the kind of drag and drop design that I’ve so missed in Ruby up to now. Moving Ruby off the commandline and into a visual design environment is (in my view) a major improvement.

Our IronRuby IDE combines the ability to design the user interface by dragging and dropping controls from the Toolbox (left) and then write the program in our Ruby editor (top).

Even in the alpha version of our IronRuby IDE you can use the normal form design features such as alignment guides (being used here to line up the buttons) and the Properties panel (on the right)

I should say that IronRuby is still very much ‘in development’ and no ‘release date’ of the final version has yet been announced. Our visual design environment for IronRuby is also (inevitably) under development and we won’t be announcing a release date until IronRuby does. We anticipate having an IronRuby IDE ’ready to go’ soon after the release of IronRuby itself. In the meantime, we will be releasing the first alpha version of our IronRuby environment with the forthcoming Ruby In Steel Developer 1.2.

Bookmark and Share   Keywords:  development  IronRuby  visual design
© SapphireSteel Software 2013