summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Pablo Ugarte <juanpablougarte@gmail.com>2013-07-11 16:09:26 -0300
committerJuan Pablo Ugarte <juanpablougarte@gmail.com>2013-08-06 07:59:39 -0300
commit419dd6148222988ef45041c6b9f04d0dfd9c93cd (patch)
treef778735c4d69d74a3b9963c9aacd761da3c32629
parente8109986442355f5d92d898479a142c65cb51f8a (diff)
downloadglade-419dd6148222988ef45041c6b9f04d0dfd9c93cd.tar.gz
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
-rw-r--r--gladeui/glade-design-layout.c188
-rw-r--r--gladeui/glade-widget-adaptor.c91
-rw-r--r--gladeui/glade-widget-adaptor.h28
-rw-r--r--gladeui/glade-widget.c21
-rw-r--r--gladeui/glade-widget.h4
-rw-r--r--gladeui/glade-xml-utils.h1
6 files changed, 247 insertions, 86 deletions
diff --git a/gladeui/glade-design-layout.c b/gladeui/glade-design-layout.c
index a1187605..30d4e628 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 b761de2d..8a59c2b3 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 ecbe19e2..794d1a37 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 d585939e..dd35c9e4 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 44834d4b..d594e1c5 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 80d3a382..eb79f7c7 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"