Re: widget subclassing problem




Eisenknapp, Josef said:
-----------------------------------------------
package LabelEntry;
use Glib qw(TRUE FALSE);
use Gtk2;

use strict;
use warnings;

use Glib::Object::Subclass
    Gtk2::VBox::,
    signals => {
 # currently no signals defined
       },
    properties => [
          Glib::ParamSpec->string (
       'my_text', # name
       'my_text', # nickname
       'The text shown above the entry', #blurb
       "Default entry text", # default
       [qw/readable writable/] #flags
       ),
     ]
    ;

sub INIT_INSTANCE {
    my $self = shift;

    print "label_text = ". $my_text. "\n";

    my $label = Gtk2::Label->new ( $self{my_text} );

Two problems here:  first, $my_text is not defined (i presume you have a
global in your copy), and second, the properties have not yet been set in
INIT_INSTANCE.  Instantiation is basically a sequence of INSTANCE_INIT and a
bunch of SET_PROPERTYs.  You'll have to create the Label with no string, and
then provide a property setter or SET_PROPERTY that puts the text into the
label with set_text().

If you really want to use the default, you'll have to use
$self->get ('my-text'), but beware of interesting interactions with the rest
of the system; see below.


    $label->set_alignment (0.0, 0.5); # set left horizontal alignment
and middle vertical alignment

#    $label->set_text ( $self->{my_text} );

    my $entry = Gtk2::Entry->new();

    $self->pack_start($label, FALSE, FALSE, 2);
    $self->pack_start($entry, FALSE, FALSE, 2);
    $self->show();

This is incorrect.  A widget should never show itself -- that is for client
code to decide.  The widget *should*, however, show all of its children,
because you cannot rely on client code to call show_all().

-      $self->show();
+      $label->show();
+      $entry->show();


    $self->{label} = $label;
    $self->{entry} = $entry;
}
-----------------------------------------------------------------------


Adding these two functions, along with the changes described above, makes
everything happy for me.

  sub SET_PROPERTY {
      my ($self, $pspec, $newval) = @_;
      if ($pspec->{name} eq 'my-text') {
          $self->{label}->set_text ($newval);
      }
  }
  sub GET_PROPERTY {
      my ($self, $pspec) = @_;
      if ($pspec->{name} eq 'my-text') {
          return $self->{label}->get_text;
      }
  }

Note the use of "my-text" rather than "my_text".  The property system
normalizes the strings to use dashes rather than underscores, and the values
that come back in the pspec's name field in [GS]ET_PROPERTY are normalized
like this.  You avoid the issue altogether if you use the alternative syntax
for properties...

   properties => [
      {
          pspec => Glib::ParamSpec->string ('my-text',
                                            'My Text',
                                            'The text shown above the entry',
                                            "", # default
                                            [qw/readable writable/]),
          get => sub {
              my ($self) = @_;
              return $self->{label}->get_text();
          },
          set => sub {
              my ($self, $newval) = @_;
              $self->{label}->set_text ($newval);
          },
      },
   ],



Even if i don't set it there should be a default value. Or am i wrong
here.

The default value is used if you don't override the default behavior for the
getter and setter.  However, as described above, you have to actually call
->get() for that to work.  Also, when your object is merely proxying a
property from another object, setting a default in your object is rather
pointless.  You can look up the default in the other object's property's
pspec, but that's very much overkill.


-- 
muppet <scott at asofyet dot org>





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