 | Level: Introductory Richard Hult (rhult@codefactory.se), Software engineer, CodeFactory Mikael Hallendal (micke@codefactory.se), Software engineer, CodeFactory
01 Jan 2002 developerWorks is pleased to announce the relaunch of the Linux zone's popular GNOMEnclature column. In this incarnation of the column, Mikael Hallendal and Richard Hult of CodeFactory will give you the inside information you need to make the best use of the new GNOME 2 platform. In this series, you'll learn how to use the new and improved libraries available with GNOME 2 so that you can write your own Nautilus view, panel applets, and much more. In this article, Mikael and Richard reopen the series with a gentle introduction to GTK+ 2, the new foundation for the GNOME 2 desktop environment. By the end of this article, you'll have written and compiled a few sample GTK+ 2 programs and have a good understanding of GTK+ 2's many improvements over GTK+ 1.
About this series
Welcome to the new GNOMEnclature column! We're relaunching this
column with brand new content to help you make the best
use of the GNOME 2 platform. In the first few articles, we'll cover
the differences between GNOME 2 and GNOME 1, so that your GNOME
knowledge is fully up-to-date. These articles will be an ideal
introduction for developers who want to start creating GNOME
applications, and will also be of great assistance to current GNOME
developers who need to port existing applications from GNOME 1 to
GNOME 2.
First, we'll cover the basics. Then, once everyone has a good
understanding of GNOME 2 fundamentals, we'll provide more in-depth
coverage, showing you how to take full advantage of the cool new
libraries available in the GNOME 2 platform. By the end of this
series, you'll have written your own Nautilus view, created panel
applets, and much more.
About this article
Because GNOME is built on top of GTK+, the best way to start this series is to describe the changes between GTK+
1.2 and GTK+ 2. Therefore, in this first article, we'll take a look
at GTK+ 2, giving you a brief description of the new widgets and the
new ATK and Pango libraries that GTK+ 2 uses. Later in the series,
we'll take a more in-depth look at the GTK+ 2 object system, as well
as the two new widgets touched on in this article.
Introducing GTK+ 2
Before we dive too deeply into the next generation GTK+, you're
probably curious about when you can expect GNOME 2 to be ready for
production use. GNOME 2 is scheduled to be released on 15 February
2002; the larger applications such as Gnumeric and Evolution will be
ported to GNOME 2 some time after that.
OK, so let's move on to GTK+! GTK+ was originally developed to be
used in Gimp (GTK stands for the Gimp
ToolKit). GTK+ is currently available on a number of platforms
including Linux and Windows. It's used by a tremendous number
of free software projects, including GNOME itself, Mozilla, Gimp,
and hundreds more.
Just like GTK+ 1, GTK+ 2 depends on GLib, which is a convenience
library for C developers. GLib includes lots of nice functionality
to make your programming work easier, including an object system and
data structures such as hash tables, lists, and trees.
GTK+ 2 also depends on ATK and Pango. ATK is the Accessibility
Toolkit, which enables people with disabilities to make use of GTK+
applications. Pango is a framework for rendering internationalized
text. Both packages are described later in this article.
Installing GTK+ 2
To get the most out of this article we recommend that you
go ahead and get GTK+ 2 up and running. To install GTK+ 2, you
should first ensure that pkg-config 0.8 or greater is installed on
your system. All major distributions should have a package that
provides pkg-config. Of course, GTK+ 2 also depends on external
libraries, such as glib, atk, and pango. These libraries must be
installed first before GTK+ 2 will compile. Generally, the best way
to proceed is to first download the most recent versions of the
glib, atk, pango, and gtk+ source tarballs (see Resources later in this article).
Look inside the most recent "vx.y" directory you see, currently
"v1.3".
You may find it strange that we've spent all this time talking about
GTK+ 2, yet we are recommending you install GTK+ 1.3. There's a
good reason for this: At the time this article was written, GTK+
1.3.11 was the most recent version of GTK+ available. Once GTK+ is
fully ready for production use, GTK+ 2.0 will be released. Until
then, it's fine to use GTK+ 1.3 for testing, since it includes
nearly all the new features that will be in the official GTK+ 2.0
release.
OK, now that we've cleared that up, it's time to get back to
installing the new GTK+. Because GTK+ 2 has several build-time
dependencies, it's important that you install glib first, followed
by atk, pango, and gtk+. Install each package as follows:
Listing 1. Installing GTK+ and support library sources
tar xzvf package-version.tar.gz
cd package-version
./configure
make
make install
|
Once everything is installed, you should be able to start
gtk-demo, a nice little program that lets you see GTK+ 2 in
action.
So, what's new in GTK+ 2? One feature that lots of people have
requested is the ability to use anti-aliased fonts with GTK+. This
has now been added to GTK+ 2. GTK+ 2 font anti-aliasing is
implemented using the Xft library and the XRender extension that is
part of XFree86 4 and greater.
To enable anti-aliased fonts for GTK+ 2 applications, just set the
environment variable GDK_USE_XFT=1. All GTK+ 2 applications started
from that shell where GDK_USE_XFT is set to 1 should render
anti-aliased text. If you want, go ahead and enable anti-aliased
text, and then run gtk-demo again.
Example of a dialog using anti-aliased text
Double buffering and image handling
Font anti-aliasing isn't the only graphical improvement in GTK+ 2;
GTK+ now uses double buffering to update the screen. Due to a lack
of double buffering, GTK+ 1 applications would sometimes flicker
when redrawn or resized. GTK+ 2 no longer has this problem, so new
GTK+ 2 applications will be rendered much more smoothly.
In addition to simply looking a lot prettier, GTK+ 2 offers a lot of
improvements from the developer's perspective. For example,
GdkPixbuf (previously a separate library) is now a part of GTK+.
GdkPixbuf handles the loading and saving of images in various
formats, such as GIF, PNG, JPEG, BMP, etc. Now that GdkPixbuf is
part of GTK+, GTK+ itself can take advantage of it, using it to
render alpha blended icons for menus, toolbars, and buttons.
Here's a sample GTK+ 2 program that loads a small image
called gnome.gif:
In our sample program,
we create a GtkImage object using the gtk_image_new_from_file()
function. The GtkImage object will load our image automatically,
and makes internal use of GdkPixbuf to do so:
Listing 2. Using a GtkImage object to display an image
#include <gtk/gtk.h>
int
main (int argc, char **argv)
{
GtkWidget *window;
GtkWidget *image;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (window), "destroy", gtk_main_quit, NULL);
image = gtk_image_new_from_file ("gnome.gif");
gtk_container_add (GTK_CONTAINER (window), image);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
|
Here's how to compile this simple program:
gcc `pkg-config --cflags --libs gtk+-2.0` -o image-button image-button.c
|
Once compiled, go ahead and execute ./image-button. This is what
you should see:
Pango
Pango is the new, all-singing, all-dancing framework for the layout
and rendering of internationalized text. Thanks to Pango, GTK+ 2 is
now much more useful for people who don't live in the U.S. or Europe.
Pango can handle text that flows in a direction other than
left-to-right and can manage complex languages with ease, even handling
letters that take different forms depending on the context in which
they are used.
Pango supports bi-directional text, so you can mix left-to-right
with right-to-left text; there are also plug-ins for shaping various
complex scripts like Arabic and Tamil.
There's more to Pango than just internationalization; the Pango
library handles the rendering of anti-aliased text with the help of
Xft and the XRender extension. For more details, read two developerWorks articles
about Pango (see Resources).
Unicode and UTF-8
With GTK+ 2, any string passed to a gtk_*() function is expected
to be in the Unicode UTF-8 encoding. By using UTF-8 internally, GTK+
2 eliminates an entire class of internationalization problems with
previous versions of GTK+.
Because ASCII is a subset of UTF-8, this change shouldn't make as much
of an impact in existing GTK+ code as you might imagine. However,
while ASCII maps directly to UTF-8, the reverse is not true. Many
non-English character sets take up than a single byte per
character when encoded in UTF-8. In order to handle larger than normal character
encodings, you should now use a special function called
g_utf8_next_char() (it's actually a macro) when you need to iterate
over the characters in a UTF-8 string. This macro will take care of
taking small or big byte "hops", as needed. Here's a small example,
in which we validate and iterate over a UTF-8 string:
Listing 3. Validating and iterating over a UTF-8 string
gchar *p;
g_return_if_fail (g_utf8_validate (str));
p = str;
while (p) {
gunichar c = g_utf8_get_char (p)
/* Do something with c. */
p = g_utf8_next_char (p);
}
|
If you need to convert a locale-encoded string to UTF-8, you can use:
Listing 4. Converting a locale-encoded string to UTF-8
gchar* g_locale_to_utf8 (const gchar *opsysstring,
gssize length,
gsize *bytes_read,
gsize *bytes_written,
GError **error);
|
The last three arguments can be NULL if you are not interested in
how many bytes were read and written. If you are passing a NULL-terminated string to this function, set the length to -1; for
example:
utf8_string = g_locale_to_utf8 (locale_string, -1, NULL, NULL, NULL);
|
Atk, the Accessibility Toolkit
GTK+ 2 now makes full use of ATK, the Accessibility Toolkit. ATK
makes it possible for people with disabilities such as impaired
vision or limited mobility to interact with GTK+ 2 applications. In
a future article, we'll cover ATK in more detail and show you how to
make your own applications accessible to people with disabilities.
You can visit the GNOME Accessibility Project in the meantime (see Resources).
Stock items
Both GNOME 1 and GNOME 2 have support for "stock items", allowing
developers to add common menu items and buttons to their
applications very easily. Since stock items are defined globally
rather than within the application, they make it easy to provide a
uniform look across all GNOME applications.
Typically, an individual stock item consists of an icon, a text
label, and an optional accelerator key. In addition to giving
applications a uniform look, stock items are also a great help for
internationalization since they only need to be translated once (in
the GTK+ library), rather than having application-specific data that
needs to be translated by the individual developer. For the GNOME 2
platform, stock item support has been moved from gnome-libs to GTK+,
making it possible for even more applications to have a consistent
look and feel.
Here's a snippet of example code that creates a button with a
floppy disk image and a "Save" label:
Listing 5. Creating a button with a
floppy disk image and a "Save" label
GtkWidget *button;
button = gtk_button_new_from_stock (GTK_STOCK_SAVE);
|
Here's is a screenshot showing a toolbar using four stock items:
Toolbar using four stock items
Stock items can also be used in menu items, as follows:
Listing 6. Creating a menu item with a floppy disk image and a "Save"
label
GtkWidget *menu_item;
menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE);
|
This code creates a menu item with a floppy disk image and a "Save"
label. It also automatically connects the Ctrl+S keyboard shortcut
to the menu item. Using stock items ensures that Ctrl-S will always
be the default save shortcut, no matter what program you happen to
be using.
If there is a suitable stock item available, it's highly recommended
that you take advantage of it to create your menu items, toolbars,
and buttons. Not only will you make your user interface more
consistent, but you'll also save precious time and lines of code.
You can also create stock items locally in your own
application. This can save time and code if you need to use the
items in several places, and it also makes your icons thematic.
Markup
With GTK+ 2, it's a lot easier to use different fonts, sizes, color,
and styles when specifying text widgets. This new functionality is
possible thanks to Pango, which now supports a small markup language
called GMarkup. GMarkup is a lightweight XML-like syntax that
allows you to specify different text styles by simply embedding tags
into the strings that you provide to various
gtk_*() functions. Here's an example:
Listing 7. Pango markup example
#include <gtk/gtk.h>
int
main (int argc, char **argv)
{
GtkWidget *window;
GtkWidget *label;
gchar *markup_text;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (window), "destroy",
gtk_main_quit, NULL);
label = gtk_label_new ("A <span color=\"blue\">blue</span>
<big>and</big> <b>bold</b> label");
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
gtk_container_add (GTK_CONTAINER (window), label);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
|
And to compile:
gcc `pkg-config --cflags --libs gtk+-2.0` -o label-markup label-markup.c
|
The code example, when run, will look like this:
Pango markup
Keyboard navigation
GTK+ 2 makes it much easier to create a user interface that's easily
accessible using only the keyboard, thanks to several new features. First, switching focus between different widgets is now more predictable
than in GTK+ 1. Just use Tab and the arrow keys and everything will
work as expected. Second, GtkDialog, the new dialog widget, automatically handles the Escape
key and closes the dialog. Third, it's now very easy to create keyboard accelerators, also known
as mnemonics. To create a button with a mnemonic, simply do this:
button = gtk_button_new_with_mnemonic ("_Quit");
|
The button can then be activated by pressing Alt+Q. The character
that is preceded by an underscore will be underlined, indicating
that it represents a keyboard shortcut.
Here's an example showing the use of mnemonics for notebook pages
and buttons:
GTK+ 2 mnemonics example
#include <gtk/gtk.h>
int
main (int argc, char **argv)
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *label;
GtkWidget *page;
GtkWidget *notebook;
GtkWidget *button;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (window), "destroy",
gtk_main_quit, NULL);
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
/* Create our notebook and two pages, with mnemonics. */
notebook = gtk_notebook_new ();
gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
label = gtk_label_new_with_mnemonic ("Page _1");
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
gtk_label_new ("Page one"), label);
label = gtk_label_new_with_mnemonic ("Page _2");
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
gtk_label_new ("Page two"), label);
/* Create a button with a mnemonic as well. */
button = gtk_button_new_with_mnemonic ("_Quit");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
/* Make the quit button actually quit. */
g_signal_connect (button, "clicked", gtk_main_quit, NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
|
To compile:
gcc `pkg-config --cflags --libs gtk+-2.0` -o mnemonics mnemonics.c
|
Note the mnemonics in the resulting image:
GTK+ mnemonics
GtkTreeView
GtkTreeView is a new tree and list widget that replaces GtkCList
and GtkCTree. In the past, there was poor logical separation between
data and view, and it was difficult to write custom cell
renderers. With GtkTreeView, these problems have been resolved. As
a bonus, GtkTreeView has an editable text cell, and features
animated expander arrows for a bit of eye candy.
GtkTreeView in action
GtkTextView
The new GtkTextView widget is a huge improvement over the old
GtkText widget. It has a lot of nice features:
-
It supports the use of mixed fonts, styles, and text colors, and you
can set line spacing and adjustment on a line-by-line basis.
-
Since all text is represented in UTF-8 and rendered using
Pango, GtkTextView is fully internationalized.
-
Long lines can be word-wrapped or by wrapped by character if preferred.
-
You can embed images, and even other widgets.
-
Since GtkTextView uses a Model/View/Controller design, it supports
multiple views of the same text buffer.
Here's what the new GtkTextView widget looks like when rendered:
GtkTextView in action
Conclusion
Now that we've taken a good look at the new functionality available
in GTK+ 2, we're ready to start exploring the rest of the GNOME 2
platform. Please join us in our next article when we take a look at
the new Glib-2 object system.
See you then!
Resources
About the authors  | |  | Richard Hult works for CodeFactory and has been a GNOME
developer for about three years. At CodeFactory, Richard maintains MrProject, a GNOME
project management application. Richard is also the
author and maintainer of Oregano, a
GNOME circuit design application.
|
 | |  | Mikael Hallendal is a GNOME developer for CodeFactory in Sweden, currently
working on MrProject, a GNOME
project management application. In addition, Mikael is developing a help
browser for GNOME 2.0 called "Yelp", and is also maintaining DevHelp, a document browser for
developers. As if that weren't enough, Mikael also serves as the Desktop Team
Leader for Gentoo Linux.
|
Rate this page
|  |