Subclassing in Ruby/GTK+
Davyd is spot on when bringing up the use of subclassing in GTK+. This is a step that comes natural for most people used to OO programming but (probably due to having to write a lot of boiler plate code) often is neglected by GTK+ application developers.
While many feel it’s daunting to subclass GTK+ widgets in C, it can be really nice when writing applications in other languages. Just like Davyd showed, Python is such a language, so is Ruby which I will show a similar brief example of here for those that are trying to get into Ruby/GTK+.
require 'gtk2'
# Defining OpenFileDialog
class OpenFileDialog < Gtk::FileChooserDialog
@@CWD = nil
def initialize(parent_window)
super("Open file", parent_window,
Gtk::FileChooser::ACTION_OPEN, nil,
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
[Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_OK])
self.default_response = Gtk::Dialog::RESPONSE_OK
self.current_folder = @@CWD unless @@CWD.nil?
signal_connect :response do |dialog, response|
@@CWD = self.current_folder if response == Gtk::Dialog::RESPONSE_OK
end
end
end
# Using OpenFileDialog
2.times do
d = OpenFileDialog.new(nil)
d.run do |response|
puts "filename = #{d.filename}" if response == Gtk::Dialog::RESPONSE_OK
end
d.destroy
end
The second half simply to try it out. For a nicer paste, see http://pastie.caboo.se/148847.
But it’s so hard in C!
Writing all the boilerplate by hand is a lot of work and error prone. However, here are two tips for making life easier.
The first way is to implement a dummy object that you later copy and query/replace. A nice tool for using this method is Regexxer) that lets you easily change the dummy name into your object name. I suggest you hook up your dummy object in the Makefile in order to make sure it always builds.
The other solution is to use a generator script such as Spuug to generate all the boilerplate for you. It makes it very easy to create new subclasses when you need them.
Update: As Johannes pointed out in a comment, Anjuta also comes with a generator for subclassing.
Just to mention it: Anjuta also has a code generator for subclassing in C for Glib/Gtk+.
Johannes, excellent point. Updated the post.
One (IMHO) problem with gtk on ruby is that you can directly override methods representing signal handlers. That makes subclassing in ruby a little bit less nice than it could be. For example, in C# I would write something like:
public class MyButton : Button { protected override void OnClicked () { // Do something on click! } }In ruby-gtk you can’t subclass like this.
Well, you can, however it seems there is a bug in the bindings somewhere causing the “super” operator to fail if you do.
The way to do it is:
class MyButton < Gtk::Button type_register def signal_do_clicked # Do something on click end endFor the “don’t want to depend on a runtime” people vala might be a good way too. I’m sure it can easyly subclass gobjects too.
Arc posted a follow up about how to do this in Vala for those that are interested,
http://aruiz.typepad.com/siliconisland/2008/02/subclassing-in.html
I think the difficulty of subclassing (and things in general, but subclassing is the biggest problem) is a huge barrier in GTK+ development. I’ve often wanted to contribute and work on existing GTK+ apps and such, but those are written largely in C. There are problems in a few apps that would be easily solved with a subclass, but the difficulty is a problem.
That one could replace the entire GObject tutorial (which doesn’t even mention subclassing, from what I can see) with a few paragraphs in C++ or Ruby or seems somewhat silly.
In comparison, as a potential GNOME contributor who has started hacking on KDE4 instead, the cleanness and niceness of CMake, Qt, KDE’s libraries, etc. make working on it a pleasure. It takes me very little time to find the relevant code for a desired change in a KDE program, even if the relevant bit is in some other library four super-classes away. For someone who doesn’t know the code, trying to help out on a GTK project is daunting.
I don’t know what can be done, since existing apps are already in C, and I’m not sure how one could make subclasses work nicely in C… maybe a comprehensive set of *official* macros covering everything would help.
Anyway, it would be nice a lot if GTK hacking were made easier for mere mortals. I suspect I’m not the only one turned away by GObject.
[...] my previous example, I passed the arguments like usual to the super call. It turns out that when you have registered [...]