Re: an additional argument flag




Kenneth Albanowski <kjahds@kjahds.com> writes:

> On 22 Feb 1998, Tero Pulkkinen wrote:
> 
> > Deriving from widgets is the only thing we need to do with gtk--. No
> > black magic involved. Deriving from widgets currently requires that
> > we rewrite all *_new() methods. On some widgets this cut/paste is kinda
> > large as there is static methods called from *_new() methods :)
> 
> Have you found some way of deal with class signals (or whatever you want
> to call the signal slots that are held in the class object) in a
> reasonable manner? Then again, C++ isn't an interpreter, so you won't have
> many of the difficulties I ran into with Perl. 

I think the difficulty that you are referring to is that you
want to override the default handlers, but the default handlers
don't go through the marshalling system.

I think there is a an easy solution to this:

Signal handlers are called in the order:

     default handlers of type RUN_FIRST or RUN_BOTH

     signals connected normally

     default handlers of type RUN_AFTER or RUN_BOTH.

     signals connect "after"

Also, signals connected for a certain type are run in the
order connected. So to override a signal, that is say RUN_AFTER,
for a Foo widget, you use a (GTK) class derived from Foo, and
"simply" zero out the default handler, and attach your substitute
"after". (default handler = NULL, means no default handler)

There are some details to be worked out, but that is the general
scheme. You probably don't want to follow gtk-- and hook
every default handler through Perl, because there would be
too much overhead - instead I would use something like:

@MyFoo::ISA = qw(Gtk::Foo);

sub new {
   my $pkg = shift;
   my $self = $pkg->SUPER::new();

   $self->override ("realize" => \&my_realize,
                    "size_request" => \&my_size_request);
}

The big problem is to simulate things, that in C look like:

static void
gtk_menu_item_destroy (GtkObject *object)
{
  GtkMenuItem *menu_item;

  g_return_if_fail (object != NULL);
  g_return_if_fail (GTK_IS_MENU_ITEM (object));

  menu_item = GTK_MENU_ITEM (object);

  if (menu_item->submenu)
    gtk_widget_destroy (menu_item->submenu);

  if (GTK_OBJECT_CLASS (parent_class)->destroy)
    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}

The problem is that last line - basically it either requires writing
some customf XS code for each signal, or marshalling the arguments
back from Perl into a GtkArgs structure than calling the C Marshaller
for the signal on the parent's default handler.

If there was a way of connecting a signal handler before
a "RUN_FIRST" handler, there would be an easy, if inelegant
way of handling such chaining - simply, if the signal handler
is chained, don't NULL out the default handler for the overriden
signal. But adding signals that are connected "before" is
not really an attractive possibility - this would approximately
increase overhead by 50% for every signal emission.

GTK definitely wasn't designed to allow deriving new widget
types in interpreted languages (or any language other than C) -
and I'm somewhat dubious of the worthwhile-ness of the goal.
The multi-lingual nature of GTK will be best served if new
widgets are written in C. On the other hand, if people
want to do it, there should be a way.

Regards,
                                        Owen



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