diff options
author | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2013-07-11 16:09:26 -0300 |
---|---|---|
committer | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2013-08-06 07:59:39 -0300 |
commit | 419dd6148222988ef45041c6b9f04d0dfd9c93cd (patch) | |
tree | f778735c4d69d74a3b9963c9aacd761da3c32629 | |
parent | e8109986442355f5d92d898479a142c65cb51f8a (diff) | |
download | glade-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.c | 188 | ||||
-rw-r--r-- | gladeui/glade-widget-adaptor.c | 91 | ||||
-rw-r--r-- | gladeui/glade-widget-adaptor.h | 28 | ||||
-rw-r--r-- | gladeui/glade-widget.c | 21 | ||||
-rw-r--r-- | gladeui/glade-widget.h | 4 | ||||
-rw-r--r-- | 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 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" |