9.2. Bringing the code and method of implementation together

Create a Gtk2::Dialog containing Save and Undo buttons.

When you create a Gtk2::Dialog box, you can specify which Gtk2::Stock buttons needs to be added. Gtk2::Dialog has standard response types that you tie to any specified button. We tied accept to the gtk-save button, and we also tied reject to the gtk-undo button. Check Gtk2::Dialog's man page to get a list of Gtk2::ResponseTypes. One way to enable or disable an action button is by:

$dialog->set_response_sensitive ($response_id, $setting) 

	* $response_id (Gtk2::ResponseType)
	* $setting (boolean)
This is convenient since it does not require you to know the Gtk2::Button that is tied to the response type.

The following snippet show how it was done in our program

my $window = Gtk2::Dialog->new('Dialog & Entry Demo',
                              undef,
                              [qw/modal destroy-with-parent/],
                              'gtk-undo'     => 'reject',
			      'gtk-save'     => 'accept',
			      );
			      
$window->set_response_sensitive ('reject', FALSE);
$window->set_response_sensitive ('accept', FALSE);

Add an Gtk2::Entry widget to the Gtk2::Dialog

To get the top Gtk2::VBox of a Gtk2::Dialog, we use the vbox method of Gtk2::Dialog. This will cause the Gtk2::Dialog to return the top Gtk2::VBox. Now we can add the widgets we want to that Gtk2::VBox

my $vbox = $window->vbox;

Read the current value and assign it to the Gtk2::Entry widget.

#get the original value 
	my $ent_orig = &get_init_val();
	$entry->set_text($ent_orig);

Tip

One possible way to handle more complex and bigger lists of values which need to populate current values, is to create a Perl hash (associative array) before you show the window, and then extract the various values from it, feeding it to the widgets.

Check for changes in the value of the Gtk2::Entry widget. If there were any changes, and it is not bogus values, activate the Save and Undo buttons.

To check if the value of Gtk2::Entry changed, we connect to the changed signal. This signal is emitted on every change to the Gtk2::Entry. We can then call the get_text method of Gtk2::Entry to examine the latest change, and decide what to do. [1]

Caution

changed is not listed as an available signal to Gtk2::Entry on its man page.

 
$entry->signal_connect (changed => sub {
	# desensitize the save button if the entry is empty or blank
     	my $text = $entry->get_text;
	$window->set_response_sensitive ('accept', $text !~ m/^\s*$/);
	$window->set_response_sensitive ('reject', TRUE);
});

When Save is clicked, give the user an indication, and exit the application.

Gtk2::Dialog has a signal response (Gtk2::Dialog, integer). The second value "integer" can be confusing, since it is actually the name of Gtk2::ResponseType. This signal gets emitted when the user clicks on a button in the "action_area". You can then discover which button was clicked, by examining the value of the second argument sent to the signal handler.

 
$window->signal_connect(response => sub {
		print "YOU CLICKED: ".$_[1]."\n";
We filter for accept, and do our magick.
 
if($_[1] =~ m/accept/){
	my $new_val = $entry->get_text();
	&show_message_dialog($window,'info',"Old value: $ent_orig\nNew value: $new_val");
	Gtk2->main_quit;
}

When the Undo button is clicked, re-read the original value, and set the Gtk2::Entry widget accordingly, also gray the buttons out again.

#if the person clicked undo, we reload the original value, and gray out
#the undo button
if($_[1] =~ m/reject/){
	$entry->set_text($ent_orig);
	$window->set_response_sensitive ('reject', FALSE);
	$window->set_response_sensitive ('accept', FALSE);
}	
The code above is straight forward.

Conclusion and tips

$dialog->run is useful to freeze your program UNTIL the user respond to the Gtk2::Dialog. This function enters a recursive main loop and waits for the user to respond to the dialog, returning the response ID corresponding to the button the user clicked. To find out more about $dialog->run, check the man page of Gtk2::Dialog.

To create an application that needs to change values (in a file, or database for instance), care must be put into ways of extracting the current values. This may be during the first display of the program, or on subsequent events like the click of an "undo" button.

You may create a hash during startup, this will create a central data structure that you address and write to, to get and set required values.

To create a hash, you do the following:

	my %hash;
	
To change or append a value to it, you must supply a unique key, and corresponding value for the key.
	$hash{'value1'} = "Perl";
	$hash{'value2'} = 'Gtk2';
	$hash{'value3'} = 'Foo';
	
To get a value from it, you specify which key's value you are looking for.
	$entry->set_text($hash{'value3'});
	
When you attach a Gtk2::Label to a Gtk2::Table, the text will be in the center, this does not look good, especially when you have a few Gtk2::Label objects below each other. To justify them, you may have tried the $label->set_justify ($jtype) method that is part of the Gtk2::Label widget to no avail.

This will only justify multi-lines of a Gtk2::Label.

To move the text within a label, you need to use the Gtk2::Misc object's $misc->set_alignment ($xalign, $yalign) method. You can then move the text to the top, bottom, left or right within the label. In the program above, we moved it to the right, so it is close to the Gtk2::Entry widget. The $misc->set_alignment ($xalign, $yalign) takes double values as arguments.

	#$misc->set_alignment ($xalign, $yalign) 
		$label->set_alignment(1,0.5);
	
The above snippet will center the text vertically within the label, but move it to the right horizontally.

Notes

[1]

We filter bogus values by using Perl regular expressions. This is one of Perl's strong points, and, although cryptic at first, so powerful, that it is one the first things you dearly mis when programming in any other language. We ask that $text should not (!~) match (m) the following: Start(^) with a space character (\s), zero on more (*) and also end ($) with it.

A space (\s) character also includes tabs. The phrase to match is always between "/" characters. There are lots of sources available on the Internet to teach you more about regular expressions in Perl, should you need a proper introduction.