CellRendererSpinButton in a List



Hi, 
I've been beating my head against a wall
for awhile, so I better ask muppet....where the buck stops. :-)

I'm trying to setup a basic example for myself, putting
different cellrenderers into a list.
I have the text, combos, and toggle setup ok, but
the spinbutton is giving me fits. 

I've used the basic CellRendererSpinButton package
which has been mentioned here before. The problem is that
I can't seem to get the spin box to update to it's new value
in the list. I can spin them up and down, and when I set them,
with a click or enter, they revert to 0.

If I manually edit the cell, and press enter, the liststore seems
to get the value, but it does not appear in the spinbox cell, which
remains 0.00.  

In the interest of simplicity, I put a super simple example below.

#!/usr/bin/perl -w
use strict;
use Gtk2 -init;
use Gtk2::Gdk::Keysyms;

package Gtk2::CellRendererSpinButton;
use POSIX qw(DBL_MAX UINT_MAX);
use constant x_padding => 2;
use constant y_padding => 3;

use Glib::Object::Subclass "Gtk2::CellRenderer",
 signals => {
   edited => {
      flags       => [ qw(run-last) ],
      param_types => [ qw(Glib::String Glib::Double) ],
   },
 },
 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->{ editable } = 0;
   $self->{ digits }   = 2;
   $self->{ value }    = 0.0;
   $self->{ min }      = 0.0;
   $self->{ max }      = 100.0;
   $self->{ step }     = 5.0;
   $self->{ xalign }   = 1.0;
}

sub calc_size {
   my ( $cell, $layout, $area ) = @_;
   my ( $width, $height ) = $layout->get_pixel_size();

   return (
        $area
      ? $cell->{ xalign } * ( $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->{ digits };
   sprintf $format, $cell->{ value };
}

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" ) );

   $spin_button->grab_focus();

   $spin_button->signal_connect(
      key_press_event => sub {
         my ( $event_box, $event ) = @_;

         if (  $event->keyval == $Gtk2::Gdk::Keysyms{ Return }
            || $event->keyval == $Gtk2::Gdk::Keysyms{ KP_Enter } )
         {
            $spin_button->update();
            $cell->signal_emit( edited => $path, $spin_button->get_value() );
            $spin_button->destroy();
            return 1;
         }
         elsif ( $event->keyval == $Gtk2::Gdk::Keysyms{ Up } ) {
            $spin_button->spin( 'step-forward',
               ( $spin_button->get_increments() )[ 0 ] );
            return 1;
         }
         elsif ( $event->keyval == $Gtk2::Gdk::Keysyms{ Down } ) {
            $spin_button->spin( 'step-backward',
               ( $spin_button->get_increments() )[ 0 ] );
            return 1;
         }

         return 0;
      }
   );

   $spin_button->show_all();

   return $spin_button;
}
1;

################################################################
package main;

my $window = Gtk2::Window->new( "toplevel" );
$window->set_title( "CellRendererSpinButton" );
$window->signal_connect( delete_event => sub { Gtk2->main_quit(); } );

my $model = Gtk2::ListStore->new( qw(Glib::Double) );
my $view  = Gtk2::TreeView->new( $model );

#setup init value 
$model->set( $model->append(), 0 => 42.42 );

my $renderer = Gtk2::CellRendererSpinButton->new();

$renderer->set(
   mode   => "editable",
   min    => 0,
   max    => 1000,
   step   => 2,
   digits => 1
);

$renderer->signal_connect( edited => \&cell_edited );

my $column =
 Gtk2::TreeViewColumn->new_with_attributes( "1 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();

#use Devel::Symdump;
#my $obj = Devel::Symdump->new('Gtk2::CellRendererSpinButton');
#print $obj->as_string;

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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]