GLADE and GtkContainer... replacing children



Hi, I'd like to propose an child replace function to GtkContainer, instead of 
having one large function that checks to see what kind of GtkContainer it is 
and then replacing its child. This way each GtkContainer class can have its 
own implementation of replacing a child with out GLADE (or other programs) 
having to know each type of container there is, so if a new type of container 
is added or an old type of container is altered then GLADE does not have to 
be completely aware of this to operate with it (more seemless). This is how I 
see it changing...

///////////in gtkcontainer.h :

struct _GtkContainerClass
{
  GtkWidgetClass parent_class;
  
  guint   n_child_args;

  void (* add)              (GtkContainer    *container,
                 GtkWidget   *widget);
  void (* remove)           (GtkContainer    *container,
                 GtkWidget   *widget);
  void (* check_resize)     (GtkContainer    *container);
  void (* forall)           (GtkContainer    *container,
                 gboolean     include_internals,
                 GtkCallback      callback,
                 gpointer     callbabck_data);
  gint (* focus)            (GtkContainer    *container,
                 GtkDirectionType  direction);
  void (* set_focus_child)  (GtkContainer    *container,
                 GtkWidget   *widget);
  GtkType (*child_type)     (GtkContainer   *container);
  void    (*set_child_arg)  (GtkContainer   *container,
                 GtkWidget      *child,
                 GtkArg         *arg,
                 guint           arg_id);
  void    (*get_child_arg)  (GtkContainer   *container,
                 GtkWidget      *child,
                 GtkArg         *arg,
                 guint           arg_id);
  gchar*  (*composite_name) (GtkContainer   *container,
                 GtkWidget  *child);
  void (* replace)          (GtkContainer    *container,
                 GtkWidget   *child,
                 GtkWidget   *replacement);

  /* Padding for future expansion */
  GtkFunction pad1;
  GtkFunction pad2;
};

////////

void    gtk_container_replace        (GtkContainer     *container,
                      GtkWidget    *child,
                      GtkWidget    *replace);

///////////in gtkcontainer.c :

static void gtk_container_replace_unimplemented (GtkContainer      *container,
                         GtkWidget         *child,
                         GtkWidget         *replacement);

///////

  class->replace = gtk_container_replace_unimplemented;

///////

static void
gtk_container_add_unimplemented (GtkContainer     *container,
                         GtkWidget         *child,
                         GtkWidget         *replacement)
{
  g_warning ("GtkContainerClass::add not implemented for `%s'", gtk_type_name 
(GTK_OBJECT_TYPE (container)));
}

///////

void
gtk_container_add (GtkContainer *container,
           GtkWidget    *child,
           GtkWidget    *replacement)
{
  GtkContainerClass *class;

  g_return_if_fail (container != NULL);
  g_return_if_fail (GTK_IS_CONTAINER (container));
  g_return_if_fail (child != NULL);
  g_return_if_fail (GTK_IS_WIDGET (child));
  g_return_if_fail (replacement != NULL);
  g_return_if_fail (GTK_IS_WIDGET (replacement));
  g_return_if_fail (replacement->parent == NULL);

  class = GTK_CONTAINER_GET_CLASS (container);

  if (!GTK_OBJECT_CONSTRUCTED (replacement))
    gtk_object_default_construct (GTK_OBJECT (replacement));
  if (class->replace)
    class->replace (container, child, replacement);
}

///////////in gtkbin.c :

static void gtk_bin_replace     (GtkContainer   *container,
                 GtkWidget   *child,
                 GtkWidget   *replacement);

///////

  container_class->replace = gtk_bin_replace;

///////

static void
gtk_bin_replace (GtkContainer *container,
         GtkWidget   *child,
         GtkWidget   *replacement)
{
  g_return_if_fail (container != NULL);
  g_return_if_fail (GTK_IS_BIN (container));
  g_return_if_fail (child != NULL);
  g_return_if_fail (replacement != NULL);

  gtk_container_remove (GTK_CONTAINER (container), child);
  gtk_container_add (GTK_CONTAINER (container), replacement);
}

///////////in gtkbox.c :

static void gtk_box_replace     (GtkContainer   *container,
                 GtkWidget   *child,
                 GtkWidget   *replacement);

///////

  container_class->replace = gtk_box_replace;

///////

static void
gtk_box_replace (GtkContainer *container,
         GtkWidget   *child,
         GtkWidget   *replacement)
{
  gboolean expand, fill;
  guint padding;
  GtkPackType pack_type;
  gint pos;
  GList *children;
  GtkBoxChild *boxchild;
  GtkBox *box;

  g_return_if_fail (container != NULL);
  g_return_if_fail (GTK_IS_BOX (container));
  g_return_if_fail (child != NULL);
  g_return_if_fail (replacement != NULL);

  box = GTK_BOX (container);
  for (children = box->children; children; children = children->next, pos++)
    {
      boxchild = children->data;
      if (widget == boxchild->widget)
        {
      break;
        }
    }
  g_return_if_fail (child == boxchild->widget);

  gtk_box_query_child_packing (box, child,
                   &expand, &fill, &padding, &pack_type);

  gtk_container_remove (GTK_CONTAINER (widget), child);
  gtk_container_add (GTK_CONTAINER (widget), replacement);

  gtk_box_set_child_packing (box, replacement, expand, fill,
                 padding, pack_type);
  gtk_box_reorder_child (box, replacement, pos);
}


Well, I think you get the idea (I mostly got this code from GLADEs 
gb_widget_replace_child function), since I do not have write access to the 
repository and I do not know if someone is doing this already, I'm not sure 
how much I should do here. This will help GLADE, I'm pretty sure, from having 
to have specific code for each type of container widget. It will also help a 
project I am starting to develope which is similar to GLADE (a diffrent 
aproach that GLADE may benefit from).

Leyland Needham




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