Object
+--- Widget
+--- Calendar
The Calendar widget is an effective way to display and retrieve date related information. It is a very simple widget to create and work with.
Creating a Calendar widget is a simple as:
$calendar = new Gtk::Calendar();
There might be times where you need to change a lot of
information within this widget and the following functions allow
you to make multiple change to a Calendar widget without the
user seeing multiple on-screen updates.
$calendar->freeze();
$calendar->thaw();
They work just like the freeze/thaw functions of other widgets.
The Calendar widget has a few options that allow you to change
the way the widget both looks and operates by using the
following function:
$calendar->display_options( $flags );
The
$flags
argument can be formed by combining any of the following five
options:
'heading' - this option specifies that the month and year should be shown when drawing the calendar.
'show_day_names' - this option specifies that the three letter descriptions should be displayed for each day (eg MON,TUE...).
'no_month_change' - this option states that the user should not and can not change the currently displayed month. This can be good if you only need to display a particular month such as if you are displaying 12 calendar widgets for every month in a particular year.
'show_week_numbers' - this option specifies that the number for each week should be displayed down the left side of the calendar. (eg. Jan 1 = Week 1,Dec 31 = Week 52).
'week_start_monday' - this option states that the calander week will start on Monday instead of Sunday which is the default. This only affects the order in which days are displayed from left to right.
The following functions are used to set the the currently
displayed date:
$calendar->select_month( $month, $year );
$calendar->select_day( $day );
The return value from
select_month()
is a true or false value indicating whether the selection was
successful.
With select_day() the specified day number is selected within the current month, if that is possible. A $day value of 0 will deselect any current selection.
In addition to having a day selected, any number of days in the
month may be "marked". A marked day is highlighted within the
calendar display. The following functions are provided to
manipulate marked days:
$calendar->mark_day( $day );
$calendar->unmark_day( $day );
$calendar->clear_marks();
The currently marked days are stored within an array. This array
is 31 elements long so to test whether a particular day is
currently marked, you need to access the corresponding element
of the array (don't forget that the array elements are numbered
0 to 30). For example:
if ( $calendar->marked_date[ $day - 1 ] )
{
print( "Day $day is marked\n" );
}
Note that marks are persistent across month and year changes.
The final Calendar widget function is used to retrieve the
currently selected date, month and/or year.
( $year, $month, $day ) = $calendar->get_date();
The Calendar widget can generate a number of signals indicating date selection and change. The names of these signals are self explanatory, and are:
'month_changed'
'day_selected'
'day_selected_double_click'
'prev_month'
'next_month'
'prev_year'
'next_year'
That just leaves us with the need to put all of this together into example code.
Calendar Widget Example Source
#!/usr/bin/perl -w # Be advised, this program is more complicated than the others in the # tutorial. However, I wanted to document as many features as # possible. I am also taking advantage of Perl data structures more # heavily than normal. use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $year_base = 1900; my $i; my @flags = ( "Show Heading", "Show Day Names", "No Month Change", "Show Week Numbers", "Week Start Monday" ); my %calendar_data = ( " ", " " ); my $window; my $vbox; my $vbox2; my $vbox3; my $hbox; my $hbbox; my $calendar; my $toggle; my $button; my $frame; my $separator; my $label; my $bbox; # Set up calendar data $calendar_data{ "window" } = undef; $calendar_data{ "font" } = undef; $calendar_data{ "font_dialog" } = undef; $calendar_data{ "settings" } = [ 0, 0, 0, 0, 0 ]; # Create the window $window = new Gtk::Window( 'toplevel' ); $window->set_title( "Calendar Example" ); $window->border_width( 5 ); $window->signal_connect( 'destroy', sub { Gtk-> exit ( 0 ); } ); $window->signal_connect( 'delete-event', \>k_false ); $window->set_policy( $false, $false, $true ); $vbox = new Gtk::VBox( $false, 10 ); $window->add( $vbox ); # The top part of the window, Calendar, flags and fontsel. $hbox = new Gtk::HBox( $false, 10 ); $vbox->pack_start( $hbox, $true, $true, 10 ); $hbbox = new Gtk::HButtonBox(); $hbox->pack_start( $hbbox, $false, $false, 10 ); $hbbox->set_layout( 'spread' ); $hbbox->set_spacing( 5 ); # Create the Calendar widget $frame = new Gtk::Frame( "Calendar" ); $hbbox->pack_start( $frame, $false, $true, 10 ); $calendar = new Gtk::Calendar(); $calendar_data{ "window" } = $calendar; calendar_set_flags(); $calendar->mark_day( 19 ); $frame->add( $calendar ); # Set up calendar callbacks $calendar->signal_connect( 'month_changed', \&calendar_month_changed ); $calendar->signal_connect( 'day_selected', \&calendar_day_selected ); $calendar->signal_connect( 'day_selected_double_click', \&calendar_day_selected_double_click ); $calendar->signal_connect( 'prev_month', \&calendar_prev_month ); $calendar->signal_connect( 'next_month', \&calendar_next_month ); $calendar->signal_connect( 'prev_year', \&calendar_prev_year ); $calendar->signal_connect( 'next_year', \&calendar_next_year ); $separator = new Gtk::VSeparator(); $hbox->pack_start( $separator, $false, $true, 0 ); $vbox2 = new Gtk::VBox( $false, 10 ); $hbox->pack_start( $vbox2, $false, $false, 10 ); # Build the Right frame with the flags in $frame = new Gtk::Frame( "Flags" ); $vbox2->pack_start( $frame, $true, $true, 10 ); $vbox3 = new Gtk::VBox( $true, 5 ); $frame->add( $vbox3 ); for $i ( 0..4 ) { $toggle = new Gtk::CheckButton( $flags[ $i ] ); $toggle->signal_connect( 'toggled', \&calendar_toggle_flag ); $vbox3->pack_start( $toggle, $true, $true, 0 ); $calendar_data{ 'flag_checkboxes' }[ $i ] = $toggle; } # Build the right font-button $button = new Gtk::Button( "Font..." ); $button->signal_connect( 'clicked', \&calendar_select_font ); $vbox2->pack_start( $button, $false, $false, 0 ); # Build the Signal-event part. $frame = new Gtk::Frame( "Signal Events" ); $vbox->pack_start( $frame, $true, $true, 10 ); $vbox2 = new Gtk::VBox( $true, 5 ); $frame->add( $vbox2 ); # Frame to report signals $hbox = new Gtk::HBox( $false, 3 ); $vbox2->pack_start( $hbox, $false, $true, 0 ); $label = new Gtk::Label( "Signal:" ); $hbox->pack_start( $label, $false, $true, 0 ); $calendar_data{ "last_sig" } = new Gtk::Label( " " ); $hbox->pack_start( $calendar_data{ "last_sig" }, $false, $true, 0 ); $hbox = new Gtk::HBox( $false, 3 ); $vbox2->pack_start( $hbox, $false, $true, 0 ); $label = new Gtk::Label( "Previous Signal:" ); $hbox->pack_start( $label, $false, $true, 0 ); $calendar_data{ "prev_sig" } = new Gtk::Label( " " ); $hbox->pack_start( $calendar_data{ "prev_sig" }, $false, $true, 0 ); $hbox = new Gtk::HBox( $false, 3 ); $vbox2->pack_start( $hbox, $false, $true, 0 ); $label = new Gtk::Label( "Second Previous Signal:" ); $hbox->pack_start( $label, $false, $true, 0 ); $calendar_data{ "prev2_sig" } = new Gtk::Label( " " ); $hbox->pack_start( $calendar_data{ "prev2_sig" }, $false, $true, 0 ); $bbox = new Gtk::HButtonBox(); $vbox->pack_start( $bbox, $false, $false, 0 ); $bbox->set_layout( 'end' ); # Close button $button = new Gtk::Button( "Close" ); $button->signal_connect( 'clicked', sub { Gtk-> exit ( 0 ); } ); $bbox->add( $button ); $button->can_default( $true ); $button->grab_default(); $window->show_all(); main Gtk; exit ( 0 ); ### Subroutines # Function that takes the selected calendar date and converts it to a # American style string. sub calendar_date_to_string { my $string; my $year; my $month; my $day; my @months = qw( January February March April May June July August September October November December ); ( $year, $month, $day ) = $calendar_data{ 'window' }->get_date(); $string = $months[ $month ] . " " . $day . ", " . $year; return ( $string ); } # Add a new string to the signal strings, moving previous strings to # their appropriate place. sub calendar_set_signal_strings { my ( $sig_str ) = @_; my $prev_sig; $prev_sig = $calendar_data{ 'prev_sig' }->get(); $calendar_data{ 'prev2_sig' }->set( $prev_sig ); $prev_sig = $calendar_data{ 'last_sig' }->get(); $calendar_data{ 'prev_sig' }->set( $prev_sig ); $calendar_data{ 'last_sig' }->set( $sig_str ); } # Callback to report that the month has been changed. sub calendar_month_changed { my $buffer = "month_changed: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # Callback to report that the day has been changed. sub calendar_day_selected { my $buffer = "day_selected: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # Callback to report that the previous month button has been pressed. sub calendar_prev_month { my $buffer = "prev_month: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # Callback to report that the next month button has been pressed. sub calendar_next_month { my $buffer = "next_month: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # Callback to report that the previous year button has been pressed. sub calendar_prev_year { my $buffer = "prev_year: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # Callback to report that the next year button has been pressed. sub calendar_next_year { my $buffer = "next_year: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # A function that set the calendar settings based on the toggle # buttons. sub calendar_set_flags { my $i; my $options = 0; for ( $i = 0; $i < 5; $i++ ) { if ( $calendar_data{ 'settings' }[ $i ] ) { $options = $options + ( 1 << $i ); } } if ( $calendar_data{ 'window' } ) { $calendar_data{ 'window' }->display_options( $options ); } } # Callback for radio buttons. When toggled, they change the # appropriate calendar setting. sub calendar_toggle_flag { my ( $toggle ) = @_; my $j = 0; for my $i ( 0..4 ) { if ( $calendar_data{ 'flag_checkboxes' }[ $i ] == $toggle ) { $j = $i; } } $calendar_data{ 'settings' }[$j] = not $calendar_data{ 'settings' }[$j]; calendar_set_flags(); } # Callback called when the OK button of the font dialog is clicked on. sub calendar_font_selection_ok { my ( $button ) = @_; my $style; my $font; $calendar_data{'font'} = $calendar_data{ 'font_dialog' }->get_font_name(); if ( $calendar_data{ 'window' } ) { $font = $calendar_data{ 'font_dialog' }->get_font(); if ( $font ) { $style=new Gtk::Style(); $style->font($font); $calendar_data{ 'window' }->set_style( $style ); } } } # Callback attached to the "Change Font" button. It starts up a font # dialog, allowing you to set a new font. sub calendar_select_font { my ( $button ) = @_; my $window; if ( $calendar_data{ 'font_dialog' } ) { $window = $calendar_data{ 'font_dialog' }; } else { $window = new Gtk::FontSelectionDialog( "Font Selection Dialog" ); $window->position( 'mouse' ); $window->signal_connect( 'destroy', sub { $window->destroyed(); } ); $window->ok_button->signal_connect( 'clicked', \&calendar_font_selection_ok ); $window->cancel_button->signal_connect( 'clicked', sub { $window->hide(); } ); $calendar_data{ 'font_dialog' } = $window; } if ( $window->visible ) { $window->destroy(); } else { $window->show(); } } # END EXAMPLE PROGRAM
Calendar Example Screenshot