Re: size_request/size_allocate question




On Oct 14, 2005, at 5:52 AM, Jaap Karssenberg wrote:

I try to subclass Gtk2::HBox and I want to handle size allocation myself. I figured overloading size_request() and size_allocation() would do the trick, but these methods don't get called when the widget is shown :( I've included my code below, does anyone have a suggestion what I do wrong ?

That's not how you override signals. This is another case of the GObject-as-a-perl-object abstraction leaking some of the GObject details.

size-request and size-allocate are widget signals. The methods size_request() and size_allocate() emit the corresponding signals, and the real work happens in the class closure for the signal handler.

What you have done is provide a new implementation of the methods that will be seen by perl when it searches for the method by $widget- >size_request() by looking at the actual type of $widget and searching @ISA. The problem is that for any *interesting* invocation of this method, it will be called from the C function gtk_widget_size_request(), deep within gtk+ --- that is, control never gets to the perl method lookup! You have to ensure that these things are invoked by C code, which means that normal perl OO stuff doesn't work quite right.

The way to do this, then, is to override the "class closure" for the signal.

See also: http://gtk2-perl.sourceforge.net/doc/ subclassing_widgets_in_perl.html (which explains the above situation) and http://gtk2-perl.sourceforge.net/doc/examples/ histogramplot.pl.html (which has a size-request override).


Also, as you'd written it, the constructor was completely broken. SUPER::new would find Gtk2::HBox::new(), which unconditionally calls gtk_hbox_new(), giving you an actual GtkHBox blessed as a Gtk2::HBox. Your own methods would not be found, and your new subclass would not be created (the GType is wrong). The correct way to instantiate GObject subclasses is to use Glib::Object::new(); Glib::Object::Subclass will alias this for you, so you don't need to provide a constructor.

Changes to your code:
- rename size_request() to _size_request()
- rename size_allocate() to _size_allocate()
- change SUPER::size_request and SUPER::size_allocate to signal_chain_from_overridden. - add a signal map to the Subclass pragma to tell your new GType to invoke your class closures
- remove new()
- if necessary, do instance initialization (defaults, etc) in INIT_INSTANCE().


package Gtk2::Ex::ButtonPathBar;

our $VERSION = '0.01';

use strict;
use Gtk2;

use Glib::Object::Subclass
    Glib::HBox::,
    signals => {
        # provide overrides for widget signals
        size_allocate => \&_size_allocate,
        size_request => \&_size_request,
    },
    ;

# use a different name to avoid clashes and the resulting infinite loops
sub _size_request {
    my $self = shift;
    print "Got a size request\n";
    # SUPER doesn't work for signals.
    $self->signal_chain_from_overridden (@_);
}

#again, a different name
sub _size_allocate {
    my ($self, $allocation) = @_;
    my ($w, $h) = ($allocation->width, $allocation->height);
    print "got allocation for $w, $h\n";
    $self->signal_chain_from_overridden ($allocation);
}

1;
# End Code listing


--
elysse (pregnant): are your hands cold?
me: uh, i suppose so.
elysse: will you put them on me?




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