[glade] GtkGrid/GtkBox: Bring back use of GladeFixed. It wont interfere with GladeDesignLayout drag&drop b



commit 4338b2d98bc260e1479f5110aa3855429f767c33
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date:   Mon Apr 1 18:45:29 2013 -0300

    GtkGrid/GtkBox: Bring back use of GladeFixed.
      It wont interfere with GladeDesignLayout drag&drop because it does not use
      GLADE_POINTER_DRAG_RESIZE and GDK_SHIFT_MASK anymore.

 plugins/gtk+/glade-gtk-grid.c |  545 ++++++++++++++++++++++++++++++++++-------
 plugins/gtk+/glade-gtk.c      |  225 +++++++++++++++++
 plugins/gtk+/gtk+.xml.in      |    3 +
 3 files changed, 690 insertions(+), 83 deletions(-)
---
diff --git a/plugins/gtk+/glade-gtk-grid.c b/plugins/gtk+/glade-gtk-grid.c
index 916f41d..63b250d 100644
--- a/plugins/gtk+/glade-gtk-grid.c
+++ b/plugins/gtk+/glade-gtk-grid.c
@@ -31,6 +31,16 @@
 
 typedef struct
 {
+  /* comparable part: */
+  GladeWidget *widget;
+  gint left_attach;
+  gint top_attach;
+  gint width;
+  gint height;
+} GladeGridChild;
+
+typedef struct
+{
   gint left_attach;
   gint top_attach;
   gint width;
@@ -45,17 +55,20 @@ typedef enum
   DIR_RIGHT
 } GladeGridDir;
 
+static GladeGridChild grid_edit = { 0, };
+static GladeGridChild grid_cur_attach = { 0, };
+
 static void
 glade_gtk_grid_get_child_attachments (GtkWidget            *grid,
-                                     GtkWidget            *child,
-                                     GladeGridAttachments *grid_child)
+                                      GtkWidget            *child,
+                                      GladeGridAttachments *grid_child)
 {
   gtk_container_child_get (GTK_CONTAINER (grid), child,
                            "left-attach", &grid_child->left_attach,
                            "width",       &grid_child->width,
                            "top-attach",  &grid_child->top_attach,
                            "height",      &grid_child->height,
-                          NULL);
+                           NULL);
 }
 
 static gboolean
@@ -75,7 +88,7 @@ glade_gtk_grid_has_child (GtkGrid *grid,
       glade_gtk_grid_get_child_attachments (GTK_WIDGET (grid), widget, &attach);
 
       if (left_attach >= attach.left_attach && left_attach < attach.left_attach + attach.width && 
-         top_attach  >= attach.top_attach  && top_attach  < attach.top_attach  + attach.height)
+          top_attach  >= attach.top_attach  && top_attach  < attach.top_attach  + attach.height)
         {
           ret = TRUE;
           break;
@@ -87,7 +100,7 @@ glade_gtk_grid_has_child (GtkGrid *grid,
 
 static void
 glade_gtk_grid_refresh_placeholders (GtkGrid *grid,
-                                    gboolean load_finished)
+                                     gboolean load_finished)
 {
   GladeWidget *widget;
   GladeProject *project;
@@ -101,7 +114,7 @@ glade_gtk_grid_refresh_placeholders (GtkGrid *grid,
 
   /* Wait for project to finish loading */
   if (glade_project_is_loading (project) && !load_finished)
-       return;
+    return;
 
   glade_widget_property_get (widget, "n-columns", &n_columns);
   glade_widget_property_get (widget, "n-rows", &n_rows);
@@ -128,6 +141,355 @@ glade_gtk_grid_refresh_placeholders (GtkGrid *grid,
   g_list_free (children);
 }
 
+/* Takes a point (x or y depending on 'row') relative to
+* grid, and returns the row or column in which the point
+* was found.
+*/
+static gint
+glade_gtk_grid_get_row_col_from_point (GtkGrid *grid, gboolean row, gint point)
+{
+  GladeGridAttachments attach;
+  GtkAllocation allocation;
+  GList *list, *children;
+  gint span, trans_point, size, base, end;
+
+  children = gtk_container_get_children (GTK_CONTAINER (grid));
+
+  for (list = children; list; list = list->next)
+    {
+      GtkWidget *widget = list->data;
+
+      glade_gtk_grid_get_child_attachments (GTK_WIDGET (grid), widget, &attach);
+
+      if (row)
+        gtk_widget_translate_coordinates (GTK_WIDGET (grid), widget, 0, point, NULL, &trans_point);
+      else
+        gtk_widget_translate_coordinates (GTK_WIDGET (grid), widget, point, 0, &trans_point, NULL);
+
+      gtk_widget_get_allocation (widget, &allocation);
+
+      /* Find any widget in our row/column
+       */
+      end = row ? allocation.height : allocation.width;
+
+      if (trans_point >= 0 &&
+          /* should be trans_point < end ... test FIXME ! */
+          trans_point < end)
+        {
+          base = row ? attach.top_attach : attach.left_attach;
+          size = row ? allocation.height : allocation.width;
+          span = row ? attach.height     : attach.width;
+
+          return base + (trans_point * span / size);
+        }
+    }
+
+  g_list_free (children);
+
+  return -1;
+}
+
+
+static gboolean
+glade_gtk_grid_point_crosses_threshold (GtkGrid     *grid,
+                                        gboolean     row,
+                                        gint         num,
+                                        GladeGridDir dir, 
+                                        gint         point)
+{
+  GladeGridAttachments attach;
+  GtkAllocation allocation;
+  GList *list, *children;
+  gint span, trans_point, size, rowcol_size, base;
+
+  children = gtk_container_get_children (GTK_CONTAINER (grid));
+
+  for (list = children; list; list = list->next)
+    {
+      GtkWidget *widget = list->data;
+
+      glade_gtk_grid_get_child_attachments (GTK_WIDGET (grid), widget, &attach);
+
+      /* Find any widget in our row/column
+       */
+      if ((row  && num >= attach.top_attach  && num < attach.top_attach  + attach.height) ||
+          (!row && num >= attach.left_attach && num < attach.left_attach + attach.width))
+        {
+
+          if (row)
+            gtk_widget_translate_coordinates (GTK_WIDGET (grid), widget, 0, point, NULL, &trans_point);
+          else
+            gtk_widget_translate_coordinates (GTK_WIDGET (grid), widget, point, 0, &trans_point, NULL);
+
+          span = row ? attach.height : attach.width;
+          gtk_widget_get_allocation (widget, &allocation);
+          size = row ? allocation.height : allocation.width;
+
+          base = row ? attach.top_attach : attach.left_attach;
+          rowcol_size = size / span;
+          trans_point -= (num - base) * rowcol_size;
+
+#if 0
+          g_print ("dir: %s, widget size: %d, rowcol size: %d, "
+                   "requested rowcol: %d, widget base rowcol: %d, trim: %d, "
+                   "widget point: %d, thresh: %d\n",
+                   dir == DIR_UP ? "up" : dir == DIR_DOWN ? "down" :
+                     dir == DIR_LEFT ? "left" : "right",
+                     size, rowcol_size, num, base, (num - base) * rowcol_size,
+                     trans_point,
+                     dir == DIR_UP || dir == DIR_LEFT ?
+                     (rowcol_size / 2) : (rowcol_size / 2));
+#endif
+          switch (dir)
+            {
+              case DIR_UP:
+              case DIR_LEFT:
+                return trans_point <= (rowcol_size / 2);
+              case DIR_DOWN:
+              case DIR_RIGHT:
+                return trans_point >= (rowcol_size / 2);
+              default:
+                break;
+            }
+        }
+
+    }
+
+  g_list_free (children);
+
+  return FALSE;
+}
+
+static gboolean
+glade_gtk_grid_get_attachments (GladeFixed        *fixed,
+                                GtkGrid           *grid,
+                                GdkRectangle      *rect,
+                                GladeGridChild    *configure)
+{
+  GladeWidget *widget = GLADE_WIDGET (fixed);
+  gint center_x, center_y, row, column;
+  guint n_columns, n_rows;
+
+  center_x = rect->x + (rect->width / 2);
+  center_y = rect->y + (rect->height / 2);
+
+  column = glade_gtk_grid_get_row_col_from_point (grid, FALSE, center_x);
+  row    = glade_gtk_grid_get_row_col_from_point (grid, TRUE, center_y);
+
+  /* its a start, now try to grow when the rect extents
+   * reach at least half way into the next row/column 
+   */
+  configure->left_attach   = column;
+  configure->width         = 1;
+  configure->top_attach    = row;
+  configure->height        = 1;
+
+  glade_widget_property_get (widget, "n-columns", &n_columns);
+  glade_widget_property_get (widget, "n-rows", &n_rows);
+
+  if (column >= 0 && row >= 0)
+    {
+      /* Check and expand left
+       */
+      while (configure->left_attach > 0)
+        {
+          if (rect->x < fixed->child_x_origin &&
+              fixed->operation != GLADE_CURSOR_DRAG &&
+              GLADE_FIXED_CURSOR_LEFT (fixed->operation) == FALSE)
+            break;
+
+          if (glade_gtk_grid_point_crosses_threshold
+              (grid, FALSE, configure->left_attach - 1,
+               DIR_LEFT, rect->x) == FALSE)
+            break;
+
+          configure->left_attach--;
+        }
+
+      /* Check and expand right
+       */
+      while (configure->left_attach + configure->width < n_columns)
+        {
+          if (rect->x + rect->width >
+              fixed->child_x_origin + fixed->child_width_origin &&
+              fixed->operation != GLADE_CURSOR_DRAG &&
+              GLADE_FIXED_CURSOR_RIGHT (fixed->operation) == FALSE)
+            break;
+
+          if (glade_gtk_grid_point_crosses_threshold
+              (grid, FALSE, configure->left_attach + configure->width,
+               DIR_RIGHT, rect->x + rect->width) == FALSE)
+            break;
+
+          configure->width++;
+        }
+
+      /* Check and expand top
+       */
+      while (configure->top_attach > 0)
+        {
+          if (rect->y < fixed->child_y_origin &&
+              fixed->operation != GLADE_CURSOR_DRAG &&
+              GLADE_FIXED_CURSOR_TOP (fixed->operation) == FALSE)
+            break;
+
+          if (glade_gtk_grid_point_crosses_threshold
+              (grid, TRUE, configure->top_attach - 1,
+               DIR_UP, rect->y) == FALSE)
+            break;
+
+          configure->top_attach--;
+        }
+
+      /* Check and expand bottom
+       */
+      while (configure->top_attach + configure->height < n_rows)
+        {
+          if (rect->y + rect->height >
+              fixed->child_y_origin + fixed->child_height_origin &&
+              fixed->operation != GLADE_CURSOR_DRAG &&
+              GLADE_FIXED_CURSOR_BOTTOM (fixed->operation) == FALSE)
+            break;
+
+          if (glade_gtk_grid_point_crosses_threshold
+              (grid, TRUE, configure->top_attach + configure->height,
+               DIR_DOWN, rect->y + rect->height) == FALSE)
+            break;
+
+          configure->height++;
+        }
+    }
+
+  return column >= 0 && row >= 0;
+}
+
+static gboolean
+glade_gtk_grid_configure_child (GladeFixed   *fixed,
+                                GladeWidget  *child,
+                                GdkRectangle *rect,
+                                GtkWidget    *grid)
+{
+  GladeGridChild configure = { child, };
+
+  /* Sometimes we are unable to find a widget in the appropriate column,
+   * usually because a placeholder hasnt had its size allocation yet.
+   */
+  if (glade_gtk_grid_get_attachments (fixed, GTK_GRID (grid), rect, &configure))
+    {
+      if (memcmp (&configure, &grid_cur_attach, sizeof (GladeGridChild)) != 0)
+        {
+
+          glade_property_push_superuser ();
+          glade_widget_pack_property_set (child, "left-attach",
+                                          configure.left_attach);
+          glade_widget_pack_property_set (child, "width",
+                                          configure.width);
+          glade_widget_pack_property_set (child, "top-attach",
+                                          configure.top_attach);
+          glade_widget_pack_property_set (child, "height",
+                                          configure.height);
+          glade_property_pop_superuser ();
+
+          memcpy (&grid_cur_attach, &configure, sizeof (GladeGridChild));
+        }
+    }
+  return TRUE;
+}
+
+static gboolean
+glade_gtk_grid_configure_begin (GladeFixed  *fixed,
+                                GladeWidget *child,
+                                GtkWidget   *grid)
+{
+  grid_edit.widget = child;
+
+  glade_widget_pack_property_get (child, "left-attach", &grid_edit.left_attach);
+  glade_widget_pack_property_get (child, "width",       &grid_edit.width);
+  glade_widget_pack_property_get (child, "top-attach",  &grid_edit.top_attach);
+  glade_widget_pack_property_get (child, "height",      &grid_edit.height);
+
+  memcpy (&grid_cur_attach, &grid_edit, sizeof (GladeGridChild));
+
+  return TRUE;
+}
+
+static gboolean
+glade_gtk_grid_configure_end (GladeFixed  *fixed,
+                              GladeWidget *child,
+                              GtkWidget   *grid)
+{
+  GladeGridChild new_child = { child, };
+
+  glade_widget_pack_property_get (child, "left-attach", &new_child.left_attach);
+  glade_widget_pack_property_get (child, "width",       &new_child.width);
+  glade_widget_pack_property_get (child, "top-attach",  &new_child.top_attach);
+  glade_widget_pack_property_get (child, "height",      &new_child.height);
+
+  /* Compare the meaningfull part of the current edit. */
+  if (memcmp (&new_child, &grid_edit, sizeof (GladeGridChild)) != 0)
+    {
+      GValue left_attach_value = { 0, };
+      GValue width_attach_value = { 0, };
+      GValue top_attach_value = { 0, };
+      GValue height_attach_value = { 0, };
+
+      GValue new_left_attach_value = { 0, };
+      GValue new_width_attach_value = { 0, };
+      GValue new_top_attach_value = { 0, };
+      GValue new_height_attach_value = { 0, };
+
+      GladeProperty *left_attach_prop, *width_attach_prop,
+      *top_attach_prop, *height_attach_prop;
+
+      left_attach_prop   = glade_widget_get_pack_property (child, "left-attach");
+      width_attach_prop  = glade_widget_get_pack_property (child, "width");
+      top_attach_prop    = glade_widget_get_pack_property (child, "top-attach");
+      height_attach_prop = glade_widget_get_pack_property (child, "height");
+
+      g_return_val_if_fail (GLADE_IS_PROPERTY (left_attach_prop), FALSE);
+      g_return_val_if_fail (GLADE_IS_PROPERTY (width_attach_prop), FALSE);
+      g_return_val_if_fail (GLADE_IS_PROPERTY (top_attach_prop), FALSE);
+      g_return_val_if_fail (GLADE_IS_PROPERTY (height_attach_prop), FALSE);
+
+      glade_property_get_value (left_attach_prop, &new_left_attach_value);
+      glade_property_get_value (width_attach_prop, &new_width_attach_value);
+      glade_property_get_value (top_attach_prop, &new_top_attach_value);
+      glade_property_get_value (height_attach_prop, &new_height_attach_value);
+
+      g_value_init (&left_attach_value, G_TYPE_INT);
+      g_value_init (&width_attach_value, G_TYPE_INT);
+      g_value_init (&top_attach_value, G_TYPE_INT);
+      g_value_init (&height_attach_value, G_TYPE_INT);
+
+      g_value_set_int (&left_attach_value, grid_edit.left_attach);
+      g_value_set_int (&width_attach_value, grid_edit.width);
+      g_value_set_int (&top_attach_value, grid_edit.top_attach);
+      g_value_set_int (&height_attach_value, grid_edit.height);
+
+      glade_command_push_group (_("Placing %s inside %s"),
+                                glade_widget_get_name (child), 
+                                glade_widget_get_name (GLADE_WIDGET (fixed)));
+      glade_command_set_properties
+        (left_attach_prop,   &left_attach_value,   &new_left_attach_value,
+         width_attach_prop,  &width_attach_value,  &new_width_attach_value,
+         top_attach_prop,    &top_attach_value,    &new_top_attach_value,
+         height_attach_prop, &height_attach_value, &new_height_attach_value,
+         NULL);
+      glade_command_pop_group ();
+
+      g_value_unset (&left_attach_value);
+      g_value_unset (&width_attach_value);
+      g_value_unset (&top_attach_value);
+      g_value_unset (&height_attach_value);
+      g_value_unset (&new_left_attach_value);
+      g_value_unset (&new_width_attach_value);
+      g_value_unset (&new_top_attach_value);
+      g_value_unset (&new_height_attach_value);
+    }
+
+  return TRUE;
+}
+
 static void
 glade_gtk_grid_parse_finished (GladeProject *project, GObject *container)
 {
@@ -148,7 +510,7 @@ glade_gtk_grid_parse_finished (GladeProject *project, GObject *container)
 
       n_row = attach.top_attach + attach.height;
       n_column = attach.left_attach + attach.width;
-      
+
       if (row < n_row) row = n_row;
       if (column < n_column) column = n_column;
     }
@@ -163,15 +525,25 @@ glade_gtk_grid_parse_finished (GladeProject *project, GObject *container)
 }
 
 void
-glade_gtk_grid_post_create (GladeWidgetAdaptor * adaptor,
-                             GObject * container, GladeCreateReason reason)
+glade_gtk_grid_post_create (GladeWidgetAdaptor *adaptor,
+                            GObject            *container,
+                            GladeCreateReason   reason)
 {
   GladeWidget *gwidget = glade_widget_get_from_gobject (container);
 
+  g_signal_connect (G_OBJECT (gwidget), "configure-child",
+                    G_CALLBACK (glade_gtk_grid_configure_child), container);
+
+  g_signal_connect (G_OBJECT (gwidget), "configure-begin",
+                    G_CALLBACK (glade_gtk_grid_configure_begin), container);
+
+  g_signal_connect (G_OBJECT (gwidget), "configure-end",
+                    G_CALLBACK (glade_gtk_grid_configure_end), container);
+
   if (reason == GLADE_CREATE_LOAD)
     g_signal_connect (glade_widget_get_project (gwidget), "parse-finished",
-                     G_CALLBACK (glade_gtk_grid_parse_finished),
-                     container);
+                      G_CALLBACK (glade_gtk_grid_parse_finished),
+                      container);
 }
 
 static gboolean
@@ -188,11 +560,11 @@ glade_gtk_grid_widget_exceeds_bounds (GtkGrid *grid, gint n_rows, gint n_cols)
       GtkWidget *widget = list->data;
 
       if (GLADE_IS_PLACEHOLDER (widget)) continue;
-          
+
       glade_gtk_grid_get_child_attachments (GTK_WIDGET (grid), widget, &attach);
 
       if (attach.left_attach + attach.width  > n_cols || 
-         attach.top_attach  + attach.height > n_rows)
+          attach.top_attach  + attach.height > n_rows)
         {
           ret = TRUE;
           break;
@@ -205,7 +577,7 @@ glade_gtk_grid_widget_exceeds_bounds (GtkGrid *grid, gint n_rows, gint n_cols)
 }
 
 static void
-gtk_grid_children_callback (GtkWidget * widget, gpointer client_data)
+gtk_grid_children_callback (GtkWidget *widget, gpointer client_data)
 {
   GList **children;
 
@@ -214,8 +586,8 @@ gtk_grid_children_callback (GtkWidget * widget, gpointer client_data)
 }
 
 GList *
-glade_gtk_grid_get_children (GladeWidgetAdaptor * adaptor,
-                              GtkContainer * container)
+glade_gtk_grid_get_children (GladeWidgetAdaptor *adaptor, 
+                             GtkContainer       *container)
 {
   GList *children = NULL;
 
@@ -228,8 +600,9 @@ glade_gtk_grid_get_children (GladeWidgetAdaptor * adaptor,
 }
 
 void
-glade_gtk_grid_add_child (GladeWidgetAdaptor * adaptor,
-                           GObject * object, GObject * child)
+glade_gtk_grid_add_child (GladeWidgetAdaptor *adaptor,
+                          GObject            *object,
+                          GObject            *child)
 {
   g_return_if_fail (GTK_IS_GRID (object));
   g_return_if_fail (GTK_IS_WIDGET (child));
@@ -240,8 +613,9 @@ glade_gtk_grid_add_child (GladeWidgetAdaptor * adaptor,
 }
 
 void
-glade_gtk_grid_remove_child (GladeWidgetAdaptor * adaptor,
-                              GObject * object, GObject * child)
+glade_gtk_grid_remove_child (GladeWidgetAdaptor *adaptor,
+                             GObject            *object,
+                             GObject            *child)
 {
   g_return_if_fail (GTK_IS_GRID (object));
   g_return_if_fail (GTK_IS_WIDGET (child));
@@ -253,9 +627,9 @@ glade_gtk_grid_remove_child (GladeWidgetAdaptor * adaptor,
 
 void
 glade_gtk_grid_replace_child (GladeWidgetAdaptor *adaptor,
-                              GObject *container,
-                              GObject *current,
-                              GObject *new_widget)
+                              GObject            *container,
+                              GObject            *current,
+                              GObject            *new_widget)
 {
   g_return_if_fail (GTK_IS_GRID (container));
   g_return_if_fail (GTK_IS_WIDGET (current));
@@ -279,8 +653,9 @@ glade_gtk_grid_replace_child (GladeWidgetAdaptor *adaptor,
 }
 
 static void
-glade_gtk_grid_set_n_common (GObject * object, const GValue * value,
-                              gboolean for_rows)
+glade_gtk_grid_set_n_common (GObject      *object,
+                             const GValue *value,
+                             gboolean      for_rows)
 {
   GladeWidget *widget;
   GtkGrid *grid;
@@ -307,9 +682,10 @@ glade_gtk_grid_set_n_common (GObject * object, const GValue * value,
 }
 
 void
-glade_gtk_grid_set_property (GladeWidgetAdaptor * adaptor,
-                              GObject * object,
-                              const gchar * id, const GValue * value)
+glade_gtk_grid_set_property (GladeWidgetAdaptor *adaptor,
+                             GObject            *object,
+                             const gchar        *id,
+                             const GValue       *value)
 {
   if (!strcmp (id, "n-rows"))
     glade_gtk_grid_set_n_common (object, value, TRUE);
@@ -321,8 +697,9 @@ glade_gtk_grid_set_property (GladeWidgetAdaptor * adaptor,
 }
 
 static gboolean
-glade_gtk_grid_verify_n_common (GObject * object, const GValue * value,
-                                 gboolean for_rows)
+glade_gtk_grid_verify_n_common (GObject      *object,
+                                const GValue *value,
+                                gboolean      for_rows)
 {
   GtkGrid *grid = GTK_GRID (object);
   GladeWidget *widget;
@@ -341,9 +718,10 @@ glade_gtk_grid_verify_n_common (GObject * object, const GValue * value,
 }
 
 gboolean
-glade_gtk_grid_verify_property (GladeWidgetAdaptor * adaptor,
-                                 GObject * object,
-                                 const gchar * id, const GValue * value)
+glade_gtk_grid_verify_property (GladeWidgetAdaptor  *adaptor,
+                                GObject             *object,
+                                const gchar         *id,
+                                const GValue        *value)
 {
   if (!strcmp (id, "n-rows"))
     return glade_gtk_grid_verify_n_common (object, value, TRUE);
@@ -357,19 +735,20 @@ glade_gtk_grid_verify_property (GladeWidgetAdaptor * adaptor,
 }
 
 void
-glade_gtk_grid_set_child_property (GladeWidgetAdaptor * adaptor,
-                                    GObject * container,
-                                    GObject * child,
-                                    const gchar * property_name, GValue * value)
+glade_gtk_grid_set_child_property (GladeWidgetAdaptor *adaptor,
+                                   GObject            *container,
+                                   GObject            *child,
+                                   const gchar        *property_name,
+                                   GValue             *value)
 {
   g_return_if_fail (GTK_IS_GRID (container));
   g_return_if_fail (GTK_IS_WIDGET (child));
   g_return_if_fail (property_name != NULL && value != NULL);
 
   GWA_GET_CLASS
-      (GTK_TYPE_CONTAINER)->child_set_property (adaptor,
-                                                container, child,
-                                                property_name, value);
+    (GTK_TYPE_CONTAINER)->child_set_property (adaptor,
+                                              container, child,
+                                              property_name, value);
 
   if (strcmp (property_name, "left-attach") == 0 ||
       strcmp (property_name, "top-attach")  == 0 ||
@@ -383,14 +762,14 @@ glade_gtk_grid_set_child_property (GladeWidgetAdaptor * adaptor,
 
 static gboolean
 glade_gtk_grid_verify_attach_common (GObject     *object,
-                                    GValue      *value,
-                                    const gchar *prop,
-                                    const gchar *parent_prop)
+                                     GValue      *value,
+                                     const gchar *prop,
+                                     const gchar *parent_prop)
 {
   GladeWidget *widget, *parent;
   guint parent_val;
   gint val, prop_val;
-  
+
   widget = glade_widget_get_from_gobject (object);
   g_return_val_if_fail (GLADE_IS_WIDGET (widget), TRUE);
   parent = glade_widget_get_parent (widget);
@@ -402,16 +781,16 @@ glade_gtk_grid_verify_attach_common (GObject     *object,
 
   if (val < 0 || (val+prop_val) > parent_val)
     return FALSE;
-  
+
   return TRUE;
 }
 
 gboolean
 glade_gtk_grid_child_verify_property (GladeWidgetAdaptor *adaptor,
-                                      GObject *container,
-                                      GObject *child,
-                                      const gchar *id,
-                                      GValue *value)
+                                      GObject            *container,
+                                      GObject            *child,
+                                      const gchar        *id,
+                                      GValue             *value)
 {
   if (!strcmp (id, "left-attach"))
     return glade_gtk_grid_verify_attach_common (child, value, "width", "n-columns");
@@ -423,23 +802,23 @@ glade_gtk_grid_child_verify_property (GladeWidgetAdaptor *adaptor,
     return glade_gtk_grid_verify_attach_common (child, value, "top-attach", "n-rows");
   else if (GWA_GET_CLASS (GTK_TYPE_CONTAINER)->child_verify_property)
     GWA_GET_CLASS
-        (GTK_TYPE_CONTAINER)->child_verify_property (adaptor,
-                                                     container, child,
-                                                     id, value);
+    (GTK_TYPE_CONTAINER)->child_verify_property (adaptor,
+                                                 container, child,
+                                                 id, value);
 
   return TRUE;
 }
 
 static void
 glade_gtk_grid_child_insert_remove_action (GladeWidgetAdaptor *adaptor, 
-                                           GObject            *container, 
-                                           GObject            *object, 
-                                           const gchar        *group_format, 
-                                           const gchar        *n_row_col, 
-                                           const gchar        *attach1,    /* should be smaller (top/left) 
attachment */
-                                            const gchar        *attach2,      /* should be larger 
(bot/right) attachment */
-                                            gboolean            remove, 
-                                           gboolean            after)
+                                           GObject            *container, 
+                                           GObject            *object, 
+                                           const gchar        *group_format, 
+                                           const gchar        *n_row_col, 
+                                           const gchar        *attach1,    /* should be smaller (top/left) 
attachment */
+                                           const gchar        *attach2,      /* should be larger (bot/right) 
attachment */
+                                           gboolean            remove, 
+                                           gboolean            after)
 {
   GladeWidget *parent;
   GList *children, *l;
@@ -543,53 +922,53 @@ glade_gtk_grid_child_insert_remove_action (GladeWidgetAdaptor *adaptor,
 }
 
 void
-glade_gtk_grid_child_action_activate (GladeWidgetAdaptor * adaptor,
-                                       GObject * container,
-                                       GObject * object,
-                                       const gchar * action_path)
+glade_gtk_grid_child_action_activate (GladeWidgetAdaptor *adaptor,
+                                      GObject            *container,
+                                      GObject            *object,
+                                      const gchar        *action_path)
 {
   if (strcmp (action_path, "insert_row/after") == 0)
     {
       glade_gtk_grid_child_insert_remove_action (adaptor, container, object,
-                                                  _("Insert Row on %s"),
-                                                  "n-rows", "top-attach",
-                                                  "height", FALSE, TRUE);
+                                                 _("Insert Row on %s"),
+                                                 "n-rows", "top-attach",
+                                                 "height", FALSE, TRUE);
     }
   else if (strcmp (action_path, "insert_row/before") == 0)
     {
       glade_gtk_grid_child_insert_remove_action (adaptor, container, object,
-                                                  _("Insert Row on %s"),
-                                                  "n-rows", "top-attach",
-                                                  "height",
-                                                  FALSE, FALSE);
+                                                 _("Insert Row on %s"),
+                                                 "n-rows", "top-attach",
+                                                 "height",
+                                                 FALSE, FALSE);
     }
   else if (strcmp (action_path, "insert_column/after") == 0)
     {
       glade_gtk_grid_child_insert_remove_action (adaptor, container, object,
-                                                  _("Insert Column on %s"),
-                                                  "n-columns", "left-attach",
-                                                  "width", FALSE, TRUE);
+                                                 _("Insert Column on %s"),
+                                                 "n-columns", "left-attach",
+                                                 "width", FALSE, TRUE);
     }
   else if (strcmp (action_path, "insert_column/before") == 0)
     {
       glade_gtk_grid_child_insert_remove_action (adaptor, container, object,
-                                                  _("Insert Column on %s"),
-                                                  "n-columns", "left-attach",
-                                                  "width", FALSE, FALSE);
+                                                 _("Insert Column on %s"),
+                                                 "n-columns", "left-attach",
+                                                 "width", FALSE, FALSE);
     }
   else if (strcmp (action_path, "remove_column") == 0)
     {
       glade_gtk_grid_child_insert_remove_action (adaptor, container, object,
-                                                  _("Remove Column on %s"),
-                                                  "n-columns", "left-attach",
-                                                  "width", TRUE, FALSE);
+                                                 _("Remove Column on %s"),
+                                                 "n-columns", "left-attach",
+                                                 "width", TRUE, FALSE);
     }
   else if (strcmp (action_path, "remove_row") == 0)
     {
       glade_gtk_grid_child_insert_remove_action (adaptor, container, object,
-                                                _("Remove Row on %s"),
-                                                "n-rows", "top-attach",
-                                                "height", TRUE, FALSE);
+                                                 _("Remove Row on %s"),
+                                                 "n-rows", "top-attach",
+                                                 "height", TRUE, FALSE);
     }
   else
     GWA_GET_CLASS (GTK_TYPE_CONTAINER)->child_action_activate (adaptor,
diff --git a/plugins/gtk+/glade-gtk.c b/plugins/gtk+/glade-gtk.c
index ed4ac58..7fd6757 100644
--- a/plugins/gtk+/glade-gtk.c
+++ b/plugins/gtk+/glade-gtk.c
@@ -1360,6 +1360,231 @@ glade_gtk_create_fixed_widget (GladeWidgetAdaptor * adaptor,
                                               first_property_name, var_args);
 }
 
+typedef struct
+{
+  GtkWidget *widget;
+  gint position;
+} GladeGtkBoxChild;
+
+static GList *glade_gtk_box_original_positions = NULL;
+
+static gboolean
+glade_gtk_box_configure_child (GladeFixed * fixed,
+                               GladeWidget * child,
+                               GdkRectangle * rect, GtkWidget * box)
+{
+  GList *list, *children;
+  GtkWidget *bchild;
+  GtkAllocation allocation, bchild_allocation;
+  gint point, trans_point, span,
+      iter_span, position, old_position, offset, orig_offset;
+  gboolean found = FALSE;
+
+  gtk_widget_get_allocation (GTK_WIDGET (glade_widget_get_object (child)), &allocation);
+
+  if (gtk_orientable_get_orientation (GTK_ORIENTABLE (box)) == GTK_ORIENTATION_HORIZONTAL)
+    {
+      point = fixed->mouse_x;
+      span = allocation.width;
+      offset = rect->x;
+      orig_offset = fixed->child_x_origin;
+    }
+  else
+    {
+      point = fixed->mouse_y;
+      span = allocation.height;
+      offset = rect->y;
+      orig_offset = fixed->child_y_origin;
+    }
+
+  glade_widget_pack_property_get (child, "position", &old_position);
+
+  children = gtk_container_get_children (GTK_CONTAINER (box));
+
+  for (list = children; list; list = list->next)
+    {
+      bchild = list->data;
+
+      if (bchild == GTK_WIDGET (glade_widget_get_object (child)))
+        continue;
+
+      /* Find the widget in the box where the center of
+       * this rectangle fits... and set the position to that
+       * position.
+       */
+
+      gtk_widget_get_allocation (GTK_WIDGET (bchild), &bchild_allocation);
+      if (gtk_orientable_get_orientation (GTK_ORIENTABLE (box)) == GTK_ORIENTATION_HORIZONTAL)
+        {
+          gtk_widget_translate_coordinates
+              (GTK_WIDGET (box), bchild, point, 0, &trans_point, NULL);
+
+          iter_span = bchild_allocation.width;
+        }
+      else
+        {
+          gtk_widget_translate_coordinates
+              (GTK_WIDGET (box), bchild, 0, point, NULL, &trans_point);
+          iter_span = bchild_allocation.height;
+        }
+
+#if 0
+      gtk_container_child_get (GTK_CONTAINER (box),
+                               bchild, "position", &position, NULL);
+      g_print ("widget: %p pos %d, point %d, trans_point %d, iter_span %d\n",
+               bchild, position, point, trans_point, iter_span);
+#endif
+
+      if (iter_span <= span)
+        {
+          found = trans_point >= 0 && trans_point < iter_span;
+        }
+      else
+        {
+          if (offset > orig_offset)
+            found = trans_point >= iter_span - span && trans_point < iter_span;
+          else if (offset < orig_offset)
+            found = trans_point >= 0 && trans_point < span;
+        }
+
+      if (found)
+        {
+          gtk_container_child_get (GTK_CONTAINER (box),
+                                   bchild, "position", &position, NULL);
+
+#if 0
+          g_print ("setting position of %s from %d to %d, "
+                   "(point %d iter_span %d)\n",
+                   glade_widget_get_name (child), old_position, position, trans_point, iter_span);
+#endif
+
+          glade_widget_pack_property_set (child, "position", position);
+
+          break;
+        }
+
+    }
+
+  g_list_free (children);
+
+  return TRUE;
+}
+
+static gboolean
+glade_gtk_box_configure_begin (GladeFixed * fixed,
+                               GladeWidget * child, GtkWidget * box)
+{
+  GList *list, *children;
+  GtkWidget *bchild;
+
+  g_assert (glade_gtk_box_original_positions == NULL);
+
+  children = gtk_container_get_children (GTK_CONTAINER (box));
+
+  for (list = children; list; list = list->next)
+    {
+      GladeGtkBoxChild *gbchild;
+      GladeWidget *gchild;
+
+      bchild = list->data;
+      if ((gchild = glade_widget_get_from_gobject (bchild)) == NULL)
+        continue;
+
+      gbchild = g_new0 (GladeGtkBoxChild, 1);
+      gbchild->widget = bchild;
+      glade_widget_pack_property_get (gchild, "position", &gbchild->position);
+
+      glade_gtk_box_original_positions =
+          g_list_prepend (glade_gtk_box_original_positions, gbchild);
+    }
+
+  g_list_free (children);
+
+  return TRUE;
+}
+
+static gboolean
+glade_gtk_box_configure_end (GladeFixed * fixed,
+                             GladeWidget * child, GtkWidget * box)
+{
+  GList *list, *l, *children;
+  GList *prop_list = NULL;
+
+  children = gtk_container_get_children (GTK_CONTAINER (box));
+
+  for (list = children; list; list = list->next)
+    {
+      GtkWidget *bchild = list->data;
+
+      for (l = glade_gtk_box_original_positions; l; l = l->next)
+        {
+          GladeGtkBoxChild *gbchild = l->data;
+          GladeWidget *gchild = glade_widget_get_from_gobject (gbchild->widget);
+
+
+          if (bchild == gbchild->widget)
+            {
+              GCSetPropData *prop_data = g_new0 (GCSetPropData, 1);
+              prop_data->property =
+                  glade_widget_get_pack_property (gchild, "position");
+
+              prop_data->old_value = g_new0 (GValue, 1);
+              prop_data->new_value = g_new0 (GValue, 1);
+
+              glade_property_get_value (prop_data->property,
+                                        prop_data->new_value);
+
+              g_value_init (prop_data->old_value, G_TYPE_INT);
+              g_value_set_int (prop_data->old_value, gbchild->position);
+
+              prop_list = g_list_prepend (prop_list, prop_data);
+              break;
+            }
+        }
+    }
+
+  g_list_free (children);
+
+  glade_command_push_group (_("Ordering children of %s"),
+                            glade_widget_get_name (GLADE_WIDGET (fixed)));
+  glade_property_push_superuser ();
+  if (prop_list)
+    glade_command_set_properties_list (glade_widget_get_project (GLADE_WIDGET (fixed)),
+                                       prop_list);
+  glade_property_pop_superuser ();
+  glade_command_pop_group ();
+
+  for (l = glade_gtk_box_original_positions; l; l = l->next)
+    g_free (l->data);
+
+  glade_gtk_box_original_positions =
+      (g_list_free (glade_gtk_box_original_positions), NULL);
+
+
+  return TRUE;
+}
+
+void
+glade_gtk_box_post_create (GladeWidgetAdaptor * adaptor,
+                           GObject * container, GladeCreateReason reason)
+{
+  GladeWidget *gwidget = glade_widget_get_from_gobject (container);
+
+  /* Implement drag in GtkBox but not resize.
+   */
+  g_object_set (gwidget, "can-resize", FALSE, NULL);
+
+  g_signal_connect (G_OBJECT (gwidget), "configure-child",
+                    G_CALLBACK (glade_gtk_box_configure_child), container);
+
+  g_signal_connect (G_OBJECT (gwidget), "configure-begin",
+                    G_CALLBACK (glade_gtk_box_configure_begin), container);
+
+  g_signal_connect (G_OBJECT (gwidget), "configure-end",
+                    G_CALLBACK (glade_gtk_box_configure_end), container);
+
+}
+
 static gint
 sort_box_children (GtkWidget * widget_a, GtkWidget * widget_b)
 {
diff --git a/plugins/gtk+/gtk+.xml.in b/plugins/gtk+/gtk+.xml.in
index b6f6755..789f913 100644
--- a/plugins/gtk+/gtk+.xml.in
+++ b/plugins/gtk+/gtk+.xml.in
@@ -327,6 +327,8 @@ embedded in another object</_tooltip>
     </glade-widget-class>
     
     <glade-widget-class name="GtkBox" generic-name="box" _title="Box">
+      <create-widget-function>glade_gtk_create_fixed_widget</create-widget-function>
+      <post-create-function>glade_gtk_box_post_create</post-create-function>
       <get-children-function>glade_gtk_box_get_children</get-children-function>
       <set-property-function>glade_gtk_box_set_property</set-property-function>
       <get-property-function>glade_gtk_box_get_property</get-property-function>
@@ -1539,6 +1541,7 @@ embedded in another object</_tooltip>
     </glade-widget-class>
 
     <glade-widget-class name="GtkGrid" generic-name="grid" _title="Grid">
+      <create-widget-function>glade_gtk_create_fixed_widget</create-widget-function>
       <post-create-function>glade_gtk_grid_post_create</post-create-function>
       <child-set-property-function>glade_gtk_grid_set_child_property</child-set-property-function>
       <child-verify-function>glade_gtk_grid_child_verify_property</child-verify-function>



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