Gtk2-Ex-Datasheet-DBI
view release on metacpan or search on metacpan
lib/Gtk2/Ex/Datasheet/DBI.pm view on Meta::CPAN
# 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/cellrenderer_date.pl,v 1.5 2005/01/07 21:31:59 kaffeetisch Exp $
#
use strict;
use Gtk2 -init;
package Gtk2::Ex::Datasheet::DBI::CellRendererDate;
use Glib::Object::Subclass
"Gtk2::CellRenderer",
signals => {
edited => {
flags => [qw(run-last)],
param_types => [qw(Glib::String Glib::Scalar)],
},
},
properties => [
Glib::ParamSpec->boolean(
"editable",
"Editable",
"Can I change that?",
0,
[qw(readable writable)]
),
Glib::ParamSpec->string(
"date",
"Date",
"What's the date again?",
"",
[qw(readable writable)]
),
Glib::ParamSpec->string(
"format",
"Format",
"What day-month-year formatting?",
"yyyy-mm-dd",
[qw(readable writable)]
),
Glib::ParamSpec->string(
"font",
"Font",
"What size fonts should be used?",
12,
[qw(readable writable)]
)
];
use constant x_padding => 2;
use constant y_padding => 3;
use constant arrow_width => 15;
use constant arrow_height => 15;
sub hide_popup {
my ( $cell ) = @_;
Gtk2->grab_remove( $cell->{ _popup } );
$cell->{ _popup }->hide();
}
sub get_today {
my ( $cell ) = @_;
my ( $day, $month, $year ) = (localtime())[3, 4, 5];
$year += 1900;
$month += 1;
return ( $year, $month, $day );
}
sub get_date {
my ( $cell ) = @_;
my $text = $cell->get("date");
my ( $year, $month, $day ) = $text
? split(/[\/-]/, $text)
: $cell->get_today();
return ( $year, $month, $day );
}
sub add_padding {
my ( $cell, $year, $month, $day ) = @_;
return ( $year, sprintf("%02d", $month), sprintf("%02d", $day) );
}
sub INIT_INSTANCE {
my ( $cell ) = @_;
my $popup = Gtk2::Window->new ('popup');
my $vbox = Gtk2::VBox->new( 0, 0 );
my $calendar = Gtk2::Calendar->new();
$calendar->modify_font( Gtk2::Pango::FontDescription->from_string( "Arial " . $cell->get( "font" ) ) );
my $hbox = Gtk2::HBox->new( 0, 0 );
my $today = Gtk2::Button->new('Today');
my $none = Gtk2::Button->new('None');
$cell -> {_arrow} = Gtk2::Arrow->new( "down", "none" );
# We can't just provide the callbacks now because they might need access to
# cell-specific variables. And we can't just connect the signals in
# START_EDITING because we'd be connecting many signal handlers to the same
# widgets.
$today->signal_connect( clicked => sub {
$cell->{ _today_clicked_callback }->( @_ )
if ( exists( $cell->{ _today_clicked_callback } ) );
} );
$none->signal_connect( clicked => sub {
$cell->{ _none_clicked_callback }->( @_ )
if ( exists( $cell->{ _none_clicked_callback } ) );
} );
$calendar->signal_connect( day_selected_double_click => sub {
$cell->{ _day_selected_double_click_callback }->( @_ )
if ( exists( $cell->{ _day_selected_double_click_callback } ) );
} );
$calendar->signal_connect( month_changed => sub {
$cell->{ _month_changed }->( @_ )
if ( exists( $cell->{ _month_changed } ) );
} );
$hbox->pack_start( $today, 1, 1, 0 );
$hbox->pack_start( $none, 1, 1, 0 );
$vbox->pack_start( $calendar, 1, 1, 0 );
$vbox->pack_start( $hbox, 0, 0, 0 );
# Find out if the click happended outside of our window. If so, hide it.
# Largely copied from Planner (the former MrProject).
# Implement via Gtk2::get_event_widget?
$popup->signal_connect( button_press_event => sub {
my ( $popup, $event ) = @_;
if ( $event->button() == 1 ) {
my ( $x, $y ) = ( $event->x_root(), $event->y_root() );
my ( $xoffset, $yoffset ) = $popup->window()->get_root_origin();
my $allocation = $popup->allocation();
my $x1 = $xoffset + 2 * $allocation->x();
my $y1 = $yoffset + 2 * $allocation->y();
my $x2 = $x1 + $allocation->width();
my $y2 = $y1 + $allocation->height();
unless ( $x > $x1 && $x < $x2 && $y > $y1 && $y < $y2 ) {
$cell->hide_popup();
return 1;
}
}
return 0;
} );
$popup->add( $vbox );
$cell->{ _popup } = $popup;
$cell->{ _calendar } = $calendar;
}
sub START_EDITING {
my ( $cell, $event, $view, $path, $background_area, $cell_area, $flags ) = @_;
my $popup = $cell -> { _popup };
my $calendar = $cell->{ _calendar };
# Specify the callbacks. Will be called by the signal handlers set up in
# INIT_INSTANCE.
$cell->{ _today_clicked_callback } = sub {
my ($button) = @_;
my ($year, $month, $day) = $cell -> get_today();
$cell->signal_emit( edited=>$path, join( "-", $cell->add_padding( $year, $month, $day ) ) );
$cell->hide_popup();
};
$cell->{ _none_clicked_callback } = sub {
my ( $button ) = @_;
$cell->signal_emit( edited=>$path, "" );
$cell->hide_popup();
};
$cell->{ _day_selected_double_click_callback } = sub {
my ( $calendar ) = @_;
my ( $year, $month, $day ) = $calendar->get_date();
$cell->signal_emit( edited => $path, join( "-", $cell -> add_padding( $year, ++$month, $day ) ) );
$cell->hide_popup();
};
$cell->{ _month_changed } = sub {
my ( $calendar ) = @_;
my ( $selected_year, $selected_month ) = $calendar->get_date();
my ( $current_year, $current_month, $current_day ) = $cell->get_today();
if ( $selected_year == $current_year && ++$selected_month == $current_month ) {
$calendar->mark_day( $current_day );
}
else {
$calendar->unmark_day( $current_day );
}
};
my ( $year, $month, $day ) = $cell->get_date();
$calendar->select_month( $month - 1, $year );
$calendar->select_day( $day );
# Necessary to get the correct allocation of the popup.
$popup->move( -500, -500 );
$popup->show_all();
# Figure out where to put the popup - ie don't put it offscreen,
# as it's not movable ( by the user )
my $screen_height = $popup->get_screen->get_height;
my $requisition = $popup->size_request();
my $popup_width = $requisition->width;
my $popup_height = $requisition->height;
my ( $x_origin, $y_origin ) = $view->get_bin_window()->get_origin();
my ( $popup_x, $popup_y );
$popup_x = $x_origin + $cell_area->x() + $cell_area->width() - $popup_width;
$popup_x = 0 if $popup_x < 0;
$popup_y = $y_origin + $cell_area->y() + $cell_area->height();
if ( $popup_y + $popup_height > $screen_height ) {
$popup_y = $y_origin + $cell_area->y() - $popup_height;
}
$popup->move( $popup_x, $popup_y );
# Grab the focus and the pointer.
Gtk2->grab_add( $popup );
$popup->grab_focus();
Gtk2::Gdk -> pointer_grab(
$popup -> window(),
1,
[ qw( button-press-mask button-release-mask pointer-motion-mask ) ],
undef,
undef,
0
);
return;
}
sub get_date_string {
my ( $cell ) = @_;
return $cell->get('date');
}
sub calc_size {
my ( $cell, $layout ) = @_;
my ( $width, $height ) = $layout -> get_pixel_size();
return (
0,
0,
$width + x_padding * 2 + arrow_width,
$height + y_padding * 2
);
}
sub GET_SIZE {
my ( $cell, $widget, $cell_area ) = @_;
my $layout = $cell->get_layout( $widget );
$layout->set_text( $cell->get_date_string() || '' );
return $cell->calc_size( $layout );
}
sub get_layout {
my ( $cell, $widget ) = @_;
return $widget->create_pango_layout("");
}
sub RENDER {
my ( $cell, $window, $widget, $background_area, $cell_area, $expose_area, $flags ) = @_;
my $state;
if ( $flags & 'selected' ) {
lib/Gtk2/Ex/Datasheet/DBI.pm view on Meta::CPAN
$cell_area,
$cell->{ _arrow },
"",
"down",
1,
$cell_area->x + $cell_area->width - arrow_width,
$cell_area->y + $cell_area->height - arrow_height + 3, #
arrow_width - 3,
arrow_height
);
}
1;
#######################################################################################
# CellRendererTime
#######################################################################################
# Copyright (C) 2005 by Daniel Kasak ...
# ... basically a slightly modified CellRendererDate ( see above )
#
# 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.
use strict;
use Gtk2 -init;
package Gtk2::Ex::Datasheet::DBI::CellRendererTime;
use Glib::Object::Subclass
"Gtk2::CellRenderer",
signals => {
edited => {
flags => [qw(run-last)],
param_types => [qw(Glib::String Glib::Scalar)],
},
},
properties => [
Glib::ParamSpec -> boolean("editable", "Editable", "Can I change that?", 0, [qw(readable writable)]),
Glib::ParamSpec -> string("time", "Time", "What's the time again?", "", [qw(readable writable)]),
]
;
use constant x_padding => 2;
use constant y_padding => 3;
use constant arrow_width => 15;
use constant arrow_height => 15;
sub hide_popup {
my $cell = shift;
Gtk2->grab_remove( $cell->{ _popup } );
$cell->{ _popup }->hide();
}
sub get_time {
my $cell = shift;
my $text = $cell->get("time");
my ( $h, $m, $s ) = split( /:/, $text );
return ( $h, $m, $s );
}
sub add_padding {
my ( $cell, $h, $m, $s ) = @_;
return ( sprintf("%02d",$h), sprintf("%02d", $m), sprintf("%02d", $s) );
}
sub INIT_INSTANCE {
my $cell = shift;
my $popup = Gtk2::Window -> new ('popup');
my $vbox = Gtk2::VBox -> new( 0, 0 );
my $h_spinbutton = Gtk2::SpinButton -> new_with_range( 0, 23, 1 );
my $m_spinbutton = Gtk2::SpinButton -> new_with_range( 0, 59, 1 );
my $s_spinbutton = Gtk2::SpinButton -> new_with_range( 0, 59, 1 );
my $colon_1 = Gtk2::Label->new(":");
my $colon_2 = Gtk2::Label->new(":");
my $spin_hbox = Gtk2::HBox -> new( 0, 0 );
my $buttons_hbox = Gtk2::HBox->new( 0, 0 );
$cell -> {_arrow} = Gtk2::Arrow -> new("down", "none");
$spin_hbox->pack_start( $h_spinbutton, 1, 1, 0 );
$spin_hbox->pack_start( $colon_1, 1, 1, 0 );
$spin_hbox->pack_start( $m_spinbutton, 1, 1, 0 );
$spin_hbox->pack_start( $colon_2, 1, 1, 0 );
$spin_hbox->pack_start( $s_spinbutton, 1, 1, 0 );
my $ok = Gtk2::Button->new_from_stock('gtk-ok');
$buttons_hbox->pack_start( $ok, 1, 1, 0 );
$vbox -> pack_start( $spin_hbox, 0, 0, 0 );
$vbox->pack_start( $buttons_hbox, 0, 0, 0 );
# We can't just provide the callbacks now because they might need access to
# cell-specific variables. And we can't just connect the signals in
# START_EDITING because we'd be connecting many signal handlers to the same
# widgets.
$ok -> signal_connect(
clicked => sub {
$cell -> { _ok_clicked_callback } -> (@_)
if ( exists( $cell -> { _ok_clicked_callback } ) );
}
);
# Find out if the click happended outside of our window. If so, hide it.
# Largely copied from Planner (the former MrProject).
# Implement via Gtk2::get_event_widget?
$popup -> signal_connect(button_press_event => sub {
my ($popup, $event) = @_;
if ($event -> button() == 1) {
my ($x, $y) = ($event -> x_root(), $event -> y_root());
my ($xoffset, $yoffset) = $popup -> window() -> get_root_origin();
my $allocation = $popup -> allocation();
my $x1 = $xoffset + 2 * $allocation -> x();
my $y1 = $yoffset + 2 * $allocation -> y();
my $x2 = $x1 + $allocation -> width();
my $y2 = $y1 + $allocation -> height();
unless ($x > $x1 && $x < $x2 && $y > $y1 && $y < $y2) {
$cell -> hide_popup();
return 1;
}
}
return 0;
});
$popup -> add($vbox);
$cell -> { _popup } = $popup;
$cell -> { _h_spinbutton } = $h_spinbutton;
$cell -> { _m_spinbutton } = $m_spinbutton;
$cell -> { _s_spinbutton } = $s_spinbutton;
}
sub START_EDITING {
my ( $cell, $event, $view, $path, $background_area, $cell_area, $flags ) = @_;
my $popup = $cell -> { _popup };
my $h_spinbutton = $cell -> { _h_spinbutton };
my $m_spinbutton = $cell -> { _m_spinbutton };
my $s_spinbutton = $cell -> { _s_spinbutton };
my ( $h, $m, $s ) = $cell -> get_time();
$h_spinbutton->set_text( $h );
$m_spinbutton->set_text( $m );
$s_spinbutton->set_text( $s );
$cell -> { _ok_clicked_callback } = sub {
my ( $button ) = @_;
my $h = $h_spinbutton->get_text;
my $m = $m_spinbutton->get_text;
my $s = $s_spinbutton->get_text;
$cell -> signal_emit(
edited => $path,
join( ":", $cell -> add_padding($h, $m, $s ) )
);
$cell -> hide_popup();
};
# Necessary to get the correct allocation of the popup.
$popup -> move(-500, -500);
$popup -> show_all();
# Figure out where to put the popup - ie don't put it offscreen,
# as it's not movable ( by the user )
my $screen_height = $popup->get_screen->get_height;
my $requisition = $popup->size_request();
my $popup_width = $requisition->width;
my $popup_height = $requisition->height;
my ( $x_origin, $y_origin ) = $view -> get_bin_window() -> get_origin();
my ( $popup_x, $popup_y );
$popup_x = $x_origin + $cell_area->x() + $cell_area->width() - $popup_width;
$popup_x = 0 if $popup_x < 0;
$popup_y = $y_origin + $cell_area -> y() + $cell_area -> height();
if ( $popup_y + $popup_height > $screen_height ) {
$popup_y = $y_origin + $cell_area -> y() - $popup_height;
}
$popup -> move( $popup_x, $popup_y );
# Grab the focus and the pointer.
Gtk2 -> grab_add($popup);
$popup -> grab_focus();
Gtk2::Gdk->pointer_grab(
$popup->window(),
1,
[ qw( button-press-mask button-release-mask pointer-motion-mask ) ],
undef,
undef,
0
);
return;
}
sub get_time_string {
my $cell = shift;
return $cell->get('time');
}
sub calc_size {
my ( $cell, $layout ) = @_;
my ( $width, $height ) = $layout->get_pixel_size();
return (
0,
0,
$width + x_padding * 2 + arrow_width,
$height + y_padding * 2
);
}
sub GET_SIZE {
my ( $cell, $widget, $cell_area ) = @_;
my $layout = $cell->get_layout( $widget );
$layout->set_text( $cell -> get_time_string() );
return $cell->calc_size( $layout );
}
sub get_layout {
my ( $cell, $widget ) = @_;
return $widget->create_pango_layout( "" );
}
sub RENDER {
my ( $cell, $window, $widget, $background_area, $cell_area, $expose_area, $flags ) = @_;
my $state;
if ( $flags & 'selected' ) {
$state = $widget->has_focus()
( run in 0.616 second using v1.01-cache-2.11-cpan-364913b4093 )