[glade/dnd-cleanup: 3/6] GladeWidgetAdaptor: added new function glade_widget_adaptor_get_child_at_position() GladeWidget: add



commit 419dd6148222988ef45041c6b9f04d0dfd9c93cd
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date:   Thu Jul 11 16:09:26 2013 -0300

    GladeWidgetAdaptor: added new function glade_widget_adaptor_get_child_at_position() GladeWidget: added 
convenience function glade_widget_get_child_at_position() GladeDesignLayout: replaced 
glade_design_layout_find_inside_container() with new API

 gladeui/glade-design-layout.c  |  188 ++++++++++++++++++++++------------------
 gladeui/glade-widget-adaptor.c |   91 +++++++++++++++++++
 gladeui/glade-widget-adaptor.h |   28 ++++++-
 gladeui/glade-widget.c         |   21 +++++
 gladeui/glade-widget.h         |    4 +
 gladeui/glade-xml-utils.h      |    1 +
 6 files changed, 247 insertions(+), 86 deletions(-)
---
diff --git a/gladeui/glade-design-layout.c b/gladeui/glade-design-layout.c
index a118760..30d4e62 100644
--- a/gladeui/glade-design-layout.c
+++ b/gladeui/glade-design-layout.c
@@ -73,6 +73,7 @@ typedef enum
 
 struct _GladeDesignLayoutPrivate
 {
+  GladeWidget *gchild;
   GdkWindow *window, *offscreen_window;
 
   gint child_offset;
@@ -477,49 +478,6 @@ glade_design_layout_motion_notify_event (GtkWidget *widget, GdkEventMotion *ev)
   return FALSE;
 }
 
-typedef struct
-{
-  GtkWidget *toplevel;
-  gint x;
-  gint y;
-  GtkWidget *placeholder;
-  GladeWidget *gwidget;
-} GladeFindInContainerData;
-
-static void
-glade_design_layout_find_inside_container (GtkWidget                *widget,
-                                           GladeFindInContainerData *data)
-{
-  gint x, y, w, h;
-
-  if (data->gwidget || !gtk_widget_get_mapped (widget))
-    return;
-
-  gtk_widget_translate_coordinates (data->toplevel, widget, data->x, data->y,
-                                    &x, &y);
-  
-  /* Margins are not part of the widget allocation */
-  w = gtk_widget_get_allocated_width (widget) + gtk_widget_get_margin_right (widget);
-  h = gtk_widget_get_allocated_height (widget) + gtk_widget_get_margin_bottom (widget);
-
-  if (x >= (0 - gtk_widget_get_margin_left (widget)) && x < w &&
-      y >= (0 - gtk_widget_get_margin_top (widget)) && y < h)
-    {
-      if (GLADE_IS_PLACEHOLDER (widget))
-        data->placeholder = widget;
-      else
-        {
-          if (GTK_IS_CONTAINER (widget))
-            gtk_container_forall (GTK_CONTAINER (widget), (GtkCallback)
-                                  glade_design_layout_find_inside_container,
-                                  data);
-
-          if (!data->gwidget)
-            data->gwidget = glade_widget_get_from_gobject (widget);
-        }
-    }
-}
-
 static gboolean
 glade_project_is_toplevel_active (GladeProject *project, GtkWidget *toplevel)
 {
@@ -962,7 +920,6 @@ glade_design_layout_add (GtkContainer *container, GtkWidget *widget)
 {
   GladeDesignLayout *layout = GLADE_DESIGN_LAYOUT (container);
   GladeDesignLayoutPrivate *priv = layout->priv;
-  GladeWidget *gchild;
 
   layout->priv->current_width = 0;
   layout->priv->current_height = 0;
@@ -972,10 +929,13 @@ glade_design_layout_add (GtkContainer *container, GtkWidget *widget)
   GTK_CONTAINER_CLASS (glade_design_layout_parent_class)->add (container,
                                                                widget);
 
-  if ((gchild = glade_widget_get_from_gobject (G_OBJECT (widget))))
+  if (!priv->gchild &&
+      (priv->gchild = glade_widget_get_from_gobject (G_OBJECT (widget))))
     {
-      update_widget_name (layout, gchild);
-      g_signal_connect (gchild, "notify::name", G_CALLBACK (on_glade_widget_name_notify), layout);
+      update_widget_name (layout, priv->gchild);
+      g_signal_connect (priv->gchild, "notify::name",
+                        G_CALLBACK (on_glade_widget_name_notify),
+                        layout);
     }
     
   gtk_widget_queue_draw (GTK_WIDGET (container)); 
@@ -987,8 +947,14 @@ glade_design_layout_remove (GtkContainer *container, GtkWidget *widget)
   GladeWidget *gchild;
 
   if ((gchild = glade_widget_get_from_gobject (G_OBJECT (widget))))
-    g_signal_handlers_disconnect_by_func (gchild, on_glade_widget_name_notify,
-                                          GLADE_DESIGN_LAYOUT (container));
+    {
+      GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (container);
+      
+      g_signal_handlers_disconnect_by_func (gchild, on_glade_widget_name_notify,
+                                            GLADE_DESIGN_LAYOUT (container));
+      if (gchild == priv->gchild)
+        priv->gchild = NULL;
+    }
 
   GTK_CONTAINER_CLASS (glade_design_layout_parent_class)->remove (container, widget);
   gtk_widget_queue_draw (GTK_WIDGET (container));
@@ -2284,6 +2250,79 @@ _glade_design_layout_get_hot_point (GladeDesignLayout *layout,
     *y = priv->drag_y;
 }
 
+static inline gboolean
+gdl_get_child_from_event (GladeDesignLayout *layout,
+                          GdkEvent          *event,
+                          GladeWidget      **gwidget,
+                          GtkWidget        **placeholder,
+                          gint              *x,
+                          gint              *y)
+{
+  GladeDesignLayoutPrivate *priv = layout->priv;
+  GtkWidget *child;
+
+  if (!priv->gchild)
+    return TRUE;
+      
+  _glade_design_layout_coords_from_event (priv->window, event, x, y);
+
+  if ((child = glade_widget_get_child_at_position (priv->gchild,
+                                                   *x - priv->child_offset,
+                                                   *y - priv->child_offset)))
+    {
+      if (GLADE_IS_PLACEHOLDER (child))
+        {
+          *gwidget = glade_placeholder_get_parent (GLADE_PLACEHOLDER (child));
+          *placeholder = child;
+        }
+      else
+        {
+          *gwidget = glade_widget_get_from_gobject (child);
+          *placeholder = NULL;
+        }
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static inline void
+gdl_drag_source_check (GladeDesignLayout *layout,
+                       GladePointerMode   mode,
+                       GdkEvent          *event,
+                       GladeWidget       *gwidget,
+                       gint               x,
+                       gint               y)
+{
+  GladeDesignLayoutPrivate *priv = layout->priv;
+
+  if (mode == GLADE_POINTER_SELECT && 
+      event->type == GDK_BUTTON_PRESS &&
+      event->button.button == 1)
+    {
+      GObject *source;
+
+      if (gwidget && (source = glade_widget_get_object (gwidget)) &&
+          !(event->button.state & GDK_SHIFT_MASK))
+        {
+          priv->drag_source = GTK_WIDGET (source);
+
+          gtk_widget_translate_coordinates (GTK_WIDGET (layout),
+                                            priv->drag_source, x, y,
+                                            &priv->drag_x, &priv->drag_y);
+        }
+      else
+        {
+          priv->drag_source = NULL;
+        }
+    }
+  else if (event->type == GDK_BUTTON_RELEASE && event->button.button == 1)
+    {
+      priv->drag_source = NULL;
+    }
+}
+
 /*
  * _glade_design_layout_do_event:
  * @layout: A #GladeDesignLayout
@@ -2297,19 +2336,19 @@ _glade_design_layout_get_hot_point (GladeDesignLayout *layout,
 gboolean
 _glade_design_layout_do_event (GladeDesignLayout *layout, GdkEvent *event)
 {
+  GladeDesignLayoutPrivate *priv = layout->priv;
   GtkWidget *widget = GTK_WIDGET (layout);
-  GladeFindInContainerData data = { widget, 0, };
-  GladeDesignLayoutPrivate *priv;
+  GtkWidget *placeholder;
+  GladeWidget *gwidget;
   GladePointerMode mode;
   gboolean retval;
+  gint x, y;
   GList *l;
-
-  priv = layout->priv;
-
-  _glade_design_layout_coords_from_event (priv->window, event, &data.x, &data.y);
-
+  
+  if (gdl_get_child_from_event (layout, event, &gwidget, &placeholder, &x, &y))
+    return FALSE;
+    
   mode = glade_project_get_pointer_mode (priv->project);
-  glade_design_layout_find_inside_container (widget, &data);
  
   /* Check if we want to enter in margin edit mode */
   if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_2BUTTON_PRESS)  &&
@@ -2319,7 +2358,7 @@ _glade_design_layout_do_event (GladeDesignLayout *layout, GdkEvent *event)
       g_list_next (l) == NULL && GTK_IS_WIDGET (l->data) && 
       gtk_widget_is_ancestor (l->data, widget))
     {
-      if (gdl_get_margins_from_pointer (widget, l->data, data.x, data.y))
+      if (gdl_get_margins_from_pointer (widget, l->data, x, y))
         {
           if (event->button.button == 2)
             {
@@ -2340,37 +2379,18 @@ _glade_design_layout_do_event (GladeDesignLayout *layout, GdkEvent *event)
         }
     }
 
-  if (event->type == GDK_BUTTON_PRESS && event->button.button == 1 &&
-      mode == GLADE_POINTER_SELECT)
-    {
-      GObject *source;
-
-      if (!(event->button.state & GDK_SHIFT_MASK) &&
-          data.gwidget && (source = glade_widget_get_object (data.gwidget)))
-        {
-          priv->drag_source = GTK_WIDGET (source);
-
-          gtk_widget_translate_coordinates (widget, priv->drag_source,
-                                            data.x, data.y,
-                                            &priv->drag_x, &priv->drag_y);
-        }
-      else
-        {
-          priv->drag_source = NULL;
-        }
-    }
-  else if (event->type == GDK_BUTTON_RELEASE && event->button.button == 1)
-    {
-      priv->drag_source = NULL;
-    }
+  /* Check if this event could start a drag event and save the initial
+   * coordinates for later.
+   */
+  gdl_drag_source_check (layout, mode, event, gwidget, x, y);
 
   _glade_design_view_freeze (priv->view);
   
   /* Try the placeholder first */
-  if (data.placeholder && gtk_widget_event (data.placeholder, event)) 
+  if (placeholder && gtk_widget_event (placeholder, event)) 
     retval = TRUE;
-  else if (data.gwidget) /* Then we try a GladeWidget */
-    retval = glade_widget_event (data.gwidget, event);
+  else if (gwidget) /* Then we try a GladeWidget */
+    retval = glade_widget_event (gwidget, event);
   else
     retval = FALSE;
 
diff --git a/gladeui/glade-widget-adaptor.c b/gladeui/glade-widget-adaptor.c
index b761de2..8a59c2b 100644
--- a/gladeui/glade-widget-adaptor.c
+++ b/gladeui/glade-widget-adaptor.c
@@ -297,6 +297,20 @@ glade_widget_adaptor_has_internal_children (GladeWidgetAdaptor *adaptor)
   return adaptor->priv->internal_children != NULL;
 }
 
+GtkWidget *
+glade_widget_adaptor_get_child_at_position (GladeWidgetAdaptor *adaptor,
+                                            GtkWidget          *widget,
+                                            gint                x,
+                                            gint                y)
+{
+  g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+  return GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->get_child_at_position (adaptor,
+                                                                          widget,
+                                                                          x, y);
+}
+
 static gint
 gwa_signal_comp (gpointer a, gpointer b)
 {
@@ -1356,6 +1370,78 @@ glade_widget_adaptor_object_get_children (GladeWidgetAdaptor *adaptor,
   return children;
 }
 
+typedef struct
+{
+  GtkWidget *toplevel;
+  GtkWidget *child;
+  gint x, y;
+} FindInContainerData;
+
+static void
+gwa_find_inside_container (GtkWidget *widget, FindInContainerData *data)
+{
+  gint x, y, w, h;
+
+  if (data->child || !gtk_widget_get_mapped (widget))
+    return;
+
+  gtk_widget_translate_coordinates (data->toplevel, widget, data->x, data->y,
+                                    &x, &y);
+  
+  /* Margins are not part of the widget allocation */
+  w = gtk_widget_get_allocated_width (widget) + gtk_widget_get_margin_right (widget);
+  h = gtk_widget_get_allocated_height (widget) + gtk_widget_get_margin_bottom (widget);
+
+  if (x >= (0 - gtk_widget_get_margin_left (widget)) && x < w &&
+      y >= (0 - gtk_widget_get_margin_top (widget)) && y < h)
+    {
+      if (GLADE_IS_PLACEHOLDER (widget))
+        data->child = widget;
+      else
+        {
+          GladeWidget *gwidget = glade_widget_get_from_gobject (widget);
+
+          if (GTK_IS_CONTAINER (widget))
+            {
+              if (gwidget)
+                data->child = glade_widget_get_child_at_position (gwidget, x, y);
+              else
+                gtk_container_forall (GTK_CONTAINER (widget),
+                                      (GtkCallback) gwa_find_inside_container,
+                                      data);
+            }
+          
+          if (!data->child && gwidget)
+            data->child = widget;
+        }
+    }
+}
+
+static GtkWidget *
+glade_widget_adaptor_object_get_child_at_position (GladeWidgetAdaptor *adaptor,
+                                                   GtkWidget          *widget,
+                                                   gint                x,
+                                                   gint                y)
+{
+  if (!gtk_widget_get_mapped (widget))
+    return NULL;
+
+  if (x >= 0 && x <= gtk_widget_get_allocated_width (widget) &&
+      y >= 0 && y <= gtk_widget_get_allocated_height (widget))
+    {
+      if (GTK_IS_CONTAINER (widget))
+        {
+          FindInContainerData data = {widget, NULL, x, y};
+          gtk_container_forall (GTK_CONTAINER (widget),
+                                (GtkCallback) gwa_find_inside_container,
+                                &data);
+
+          return (data.child) ? data.child : widget;
+        }
+      return widget;
+    }
+  return NULL;
+}
 
 /*******************************************************************************
             GladeWidgetAdaptor type registration and class initializer
@@ -1411,6 +1497,7 @@ glade_widget_adaptor_class_init (GladeWidgetAdaptorClass *adaptor_class)
   adaptor_class->create_eprop = glade_widget_adaptor_object_create_eprop;
   adaptor_class->string_from_value = glade_widget_adaptor_object_string_from_value;
   adaptor_class->create_editable = glade_widget_adaptor_object_create_editable;
+  adaptor_class->get_child_at_position = glade_widget_adaptor_object_get_child_at_position;
 
   /* Base defaults here */
   adaptor_class->toplevel = FALSE;
@@ -1640,6 +1727,10 @@ gwa_extend_with_node_load_sym (GladeWidgetAdaptorClass *klass,
                                     &symbol))
     klass->create_editable = symbol;
 
+  if (glade_xml_load_sym_from_node (node, module,
+                                    GLADE_TAG_GET_CHILD_AT_POSITION_FUNCTION,
+                                    &symbol))
+    klass->get_child_at_position = symbol;
 }
 
 static void
diff --git a/gladeui/glade-widget-adaptor.h b/gladeui/glade-widget-adaptor.h
index ecbe19e..794d1a3 100644
--- a/gladeui/glade-widget-adaptor.h
+++ b/gladeui/glade-widget-adaptor.h
@@ -571,6 +571,24 @@ typedef gchar   *(* GladeStringFromValueFunc) (GladeWidgetAdaptor *adaptor,
 typedef GladeEditable *(* GladeCreateEditableFunc) (GladeWidgetAdaptor   *adaptor,
                                                    GladeEditorPageType   type);
 
+/**
+ * GladeGetChildAtPositionFunc:
+ * @adaptor: A #GladeWidgetAdaptor
+ * @widget: A #GtkWidget
+ * @x: x position in @widget allocation coordinates
+ * @y: y position in @widget allocation coordinates
+ * 
+ * If @widget is a container it will return the child at the position @x @y that has
+ * an assosiated #GladeWidget or is a #GladePlaceholder otherwise it will return 
+ * @widget if the coordinates are inside its allocation.
+ *
+ * Returns: The widget found at position @x @y or NULL.
+ */
+typedef GtkWidget *(* GladeGetChildAtPositionFunc) (GladeWidgetAdaptor *adaptor,
+                                                    GtkWidget          *widget,
+                                                    gint                x,
+                                                    gint                y);
+
 
 /* Note that everything that must be processed at the creation of
  * every instance is managed on the instance structure, and everywhere
@@ -681,13 +699,14 @@ struct _GladeWidgetAdaptorClass
 
   GladeDestroyObjectFunc       destroy_object;    /* Object destructor */
   GladeWriteWidgetFunc         write_widget_after;/* Writes widget attributes to the xml (after children) */
-    
+
+  GladeGetChildAtPositionFunc  get_child_at_position;
+
   void   (* glade_reserved1)   (void);
   void   (* glade_reserved2)   (void);
   void   (* glade_reserved3)   (void);
   void   (* glade_reserved4)   (void);
   void   (* glade_reserved5)   (void);
-  void   (* glade_reserved6)   (void);
 };
 
 #define glade_widget_adaptor_create_widget(adaptor, query, ...) \
@@ -871,6 +890,11 @@ GladeWidgetAdaptor   *glade_widget_adaptor_get_parent_adaptor (GladeWidgetAdapto
 
 gboolean              glade_widget_adaptor_has_internal_children (GladeWidgetAdaptor *adaptor);
 
+GtkWidget            *glade_widget_adaptor_get_child_at_position (GladeWidgetAdaptor *adaptor,
+                                                                  GtkWidget          *widget,
+                                                                  gint                x,
+                                                                  gint                y);
+
 G_END_DECLS
 
 #endif /* _GLADE_WIDGET_ADAPTOR_H_ */
diff --git a/gladeui/glade-widget.c b/gladeui/glade-widget.c
index d585939..dd35c9e 100644
--- a/gladeui/glade-widget.c
+++ b/gladeui/glade-widget.c
@@ -4887,3 +4887,24 @@ glade_widget_get_packing_properties (GladeWidget *widget)
 
   return widget->priv->packing_properties;
 }
+
+/**
+ * glade_widget_get_child_at_position:
+ * @x: x position in @widget coordinates
+ * @y: y position in @widget coordinates
+ * 
+ * Returns: The widget found at position @x @y or NULL.
+ */
+GtkWidget *
+glade_widget_get_child_at_position  (GladeWidget *widget, gint x, gint y)
+{
+  GladeWidgetPrivate *priv;
+
+  g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL);
+  priv = widget->priv;
+  g_return_val_if_fail (GTK_IS_WIDGET (priv->object), NULL);
+
+  return glade_widget_adaptor_get_child_at_position (priv->adaptor,
+                                                     GTK_WIDGET (priv->object),
+                                                     x, y);
+}
diff --git a/gladeui/glade-widget.h b/gladeui/glade-widget.h
index 44834d4..d594e1c 100644
--- a/gladeui/glade-widget.h
+++ b/gladeui/glade-widget.h
@@ -220,6 +220,10 @@ gboolean                glade_widget_depends                (GladeWidget      *w
 
 GdkDevice              *glade_widget_get_device_from_event  (GdkEvent *event);
 
+GtkWidget              *glade_widget_get_child_at_position  (GladeWidget *widget,
+                                                             gint         x,
+                                                             gint         y);
+
 /*******************************************************************************
                       Project, object property references
  *******************************************************************************/
diff --git a/gladeui/glade-xml-utils.h b/gladeui/glade-xml-utils.h
index 80d3a38..eb79f7c 100644
--- a/gladeui/glade-xml-utils.h
+++ b/gladeui/glade-xml-utils.h
@@ -116,6 +116,7 @@ typedef struct _GladeProject        GladeProject;
 #define GLADE_TAG_CREATE_EPROP_FUNCTION           "create-editor-property-function"
 #define GLADE_TAG_STRING_FROM_VALUE_FUNCTION      "string-from-value-function"
 #define GLADE_TAG_CREATE_EDITABLE_FUNCTION        "create-editable-function"
+#define GLADE_TAG_GET_CHILD_AT_POSITION_FUNCTION  "get-child-at-position-function"
 #define GLADE_TAG_PROPERTIES                      "properties"
 #define GLADE_TAG_PACKING_PROPERTIES              "packing-properties"
 #define GLADE_TAG_PROPERTY                        "property"


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