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.

Quick “unlock slider” hack in GTK+

Went to town and bought an ipod touch during the weekend in order to be able to try out the UI a bit first hand. Quite a lot of the effects and animations should be possible to implement in a GTK+ UI fairly easily while some others will obviously want some kind of 3D acceleration.

I hacked up a quick test for making the kind of “unlock slider” that the ipod have for locking the screen from input. I am simply subclassing the GtkHScale and adding some animation to it.

Unlock Slider
For better resolution, see unlock-slider.mov

I started by adding my own handler for value-changed which checks whether the threshold for when to emit the unlocked signal is met. Otherwise an animation to bring the slider back to the original state is started:

static void
slider_value_changed (GtkRange *range)
{
	UnlockSliderPriv *priv;

	priv = GET_PRIV (range);

	if (priv->start_value != 0.0) {
		return;
	}

	if (gtk_range_get_value (range) < THRESHOLD) {
		priv->start_value = gtk_range_get_value (range);
		gtk_timeline_start (priv->timeline);
	} else {
		gtk_range_set_value (range, 1.0);
		priv->start_value = 0.0;
		g_signal_emit (range, signals[UNLOCKED], 0);
	}
}

This is using the GtkTimeline from #444659 . I’m then using the frame and finished signals from the timeline to update the slider to create the desired animation.

static void
slider_frame_cb (GtkTimeline  *timeline,
				 gdouble       progress,
				 UnlockSlider *slider)
{
	UnlockSliderPriv *priv;

	priv = GET_PRIV (slider);

	gtk_range_set_value (GTK_RANGE (slider), (1.0 - progress) * priv->start_value);
}

static void
slider_finished_cb (GtkTimeline *timeline, UnlockSlider *slider)
{
	UnlockSliderPriv *priv;

	priv = GET_PRIV (slider);

	gtk_range_set_value (GTK_RANGE (slider), 0.0);
	priv->start_value = 0.0;
	gtk_timeline_rewind (priv->timeline);
}

That’s about it for creating a simple animation looking as the video above. The full code (including the boilerplate and window creation code can be found in our git repository.

It would obviously need some artistic love and subclassing the GtkHScale is probably not the approach I would take for a real world application but it served well for a quick example.

Eclipse for C programming

A few weeks back I started trying out Eclipse after reading that Eclipse 3.3 with CDT 4.0 (C/C++ Development Tools) was released.

For anyone who want to try this out, don’t use gcj. I started out trying the gcj compiled version which turned out to be a lot slower (to the point where it was lagging when you typed). After switching to Suns JDK, speed of the UI was great.

I’ve semi-followed CDT for a while in the hope that it will be able to provide a nice IDE for C development. Not only an editor with GDB-integration (Emacs and Vim does that :) ) but also some of the nicer features you can find in modern IDEs. Like code awareness, indexing of symbols, type-ahead completion, refactoring capabilities etc.

With CDT 4.0 it is definitely becoming usable for programming C and comes with many nice features that can improve your productivity and reduce jumping around in the code just to look at definitions/implementations of certain functions.

For example when you hover a function call you get a tooltip with as much information possible (if Eclipse can access the implementation it will show it, otherwise the declaration).

A short screencast showing a session hacking Loudmouth 2 which is the project I’ve used for trying Eclipse out over the last few weeks.


(OGG)Google video

The refactoring bits leaves a lot to be desired (only supports function renaming at the moment) but there seems to be a lot of momentum around the project so I’m hopeful.All in all Eclipse is really becoming useful even for us old school C hackers :)

Next Page »

Close
E-mail It