]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkbox.c
do not avoid to queue for a resize if the container is not visible, we
[~andy/gtk] / gtk / gtkbox.c
index dfb2fed087c9b52a3a965e94cc5c9c692d0f6a10..0b0b0a58fc374a9169af6c1cb8fdf486a88cfd10 100644 (file)
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
  */
 #include "gtkbox.h"
 
+enum {
+  ARG_0,
+  ARG_SPACING,
+  ARG_HOMOGENEOUS
+};
+
+enum {
+  CHILD_ARG_0,
+  CHILD_ARG_EXPAND,
+  CHILD_ARG_FILL,
+  CHILD_ARG_PADDING,
+  CHILD_ARG_PACK_TYPE,
+  CHILD_ARG_POSITION
+};
 
 static void gtk_box_class_init (GtkBoxClass    *klass);
 static void gtk_box_init       (GtkBox         *box);
-static void gtk_box_destroy    (GtkObject      *object);
+static void gtk_box_get_arg    (GtkBox         *box,
+                               GtkArg         *arg,
+                               guint           arg_id);
+static void gtk_box_set_arg    (GtkBox         *box,
+                               GtkArg         *arg,
+                               guint           arg_id);
 static void gtk_box_map        (GtkWidget      *widget);
 static void gtk_box_unmap      (GtkWidget      *widget);
 static void gtk_box_draw       (GtkWidget      *widget,
@@ -34,15 +54,24 @@ static void gtk_box_remove     (GtkContainer   *container,
 static void gtk_box_foreach    (GtkContainer   *container,
                                GtkCallback     callback,
                                gpointer        callback_data);
-
+static void gtk_box_set_child_arg (GtkContainer   *container,
+                                  GtkWidget      *child,
+                                  GtkArg         *arg,
+                                  guint           arg_id);
+static void gtk_box_get_child_arg (GtkContainer   *container,
+                                  GtkWidget      *child,
+                                  GtkArg         *arg,
+                                  guint           arg_id);
+static GtkType gtk_box_child_type (GtkContainer   *container);
+     
 
 static GtkContainerClass *parent_class = NULL;
 
 
-guint
-gtk_box_get_type ()
+GtkType
+gtk_box_get_type (void)
 {
-  static guint box_type = 0;
+  static GtkType box_type = 0;
 
   if (!box_type)
     {
@@ -53,10 +82,11 @@ gtk_box_get_type ()
        sizeof (GtkBoxClass),
        (GtkClassInitFunc) gtk_box_class_init,
        (GtkObjectInitFunc) gtk_box_init,
-       (GtkArgFunc) NULL,
+       (GtkArgSetFunc) gtk_box_set_arg,
+        (GtkArgGetFunc) gtk_box_get_arg,
       };
 
-      box_type = gtk_type_unique (gtk_container_get_type (), &box_info);
+      box_type = gtk_type_unique (GTK_TYPE_CONTAINER, &box_info);
     }
 
   return box_type;
@@ -73,9 +103,15 @@ gtk_box_class_init (GtkBoxClass *class)
   widget_class = (GtkWidgetClass*) class;
   container_class = (GtkContainerClass*) class;
 
-  parent_class = gtk_type_class (gtk_container_get_type ());
+  parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
 
-  object_class->destroy = gtk_box_destroy;
+  gtk_object_add_arg_type ("GtkBox::spacing", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_SPACING);
+  gtk_object_add_arg_type ("GtkBox::homogeneous", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HOMOGENEOUS);
+  gtk_container_add_child_arg_type ("GtkBox::expand", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_EXPAND);
+  gtk_container_add_child_arg_type ("GtkBox::fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_FILL);
+  gtk_container_add_child_arg_type ("GtkBox::padding", GTK_TYPE_ULONG, GTK_ARG_READWRITE, CHILD_ARG_PADDING);
+  gtk_container_add_child_arg_type ("GtkBox::pack_type", GTK_TYPE_PACK_TYPE, GTK_ARG_READWRITE, CHILD_ARG_PACK_TYPE);
+  gtk_container_add_child_arg_type ("GtkBox::position", GTK_TYPE_LONG, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
 
   widget_class->map = gtk_box_map;
   widget_class->unmap = gtk_box_unmap;
@@ -85,6 +121,9 @@ gtk_box_class_init (GtkBoxClass *class)
   container_class->add = gtk_box_add;
   container_class->remove = gtk_box_remove;
   container_class->foreach = gtk_box_foreach;
+  container_class->child_type = gtk_box_child_type;
+  container_class->set_child_arg = gtk_box_set_child_arg;
+  container_class->get_child_arg = gtk_box_get_child_arg;
 }
 
 static void
@@ -97,18 +136,179 @@ gtk_box_init (GtkBox *box)
   box->homogeneous = FALSE;
 }
 
+static void
+gtk_box_set_arg (GtkBox       *box,
+                GtkArg       *arg,
+                guint         arg_id)
+{
+  switch (arg_id)
+    {
+    case ARG_SPACING:
+      gtk_box_set_spacing (box, GTK_VALUE_INT (*arg));
+      break;
+    case ARG_HOMOGENEOUS:
+      gtk_box_set_homogeneous (box, GTK_VALUE_BOOL (*arg));
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+gtk_box_get_arg (GtkBox       *box,
+                GtkArg       *arg,
+                guint         arg_id)
+{
+  switch (arg_id)
+    {
+    case ARG_SPACING:
+      GTK_VALUE_INT (*arg) = box->spacing;
+      break;
+    case ARG_HOMOGENEOUS:
+      GTK_VALUE_BOOL (*arg) = box->homogeneous;
+      break;
+    default:
+      arg->type = GTK_TYPE_INVALID;
+      break;
+    }
+}
+
+static GtkType
+gtk_box_child_type     (GtkContainer   *container)
+{
+  return GTK_TYPE_WIDGET;
+}
+
+static void
+gtk_box_set_child_arg (GtkContainer   *container,
+                      GtkWidget      *child,
+                      GtkArg         *arg,
+                      guint           arg_id)
+{
+  gboolean expand = 0;
+  gboolean fill = 0;
+  guint padding = 0;
+  GtkPackType pack_type = 0;
+
+  if (arg_id != CHILD_ARG_POSITION)
+    gtk_box_query_child_packing (GTK_BOX (container),
+                                child,
+                                &expand,
+                                &fill,
+                                &padding,
+                                &pack_type);
+  
+  switch (arg_id)
+    {
+    case CHILD_ARG_EXPAND:
+      gtk_box_set_child_packing (GTK_BOX (container),
+                                child,
+                                GTK_VALUE_BOOL (*arg),
+                                fill,
+                                padding,
+                                pack_type);
+      break;
+    case CHILD_ARG_FILL:
+      gtk_box_set_child_packing (GTK_BOX (container),
+                                child,
+                                expand,
+                                GTK_VALUE_BOOL (*arg),
+                                padding,
+                                pack_type);
+      break;
+    case CHILD_ARG_PADDING:
+      gtk_box_set_child_packing (GTK_BOX (container),
+                                child,
+                                expand,
+                                fill,
+                                GTK_VALUE_ULONG (*arg),
+                                pack_type);
+      break;
+    case CHILD_ARG_PACK_TYPE:
+      gtk_box_set_child_packing (GTK_BOX (container),
+                                child,
+                                expand,
+                                fill,
+                                padding,
+                                GTK_VALUE_ENUM (*arg));
+      break;
+    case CHILD_ARG_POSITION:
+      gtk_box_reorder_child (GTK_BOX (container),
+                            child,
+                            GTK_VALUE_LONG (*arg));
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+gtk_box_get_child_arg (GtkContainer   *container,
+                      GtkWidget      *child,
+                      GtkArg         *arg,
+                      guint           arg_id)
+{
+  gboolean expand = 0;
+  gboolean fill = 0;
+  guint padding = 0;
+  GtkPackType pack_type = 0;
+  GList *list;
+
+  if (arg_id != CHILD_ARG_POSITION)
+    gtk_box_query_child_packing (GTK_BOX (container),
+                                child,
+                                &expand,
+                                &fill,
+                                &padding,
+                                &pack_type);
+  
+  switch (arg_id)
+    {
+    case CHILD_ARG_EXPAND:
+      GTK_VALUE_BOOL (*arg) = expand;
+      break;
+    case CHILD_ARG_FILL:
+      GTK_VALUE_BOOL (*arg) = fill;
+      break;
+    case CHILD_ARG_PADDING:
+      GTK_VALUE_ULONG (*arg) = padding;
+      break;
+    case CHILD_ARG_PACK_TYPE:
+      GTK_VALUE_ENUM (*arg) = pack_type;
+      break;
+    case CHILD_ARG_POSITION:
+      GTK_VALUE_LONG (*arg) = 0;
+      for (list = GTK_BOX (container)->children; list; list = list->next)
+       {
+         GtkBoxChild *child_entry;
+
+         child_entry = list->data;
+         if (child_entry->widget == child)
+           break;
+         GTK_VALUE_LONG (*arg)++;
+       }
+      if (!list)
+       GTK_VALUE_LONG (*arg) = -1;
+      break;
+    default:
+      arg->type = GTK_TYPE_INVALID;
+      break;
+    }
+}
+
 void
 gtk_box_pack_start (GtkBox    *box,
                    GtkWidget *child,
-                   gint       expand,
-                   gint       fill,
-                   gint       padding)
+                   gboolean   expand,
+                   gboolean   fill,
+                   guint      padding)
 {
   GtkBoxChild *child_info;
 
   g_return_if_fail (box != NULL);
   g_return_if_fail (GTK_IS_BOX (box));
   g_return_if_fail (child != NULL);
+  g_return_if_fail (child->parent == NULL);
 
   child_info = g_new (GtkBoxChild, 1);
   child_info->widget = child;
@@ -139,15 +339,16 @@ gtk_box_pack_start (GtkBox    *box,
 void
 gtk_box_pack_end (GtkBox    *box,
                  GtkWidget *child,
-                 gint       expand,
-                 gint       fill,
-                 gint       padding)
+                 gboolean   expand,
+                 gboolean   fill,
+                 guint      padding)
 {
   GtkBoxChild *child_info;
 
   g_return_if_fail (box != NULL);
   g_return_if_fail (GTK_IS_BOX (box));
   g_return_if_fail (child != NULL);
+  g_return_if_fail (child->parent == NULL);
 
   child_info = g_new (GtkBoxChild, 1);
   child_info->widget = child;
@@ -198,8 +399,8 @@ gtk_box_pack_end_defaults (GtkBox    *box,
 }
 
 void
-gtk_box_set_homogeneous (GtkBox *box,
-                        gint    homogeneous)
+gtk_box_set_homogeneous (GtkBox  *box,
+                        gboolean homogeneous)
 {
   g_return_if_fail (box != NULL);
   g_return_if_fail (GTK_IS_BOX (box));
@@ -225,35 +426,145 @@ gtk_box_set_spacing (GtkBox *box,
     }
 }
 
-
-static void
-gtk_box_destroy (GtkObject *object)
+void
+gtk_box_reorder_child (GtkBox                   *box,
+                      GtkWidget                *child,
+                      gint                      position)
 {
-  GtkBox *box;
-  GtkBoxChild *child;
-  GList *children;
+  GList *list;
 
-  g_return_if_fail (object != NULL);
-  g_return_if_fail (GTK_IS_BOX (object));
+  g_return_if_fail (box != NULL);
+  g_return_if_fail (GTK_IS_BOX (box));
+  g_return_if_fail (child != NULL);
 
-  box = GTK_BOX (object);
+  list = box->children;
+  while (list)
+    {
+      GtkBoxChild *child_info;
 
-  children = box->children;
-  while (children)
+      child_info = list->data;
+      if (child_info->widget == child)
+       break;
+
+      list = list->next;
+    }
+
+  if (list && box->children->next)
     {
-      child = children->data;
-      children = children->next;
+      GList *tmp_list;
+
+      if (list->next)
+       list->next->prev = list->prev;
+      if (list->prev)
+       list->prev->next = list->next;
+      else
+       box->children = list->next;
 
-      child->widget->parent = NULL;
-      gtk_object_unref (GTK_OBJECT (child->widget));
-      gtk_widget_destroy (child->widget);
-      g_free (child);
+      tmp_list = box->children;
+      while (position && tmp_list->next)
+       {
+         position--;
+         tmp_list = tmp_list->next;
+       }
+
+      if (position)
+       {
+         tmp_list->next = list;
+         list->prev = tmp_list;
+         list->next = NULL;
+       }
+      else
+       {
+         if (tmp_list->prev)
+           tmp_list->prev->next = list;
+         else
+           box->children = list;
+         list->prev = tmp_list->prev;
+         tmp_list->prev = list;
+         list->next = tmp_list;
+       }
+
+      if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
+       gtk_widget_queue_resize (child);
     }
+}
 
-  g_list_free (box->children);
+void
+gtk_box_query_child_packing (GtkBox             *box,
+                            GtkWidget          *child,
+                            gboolean           *expand,
+                            gboolean           *fill,
+                            guint              *padding,
+                            GtkPackType        *pack_type)
+{
+  GList *list;
+  GtkBoxChild *child_info;
 
-  if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+  g_return_if_fail (box != NULL);
+  g_return_if_fail (GTK_IS_BOX (box));
+  g_return_if_fail (child != NULL);
+
+  list = box->children;
+  while (list)
+    {
+      child_info = list->data;
+      if (child_info->widget == child)
+       break;
+
+      list = list->next;
+    }
+
+  if (list)
+    {
+      if (expand)
+       *expand = child_info->expand;
+      if (fill)
+       *fill = child_info->fill;
+      if (padding)
+       *padding = child_info->padding;
+      if (pack_type)
+       *pack_type = child_info->pack;
+    }
+}
+
+void
+gtk_box_set_child_packing (GtkBox               *box,
+                          GtkWidget            *child,
+                          gboolean              expand,
+                          gboolean              fill,
+                          guint                 padding,
+                          GtkPackType           pack_type)
+{
+  GList *list;
+  GtkBoxChild *child_info;
+
+  g_return_if_fail (box != NULL);
+  g_return_if_fail (GTK_IS_BOX (box));
+  g_return_if_fail (child != NULL);
+
+  list = box->children;
+  while (list)
+    {
+      child_info = list->data;
+      if (child_info->widget == child)
+       break;
+
+      list = list->next;
+    }
+
+  if (list)
+    {
+      child_info->expand = expand != FALSE;
+      child_info->fill = fill != FALSE;
+      child_info->padding = padding;
+      if (pack_type == GTK_PACK_END)
+       child_info->pack = GTK_PACK_END;
+      else
+       child_info->pack = GTK_PACK_START;
+
+      if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
+       gtk_widget_queue_resize (child);
+    }
 }
 
 static void
@@ -400,13 +711,19 @@ gtk_box_remove (GtkContainer *container,
 
       if (child->widget == widget)
        {
+         gboolean was_visible;
+
+         was_visible = GTK_WIDGET_VISIBLE (widget);
          gtk_widget_unparent (widget);
 
          box->children = g_list_remove_link (box->children, children);
          g_list_free (children);
          g_free (child);
 
-         if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+         /* queue resize regardless of GTK_WIDGET_VISIBLE (container),
+          * since that's what is needed by toplevels.
+          */
+         if (was_visible)
            gtk_widget_queue_resize (GTK_WIDGET (container));
 
          break;