Re: [Language Binders] Re: Chaining Class Closures



On Tue, 30 Oct 2001, James Henstridge wrote:

>   class PythonWidget(gtk.Widget):
>       def do_show(self, invocation_hint):
>           print "show!"
>           return invocation_hint()  # or possibly pass the self arg as well?
>   gobject.type_register(PythonWidget)
>   gobject.override_class_closure(PythonWidget, 'show')
> 
> I might make this simpler in the future by making gobject.type_register 
> search for signals to override (list all signals of the parent class, 
> check for equivalent methods on the new class).  However, this would 
> require initialising the class structure of every type that gets 
> overriden on startup.  I don't yet know if that is acceptable.
> 
> One thing which isn't completely clear is whether 
> g_signal_chain_from_overridden chains up to the direct parent, or to the 
> class above where the class where the signal closure was overriden.  I 
> would prefer that it goes up to the previous class closure, so that 
> overriding an already overriden signal in python is a bit easier:
>   class PythonWidget2(PythonWidget):
>       def show(self, invocation_hint):
>           print "chaining up to PythonWidget"
>           return PythonWidget.show(self, invocation_hint)
>   gobject.type_register(PythonWidget2)
> 
> If g_signal_chain_from_overriden chained up to the next class, the 
> procedure would go:
>   PythonWidget2.show called by signal class closure marshal
>   PythonWidget.show called by PythonWidget2.show
>   invocation_hint() executed, calling class closure for PythonWidget class
>   PythonWidget2.show called by signal class closure marshal
>   PythonWidget.show called by PythonWidget2.show
>   invocation_hint() executed, calling class closure for GtkWidget class
>   gtk_widget_real_show() called

erm, i can't make too much sense of this, why would PythonWidget2.show
be called twice?

in any case, i think i can make things clearer by telling how the signal system
should handle this, suppose you derive:
A<-B<-C<-D<-E<-F
and install closures (through signal_new() or g_signal_override_class_closure(),
internally, that's the same):
add_closure (A, Aclosure);
add_closure (C, Cclosure);
add_closure (E, Eclosure);

with Eclosure doing { chain (invocation_hint); }
and Cclosure doing { chain (invocation_hint); }

then things should work as follows:

emitting signal on object of type F:
  type = F; closure = NULL;
  while (!closure) {
    closure = fetch_closure (type);
    type = parent_type (type);
  }
  invocation_hint->type = type;
  /* this ends up with:
   * closure == Eclosure and
   * invocation_hint->type == D, since
   * there was no closure added to F, and because
   * D is parent type of E
   */
  closure(invocation_hint);

chaining from Eclosure:
  type = invocation_hint->type; /* D */
  closure = NULL;
  while (!closure) {
    closure = fetch_closure (type);
    type = parent_type (type);
  }
  invocation_hint->type = type;
  /* this ends up with:
   * closure == Cclosure;
   * invocation_hint->type == B
   */

and finally chaining from Cclosure:
  type = invocation_hint->type; /* B */
  closure = NULL;
  while (!closure) {
    closure = fetch_closure (type);
    type = parent_type (type);
  }
  invocation_hint->type = type;
  /* this ends up with:
   * closure == Aclosure;
   * invocation_hint->type == 0
   */

> If g_signal_chain_from_overriden immediately chains to GtkWidget's 
> implementation, everything should work fine.

when calling a function implemented by a certain type,
g_signal_chain_from_overriden() will chain up to the nextmost parent type
which provides a closure. so as long as you override every gtk-created
signal only once, the nextmost parent type providing a closure should always
be a gtk implemented widget.

> 
> James.
> 

---
ciaoTJ





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