The Art of Writing a Bonobo Control

Dirk-Jan C. Binnema

Revision History
Revision 1.0.1August 11, 2001
Update: -Wall cleanups, OAF_INFO_PATH notice, misc. other stuff
Revision 1.0.0April 4, 2001
Release: ready for mass consumption
Revision 0.8.0October, 2001
Draft

Table of Contents
Introduction
Writing a Bonobo Control
Writing a Bonobo Container
Conclusion

In this article, I'll try to give a practical introduction into the Art of Writing Bonobo Controls, and also provide some backgrounds. Turning the example into anything useful is left as an exercise to the reader. If you've never done any GTK+/GNOME programming, it may be a bit hard to follow; I suggest reading a good book on the subject first. At the end of this article, I've included some suggestions.

You can find the most recent HTML-version of this tutorial at http://www.djcbsoftware.nl/projecten/bonobo_controls, or download a tarball with the Docbook-source and the example code at http://www.djcbsoftware.nl/projecten/bonobo_controls/bonobo_controls.tar.gz

For comments, suggestions etc, you can reach me at djcb@djcbsoftware.nl. Thanks to all the people who have helped in getting this tutorial in it's current state. You know who you are!

Introduction

Bonobo

Bonobo is the component model that has grown from the GNOME project. Originally, Bonobo was designed and implemented by Miguel de Icaza, heavily inspired by Microsoft's OLE2. Now, what can we do with a component model? A lot of things:

  • embeddable documents (i.e. a word-processing document inside a spreadsheet);

  • controls (i.e., meta-widgets available through CORBA);

  • scripting[1] and automation (e.g., writing some Perl to control Gnumeric). Currently, there's some work being done on a Perl-binding for Bonobo.

In this article, I'll try to explain how to write a Bonobo control, and how to embed it into your application. It's not hard at all, although it may take some time to really understand it. Also note that Bonobo has been in a state of flux in the not-too-distant past; fortunately, it has stabelized now for the GNOME 1.4 release. In fact, at April 10 2001, Bonobo version 1.0 was released, and I have verified that the sample code works correctly with Bonobo 1.0. [1]

Bonobo background

Before we dive into straight howtoism, let's have a short discussion of Bonobo's background, and its roots in CORBA and OLE2.

As stated, Bonobo is a component model or object model (I use the terms interchangeably), i.e., a technology that aims at having lots of objects interact. For a powerful object model, it's important to be able to 'connect' to this model in many different ways; i.e. you want to be able to freely choose the programming language for some task, while being able to connect to existing objects written in other languages. And you may want to access these objects from different machines, running different OS's, etc. This is the kind of stuff CORBA was designed for, and this is exactly why Bonobo uses it.

By setting standards, the CORBA runtime system can deal with the low-level plumbing of connecting objects. The question remains how to discover what capabilities other objects have, because this is a prerequisite for using them. The stuff that objects expose to the outside world, such as methods, attributes etc. is called the object's interface. This is very similar to C++ class definitions, or Java or Objective-C interfaces. To describe such interfaces, CORBA defines a special language, the interface definition language (IDL). The external interface of CORBA objects is specified completely in IDL, and IDL-compilers generate the plumbing code (skeletons and stubs) for you to enable communication between objects from the IDL descriptions.

In 1993, Microsoft introduced OLE2 to do some of the same things CORBA does, but primarily aimed at desktop-related things, such as embedding documents within each other, and controls. Bonobo's interfaces are very much 'inspired' by the OLE2 interfaces. On top of that, Bonobo also provides a default implementation for these interfaces, using GTK+ and its object system. Now, instead of writing lots of boilerplate code, writing a Bonobo control only takes a couple of lines of code, as I will show you. Still, you have the freedom to override any of the default implementations if you need to.

Note that what Bonobo really does is defining a communication protocol between objects, and that this protocol is defined in a number of IDL interfaces. So, in principle you could take these interfaces and implement them using Qt, Java, ncurses or whatever. The resulting objects would then be able to interact seamlessly, no matter what toolkit they'd be using. In theory, at least.

Ok, now back to howto-mode.

Notes

[1]

Bonobo-support for embedded scripting is not implemented yet. I have some ideas how to it, but I lack the time...