[glade] * plugins/gtk+/Makefile.am, plugins/gtk+/glade-gtk-grid.c, plugins/gtk+/gtk+.xml.in: Added suppo
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glade] * plugins/gtk+/Makefile.am, plugins/gtk+/glade-gtk-grid.c, plugins/gtk+/gtk+.xml.in: Added suppo
- Date: Thu, 24 Feb 2011 19:00:56 +0000 (UTC)
commit e7ce283fb809527385e8d833ab5470f7c63f2820
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Thu Feb 24 15:56:54 2011 +0900
* plugins/gtk+/Makefile.am, plugins/gtk+/glade-gtk-grid.c, plugins/gtk+/gtk+.xml.in:
Added support for GtkGrid.
ChangeLog | 3 +
plugins/gtk+/Makefile.am | 1 +
plugins/gtk+/glade-gtk-grid.c | 983 +++++++++++++++++++++++++++++++++++++++++
plugins/gtk+/gtk+.xml.in | 56 +++
4 files changed, 1043 insertions(+), 0 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 5d19f2f..6027711 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,9 @@
* gladeui/glade-placeholder.c: Make placeholders expand by default.
+ * plugins/gtk+/Makefile.am, plugins/gtk+/glade-gtk-grid.c, plugins/gtk+/gtk+.xml.in:
+ Added support for GtkGrid.
+
2011-02-17 Tristan Van Berkom <tristanvb openismus com>
* plugins/gtk+/glade-gtk.c, plugins/gtk+/glade-gtk-table.c, plugins/gtk+/Makefile.am:
diff --git a/plugins/gtk+/Makefile.am b/plugins/gtk+/Makefile.am
index aae6c09..957163a 100644
--- a/plugins/gtk+/Makefile.am
+++ b/plugins/gtk+/Makefile.am
@@ -43,6 +43,7 @@ libgladegtk_la_SOURCES = \
glade-tool-item-group-editor.c \
glade-string-list.c \
glade-gtk-table.c \
+ glade-gtk-grid.c \
glade-gtk-marshallers.c
libgladegtk_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
diff --git a/plugins/gtk+/glade-gtk-grid.c b/plugins/gtk+/glade-gtk-grid.c
new file mode 100644
index 0000000..e461b46
--- /dev/null
+++ b/plugins/gtk+/glade-gtk-grid.c
@@ -0,0 +1,983 @@
+/*
+ * glade-gtk-grid.c - GladeWidgetAdaptor for GtkGrid widget
+ *
+ * Copyright (C) 2011 Openismus GmbH
+ *
+ * Authors:
+ * Tristan Van Berkom <tristanvb openismus com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+#include <string.h>
+
+#include "glade-fixed.h"
+
+typedef struct
+{
+ gint left_attach;
+ gint top_attach;
+ gint width;
+ gint height;
+} GladeGridAttachments;
+
+typedef struct
+{
+ /* comparable part: */
+ GladeWidget *widget;
+ gint left_attach;
+ gint top_attach;
+ gint width;
+ gint height;
+} GladeGridChild;
+
+typedef enum
+{
+ DIR_UP,
+ DIR_DOWN,
+ DIR_LEFT,
+ 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)
+{
+ 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);
+}
+
+/* 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_UINT);
+ g_value_init (&width_attach_value, G_TYPE_UINT);
+ g_value_init (&top_attach_value, G_TYPE_UINT);
+ g_value_init (&height_attach_value, G_TYPE_UINT);
+
+ g_value_set_uint (&left_attach_value, grid_edit.left_attach);
+ g_value_set_uint (&width_attach_value, grid_edit.width);
+ g_value_set_uint (&top_attach_value, grid_edit.top_attach);
+ g_value_set_uint (&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;
+}
+
+void
+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);
+}
+
+static gboolean
+glade_gtk_grid_has_child (GtkGrid * grid, guint left_attach,
+ guint top_attach)
+{
+ GList *list, *children;
+ gboolean ret = FALSE;
+
+ children = gtk_container_get_children (GTK_CONTAINER (grid));
+
+ for (list = children; list && list->data; list = list->next)
+ {
+ GladeGridAttachments attach;
+ GtkWidget *widget = list->data;
+
+ 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)
+ {
+ ret = TRUE;
+ break;
+ }
+ }
+
+ g_list_free (children);
+
+ return ret;
+}
+
+static gboolean
+glade_gtk_grid_widget_exceeds_bounds (GtkGrid * grid, gint n_rows,
+ gint n_cols)
+{
+ GList *list, *children;
+ gboolean ret = FALSE;
+
+ children = gtk_container_get_children (GTK_CONTAINER (grid));
+
+ for (list = children; list && list->data; list = list->next)
+ {
+ GladeGridAttachments attach;
+ GtkWidget *widget = list->data;
+
+ glade_gtk_grid_get_child_attachments (GTK_WIDGET (grid), widget, &attach);
+
+ if (GLADE_IS_PLACEHOLDER (widget) == FALSE &&
+ (attach.left_attach + attach.width > n_cols ||
+ attach.top_attach + attach.height > n_rows))
+ {
+ ret = TRUE;
+ break;
+ }
+ }
+
+ g_list_free (children);
+
+ return ret;
+}
+
+static void
+glade_gtk_grid_refresh_placeholders (GtkGrid * grid)
+{
+ GladeWidget *widget;
+ GList *list, *children;
+ guint n_columns, n_rows;
+ gint i, j;
+
+ widget = glade_widget_get_from_gobject (GTK_WIDGET (grid));
+ glade_widget_property_get (widget, "n-columns", &n_columns);
+ glade_widget_property_get (widget, "n-rows", &n_rows);
+
+ children = gtk_container_get_children (GTK_CONTAINER (grid));
+
+ for (list = children; list && list->data; list = list->next)
+ {
+ if (GLADE_IS_PLACEHOLDER (list->data))
+ gtk_container_remove (GTK_CONTAINER (grid), GTK_WIDGET (list->data));
+ }
+ g_list_free (children);
+
+ for (i = 0; i < n_columns; i++)
+ for (j = 0; j < n_rows; j++)
+ if (glade_gtk_grid_has_child (grid, i, j) == FALSE)
+ {
+ gtk_grid_attach (grid, glade_placeholder_new (),
+ i, j, 1, 1);
+ }
+ gtk_container_check_resize (GTK_CONTAINER (grid));
+}
+
+static void
+gtk_grid_children_callback (GtkWidget * widget, gpointer client_data)
+{
+ GList **children;
+
+ children = (GList **) client_data;
+ *children = g_list_prepend (*children, widget);
+}
+
+GList *
+glade_gtk_grid_get_children (GladeWidgetAdaptor * adaptor,
+ GtkContainer * container)
+{
+ GList *children = NULL;
+
+ g_return_val_if_fail (GTK_IS_GRID (container), NULL);
+
+ gtk_container_forall (container, gtk_grid_children_callback, &children);
+
+ /* GtkGrid has the children list already reversed */
+ return children;
+}
+
+void
+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));
+
+ gtk_container_add (GTK_CONTAINER (object), GTK_WIDGET (child));
+
+ glade_gtk_grid_refresh_placeholders (GTK_GRID (object));
+}
+
+void
+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));
+
+ gtk_container_remove (GTK_CONTAINER (object), GTK_WIDGET (child));
+
+ glade_gtk_grid_refresh_placeholders (GTK_GRID (object));
+}
+
+void
+glade_gtk_grid_replace_child (GladeWidgetAdaptor * adaptor,
+ GtkWidget * container,
+ GtkWidget * current, GtkWidget * new_widget)
+{
+ g_return_if_fail (GTK_IS_GRID (container));
+ g_return_if_fail (GTK_IS_WIDGET (current));
+ g_return_if_fail (GTK_IS_WIDGET (new_widget));
+
+ /* Chain Up */
+ GWA_GET_CLASS
+ (GTK_TYPE_CONTAINER)->replace_child (adaptor,
+ G_OBJECT (container),
+ G_OBJECT (current),
+ G_OBJECT (new_widget));
+
+ /* If we are replacing a GladeWidget, we must refresh placeholders
+ * because the widget may have spanned multiple rows/columns, we must
+ * not do so in the case we are pasting multiple widgets into a grid,
+ * where destroying placeholders results in default packing properties
+ * (since the remaining placeholder templates no longer exist, only the
+ * first pasted widget would have proper packing properties).
+ */
+ if (glade_widget_get_from_gobject (new_widget) == NULL)
+ glade_gtk_grid_refresh_placeholders (GTK_GRID (container));
+
+}
+
+static void
+glade_gtk_grid_set_n_common (GObject * object, const GValue * value,
+ gboolean for_rows)
+{
+ GladeWidget *widget;
+ GtkGrid *grid;
+ guint new_size, n_columns, n_rows;
+
+ grid = GTK_GRID (object);
+ widget = glade_widget_get_from_gobject (GTK_WIDGET (grid));
+
+ glade_widget_property_get (widget, "n-columns", &n_columns);
+ glade_widget_property_get (widget, "n-rows", &n_rows);
+
+ new_size = g_value_get_uint (value);
+
+ if (new_size < 1)
+ return;
+
+ if (glade_gtk_grid_widget_exceeds_bounds
+ (grid, for_rows ? new_size : n_rows, for_rows ? n_columns : new_size))
+ /* Refuse to shrink if it means orphaning widgets */
+ return;
+
+ /* Fill grid with placeholders */
+ glade_gtk_grid_refresh_placeholders (grid);
+}
+
+void
+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);
+ else if (!strcmp (id, "n-columns"))
+ glade_gtk_grid_set_n_common (object, value, FALSE);
+ else
+ GWA_GET_CLASS (GTK_TYPE_CONTAINER)->set_property (adaptor, object,
+ id, value);
+}
+
+static gboolean
+glade_gtk_grid_verify_n_common (GObject * object, const GValue * value,
+ gboolean for_rows)
+{
+ GtkGrid *grid = GTK_GRID (object);
+ GladeWidget *widget;
+ guint n_columns, n_rows, new_size = g_value_get_uint (value);
+
+ widget = glade_widget_get_from_gobject (GTK_WIDGET (grid));
+ glade_widget_property_get (widget, "n-columns", &n_columns);
+ glade_widget_property_get (widget, "n-rows", &n_rows);
+
+ if (glade_gtk_grid_widget_exceeds_bounds
+ (grid, for_rows ? new_size : n_rows, for_rows ? n_columns : new_size))
+ /* Refuse to shrink if it means orphaning widgets */
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+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);
+ else if (!strcmp (id, "n-columns"))
+ return glade_gtk_grid_verify_n_common (object, value, FALSE);
+ else if (GWA_GET_CLASS (GTK_TYPE_CONTAINER)->verify_property)
+ GWA_GET_CLASS (GTK_TYPE_CONTAINER)->verify_property (adaptor, object,
+ id, value);
+
+ return TRUE;
+}
+
+void
+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);
+
+ if (strcmp (property_name, "bottom-attach") == 0 ||
+ strcmp (property_name, "left-attach") == 0 ||
+ strcmp (property_name, "right-attach") == 0 ||
+ strcmp (property_name, "top-attach") == 0)
+ {
+ /* Refresh placeholders */
+ glade_gtk_grid_refresh_placeholders (GTK_GRID (container));
+ }
+
+}
+
+static gboolean
+glade_gtk_grid_verify_attach_common (GObject *object,
+ GValue *value,
+ gint *val,
+ const gchar *prop,
+ gint *prop_val,
+ const gchar *parent_prop,
+ guint *parent_val)
+{
+ GladeWidget *widget, *parent;
+
+ widget = glade_widget_get_from_gobject (object);
+ g_return_val_if_fail (GLADE_IS_WIDGET (widget), TRUE);
+ parent = glade_widget_get_parent (widget);
+ g_return_val_if_fail (GLADE_IS_WIDGET (parent), TRUE);
+
+ *val = g_value_get_int (value);
+ glade_widget_property_get (widget, prop, prop_val);
+ glade_widget_property_get (parent, parent_prop, parent_val);
+
+ return FALSE;
+}
+
+static gboolean
+glade_gtk_grid_verify_left_top_attach (GObject * object,
+ GValue * value,
+ const gchar * prop,
+ const gchar * parent_prop)
+{
+ guint parent_val;
+ gint val, prop_val;
+
+ if (glade_gtk_grid_verify_attach_common (object, value, &val,
+ prop, &prop_val,
+ parent_prop, &parent_val))
+ return FALSE;
+
+ if (val >= parent_val || val >= prop_val)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+glade_gtk_grid_verify_right_bottom_attach (GObject * object,
+ GValue * value,
+ const gchar * prop,
+ const gchar * parent_prop)
+{
+ guint parent_val;
+ gint val, prop_val;
+
+ if (glade_gtk_grid_verify_attach_common (object, value, &val,
+ prop, &prop_val,
+ parent_prop, &parent_val))
+ return FALSE;
+
+ if (val <= prop_val || 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)
+{
+ if (!strcmp (id, "left-attach"))
+ return glade_gtk_grid_verify_left_top_attach (child,
+ value,
+ "right-attach", "n-columns");
+ else if (!strcmp (id, "right-attach"))
+ return glade_gtk_grid_verify_right_bottom_attach (child,
+ value,
+ "left-attach",
+ "n-columns");
+ else if (!strcmp (id, "top-attach"))
+ return glade_gtk_grid_verify_left_top_attach (child,
+ value,
+ "bottom-attach", "n-rows");
+ else if (!strcmp (id, "bottom-attach"))
+ return glade_gtk_grid_verify_right_bottom_attach (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);
+
+ 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)
+{
+ GladeWidget *parent;
+ GList *children, *l;
+ gint child_pos, size, offset;
+
+ gtk_container_child_get (GTK_CONTAINER (container),
+ GTK_WIDGET (object),
+ after ? attach2 : attach1, &child_pos, NULL);
+
+ parent = glade_widget_get_from_gobject (container);
+ glade_command_push_group (group_format, glade_widget_get_name (parent));
+
+ children = glade_widget_adaptor_get_children (adaptor, container);
+ /* Make sure widgets does not get destroyed */
+ g_list_foreach (children, (GFunc) g_object_ref, NULL);
+
+ glade_widget_property_get (parent, n_row_col, &size);
+
+ if (remove)
+ {
+ GList *del = NULL;
+ /* Remove children first */
+ for (l = children; l; l = g_list_next (l))
+ {
+ GladeWidget *gchild = glade_widget_get_from_gobject (l->data);
+ gint pos1, pos2;
+
+ /* Skip placeholders */
+ if (gchild == NULL)
+ continue;
+
+ glade_widget_pack_property_get (gchild, attach1, &pos1);
+ glade_widget_pack_property_get (gchild, attach2, &pos2);
+ if ((pos1 + 1 == pos2) && ((after ? pos2 : pos1) == child_pos))
+ {
+ del = g_list_prepend (del, gchild);
+ }
+ }
+ if (del)
+ {
+ glade_command_delete (del);
+ g_list_free (del);
+ }
+ offset = -1;
+ }
+ else
+ {
+ /* Expand the grid */
+ glade_command_set_property (glade_widget_get_property (parent, n_row_col),
+ size + 1);
+ offset = 1;
+ }
+
+ /* Reorder children */
+ for (l = children; l; l = g_list_next (l))
+ {
+ GladeWidget *gchild = glade_widget_get_from_gobject (l->data);
+ gint pos;
+
+ /* Skip placeholders */
+ if (gchild == NULL)
+ continue;
+
+ /* if removing, do top/left before bot/right */
+ if (remove)
+ {
+ /* adjust top-left attachment */
+ glade_widget_pack_property_get (gchild, attach1, &pos);
+ if (pos > child_pos || (after && pos == child_pos))
+ {
+ glade_command_set_property (glade_widget_get_pack_property
+ (gchild, attach1), pos + offset);
+ }
+
+ /* adjust bottom-right attachment */
+ glade_widget_pack_property_get (gchild, attach2, &pos);
+ if (pos > child_pos || (after && pos == child_pos))
+ {
+ glade_command_set_property (glade_widget_get_pack_property
+ (gchild, attach2), pos + offset);
+ }
+
+ }
+ /* if inserting, do bot/right before top/left */
+ else
+ {
+ /* adjust bottom-right attachment */
+ glade_widget_pack_property_get (gchild, attach2, &pos);
+ if (pos > child_pos)
+ {
+ glade_command_set_property (glade_widget_get_pack_property
+ (gchild, attach2), pos + offset);
+ }
+
+ /* adjust top-left attachment */
+ glade_widget_pack_property_get (gchild, attach1, &pos);
+ if (pos >= child_pos)
+ {
+ glade_command_set_property (glade_widget_get_pack_property
+ (gchild, attach1), pos + offset);
+ }
+ }
+ }
+
+ if (remove)
+ {
+ /* Shrink the grid */
+ glade_command_set_property (glade_widget_get_property (parent, n_row_col),
+ size - 1);
+ }
+
+ g_list_foreach (children, (GFunc) g_object_unref, NULL);
+ g_list_free (children);
+
+ glade_command_pop_group ();
+}
+
+void
+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",
+ "bottom-attach", 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",
+ "bottom-attach",
+ 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",
+ "right-attach", 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",
+ "right-attach", 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",
+ "right-attach", 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",
+ "bottom-attach", TRUE, FALSE);
+ }
+ else
+ GWA_GET_CLASS (GTK_TYPE_CONTAINER)->child_action_activate (adaptor,
+ container,
+ object,
+ action_path);
+}
diff --git a/plugins/gtk+/gtk+.xml.in b/plugins/gtk+/gtk+.xml.in
index a955ca1..bc1d4f3 100644
--- a/plugins/gtk+/gtk+.xml.in
+++ b/plugins/gtk+/gtk+.xml.in
@@ -1392,6 +1392,61 @@ embedded in another object</_tooltip>
</packing-properties>
</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>
+ <get-children-function>glade_gtk_grid_get_children</get-children-function>
+ <add-child-function>glade_gtk_grid_add_child</add-child-function>
+ <remove-child-function>glade_gtk_grid_remove_child</remove-child-function>
+ <replace-child-function>glade_gtk_grid_replace_child</replace-child-function>
+ <set-property-function>glade_gtk_grid_set_property</set-property-function>
+ <verify-function>glade_gtk_grid_verify_property</verify-function>
+ <child-action-activate-function>glade_gtk_grid_child_action_activate</child-action-activate-function>
+
+ <packing-actions>
+ <action id="insert_row" _name="Insert Row" stock="gtk-add">
+ <action id="before" _name="Before"/>
+ <action id="after" _name="After"/>
+ </action>
+ <action id="insert_column" _name="Insert Column" stock="gtk-add">
+ <action id="before" _name="Before"/>
+ <action id="after" _name="After"/>
+ </action>
+ <action id="remove_row" _name="Remove Row" stock="gtk-remove"/>
+ <action id="remove_column" _name="Remove Column" stock="gtk-remove"/>
+ </packing-actions>
+
+ <properties>
+ <property id="n-rows" _name="Rows" default="3" query="True" needs-sync="True">
+ <parameter-spec>
+ <type>GParamUInt</type>
+ </parameter-spec>
+ <_tooltip>The number of rows for this grid</_tooltip>
+ </property>
+ <property id="n-columns" _name="Columns" default="3" query="True" needs-sync="True">
+ <parameter-spec>
+ <type>GParamUInt</type>
+ </parameter-spec>
+ <_tooltip>The number of columns for this grid</_tooltip>
+ </property>
+ </properties>
+
+ <packing-properties>
+ <property id="x-options" transfer-on-paste="True">
+ <displayable-values>
+ <value id="GTK_EXPAND" _name="Expand"/>
+ <value id="GTK_SHRINK" _name="Shrink"/>
+ <value id="GTK_FILL" _name="Fill"/>
+ </displayable-values>
+ </property>
+ <property id="y-options" transfer-on-paste="True"/>
+ <property id="x-padding" transfer-on-paste="True"/>
+ <property id="y-padding" transfer-on-paste="True"/>
+ </packing-properties>
+ </glade-widget-class>
+
<glade-widget-class name="GtkPaned" generic-name="paned" _title="Paned">
<post-create-function>glade_gtk_paned_post_create</post-create-function>
<add-child-function>glade_gtk_paned_add_child</add-child-function>
@@ -3516,6 +3571,7 @@ embedded in another object</_tooltip>
<glade-widget-class-ref name="GtkHBox"/>
<glade-widget-class-ref name="GtkVBox"/>
<glade-widget-class-ref name="GtkTable"/>
+ <glade-widget-class-ref name="GtkGrid"/>
<glade-widget-class-ref name="GtkNotebook"/>
<glade-widget-class-ref name="GtkFrame"/>
<glade-widget-class-ref name="GtkAspectFrame"/>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]