Chapter 9. Gtk2::Dialog and Gtk2::Entry

Objective

When using a Gtk2::Entry widget, you usually call up a value already in existence, and assigns it to the Gtk2::Entry. This value may get changed by the user. (a value in a config file or a field in a database). Gtk2::Entrys may show up in a Gtk2::Dialog box.

A Gtk2::Dialog box is a subclass of Gtk2::Window. A brief description: " Dialog boxes are a convenient way to prompt the user for a small amount of input, eg. to display a message, ask a question, or anything else that does not require extensive effort on the user's part. "

Then the man page gives us more info: "Gtk+ treats a dialog as a window split vertically. The top section is a Gtk2::VBox, and is where widgets such as a Gtk2::Label or a Gtk2::Entry should be packed. The bottom area is known as the "action_area". This is generally used for packing buttons into the dialog which may perform functions such as cancel, ok, or apply. The two areas are separated by a Gtk2::HSeparator."

This lesson will go through a simple program that uses a Gtk2::Dialog with one entry widget, an undo, and a save button. The program will also implement error checking, to prevent bogus entries.

Table 9-1. Gtk2 object classes used

Gtk2 Class Name
Gtk2::Window
Gtk2::VBox
Gtk2::HBox
Gtk2::Button
Gtk2::Entry
Gtk2::Dialog
Gtk2::MessageDialog

Method of implementation

We need to implement the following steps in the program:

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

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

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

  4. 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.

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

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

The screenshot

Figure 9-1. Gtk2::Dialog and Gtk2::Entry

9.1. The Code

The program can be found here: 'Entry Demo'

  
  1 #! /usr/bin/perl
  2 
  3 use strict;
  4 use Glib qw/TRUE FALSE/;
  5 use Gtk2 'init';
  6 
  7 my $window = Gtk2::Dialog->new('Dialog & Entry Demo',
  8                               undef,
  9                               [qw/modal destroy-with-parent/],
 10                               'gtk-undo'     => 'reject',
 11 			      'gtk-save'     => 'accept',
 12 			      );
 13 			      
 14 $window->set_response_sensitive ('reject', FALSE);
 15 $window->set_response_sensitive ('accept', FALSE);
 16 
 17 $window->signal_connect('delete-event'=> sub {Gtk2->main_quit()});
 18 $window->set_position('center-always');
 19 
 20 &fill_dialog($window);
 21 
 22 $window->show();
 23 Gtk2->main();
 24 
 25 sub fill_dialog {
 26 
 27 my ($window) = @_;
 28 
 29 my $vbox = $window->vbox;
 30 $vbox->set_border_width(5);
 31 	#-------------------------------------
 32 	my $table = Gtk2::Table->new (1, 2, FALSE);
 33 		my $label = Gtk2::Label->new_with_mnemonic("_Value of entry: ");
 34 		#$misc->set_alignment ($xalign, $yalign) 
 35 		$label->set_alignment(1,0.5);
 36 	$table->attach_defaults ($label, 0, 1, 0,1);
 37 		my $entry = Gtk2::Entry->new();
 38 		#get the original value 
 39 		my $ent_orig = &get_init_val();
 40 		$entry->set_text($ent_orig);
 41 		
 42 		 $entry->signal_connect (changed => sub {
 43 		# desensitize the save button if the entry is empty or blank
 44      			my $text = $entry->get_text;
 45 			$window->set_response_sensitive ('accept', $text !~ m/^\s*$/);
 46 			$window->set_response_sensitive ('reject', TRUE);
 47       		});
 48 		
 49 		$label->set_mnemonic_widget ($entry);
 50 	$table->attach_defaults($entry,1,2,0,1);
 51 	#---------------------------------------
 52 $vbox->pack_start($table,0,0,4);
 53 
 54 
 55 	#this is a nifty thing :) from the documentation:
 56 	#response (Gtk2::Dialog, integer) - thus the second element generated during the signal emitting
 57 	#will be the button's name
 58 	$window->signal_connect(response => sub {
 59 		print "YOU CLICKED: ".$_[1]."\n";
 60 		#if the person clicked save, we show a message
 61 		if($_[1] =~ m/accept/){
 62 			my $new_val = $entry->get_text();
 63 			&show_message_dialog($window,'info',"Old value: $ent_orig\nNew value: $new_val");
 64 			Gtk2->main_quit;
 65 		}
 66 		#if the person clicked undo, we reload the original value, and gray out
 67 		#the undo button
 68 		if($_[1] =~ m/reject/){
 69 			$entry->set_text($ent_orig);
 70 			$window->set_response_sensitive ('reject', FALSE);
 71 			$window->set_response_sensitive ('accept', FALSE);
 72 		}
 73 	});
 74 
 75 	$vbox->show_all();
 76 return $vbox;
 77 }
 78 
 79 
 80 sub get_init_val {
 81 	my $init_val = "The_Original_Value";
 82 	return $init_val;
 83 }
 84 
 85 sub show_message_dialog {
 86 #you tell it what to display, and how to display it
 87 #$icon can be one of the following:	a) 'info'
 88 #					b) 'warning'
 89 #					c) 'error'
 90 #					d) 'question'
 91 #$text can be pango markup text, or just plain text, IE the message
 92 my ($parent,$icon,$text) = @_;
 93  
 94 my $dialog = Gtk2::MessageDialog->new_with_markup ($parent,
 95 					[qw/modal destroy-with-parent/],
 96 					$icon,
 97 					'ok',
 98 					sprintf "$text");
 99 				
100 		$dialog->run;
101 		$dialog->destroy;
102 		
103 }