Hi,
Here is a working package, for the
Gtk2::CellRendererSpinButton.
It sets initial value, updates itself, and sets
new initial value at each edit.
I use a package global to hold the current value,
and if anyone knows a better way, my ears are open.
#!/usr/bin/perl -w
use strict;
use Gtk2 -init;
# package Gtk2::CellRendererSpinButtonZ;
#
# with a simple example usage
#
#this package is based on the Mup::CellRendererSpinButton
#by muppet, but added
#
# 1. SET_PROPERTY sub to load and show initial values
# 2. an extra signal handler for the focus-out to set
# the spinbox, when going out of focus
# 3. a global $cur_val to maintain the initial editing
# start point
package Gtk2::CellRendererSpinButtonZ;
use POSIX qw(DBL_MAX UINT_MAX);
use constant x_padding => 2;
use constant y_padding => 3;
use Gtk2::Gdk::Keysyms;
#global to hold current value to load when start editing
my $cur_val;
use Glib::Object::Subclass "Gtk2::CellRenderer",
signals => {
edited => {
flags => [ qw(run-last) ],
param_types => [ qw(Glib::String Glib: ouble)
],
},
},
properties => [
Glib::ParamSpec->double(
"xalign", "Horizontal
Alignment",
"Where am i?", 0.0, 1.0, 1.0, [
qw(readable writable) ]
),
Glib::ParamSpec->boolean(
"editable",
"Editable",
"Can I change that?", 0,
[ qw(readable writable) ]
),
Glib::ParamSpec->uint(
"digits",
"Digits",
"How picky are you?", 0,
UINT_MAX, 2,
[ qw(readable writable) ]
),
map {
Glib::ParamSpec->double(
$_->[ 0 ],
$_->[ 1 ],
$_->[ 2 ],
0.0, DBL_MAX,
$_->[ 3 ],
[ qw(readable writable) ]
)
} (
[ "value", "Value", "How
much is the fish?", 0.0 ],
[ "min", "Min", "No
way, I have to live!", 0.0 ],
[ "max", "Max", "Ah,
you're too generous.", 100.0 ],
[ "step", "Step",
"Okay.", 5.0 ]
)
];
sub INIT_INSTANCE {
my $self = shift;
$self-> = 0;
$self-> = 2;
$self-> = 0.0;
$self-> = 0.0;
$self-> = 100.0;
$self-> = 5.0;
$self-> = 1.0;
}
sub SET_PROPERTY {
my ($self, $pspec, $val) = _;
$self->{ $pspec->get_name } = $val;
# set the initial editing value
if ($pspec->get_name eq 'value') {
$cur_val = $val;
}
}
sub calc_size {
my ( $cell, $layout, $area ) = _;
my ( $width, $height ) = $layout->get_pixel_size();
return (
$area
? $cell-> * ( $area->width - ( $width
+ 3 * x_padding ) )
: 0,
0,
$width + x_padding * 2,
$height + y_padding * 2
);
}
sub format_text {
my $cell = shift;
my $format = sprintf '%%.%df', $cell->;
sprintf $format, $cell->;
}
sub GET_SIZE {
my ( $cell, $widget, $area ) = _;
my $layout = $cell->get_layout( $widget );
$layout->set_text( $cell->format_text );
return $cell->calc_size( $layout, $area );
}
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()
? 'selected'
: 'active';
}
else {
$state =
$widget->state() eq 'insensitive'
? 'insensitive'
: 'normal';
}
my $layout = $cell->get_layout( $widget );
$layout->set_text( $cell->format_text );
my ( $x_offset, $y_offset, $width, $height ) =
$cell->calc_size( $layout, $cell_area );
$widget->get_style->paint_layout(
$window,
$state,
1,
$cell_area,
$widget,
"cellrenderertext",
$cell_area->x() + $x_offset + x_padding,
$cell_area->y() + $y_offset + y_padding,
$layout
);
}
sub START_EDITING {
my ( $cell, $event, $view, $path, $background_area,
$cell_area, $flags ) =
_;
my $spin_button =
Gtk2::SpinButton->new_with_range( $cell->get(
qw(min max step) ) );
$spin_button->set_value( $cell->get(
"value" ) );
$spin_button->set_digits( $cell->get(
"digits" ) );
#set initial point for editing
$spin_button->set_value( $cur_val );
$spin_button->grab_focus();
$spin_button->signal_connect(
key_press_event => sub {
my ( $event_box, $event ) = _;
if ( $event->keyval == $Gtk2::Gdk::Keysyms
|| $event->keyval == $Gtk2::Gdk::Keysyms )
{
$spin_button->update();
$cell->signal_emit( edited => $path,
$spin_button->get_value() );
$spin_button->destroy();
return 1;
}
elsif ( $event->keyval == $Gtk2::Gdk::Keysyms ) {
$spin_button->spin( 'step-forward',
( $spin_button->get_increments() )[ 0 ] );
return 1;
}
elsif ( $event->keyval == $Gtk2::Gdk::Keysyms ) {
$spin_button->spin( 'step-backward',
( $spin_button->get_increments() )[ 0 ] );
return 1;
}
return 0;
}
);
$spin_button->signal_connect(
'focus-out-event' => sub {
my ( $event_box, $event ) = _;
$spin_button->update();
$cell->signal_emit( edited => $path,
$spin_button->get_value() );
#set the init value for next edit
$cur_val = $spin_button->get_value();
return 0;
}
);
$spin_button->show_all();
return $spin_button;
}
1;
############################################################
####
package main;
my $window = Gtk2::Window->new( "toplevel" );
$window->set_title( "CellRendererSpinButtonZ
demo" );
$window->signal_connect( delete_event => sub {
Gtk2->main_quit(); } );
my $model = Gtk2::ListStore->new( qw(Glib: ouble)
);
my $view = Gtk2::TreeView->new( $model );
#setup init value
$model->set( $model->append(), 0 => 42.42 );
my $renderer = Gtk2::CellRendererSpinButtonZ->new();
$renderer->set(
mode => "editable",
min => 0,
max => 1000,
step => 1.0,
digits => 2
);
$renderer->signal_connect( edited =>
\&cell_edited );
my $column =
Gtk2::TreeViewColumn->new_with_attributes( "2
digit", $renderer, value => 0 );
$view->append_column( $column );
my $vbox = Gtk2::VBox->new( 0, 5 );
$vbox->pack_start( $view, 1, 1, 0 );
my $button = Gtk2::Button->new( "Show Values"
);
$button->signal_connect( "clicked" => sub
{ &show_values( _ ); } );
$vbox->pack_start( $button, 0, 0, 0 );
$window->add( $vbox );
$window->show_all();
Gtk2->main();
############################################################
########
sub cell_edited {
my ( $cell, $path, $new_value ) = _;
$model->set( $model->get_iter(
Gtk2::TreePath->new_from_string( $path ) ),
0 => $new_value );
}
############################################################
########
sub show_values {
my $treeselection = $view->get_selection;
my $iter = $treeselection->get_selected;
print $model->get( $iter, 0 ), "\n";
}
__END__
--
I'm not really a human, but I play one on earth.
http://zentara.net/japh.
html
_______________________________________________
gtk-perl-list mailing list
gtk-perl-list gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-perl-list
|
On Mar 6, 2006, at 3:57 PM, zentara wrote:
> Hi,
> Here is a working package, for the
> Gtk2::CellRendererSpinButton.
>
> It sets initial value, updates itself, and sets
> new initial value at each edit.
>
> I use a package global to hold the current value,
> and if anyone knows a better way, my ears are open.
You don't need the global at all. You pass the new value
through
the "new value" parameter of the edited signal.
The cell renderer
should not alter its own value --- that's for client code
to do, if
desired, in the "edited" callback. (Definitely
"if desired" --
imagine a situation in which the SpinButton is used in a
TreeView
using a custom TreeModel, whose data actually reflects state
elsewhere in the system. In this situation, having the
CellRenderer
set the value directly on the model may be quite bad. This
is always
left for the client code to perform.)
I simply removed from your new code all lines that refer to
$cur_val,
and it all works as expected. In fact, if you press Enter
in the
spinbutton after editing, the 'edited' signal gets emitted
twice ---
once explictly from key-press-event., and again from
focus-out-event
as the cell editor is being destroyed.
The original code required you to press "Enter"
to "commit" the
value, and allowed you to press "Esc" to cancel
changing it. If you
don't care about the distinction, then you don't even need
to handle
"Enter" specially, and can just rely on the
focus-out-event.
> sub SET_PROPERTY {
> my ($self, $pspec, $val) = _;
> $self->{ $pspec->get_name } = $val;
>
> # set the initial editing value
> if ($pspec->get_name eq 'value') {
> $cur_val = $val;
> }
> }
After you remove the global, you have a SET_PROPERTY which
is merely
a perl implementation of what the XS code already does.
--
And then mama would throw the live crawdads in the boilin'
water.
And one day I decided I'd make my own crawdads. So I threw
the
crawdads in the pot, but without any water. It was just
like makin'
popcorn.
-- Ear-bending cellmate, "Raising Arizona"
_______________________________________________
gtk-perl-list mailing list
gtk-perl-list gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-perl-list
|