This chapter describes how to write a new GtkWidget. A widget is any GtkObject that derives from GtkWidget; before reading this chapter, you should be familiar with the chapter called The GTK+ Object and Type System. This chapter will discuss the details of GtkWidget, but will not re-explain GtkObject in general. You will also need to know something about GDK to write a widget; be sure to skim the chapter called GDK Basics if you haven't.
Widgets are easy to create; you only need to cut-and-paste the usual GtkObject boilerplate (instance and class initializers, a get_type() function, and so on), and then implement your widget's functionality. Writing new widgets is an important application development technique.
After a brief overview, this chapter jumps straight to the implementation of a very simple widget called GtkEv. Then it takes a step back, describing widget implementation more systematically. It ends with more examples, taken from GTK+ itself. (It pays to become familiar with the GTK+ source code: often the easiest way to implement a widget is to subclass or slightly modify the most similar stock GTK+ widget. Of course, you must comply with the terms of GTK+'s license if you cut-and-paste code from the library.)
This section gives a brief overview, including the different kinds of widget you might encounter, and the general functionality a GtkWidget is required to have.
The term "widget" is really very broad, since it encompasses any object that implements the GtkWidget interface. There are many ways to classify widgets:
Containers are widgets that store other widgets inside, such as the boxes and tables described in the chapter called GTK+ Basics. As the chapter called GTK+ Basics discussed, containers can be subdivided into those that add functionality to a single child (GtkButton, GtkFrame, GtkEventBox, etc.), and those that manage layout for multiple children (GtkBox, GtkTable, etc.). Container widgets are harder to implement than "plain" widgets because the GtkContainer interface must be implemented in addition to the GtkWidget interface.
Composite widgets are containers that already contain a useful collection of child widgets in a nice package. For example, the GtkFileSelection widget is a subclass of GtkWindow that already contains a list widget to show files, dialog buttons, and so on. Widgets like this are easy to write, and are a convenient way to code applications. You could write a "MainWindow" widget for your main application window, for example, and then create a new instance of the widget whenever the user opens a new document. GnomeApp and GnomeDialog are two important composite widgets in Gnome.
Non-container widgets can be actual controls (buttons, scroll bars, etc.), information displays (GtkLabel), or decorative flourishes (GtkSeparator, for example). As the chapter called GTK+ Basics briefly mentioned, there are two major ways to implement widgets: most widgets (those that need to receive events or draw their own background) have an associated GdkWindow; "no window" widgets draw on their parent container. Widgets without windows are implemented slightly differently. All containers have a GdkWindow (since widgets without one might need to draw on it, among other reasons).
This chapter presents several widgets as examples, including a GtkEv widget written especially for this book, GtkVBox from GTK+, and GnomeAppBar from libgnomeui.
A minimal widget implements the following (though GtkWidget's default implementation may be sufficient in many cases):
Creation and destruction; this means the usual GtkObject boilerplate (instance and class initializers, shutdown, destroy and finalize methods). See the chapter called The GTK+ Object and Type System, especially the section called Object and Class Structures in the chapter called The GTK+ Object and Type System and the section called Object Finalization in the chapter called The GTK+ Object and Type System. Also see the section called Widget Life Cycle in the chapter called GTK+ Basics.
The realize/map/unmap/unrealize cycle discussed in the section called Realizing, Mapping, and Showing in the chapter called GTK+ Basics. Widgets must be able to create and uncreate their associated X resources any number of times, and they must be able to show and hide themselves any number of times.
Geometry negotiation, discussed in the section called Size Allocation in the chapter called GTK+ Basics. Your widget must respond to size requests, and honor size allocations.
Drawing; widgets must be able to draw themselves on the screen. For container widgets, the widget itself may be invisible but it must ensure child widgets are drawn.
The widget's unique functionality. Typically this means implementing handlers for some of the widget's event signals.