Naver Perl Community & Study Cafe


2009.09.01 21:54

Gtk2::Calendar

Gtk2 모듈에 소속되어 있는 Calendar 모듈 을 소개하려 한다.

이 모듈은 뜻 그대로 달력 모듈이다.


일단 예제코드부터 먼저 보고 시작하도록 하자.





#!/usr/bin/perl -w

# 요기는 뭐 별로 신경쓰지 않아도 된다.
# Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson, Mattias Gr?lund
# Copyright (C) 2000 Tony Gale
# 
# Copyright (C) 2003 by the gtk2-perl team (see the file AUTHORS for the full
# list)
# 
# This library is free software; you can redistribute it and/or modify it under
# the terms of the GNU Library General Public License as published by the Free
# Software Foundation; either version 2.1 of the License, or (at your option)
# any later version.
# 
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
# more details.
# 
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307  USA.
#
# $Header: /cvsroot/gtk2-perl/gtk2-perl-xs/Gtk2/examples/calendar.pl,v 1.7 2004/03/14 08:55:48 muppetman Exp $
#

# this was originally gtk-2.2.1/examples/calendar/calendar.c
# ported to gtk2-perl (and perl-ized) by rm

use strict;
use Gtk2;

use Glib ':constants'; 
 
use constant DEF_PAD => 10;
use constant DEF_PAD_SMALL => 5;

use constant TM_YEAR_BASE => 1900;

sub calendar_select_font # 폰트를 변경시켜주는 함수이다. 이부분도 중요하지는 않다.
{
	my $calendar = shift;

	my $fsd = Gtk2::FontSelectionDialog->new ('Font Selection Dialog');
	$fsd->set_position('mouse');

	$fsd->set_font_name ($calendar->get_style->font_desc->to_string);

	$fsd->signal_connect ('response' => sub {
		my (undef, $response) = @_;
		if ($response eq 'ok') {
			my $font_name = $fsd->get_font_name;
			return unless $font_name;
			$calendar->modify_font
				(Gtk2::Pango::FontDescription->from_string
				 	($font_name));
		}
		$fsd->destroy;
	});

	$fsd->show;
}


sub calendar_set_signal_strings
{
	my $sig_ref = shift;
	my $new_sig = shift;

	$sig_ref->{prev2}->set_text($sig_ref->{prev}->get_text);
	$sig_ref->{prev}->set_text($sig_ref->{curr}->get_text);
	$sig_ref->{curr}->set_text($new_sig);
}

sub create_calendar  # 핵심적인 함수이다. 달력을 생성해준다.
{
	my $window;
	my $vbox;
	my $vbox2;
	my $vbox3;
	my $hbox;
	my $hbbox;
	my $calendar;
	my @toggles;
	my $button;
	my $frame;
	my $separator;
	my $label;
	my $bbox;
	my $i;
  
    	my %signals = (); # 레이블을 쉽게 바꾸기 위해 signals 해쉬를 미리 만든다.
                           # 이 작업을 활용하면 상당히 편하게 코드 작성이 가능하다.   
	$window = Gtk2::Window->new("toplevel");
  	$window->set_title('GtkCalendar Example');
  
	$window->set_border_width(5);
	$window->signal_connect( 'destroy' => sub {
			Gtk2->main_quit;
		} );
	$window->set_resizable(FALSE);

	$vbox = Gtk2::VBox->new(FALSE, DEF_PAD);
	$window->add($vbox);

	#
	# The top part of the window, Calendar, flags and fontsel.
	#

	$hbox = Gtk2::HBox->new(FALSE, DEF_PAD);
	$vbox->pack_start($hbox, TRUE, TRUE, DEF_PAD);
  
	$hbbox = Gtk2::HButtonBox->new;
	$hbox->pack_start($hbbox, FALSE, FALSE, DEF_PAD);
	$hbbox->set_layout('spread');
	$hbbox->set_spacing(5);

	# Calendar widget
	$frame = Gtk2::Frame->new('Calendar');
	$hbbox->pack_start($frame, FALSE, TRUE, DEF_PAD);
	$calendar = Gtk2::Calendar->new; #  이 부분이 중요하다 달력을 생성한다.

	$calendar->mark_day(19);         #  19일에 진하게 표시를 한다.
	$frame->add($calendar);          #  frame 에 달력을 추가한다.
	$calendar->display_options([]);
         # 여기부터는 달을 바꾸거나, 날짜를 클릭할때 일어나는 여러 이벤트를 설정하였다.
	$calendar->signal_connect( 'month_changed' => sub {      # 달이 바뀌었을때
			my ($year, $month, $day) = $calendar->get_date; 
			calendar_set_signal_strings($_[1], 'month changed: '.
				sprintf("%02d/%d/%d", $month+1, $day, $year) );
		}, \%signals );
	$calendar->signal_connect( 'day_selected' => sub {       # 날짜를 선택했을 때
			my ($year, $month, $day) = $calendar->get_date; 
			calendar_set_signal_strings($_[1], 'day selected: '.
				sprintf("%02d/%d/%d", $month+1, $day, $year) );
		}, \%signals );
	$calendar->signal_connect( 'day_selected_double_click' => sub {  #날짜 더블클릭
			my ($year, $month, $day) = $calendar->get_date; 
			calendar_set_signal_strings($_[1], 
				'day selected double click: '.
				sprintf("%02d/%d/%d", $month+1, $day, $year) );
		}, \%signals );
	$calendar->signal_connect( 'prev_month' => sub {         # 이전달 클릭
			my ($year, $month, $day) = $calendar->get_date; 
			calendar_set_signal_strings($_[1], 'prev month: '.
				sprintf("%02d/%d/%d", $month+1, $day, $year) );
		}, \%signals );
	$calendar->signal_connect( 'next_month' => sub {         # 다음달 클릭
			my ($year, $month, $day) = $calendar->get_date; 
			calendar_set_signal_strings($_[1], 'next month: '.
				sprintf("%02d/%d/%d", $month+1, $day, $year) );
		}, \%signals );
	$calendar->signal_connect( 'prev_year' => sub {          
			my ($year, $month, $day) = $calendar->get_date; 
			calendar_set_signal_strings($_[1], 'prev year: '.
				sprintf("%02d/%d/%d", $month+1, $day, $year) );
		}, \%signals );
	$calendar->signal_connect( 'next_year' => sub {
			my ($year, $month, $day) = $calendar->get_date; 
			calendar_set_signal_strings($_[1], 'next year: '.
				sprintf("%02d/%d/%d", $month+1, $day, $year) );
		}, \%signals );

	$separator = Gtk2::VSeparator->new;
	$hbox->pack_start($separator, FALSE, TRUE, 0);

	$vbox2 = Gtk2::VBox->new(FALSE, DEF_PAD);
	$hbox->pack_start($vbox2, FALSE, FALSE, DEF_PAD);
  
	# Build the Right frame with the flags in

	$frame = Gtk2::Frame->new('Flags');
	$vbox2->pack_start($frame, TRUE, TRUE, DEF_PAD);
	$vbox3= Gtk2::VBox->new(TRUE, DEF_PAD_SMALL);
	$frame->add($vbox3);
         # 배열로 플래그를 만들어 플래그의 켜짐과 꺼짐에 따라 달력 모양을 바꿀 수 있다.
	my @flags = (
		'Show Heading',
		'Show Day Names',
		'No Month Change',
		'Show Week Numbers',
		'Week Start Monday',
	);
	for( $i = 0; $i < 5; $i++ )
	{
		$toggles[$i] = Gtk2::CheckButton->new($flags[$i]);
		$toggles[$i]->signal_connect( 'toggled' => sub {
				my $j;
				my $opts = [];
				for($j = 0; $j < scalar(@flags); $j++ )
				{
					if( $toggles[$j]->get_active )
					{
						push @$opts, $flags[$j];
					}
				}
				$calendar->display_options($opts);
			});
		$vbox3->pack_start($toggles[$i], TRUE, TRUE, 0);
	}
	foreach (@flags)
	{
		$_ =~ s/\s/-/g;
		$_ = lc($_);
	}
	# 폰트 교체 버튼 달력 전체의 폰트를 교체할 수 있다. 
	# Build the right font-button
	$button = Gtk2::Button->new('Font...');
	$button->signal_connect( 'clicked' => sub {
			calendar_select_font($_[1]);
		}, $calendar );
	$vbox2->pack_start($button, FALSE, FALSE, 0);

	#
	# Build the Signal-event part.
	# 여기는 시그널 이벤트 창이다. 
         # 위에서 날을 클릭하거나 달을 바꾸는 작업이 여기서 display 된다.
	$frame = Gtk2::Frame->new('Signal events');
	$vbox->pack_start($frame, TRUE, TRUE, DEF_PAD);

	$vbox2 = Gtk2::VBox->new(TRUE, DEF_PAD_SMALL);
	$frame->add($vbox2);
  
	$hbox = Gtk2::HBox->new(FALSE, 3);
	$vbox2->pack_start($hbox, FALSE, TRUE, 0);
	$label = Gtk2::Label->new('Signal:');
	$hbox->pack_start($label, FALSE, TRUE, 0);
	$signals{curr} = Gtk2::Label->new('');
	$hbox->pack_start($signals{curr}, FALSE, TRUE, 0);

	$hbox = Gtk2::HBox->new(FALSE, 3);
	$vbox2->pack_start($hbox, FALSE, TRUE, 0);
	$label = Gtk2::Label->new('Previous Signal:');
	$hbox->pack_start($label, FALSE, TRUE, 0);
	$signals{prev} = Gtk2::Label->new('');
	$hbox->pack_start($signals{prev}, FALSE, TRUE, 0);

	$hbox = Gtk2::HBox->new(FALSE, 3);
	$vbox2->pack_start($hbox, FALSE, TRUE, 0);
	$label = Gtk2::Label->new('Second Previous Signal:');
	$hbox->pack_start($label, FALSE, TRUE, 0);
	$signals{prev2} = Gtk2::Label->new('');
	$hbox->pack_start($signals{prev2}, FALSE, TRUE, 0);

	$bbox = Gtk2::HButtonBox->new;
	$vbox->pack_start($bbox, FALSE, FALSE, 0);
	$bbox->set_layout('end');

	$button = Gtk2::Button->new('Close');
	$button->signal_connect( 'clicked' => sub {
			Gtk2->main_quit;
		} );
	$bbox->add($button);
	$button->set_flags('can-default');
	$button->grab_default;

	$window->show_all;
}


Gtk2->init;

create_calendar;

Gtk2->main;

exit 0;


위에서 보면 $calender 객체를 사용하여 달력을 효율적으로 사용할 수 있다.

my ($year, $month, $day) = $calendar->get_date;

위의 작업은 선택한 날의 년, 월, 일을 얻게 해주는 작업으로

달력모듈 사용중 가장 많이 사용되지 않을까 싶다.

이건 하나의 예제 임으로 더 세부적인 동작을 알기 위해서는

http://gtk2-perl.sourceforge.net/doc/pod/Gtk2/Calendar.html

여기서 확인 바란다.


나의 경우에는 gtk2+로 다이어리를 만들어야 했기에 필수적으로 사용했지만

어디까지나 모듈을 사용하는것이라

세부적인 수정이 어렵다는 점에 아쉬움이 남았다.




하지만 이정도면 쓰는데 무리는 없을 듯!


flex에서 기본적인 달력모듈은.. 환상적이긴 했지만 말이다 ... -ㅁ-;
신고
Trackback 0 Comment 1