Glib::Object::Subclass - register a perl class as a GObject class
use Glib::Object::Subclass Some::Base::Class::, # parent class, derived from Glib::Object signals => { something_changed => { class_closure => sub { do_something_fun () }, flags => [qw(run-first)], return_type => undef, param_types => [], }, some_existing_signal => \&class_closure_override, }, properties => [ Glib::ParamSpec->string ( 'some_string', 'Some String Property', 'This property is a string that is used as an example', 'default value', [qw/readable writable/] ), ];
It doesn't ``export'' anything into your namespace, but acts more like a pragmatic module that modifies your class to make it work as a GObject class.
You may be wondering why you can't just bless a Glib::Object into a different package and add some subs. Well, if you aren't interested in object parameters, signals, or having your new class interoperate transparently with other GObject-based modules (e.g., Gtk2 and friends), then you can just re-bless.
However, a GObject's signals, properties, virtual functions, and GInterface implementations are specific to its GObjectClass. If you want to create a new GObject which was a derivative of GtkDrawingArea, but adds a new signal, you must create a new GObjectClass to which to add the new signal. If you don't, then all of the GtkDrawingAreas in your application will get that new signal!
Thus, the only way to create a new signal or object property in the Perl bindings for Glib is to register a new subclass with the GLib type system via Glib::Type::register_object(). The Glib::Object::Subclass module is a Perl-developer-friendly interface to this bit of paradigm mismatch.
The pragma requires at least one argument, the parent class name. The remaining arguments are key/value pairs, in any order, all optional:
(Actually, these parameters are all passed straight through to Glib::Type::register_object(), adding __PACKAGE__ (the current package name) as the name of the new child class.)
Except for "new", all of the following are functions and no methods. That means that you should not call the superclass method. Instead, the GObject system will call these functions per class as required, emulating normal inheritance.
The default implementation looks like this:
my ($self, $pspec) = @_; return ($self->{$pspec->get_name} || $pspec->get_default_value);
"GET_PROPERTY" is different from a C get_property method in that the perl method returns the retrieved value. For symmetry, the $newval and $pspec args on "SET_PROPERTY" are swapped from the C usage. The default get and set methods store property data in the object as hash values named for the parameter name.
The default "SET_PROPERTY" looks like this:
my ($self, $pspec, $newval) = @_; $self->{$pspec->get_name} = $newval;
Use this hook to release anything you have to clean up manually. FINALIZE_INSTANCE will be called for each perl instance, in reverse order of construction.
The default finalizer does nothing.
The DESTROY method of all perl classes derived from GTypes is implemented in the Glib module and (ab-)used for its own internal purposes. Overwriting it is not useful as it will be called multiple times, and often long before the object actually gets destroyed. Overwriting might be very harmful to your program, so never do that. Especially watch out for other classes in your ISA tree.
As of Glib 1.060, you can also specify explicit getters and setters for your properties at creation time. The default values in your properties are also honored if you don't set anything else. See Glib::Type::register_object in Glib::Type for an example.
If not present, the library will attempt to call the method named ``do_signal_name'' for the signal ``signal_name'' (uses underscores).
You'll want to be careful not to let this handler method be a publically callable method, or one that has the name name as something that emits the signal. Due to the funky ways in which Glib is different from Perl, the class closures should not inherit through normal perl inheritance.
If not specified, the default accumulator is used, and you just get the return value of the last handler to run.
Accumulators are not really documented very much in the C reference, and the perl interface here is slightly different, so here's an inordinate amount of detail for this arcane feature:
The accumulator function is called for every handler. It is given three arguments: the signal invocation hint as an anonymous hash (containing the signal name, notably); the current accumulated return value; and the value returned by the most recent handler. The accumulator must return two values: a boolean value determining whether signal emission should continue (false stops the emission), and the new value for the accumulated return value. (This is different from the C version, which writes through the return_accu.)
However, as described above, every signal allows a ``class closure''; you may override thie class closure with your own function, and you can chain from the overridden method to the original. This serves to implement virtual overrides for language bindings.
So, to override a method, you supply a subroutine reference instead of a signal description hash as the value for the name of the existing signal in the ``signals'' hash described in ``SIGNALS''.
# override some important widget methods: use Glib::Object::Subclass Gtk2::Widget::, signals => { expose_event => \&expose_event, configure_event => \&configure_event, button_press_event => \&button_press_event, button_release_event => \&button_release_event, motion_notify_event => \&motion_notify_event, # note the choice of names here... see the discussion. size_request => \&do_size_request, }
It's important to note that the handlers you supply for these are class-specific, and that normal perl method inheritance rules are not followed to invoke them from within the library. However, perl code can still find them! Therefore it's rather important that you choose your handlers' names carefully, avoiding any public interfaces that you might call from perl. Case in point, since size_request is a widget method, i chose do_size_request as the override handler.
In order to derive an object that implements a GInterface, you have to tell the GLib type system you want your class to include a GInterface. To do this, simply pass a list of package names through the ``interfaces'' key; this will add these packages to your @ISA, and cause perl to invoke methods that you must provide.
package Mup::MultilineEntry; use Glib::Object::Subclass 'Gtk2::TextView', interfaces => [ 'Gtk2::CellEditable' ], ;
# perl will now invoke these methods, which are part of the # GtkCellEditable GInterface, when somebody invokes the # corresponding lower-case methods on your objects. sub START_EDITING { warn "start editing\n"; } sub EDITING_DONE { warn "editing done\n"; } sub REMOVE_WIDGET { warn "remove widget\n"; }
GObject - http://developer.gnome.org/doc/API/2.0/gobject/
This library is free software; you can redistribute it and/or modify it under the terms of the Lesser General Public License (LGPL). For more information, see http://www.fsf.org/licenses/lgpl.txt
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |