diff options
author | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2013-07-11 17:26:33 -0300 |
---|---|---|
committer | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2013-08-19 15:01:54 -0300 |
commit | 5edf71dc7030aefa3671edc36077d046306624f4 (patch) | |
tree | c17ebc7343844ff50c7e583eb8cc7b7939ea8c52 | |
parent | c456aba9ec07dbcdebdd85b4a7756b3563e5ab14 (diff) | |
download | glade-5edf71dc7030aefa3671edc36077d046306624f4.tar.gz |
Fixed rendering issues now that we support GtkOverlay and overlay children can be outside of its parent allocation.
-rw-r--r-- | gladeui/glade-design-layout.c | 101 |
1 files changed, 75 insertions, 26 deletions
diff --git a/gladeui/glade-design-layout.c b/gladeui/glade-design-layout.c index a1d6de87..8a48aede 100644 --- a/gladeui/glade-design-layout.c +++ b/gladeui/glade-design-layout.c @@ -81,7 +81,7 @@ struct _GladeDesignLayoutPrivate GdkCursor *cursor; /* Current cursor */ GdkCursor *cursors[N_ACTIVITY]; - gint current_width, current_height; + GdkRectangle child_rect; PangoLayout *widget_name; gint layout_width; @@ -129,16 +129,17 @@ G_DEFINE_TYPE (GladeDesignLayout, glade_design_layout, GTK_TYPE_BIN) #define RECTANGLE_POINT_IN(rect,x,y) (x >= rect.x && x <= (rect.x + rect.width) && y >= rect.y && y <= (rect.y + rect.height)) static Margins -gdl_get_margins_from_pointer (GtkWidget *child, GtkWidget *widget, gint x, gint y) +gdl_get_margins_from_pointer (GladeDesignLayout *layout, GtkWidget *widget, gint x, gint y) { + GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (layout); gint width, height, xx, yy, top, bottom, left, right; + GdkRectangle rec, child_rec; Margins margin = 0; - GdkRectangle rec; - + width = gtk_widget_get_allocated_width (widget); height = gtk_widget_get_allocated_height (widget); - gtk_widget_translate_coordinates (widget, child, 0, 0, &xx, &yy); + gtk_widget_translate_coordinates (widget, GTK_WIDGET (layout), 0, 0, &xx, &yy); top = gtk_widget_get_margin_top (widget); bottom = gtk_widget_get_margin_bottom (widget); @@ -150,6 +151,14 @@ gdl_get_margins_from_pointer (GtkWidget *child, GtkWidget *widget, gint x, gint rec.width = width + left + right + (OUTLINE_WIDTH * 2); rec.height = height + top + bottom + (OUTLINE_WIDTH * 2); + gtk_widget_get_allocation (gtk_bin_get_child (GTK_BIN (layout)), &child_rec); + child_rec.x = (child_rec.x + priv->child_offset) - OUTLINE_WIDTH; + child_rec.y = (child_rec.y + priv->child_offset) - OUTLINE_WIDTH; + child_rec.width += OUTLINE_WIDTH * 2; + child_rec.height += OUTLINE_WIDTH * 2; + + gdk_rectangle_intersect (&rec, &child_rec, &rec); + if (RECTANGLE_POINT_IN (rec, x, y)) { if (y <= yy + OUTLINE_WIDTH) margin |= MARGIN_TOP; @@ -169,9 +178,7 @@ gdl_get_activity_from_pointer (GladeDesignLayout *layout, gint x, gint y) if (priv->selection) { - priv->margin = gdl_get_margins_from_pointer (GTK_WIDGET (layout), - priv->selection, - x, y); + priv->margin = gdl_get_margins_from_pointer (layout, priv->selection, x, y); if (priv->margin) { @@ -877,7 +884,7 @@ glade_design_layout_size_allocate (GtkWidget *widget, gint height, offset; offset = gtk_container_get_border_width (GTK_CONTAINER (widget)) + PADDING + OUTLINE_WIDTH; - priv->child_offset = offset; + priv->child_rect.x = priv->child_rect.y = priv->child_offset = offset; if (priv->widget_name) pango_layout_get_pixel_size (priv->widget_name, NULL, &height); @@ -885,8 +892,8 @@ glade_design_layout_size_allocate (GtkWidget *widget, height = PADDING; alloc.x = alloc.y = 0; - priv->current_width = alloc.width = allocation->width - (offset * 2); - priv->current_height = alloc.height = allocation->height - (offset + OUTLINE_WIDTH * 1.5 + height); + priv->child_rect.width = alloc.width = allocation->width - (offset * 2); + priv->child_rect.height = alloc.height = allocation->height - (offset + OUTLINE_WIDTH * 1.5 + height); if (gtk_widget_get_realized (widget)) gdk_window_move_resize (priv->offscreen_window, @@ -921,8 +928,8 @@ glade_design_layout_add (GtkContainer *container, GtkWidget *widget) GladeDesignLayout *layout = GLADE_DESIGN_LAYOUT (container); GladeDesignLayoutPrivate *priv = layout->priv; - layout->priv->current_width = 0; - layout->priv->current_height = 0; + priv->child_rect.width = 0; + priv->child_rect.height = 0; gtk_widget_set_parent_window (widget, priv->offscreen_window); @@ -1352,25 +1359,23 @@ draw_selection_nodes (cairo_t *cr, GtkWidget *widget = priv->selection; gint top, bottom, left, right; gint x1, x2, x3, y1, y2, y3; - GtkAllocation alloc, palloc; + GtkAllocation alloc; GdkRGBA *c1, *c2, *c3, *fg; gint x, y, w, h; + gint offset = priv->child_offset; + GdkRectangle clip = {0, }; - gtk_widget_get_allocation (widget, &alloc); - if (alloc.x < 0 || alloc.y < 0) return; + gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y); c1 = &priv->frame_color_active[0]; c2 = &priv->frame_color_active[1]; c3 = &priv->frame_color[0]; fg = &priv->fg_color; - gtk_widget_get_allocation (parent, &palloc); - + gtk_widget_get_allocation (widget, &alloc); w = alloc.width; h = alloc.height; - gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y); - top = gtk_widget_get_margin_top (widget); bottom = gtk_widget_get_margin_bottom (widget); left = gtk_widget_get_margin_left (widget); @@ -1384,6 +1389,39 @@ draw_selection_nodes (cairo_t *cr, y2 = y + h/2; y3 = y + h + bottom; + /* Calculate clipping region to avoid drawing nodes outside of the toplevel + * allocation. This could happen for example with GtkOverlay overlay children. + */ + if (offset > x1) + { + clip.x = offset; + clip.width = 0; + } + else + { + clip.x = 0; + clip.width = offset; + } + if (offset > y1) + { + clip.y = offset; + clip.height = 0; + } + else + { + clip.y = 0; + clip.height = offset; + } + + clip.width += (priv->child_rect.width + offset < x3) ? + priv->child_rect.width : gdk_window_get_width (priv->window); + clip.height += (priv->child_rect.height + offset < y3) ? + priv->child_rect.height : gdk_window_get_height (priv->window); + + cairo_save (cr); + gdk_cairo_rectangle (cr, &clip); + cairo_clip (cr); + /* Draw nodes */ cairo_set_line_width (cr, OUTLINE_WIDTH); @@ -1430,6 +1468,8 @@ draw_selection_nodes (cairo_t *cr, draw_pushpin (cr, x3, y2, 45, c3, c2, c1, fg, node & MARGIN_RIGHT, halign == GTK_ALIGN_END); } } + + cairo_restore (cr); } static gboolean @@ -1452,8 +1492,7 @@ glade_design_layout_draw (GtkWidget *widget, cairo_t *cr) /* draw offscreen widgets */ gdk_cairo_set_source_window (cr, priv->offscreen_window, priv->child_offset, priv->child_offset); - cairo_rectangle (cr, priv->child_offset, priv->child_offset, - priv->current_width, priv->current_height); + gdk_cairo_rectangle (cr, &priv->child_rect); cairo_fill (cr); /* Draw selection */ @@ -1470,7 +1509,17 @@ glade_design_layout_draw (GtkWidget *widget, cairo_t *cr) if (GTK_IS_WIDGET (selection) && gtk_widget_is_ancestor (selection, child)) { + GdkRectangle *rect = &priv->child_rect; + cairo_save (cr); + cairo_rectangle (cr, + rect->x - OUTLINE_WIDTH/2, + rect->y - OUTLINE_WIDTH/2, + rect->width + OUTLINE_WIDTH, + rect->height + OUTLINE_WIDTH); + cairo_clip (cr); draw_selection (cr, widget, selection, &priv->frame_color_active[0]); + cairo_restore (cr); + selected = TRUE; } } @@ -1482,11 +1531,11 @@ glade_design_layout_draw (GtkWidget *widget, cairo_t *cr) draw_frame (cr, priv, selected, border_width + PADDING, border_width + PADDING, - priv->current_width + 2 * OUTLINE_WIDTH, - priv->current_height + 2 * OUTLINE_WIDTH); + priv->child_rect.width + 2 * OUTLINE_WIDTH, + priv->child_rect.height + 2 * OUTLINE_WIDTH); /* Draw selection nodes if we are in margins edit mode */ - if (priv->selection) + if (priv->selection && gtk_widget_is_ancestor (priv->selection, child)) draw_selection_nodes (cr, priv, widget); } } @@ -2489,7 +2538,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, x, y)) + if (gdl_get_margins_from_pointer (layout, l->data, x, y)) { if (event->button.button == 2) { |