PROPOSAL: GtkTypeInfo and argument changes



hello everybody.

i'm herewith proposing to move then arg_set_func and arg_get_func function
pointers, currently supplied by the gtk_*_get_type() functions through the
GtkTypeInfo structures, into GtkObjectClass.
the reason they ended up in the GtkTypeInfo structure in the first place is,
a gtk_*_{g|s}et_arg() function is not meant to be overridden by derived
classes like e.g. the GtkObjectClass.destroy function.
i may extend a bit on the process of class creation in this place, in order
to get my intentions across ;)
for instance the contents of a GtkWidgetClass are determined by this creation
process:

1) a GtkObjectClass is allocated by the type system, and initialized with 0's.
   it is then initialized through gtk_object_class_init.

2) a GtkWidgetClass is allocated by the type system, and initialized with 0's.
   the GtkObjectClass portion of the GtkWidgetClass is initialized simply by
   copying the current contents of the previously allocated GtkObjectClass
   (from step 1). a few special members of the GtkObjectClass portion of the
   GtkWidgetClass are reset to certain values, e.g. the `type', `nsignals'
   or `n_args' variables of the GtkObjectClass.
   this is done through the type system directly, which implements special
   knowledge about a few base classes (currently only GtkObjectClass, but
   this is needed for `n_child_args', `set_child_arg' and `get_child_arg'
   of the GtkContainerClass as well).
   hereafter, the GtkWidgetClass gets initialized by gtk_widget_class_init.

certain GtkObjectClass members can now be overridden for the GtkWidgetClass,
e.g. the `destroy' handler, so that widget specific destruction can be
performed, without affecting other GtkObjects that are not widgets, e.g.
GtkTooltips.

so usually, overriding of base class handlers serves a meaningfull purpose
and is actually a wide-spread practice. however, on rare occasions, class
specific handler implementations are required, that cannot be overridden
and add up incrementally.
the object argument handlers GtkArgSetFunc and GtkArgGetFunc are such
handlers. for instance, the object argument "GtkObject::user_data" applied
to a GtkWidget, requires gtk_object_set_arg() to be invoked with the
data structure of the GtkWidget, whereas the "GtkWidget::visible" argument
needs gtk_widget_set_arg() to be invoked with the very structure.
as a consequence, the GtkArgSetFunc is supplied on a per-type basis, and
is always looked up for the corresponding type of an argument, regardless
of any implementations supplied by derived classes.

Note, since the get_child_arg and set_child_arg function pointers of the
GtkContainerClass are not supplied through the type system, and don't get
reset on derived classes creations, the current implementation only works
for *one* container per class branch. this needs to be fixed.

since we wouldn't want to extend the GtkTypeInfo structure incrementally,
everytime the need for a new class-specific and non-overridable handler
arrives, which would require a lot of subsequent additions to existing
widgets, i'd like to modify GtkTypeInfo from the existing

struct _GtkTypeInfo
{
  gchar *type_name;
  guint object_size;
  guint class_size;
  GtkClassInitFunc class_init_func;
  GtkObjectInitFunc object_init_func;
  GtkArgSetFunc arg_set_func;
  GtkArgGetFunc arg_get_func;
};

to

struct _GtkTypeInfo
{
  gchar *type_name;
  guint object_size;
  guint class_size;
  GtkClassInitFunc class_init_func;
  GtkObjectInitFunc object_init_func;
  GtkClassInitFunc base_class_init_func;
  gpointer reserved;
};

and provide GtkArgSetFunc and GtkArgGetFunc through GtkObjectClass.
base_class_init_func will be called for the base types portions of a
derived class upon its allocation. it's purpose is to reset fields
like the above mentioned `nsignals' and `n_args' of GtkObjectClass, or
GtkContainer.n_child_args.

so in the example of the GtkWidgetClass creation, the base_class_init_func
provided by the "GtkObject" type will be invoked for the GtkWidgetClass,
prior to invokation of gtk_widget_class_init().

unfortunately, the proposed change will require all existing
prefix_*_get_type() functions to be modified accordingly. and i guess there
is quite a lot of those out there, which do not reside on the GNOME cvs repo.

a passeble alternative method to modify GtkTypeInfo would be this

struct _GtkTypeInfo
{
  gchar *type_name;
  guint object_size;
  guint class_size;
  GtkClassInitFunc class_init_func;
  GtkObjectInitFunc object_init_func;
  gpointer reversed_1 /* old arg_set_func */;
  gpointer reversed_2 /* old arg_get_func */;
  GtkClassInitFunc base_class_init_func;
};

this will only create problems for widgets that already implement set_arg
and get_arg functions (they will just vanish), which i expect to happen
quite rarely. this would work because the type system will simply
ignore the reversed_1 and reversed_2 pointers, and compilers would
initialize base_class_init_func to (void*)0 implicitely, which is the
current behaviour of the type system anyways (no support for a
base_class_init_func functions ;).
the few people that actually have implemented get_arg and set_arg functions,
would simply assign the function pointers to newly created
GtkObjectClass.get_arg and GtkObjectClass.set_arg members in their
somehing_class_init functions, and they are set.


on another topic, people seem to want to be able to specify argument names,
omitting the type name, e.g.

  hbox =
    gtk_widget_new (GTK_TYPE_HBOX,
                    "GtkBox::homogeneous", TRUE,
                    "GtkBox::spacing", 5,
                    "GtkContainer::border_width", 0,
                    "GtkWidget::visible", TRUE,
                    "GtkWidget::parent", window,
                    "GtkObject::object_signal::destroy", gtk_widget_destroy, window,
                    NULL);
becomes

  hbox =
    gtk_widget_new (GTK_TYPE_HBOX,
                    "homogeneous", TRUE,
                    "spacing", 5,
                    "border_width", 0,
                    "visible", TRUE,
                    "parent", window,
                    "object_signal::destroy", gtk_widget_destroy, window,
                    NULL);

which is actually possible, given that argument names are attempted to
match a certain class or one of its parent classes.
this will require only a minor change to the publically exported

GtkType gtk_object_get_arg_type (const gchar *arg_name);

along the lines of

GtkType gtk_object_get_arg_type (GtkType object_type, const gchar *arg_name);

and an additional `object_type' argument for gtk_object_collect_args(), which
isn't exported through the gtk header files, though as a non-static function,
it is provided as a library symbol.
gtk_object_get_arg_type() will then lookup `arg_name' in the ususall manner,
and if the type qualifier was omitted, it'll try to lookup the argument name
for the `object_type' class and all its parents.


i'm curious towards people's responses, since the first proposed change
is a rather drastic source incompatible one.


---
ciaoTJ



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