Hi Torsten. Thanks, once again, for the reply.

On Thu, 2013-02-21 at 09:39 +0000, Torsten Schoenfeld wrote:


> On 21.02.2013 07:28, Dan Kasak wrote:
> > Can't locate object method "EDITING_STARTED" via package
> > "Gtk3::Ex::Datasheet::DBI::CellRendererText" at
> > /usr/lib64/perl5/site_perl/5.12.4/Gtk3.pm line 228.
> 
> I don't get this with my Gtk3 port of odot, so… no clue off-hand.  Can 
> you provide a self-contained example program exhibiting this?


Done. By the way ... perhaps an easier way of me getting this working is
to look at your Gtk3 port of odot ;)


> Some more comments on the code:
> 
> > package Gtk3::Ex::Datasheet::DBI::CellEditableText;
> 
> You might have to put empty implementations of the virtual functions of 
> Gtk3::CellEditable here:
> 
> sub START_EDITING {
>    # do nothing
> }
> 
> sub EDITING_DONE {
>    # do nothing
> }
> 
> sub REMOVE_WIDGET {
>    # do nothing
> }



Also done.


> > use Glib::Object::Subclass
> >    Gtk3::CellRendererText::,
> >    properties => [
> >                      Glib::ParamSpec->object(
> >                                                      "editable-widget",
> >                                                      "Editable widget",
> >                                                      "The editable
> > that's used for cell editing.",
> >
> > Gtk3::Ex::Datasheet::DBI::CellEditableText::,
> >                                                      [ qw( readable
> > writable ) ]
> >                                             ),
> 
> Do you need this property?  It was a hack in Odot, and I've now removed 
> it.  If you don't need it, you can also consider moving the creation of 
> the editable from INIT_INSTANCE to START_EDITING.


Hmmmm ... The only way I've seen a custom CellRendererText working is by
implementing a CellEditableText, as per your previous example. Perhaps I
don't need it? I didn't do it on purpose ... just pulled in example code
and tweaked until it worked.


> >              # For some reason, the last item returned by the above call to
> >              # $parent->get_columns isn't a Gtk3::TreeViewColumn, and
> > therefore
> >              # the $parent_set_cursor line fails. Avoid this.
> >              if ( ref $next_col eq 'Gtk3::TreeViewColumn' ) {
> >                  $parent->set_cursor ( $path, $next_col, 1 )
> >                      if $next_col;
> >              }
> 
> That shouldn't happen.  What is the last item if it's not a column?


This is a comment from WAY back in Gtk2 land. When everything is working
again ... I'll re-test.


> > sub GET_SIZE {
> >
> >      my ( $self, $widget, $cell_area ) = @_;
> >
> >      return $self->SUPER::GET_SIZE ( $widget, $cell_area );
> >
> > }
> 
> If you simply chain up, you can also just not provide any implementation 
> at all.  The effect will be the same, but it will be faster as it avoids 
> the roundtrip marshalling of the arguments from C to Perl back to C. 
> (And GET_SIZE will be called a lot.)


Ah. Noted. I think I must have had more functionality in there at one
point, and removed it, not realising I could remove the whole thing.



> >      #$editable->modify_font( Gtk2::Pango::FontDescription->from_string(
> > "Arial " . $cell->get( "font" ) ) );
> >      $editable->modify_font( Pango::FontDescription->from_string( "Arial
> > " . $cell->get( "font" ) ) );
> 
> Do you really want to hard-code a particular font here, completely 
> ignoring the user's preference?  If you want to modify the font size, 
> use the Gtk3::CellRendererText's "size" property (which you inherit in 
> your cell renderer).


Yeah :) To be honest ... this was to make things work properly on
Windows. At the time I was writing it ... 1/2 the users were on Windows
2000, and for some reason that escapes me now, this was required. I'm
free of these users now, by the way ;)

---

Example code that demonstrates a number of issues I'm facing. Now I
don't get the error as before, but I get a segfault instead, when
clicking inside a cell to edit :(

cell_renderer.pl:

---

use strict;

use Gtk3 -init;
use Glib qw / TRUE FALSE /;

my $builder = Gtk3::Builder->new();

$builder->add_objects_from_file( "cell_renderer.ui", "window1" );

my $treeview = $builder->get_object( "treeview1" );

my $model = Gtk3::ListStore->new(
    [
        "Glib::Int"
      , "Glib::String"
    ]
);

my $renderer_one = Gtk3::Ex::Datasheet::DBI::CellRendererText->new;
$renderer_one->set( editable => TRUE );

my $column_one = Gtk3::TreeViewColumn->new_with_attributes(
    "Column 1",
    $renderer_one,
    'text'  => 0
);

$treeview->append_column( $column_one );

my $renderer_two = Gtk3::Ex::Datasheet::DBI::CellRendererText->new;
$renderer_two->set( editable => TRUE );

my $column_two = Gtk3::TreeViewColumn->new_with_attributes(
    "Column 2",
    $renderer_two,
    'text'  => 1
);

$treeview->append_column( $column_two );

$model->set(
    $model->append
  , 0, "text 1"
  , 1, "text 2"
);

$builder->get_object( "treeview1" )->set_model( $model );

$builder->get_object( "window1" )->show;

Gtk3->main;

#######################################################################################
# Custom CellRendererText
#######################################################################################

package Gtk3::Ex::Datasheet::DBI::CellEditableText;

# Copied and pasted from Odot

use strict;
use warnings;

use Glib qw(TRUE FALSE);
use Glib::Object::Subclass
  Gtk3::TextView::,
    interfaces => [ Gtk3::CellEditable:: ]
  , properties => [
                    Glib::ParamSpec->boolean(
                                                    "editing-canceled",
                                                    "Editing canceled",
                                                    "Whether editing has
been canceled.",
                                                    FALSE,
                                                    [ qw( readable
writable ) ]
                                           )
                ];

sub START_EDITING {
    # do nothing
}

sub EDITING_DONE {
    # do nothing
}

sub REMOVE_WIDGET {
    # do nothing
}

sub set_text {
    
    my ( $editable, $text ) = @_;
    
    $text = "" unless ( defined( $text ) );
    
    $editable->get_buffer()->set_text( $text, length( $text ) );
    
}

sub get_text {
    
    my ( $editable ) = @_;
    my $buffer = $editable->get_buffer();
    
    return $buffer->get_text( $buffer->get_bounds(), TRUE );
    
}

sub select_all {
    
    my ( $editable ) = @_;
    my $buffer = $editable->get_buffer();
    
    my ( $start, $end ) = $buffer->get_bounds();
    $buffer->move_mark_by_name( insert => $start );
    $buffer->move_mark_by_name( selection_bound => $end );
    
}

1;

package Gtk3::Ex::Datasheet::DBI::CellRendererText;

# Originally from Odot, with bits and pieces from the
CellRendererSpinButton example,
# and even some of my own stuff worked in :)

use constant x_padding => 2;
use constant y_padding => 3;

use strict;
use warnings;

use Glib qw(TRUE FALSE);

use Glib::Object::Subclass
  Gtk3::CellRendererText::,
  properties => [
                    Glib::ParamSpec->object(
                                                    "editable-widget",
                                                    "Editable widget",
                                                    "The editable that's
used for cell editing.",

Gtk3::Ex::Datasheet::DBI::CellEditableText::,
                                                    [ qw( readable
writable ) ]
                                           ),
                    Glib::ParamSpec->boolean(
                                                    "number",
                                                    "Number",
                                                    "Should I apply
number formatting to the data?",
                                                    0,
                                                    [ qw( readable
writable ) ]
                                            ),
                    Glib::ParamSpec->string(
                                                    "decimals",
                                                    "Decimals",
                                                    "How many decimal
places should be displayed?",
                                                    -1,
                                                    [ qw( readable
writable ) ]
                                           ),
                    Glib::ParamSpec->boolean(
                                                    "currency",
                                                    "Currency",
                                                    "Should I prepend a
dollar sign to the data?",
                                                    0,
                                                    [ qw( readable
writable ) ]
                                            )
                ];

sub EDITING_STARTED {
    # do nothing
}

sub START_EDITING {
    
    my ( $cell, $event, $view, $path, $background_area, $cell_area,
$flags ) = @_;
    
    if ( $event ) {
        return unless ( $event->button == 1 );
    }
    
    ###
    
    my $editable = Gtk3::Ex::Datasheet::DBI::CellEditableText->new();
    
    $editable->set( border_width => $cell->get( "ypad" ) );
    
    $editable->signal_connect( key_press_event => sub {
        
        my ( $editable, $event ) = @_;
        
        if (
            $event->keyval == $Gtk3::Gdk::KEY_Return ||
            $event->keyval == $Gtk3::Gdk::KEY_KP_Enter
            and not $event-> state & qw(control-mask)
           )
        {
            
            # Grab parent
            my $parent = $editable->get_parent;
            
            $editable->{ _editing_canceled } = FALSE;
            $editable->editing_done();
            $editable->remove_widget();
            
            my ( $path, $focus_column ) = $parent->get_cursor;
            my @cols = $parent->get_columns;
            my $next_col = undef;
            
            foreach my $i (0..$#cols) {
                if ( $cols[$i] == $focus_column ) {
                    if ( $event->state >= 'shift-mask' ) {
                        # go backwards
                        $next_col = $cols[$i-1] if $i > 0;
                    } else {
                        # Go forwards
                        # First check whether the next column is
read_only
                        while ( $i-1 < $#cols ) {
                            $i++;
                            if ( ! $cols[$i]->{definition}->{read_only}
) {
                                last;
                            }
                        }
                        $next_col = $cols[$i];
                    }
                    last;
                }
            }
            
            # For some reason, the last item returned by the above call
to
            # $parent->get_columns isn't a Gtk3::TreeViewColumn, and
therefore
            # the $parent_set_cursor line fails. Avoid this.
            if ( ref $next_col eq 'Gtk3::TreeViewColumn' ) {
                $parent->set_cursor ( $path, $next_col, 1 )
                    if $next_col;
            }
            
            return TRUE;
            
        }
        
        return FALSE;
        
    });
    
    $editable -> signal_connect( editing_done => sub {
       my ( $editable ) = @_;
       my $canceled = $editable->get( 'editing-canceled' );
       # or $editable -> { _editing_canceled } if you store it directly
       $cell->stop_editing( $canceled );
       unless ( $canceled ) {
           $cell->signal_emit( edited => $path, $editable->get_text() );
       }
    });
    
    $cell->set( editable_widget => $editable );
    
    ###
    
    #$editable->modify_font( Pango::FontDescription->from_string( "Arial
" . $cell->get( "font" ) ) );
    
    $editable->{ _editing_canceled } = FALSE;
    $editable->{ _path } = $path;
    $editable->set( height_request => $cell_area->{height} );
    
    $editable->set_text( $cell->get( "text" ) );
    $editable->select_all();
    $editable->show();
    
    $editable -> signal_connect_after(
            'focus-out-event'       => sub {
                                                my ( $event_box, $event
) = @_;

$cell->signal_emit( edited => $editable->{ _path }, $editable->get_text
);
                                                return $event;
            }
                               );
    
    return $editable;
    
}

sub get_layout {
    
    my ( $cell, $widget ) = @_;
    
    return $widget->create_pango_layout( "" );
    
}

1;

---

cell_renderer.ui:

---

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <!-- interface-requires gtk+ 3.0 -->
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkLabel" id="label1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">label</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkScrolledWindow" id="scrolledwindow1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="shadow_type">in</property>
            <child>
              <object class="GtkTreeView" id="treeview1">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <child internal-child="selection">
                  <object class="GtkTreeSelection"
id="treeview-selection2"/>
                </child>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkButton" id="button1">
            <property name="label" translatable="yes">button</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">2</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

_______________________________________________
gtk-perl-list mailing list
gtk-perl-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtk-perl-list

Reply via email to