1 Comment

Presenter First in GTK and C

This post has been updated for 2012. Read the latest version.

Recently Mike Karlesky and I spent a week in the Baltimore area leading up a workshop-style training course. The intent of the workshop was to demonstrate Agile techniques applied in the embedded domain.

As part of the workshop, I created a small GTK application to demonstrate Presenter First and Model-View-Presenter. (Although a GUI application may not seem particularly embedded, the principle is the same: the view walls off some untestable library; the presenter and model allow us to test around it.) GTK turned out to be a good choice, since the events flying out of its widgets were much like the asynchronous events that come out of other windowing toolkits or hardware devices.

And here it is: the aptly named PF Calculator. Guess what? It’s a calculator. The calculator’s functionality is quite limited, in that it can only divide integers, but it still demonstrates Presenter First concepts quite well:

  • The ApplicationPresenter responds to events from the ApplicationModel and ApplicationView.
  • The ApplicationView fires events roughly corresponding to events coming from GTK widgets. Along the way, it does some translation to only relay the relevant information and remove traces of GTK in the event.
  • The ApplicationModel is used to compute the “business logic” (haha, I love that term, especially when applied in such a silly context). The Model delegates to the NumberValidator to get some help when needed.
  • And last (but not least), all of the above code was written Presenter First.

Everything is implemented in C. Here are a few notes about the implementation:

  • In a language with automatic object construction, I’d have the Presenters wire up their events in their constructor methods. Since that strategy isn’t available here, I’ve instead implemented a Presenters_RegisterForEvents function. The purpose of the function is to rip through all of the Presenters and tell them to RegisterEvents. It would be trivial to have the build system automatically generate this file in a project with many Presenters.
  • I only support one subscriptor to any single event. This is because I didn’t feel like implementing a bounded array or linked list to hold the function pointers. I did see something about a GSList data structure available in the GLib documentation, but I never got around to trying it out.
  • I call the gtk_init function in main before firing up the application. I’m not wild about this GTK-specific knowledge leaking outside of the view, but for this very simple example, it was the cleanest way to handle this detail. In a real project I’d strive to keep GTK specifics confined to views.

I depend on a number of libraries and tools to get them job done. More notes:

  • I’m using the Ceedling build and test harness developed by Mike Karlesky, Greg Williams, and Mark VanderVoord. Ceedling gives me easy access to unit testing via Unity, C mock generation via CMock, and C exceptions via CException. Ceedling also weaves everything together to create the executables.
    • Ceedling hasn’t had a 1.0 release yet, but the code available from the Sourceforge project is quite functional.
  • I used this project as an excuse to monkey around with the PCRE library. I didn’t use it extensively, but it was enough to get a taste. It turns out PCRE is tasty.
  • I also recently heard about bstring and tried it out. Again, I didn’t use it for much, but enough such that I’m sold on it.

Warning: I haven’t tried to build this code on anything other than my personal Linux system, so I can’t say how portable it is. Here are some details about my system:

  • The Linux distribution is Ubuntu 10.04.
  • The GTK development files have been installed via the libgtk2.0-dev package.
  • The PCRE development files have been installed via the libpcre3-dev package.
  • bstring is bundled with the project.
  • The build system relies on Ruby and Rake.
    The build system uses pkg-config commands to gather the build flags for PCRE and GTK. Hopefully this means it will be easier to build the project on an arbitrary system.

To build and run the application, type rake. To run all the tests, type rake test:all. To test an individual module, like ApplicationModel, type rake test:ApplicationModel.c.

Big thanks to Mike Karlesky for assisting with Ceedling, CMock, and Unity. Also thanks to Greg Williams and Mark VanderVoord for helping develop this great software.

Resources:

Edit July 13, 2010: The article was initially published without the Ubuntu package names filled in. This has been corrected.