Gtk3 and subclassing

Whilst working up a smallest working example for another bug, I've
discovered that I cannot get subclassing working when the main package
is in the same file as the module.

Below is the Gtk2 subclassing example from Muppet which I have trivially
converted to Gtk3.

I get the following error messages:

Odd number of elements in anonymous hash at
/usr/lib/x86_64-linux-gnu/perl5/5.28/Glib/Object/ line 267.
*** unhandled exception in callback:
***   Can't locate object method "get_colormap" via package
"Gtk3::EventBox" at ../ line 93.
***  ignoring at
/usr/lib/x86_64-linux-gnu/perl5/5.28/Glib/Object/ line 67.

What is going on?



#!/usr/bin/perl -w

use strict;

package Mup::ColorButton;

use Gtk3;

# this big hairy statement registers our Glib::Object-derived class
# and sets up all the signals and properties for it.
use Glib::Object::Subclass Gtk3::Button::, signals => {
        # with an empty hash for color_changed, we use all defaults,
        # which results in a signal which receives no extra parameters[2]
        # and returns no value.
        color_changed => {},
        # by supplying a subroutine reference for an existing signal,
        # we override the default handler for the class; this is how
        # you override virtual functions on Glib::Objects.
        show => \&on_show,
    properties => [
        Glib::ParamSpec->int (
                'red', # name
                'Red', # nickname
                'The Red component of the RGB color', #blurb
                0, # min
                0xffff, # max
                0xffff, # default
                [qw/readable writable/] #flags
        Glib::ParamSpec->int (
                'green', 'Green', 'The Green component of the RGB color',
                0, 0xffff, 0xffff, [qw/readable writable/]
        Glib::ParamSpec->int (
                'blue', 'Blue', 'The Blue component of the RGB color',
                0, 0xffff, 0xffff, [qw/readable writable/]

# as part of creating the C object, Glib will call the INIT_INSTANCE
# method to, surprise, initialize the instance.  this is not an inherited
# method; it will be called with a fully-qualified package name.
# most of what we used to have in the constructor goes here.
# in fact, we just inherit new() from the base class, because it does
# everything we need it to.
        my $self = shift;
        $self->{red} = 0xffff;
        $self->{green} = 0xffff;
        $self->{blue} = 0xffff;
        my $frame = Gtk3::Frame->new;
        $frame->set_border_width (3);
        $frame->set_shadow_type ('etched-in');
        $self->add ($frame);
        my $event_box = Gtk3::EventBox->new;
        $event_box->set_size_request (14, 14);
        $frame->add ($event_box);
        $self->{colorbox} = $event_box;

# in a more ambitious widget, we'd probably define GET_PROPERTY
# and SET_PROPERTY to do some custom stuff... for our purposes,
# however, the default implementation provided by Glib::Object::Subclass
# is sufficient.  (it sets the property values as hash members in the
# instance variable.)

# here we need to override the show method to set the color the
# first time we go onscreen, because we can't do that in the
# initializer (the GdkWindow does not exist yet).
sub on_show {
        my $self = shift;
        $self->set_color (red => $self->{red},
                          green => $self->{green},
                          blue => $self->{blue});
        # perl code that needs to call the parent class usually does
        # like  $self->SUPER::methodname ---- however, class_closures for
        # for Glib::Objects are not inheritable in that way; the code to
        # we need to chain may not even be perl code.  Glib provides this
        # method to provide that functionality, instead.

sub set_color {
        my $self = shift;
        my %params = @_;
        my $color = Gtk3::Gdk::Color->new ($params{red},
        $self->{colorbox}->get_colormap->alloc_color ($color, 0, 1);
        $self->{colorbox}->modify_bg ('normal', $color);
        $self->{colorbox}->modify_bg ('active', $color);
        $self->{colorbox}->modify_bg ('prelight', $color);
        $self->{red} = $params{red};
        $self->{green} = $params{green};
        $self->{blue} = $params{blue};
        # emit the color-changed signal.  note again that the signal
        # name treats - and _ as equivalent.
        $self->signal_emit ('color-changed');

package main;

use Gtk3 -init;

my $window = Gtk3::Window->new;
$window->set_title ('Color buttons');
$window->set_border_width (6);
$window->signal_connect (delete_event => sub { Gtk3->main_quit; 1 });

my $vbox = Gtk3::VBox->new;
$window->add ($vbox);

my $foo = Mup::ColorButton->new (red => 0xaaaa, green => 0x0, blue =>
$vbox->pack_start ($foo, 1, 1, 0);

$foo->signal_connect (clicked => sub {
                my $self = shift;
                my $dialog = Gtk3::ColorSelectionDialog->new ('pick a
                my $c = Gtk3::Gdk::Color->new ($self->{red},
                $self->{colorbox}->get_colormap->alloc_color ($c, 0, 1);
                $dialog->colorsel->set_current_color ($c);
                if ('ok' eq $dialog->run) {
                        my $c = $dialog->colorsel->get_current_color;
                        $self->set_color (red => $c->red,
                                          green => $c->green,
                                          blue => $c->blue);

$foo->signal_connect (color_changed => sub {
        warn "the color changed - now "
           . join (", ", $_[0]->get (qw/red green blue/))
           . ".  i should do something!";


Attachment: signature.asc
Description: OpenPGP digital signature

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