8.2. Looking at Gtk2::MessageDialog and interesting parts of our program.

Introduction

Gtk2::MessageDialog is a subclass of Gtk2::Dialog. Gtk2::Dialog in turn is a subclass of Gtk2::Window.

Gtk2::MessageDialog gets created by either the new or new_with_markup methods. The latter allows your message's text to be formatted using Pango markup. It is quite safe to use the latter, even if you display normal text without Pango markup, just ensure the text string does not contain Pango markup characters.(typically the "<" and ">" characters)

Tip

Since the Gtk2::MessageDialog usually gets used a few times, it is good programming practice to create a sub, or even a module where it can be called. In the sample program, we created the sub show_message_dialog that gets called with the type of message, the message's text, and the buttons to display on the message as arguments.

Importance of the parent window

To create a Gtk2::MessageDialog, you use the following:

widget = Gtk2::MessageDialog->new ($parent, $flags, $type, $buttons, $format, ...)

	* $parent (Gtk2::Window or undef)
	* $flags (Gtk2::DialogFlags)
	* $type (Gtk2::MessageType)
	* $buttons (Gtk2::ButtonsType)
	* $format (scalar)
	* ... (list)
$parent can be undef, but it is good practice to use a valid $parent whenever possible, especially for Gtk2::MessageDialogs. This will cause the Gtk2::MessageDialog to display on top of the parent window, instead of the middle if the screen, when $parent is undef.

If you don't set $parent, it's possible for the message dialog to get lost behind the main window, which can be confusing and infuriating to the user when the dialog is modal (because the app is now inexplicably not responding).

The top button calls the show_message_dialog sub with $parent undefined. When you move the main window around, each Gtk2::MessageDialog that gets shown, will pop up in the center of the screen, and NOT on top of the main window. With the other buttons, we use the main window as $parent. This will cause each Gtk2::MessageDialog to display on top of the main window.

Types of messages

There are different types of messages, the type of message will be indicated by the Gtk2::Dialog 's icon, as well as its title.

To obtain a list of message types (Gtk2::MessageType), we use a little-known feature in Glib that is also used in the Gtk2-Perl project for the documentation generator:

#we ask Glib to give a list of values for Gtk2::MessageType.
#Each value of the list is a hash with keys "name" and "nick",
#we then use the value of "nick" to specify the type to show.
foreach my $m_type (Glib::Type->list_values ('Gtk2::MessageType')){	
So we ask the bindings to list all the values for a particular enum type. That way, you don't have to update your program's code when a future version of Gtk+ adds a value to the enumeration, and you don't have to worry about misspelling one.

See the Glib::Type manpage for more info.

To get the nick, we use $m_type->{'nick'} from the returned hash. The message that gets displayed will also show how it was created.

Figure 8-2. Info Message

Buttons to display

This brings us to the buttons to display on the message. Taking a look at the code of the bottom button, we extract a list of all the possible button types, and loop through them, showing a message containing each button type.

#we ask Glib to give a list of values for Gtk2::ButtonsType.
#Each value of the list is a hash with keys "name" and "nick",
#we then use the value of "nick" to specify the button to show.
foreach my $b_type (Glib::Type->list_values ('Gtk2::ButtonsType')){

Displaying our message

The Gtk2::MessageDialog has a run method that gets called to show it. This will put, depending of the type of message (modal or not) either the whole program, or just the message in a loop, waiting for user input.

The run method returns a string value, indicating how the loop was terminated. In our program, this value is displayed in the calling window's label.

my $retval = $dialog->run;

Tip

You can drag the calling window to the side of the screen to get a clearer view.

Using this value, you can see if the user answered yes or no if your message contained the yes-no button type for instance.

Flashing Label

This does not have anything to do with Gtk2::MessageDialog classes. It is part of the program's main loop.

All Gtk2-Perl programs use the Glib::MainLoop implicitly when calling the Gtk2's main method. The Glib::MainLoop loop has three methods that may be of interest. The callbacks for Glib::Timeout, Glib::Timeout, and Glib::IO all expect a boolean return value. TRUE means "yes, I want to run again," FALSE means "no, please uninstall me".

Caution

Omitting this return value is a very common cause of application bugs.

  1. Glib::Timeout. This is the one we used. We specify what should be done, and how often. The time is specified in milliseconds.

    #create a flasher for the label, we will show or hide it every 1 second
    my $flash = 1;
    Glib::Timeout ->add (1000,sub{ flash_label() });

  2. Glib::Idle. This is most handy for "single-shot" deferred actions, like this:

    # schedule do_something() to run when the main loop goes idle.
    Glib::Idle->add (sub {
    	do_something ();
    	FALSE; # don't run again
    });
    This is what happens when you call "$widget->queue_redraw()", for example. You should use Glib::Timeout in other situations, when possible .

  3. Glib::IO. This is used to get data from a filehandle. We will discuss it in depth later.

Flashing the label is done simply by using the show and hide methods of the class.
sub flash_label {
#label flasher
	($flash)&&($label_feedback->hide());
	($flash)||($label_feedback->show());
	$flash = !($flash);
	return TRUE;
}