summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Pablo Ugarte <juanpablougarte@gmail.com>2011-04-24 22:12:26 -0300
committerJuan Pablo Ugarte <juanpablougarte@gmail.com>2011-10-06 16:12:20 -0300
commitb4b114b1b17f80b2ce0f41ebca8c45de75171dd8 (patch)
treed0db338b152930a8565e09fdd5cc71aaf3809df2
parent2d29c14479ad06f19d6c961479fcfcc0577880cd (diff)
downloadglade-b4b114b1b17f80b2ce0f41ebca8c45de75171dd8.tar.gz
Implemented inline margins edit mode. Now it is posible to change widget's margins
using the mouse. * gladeui/glade-design-layout.c: o fixed offscreen bg rendering bug (style context from the embedded widget should be used) o Implemented ACTIVITY_MARGINS o include widget margins on selection drawing * gladeui/glade-cursor.c: o made cursor->selector == NULL o Only set cursor if the current cursor is diferent * gladeui/glade-project.h: added GLADE_POINTER_MARGIN_MODE * gladeui/glade-placeholder.c: fixed function prototypes.
-rw-r--r--gladeui/glade-cursor.c9
-rw-r--r--gladeui/glade-design-layout.c545
-rw-r--r--gladeui/glade-placeholder.c91
-rw-r--r--gladeui/glade-project.h1
4 files changed, 502 insertions, 144 deletions
diff --git a/gladeui/glade-cursor.c b/gladeui/glade-cursor.c
index 1cdf43ee..5ebc7d92 100644
--- a/gladeui/glade-cursor.c
+++ b/gladeui/glade-cursor.c
@@ -139,8 +139,11 @@ glade_cursor_set (GladeProject *project,
break;
}
- set_cursor (project, cursor->selector);
- gdk_window_set_cursor (window, the_cursor);
+ if (the_cursor != gdk_window_get_cursor (window))
+ {
+ set_cursor (project, cursor->selector);
+ gdk_window_set_cursor (window, the_cursor);
+ }
}
/**
@@ -156,7 +159,7 @@ glade_cursor_init (void)
cursor = g_new0 (GladeCursor, 1);
- cursor->selector = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
+ cursor->selector = NULL;
cursor->add_widget = gdk_cursor_new (GDK_PLUS);
cursor->resize_top_left = gdk_cursor_new (GDK_TOP_LEFT_CORNER);
cursor->resize_top_right = gdk_cursor_new (GDK_TOP_RIGHT_CORNER);
diff --git a/gladeui/glade-design-layout.c b/gladeui/glade-design-layout.c
index 23059633..9bc2bcd1 100644
--- a/gladeui/glade-design-layout.c
+++ b/gladeui/glade-design-layout.c
@@ -47,16 +47,34 @@ typedef enum
ACTIVITY_NONE,
ACTIVITY_RESIZE_WIDTH,
ACTIVITY_RESIZE_HEIGHT,
- ACTIVITY_RESIZE_WIDTH_AND_HEIGHT
+ ACTIVITY_RESIZE_WIDTH_AND_HEIGHT,
+ ACTIVITY_MARGINS,
+ ACTIVITY_MARGINS_VERTICAL, /* These activities are only used to set the cursor */
+ ACTIVITY_MARGINS_HORIZONTAL,
+ ACTIVITY_MARGINS_TOP_LEFT,
+ ACTIVITY_MARGINS_TOP_RIGHT,
+ ACTIVITY_MARGINS_BOTTOM_LEFT,
+ ACTIVITY_MARGINS_BOTTOM_RIGHT,
+ N_ACTIVITY
} Activity;
+
+typedef enum
+{
+ MARGIN_TOP = 1 << 0,
+ MARGIN_BOTTOM = 1 << 1,
+ MARGIN_LEFT = 1 << 2,
+ MARGIN_RIGHT = 1 << 3
+} Margins;
+
struct _GladeDesignLayoutPrivate
{
GdkWindow *window, *offscreen_window;
gint child_offset;
GdkRectangle east, south, south_east;
- GdkCursor *cursors[sizeof (Activity)];
+ GdkCursor *cursor; /* Current cursor */
+ GdkCursor *cursors[N_ACTIVITY];
gint current_width, current_height;
PangoLayout *widget_name;
@@ -66,6 +84,11 @@ struct _GladeDesignLayoutPrivate
GdkRGBA frame_color[2];
GdkRGBA frame_color_active[2];
+ /* Margin edit mode */
+ GtkWidget *selection;
+ gint m_dy, m_dx;
+ Margins margin;
+
/* state machine */
Activity activity; /* the current activity */
gint dx; /* child.width - event.pointer.x */
@@ -75,6 +98,7 @@ struct _GladeDesignLayoutPrivate
/* Properties */
GladeDesignView *view;
+ GladeProject *project;
};
enum
@@ -87,11 +111,54 @@ 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 *widget, gint x, gint y)
+{
+ gint xx, yy, top, bottom, left, right;
+ GtkAllocation alloc;
+ Margins margin = 0;
+ GdkRectangle rec;
+
+ gtk_widget_get_allocation (widget, &alloc);
+ xx = alloc.x;
+ yy = alloc.y;
+
+ top = gtk_widget_get_margin_top (widget);
+ bottom = gtk_widget_get_margin_bottom (widget);
+ left = gtk_widget_get_margin_left (widget);
+ right = gtk_widget_get_margin_right (widget);
+
+ rec.x = xx - left - OUTLINE_WIDTH;
+ rec.y = yy - top - OUTLINE_WIDTH;
+ rec.width = alloc.width + left + right + (OUTLINE_WIDTH * 2);
+ rec.height = alloc.height + top + bottom + (OUTLINE_WIDTH * 2);
+
+ if (RECTANGLE_POINT_IN (rec, x, y))
+ {
+ if (y <= yy + OUTLINE_WIDTH) margin |= MARGIN_TOP;
+ else if (y >= yy + alloc.height - OUTLINE_WIDTH) margin |= MARGIN_BOTTOM;
+
+ if (x <= xx + OUTLINE_WIDTH) margin |= MARGIN_LEFT;
+ else if (x >= xx + alloc.width - OUTLINE_WIDTH) margin |= MARGIN_RIGHT;
+ }
+
+ return margin;
+}
+
static Activity
gdl_get_activity_from_pointer (GladeDesignLayout *layout, gint x, gint y)
{
GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (layout);
-
+
+ if (priv->selection)
+ {
+ priv->margin = gdl_get_margins_from_pointer (priv->selection,
+ x - priv->child_offset,
+ y - priv->child_offset);
+
+ if (priv->margin) return ACTIVITY_MARGINS;
+ }
+
if (RECTANGLE_POINT_IN (priv->south_east, x, y)) return ACTIVITY_RESIZE_WIDTH_AND_HEIGHT;
if (RECTANGLE_POINT_IN (priv->east, x, y)) return ACTIVITY_RESIZE_WIDTH;
@@ -101,6 +168,43 @@ gdl_get_activity_from_pointer (GladeDesignLayout *layout, gint x, gint y)
return ACTIVITY_NONE;
}
+static void
+gdl_set_cursor (GladeDesignLayoutPrivate *priv, GdkCursor *cursor)
+{
+ if (cursor != priv->cursor)
+ {
+ priv->cursor = cursor;
+ gdk_window_set_cursor (priv->window, cursor);
+ }
+}
+
+static Activity
+gdl_margin_get_activity (Margins margin)
+{
+ if (margin & MARGIN_TOP)
+ {
+ if (margin & MARGIN_LEFT)
+ return ACTIVITY_MARGINS_TOP_LEFT;
+ else if (margin & MARGIN_RIGHT)
+ return ACTIVITY_MARGINS_TOP_RIGHT;
+ else
+ return ACTIVITY_MARGINS_VERTICAL;
+ }
+ else if (margin & MARGIN_BOTTOM)
+ {
+ if (margin & MARGIN_LEFT)
+ return ACTIVITY_MARGINS_BOTTOM_LEFT;
+ else if (margin & MARGIN_RIGHT)
+ return ACTIVITY_MARGINS_BOTTOM_RIGHT;
+ else
+ return ACTIVITY_MARGINS_VERTICAL;
+ }
+ else if (margin & MARGIN_LEFT || margin & MARGIN_RIGHT)
+ return ACTIVITY_MARGINS_HORIZONTAL;
+
+ return ACTIVITY_NONE;
+}
+
static gboolean
glade_design_layout_leave_notify_event (GtkWidget *widget, GdkEventCrossing *ev)
{
@@ -114,7 +218,7 @@ glade_design_layout_leave_notify_event (GtkWidget *widget, GdkEventCrossing *ev)
priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
if (priv->activity == ACTIVITY_NONE)
- gdk_window_set_cursor (priv->window, NULL);
+ gdl_set_cursor (priv, NULL);
return FALSE;
}
@@ -138,10 +242,10 @@ glade_design_layout_update_child (GladeDesignLayout *layout,
static gboolean
glade_design_layout_motion_notify_event (GtkWidget *widget, GdkEventMotion *ev)
{
- GtkWidget *child;
GladeDesignLayoutPrivate *priv;
GtkAllocation allocation;
- gint x, y, new_width, new_height;
+ GtkWidget *child;
+ gint x, y;
if ((child = gtk_bin_get_child (GTK_BIN (widget))) == NULL)
return FALSE;
@@ -155,32 +259,64 @@ glade_design_layout_motion_notify_event (GtkWidget *widget, GdkEventMotion *ev)
allocation.x += priv->child_offset;
allocation.y += priv->child_offset;
-
- if (priv->activity == ACTIVITY_RESIZE_WIDTH)
- {
- new_width = x - priv->dx - PADDING - OUTLINE_WIDTH;
- allocation.width = MAX (0, new_width);
- }
- else if (priv->activity == ACTIVITY_RESIZE_HEIGHT)
+ switch (priv->activity)
{
- new_height = y - priv->dy - PADDING - OUTLINE_WIDTH;
+ case ACTIVITY_RESIZE_WIDTH:
+ allocation.width = MAX (0, x - priv->dx - PADDING - OUTLINE_WIDTH);
+ break;
+ case ACTIVITY_RESIZE_HEIGHT:
+ allocation.height = MAX (0, y - priv->dy - PADDING - OUTLINE_WIDTH);
+ break;
+ case ACTIVITY_RESIZE_WIDTH_AND_HEIGHT:
+ allocation.height = MAX (0, y - priv->dy - PADDING - OUTLINE_WIDTH);
+ allocation.width = MAX (0, x - priv->dx - PADDING - OUTLINE_WIDTH);
+ break;
+ case ACTIVITY_MARGINS:
+ {
+ gboolean shift = ev->state & GDK_SHIFT_MASK;
+ GtkWidget *selection = priv->selection;
+ Margins margin = priv->margin;
- allocation.height = MAX (0, new_height);
- }
- else if (priv->activity == ACTIVITY_RESIZE_WIDTH_AND_HEIGHT)
- {
- new_width = x - priv->dx - PADDING - OUTLINE_WIDTH;
- new_height = y - priv->dy - PADDING - OUTLINE_WIDTH;
+ if (margin & MARGIN_TOP)
+ {
+ gint val = MAX (0, priv->m_dy - y);
+ gtk_widget_set_margin_top (selection, val);
+ if (shift) gtk_widget_set_margin_bottom (selection, val);
+ }
+ else if (margin & MARGIN_BOTTOM)
+ {
+ gint val = MAX (0, y - priv->m_dy);
+ gtk_widget_set_margin_bottom (selection, val);
+ if (shift) gtk_widget_set_margin_top (selection, val);
+ }
- allocation.height = MAX (0, new_height);
- allocation.width = MAX (0, new_width);
- }
- else
- {
- Activity activity = gdl_get_activity_from_pointer (GLADE_DESIGN_LAYOUT (widget), x, y);
- gdk_window_set_cursor (priv->window, priv->cursors[activity]);
- return FALSE;
+ if (margin & MARGIN_LEFT)
+ {
+ gint val = MAX (0, priv->m_dx - x);
+ gtk_widget_set_margin_left (selection, val);
+ if (shift) gtk_widget_set_margin_right (selection, val);
+ }
+ else if (margin & MARGIN_RIGHT)
+ {
+ gint val = MAX (0, x - priv->m_dx);
+ gtk_widget_set_margin_right (selection, val);
+ if (shift) gtk_widget_set_margin_left (selection, val);
+ }
+ }
+ break;
+ default:
+ {
+ Activity activity = gdl_get_activity_from_pointer (GLADE_DESIGN_LAYOUT (widget), x, y);
+
+ if (activity == ACTIVITY_MARGINS)
+ activity = gdl_margin_get_activity (priv->margin);
+
+ /* Only set the cursor if changed */
+ gdl_set_cursor (priv, priv->cursors[activity]);
+ return TRUE;
+ }
+ break;
}
glade_design_layout_update_child (GLADE_DESIGN_LAYOUT (widget), child, &allocation);
@@ -201,8 +337,7 @@ glade_design_layout_find_inside_container (GtkWidget *widget,
GladeFindInContainerData *data)
{
GtkAllocation allocation;
- gint x;
- gint y;
+ gint x, y;
if (data->gwidget || !gtk_widget_get_mapped (widget))
return;
@@ -245,9 +380,8 @@ glade_project_is_toplevel_active (GladeProject *project, GtkWidget *toplevel)
static gboolean
glade_design_layout_button_press_event (GtkWidget *widget, GdkEventButton *ev)
{
- GtkWidget *child;
- GtkAllocation child_allocation;
GladeDesignLayoutPrivate *priv;
+ GtkWidget *child;
gint x, y;
if (ev->button != 1 ||
@@ -261,26 +395,47 @@ glade_design_layout_button_press_event (GtkWidget *widget, GdkEventButton *ev)
if (ev->type == GDK_BUTTON_PRESS)
{
- GladeWidget *gchild;
+ GtkAllocation child_allocation;
+
+ priv->activity = gdl_get_activity_from_pointer (GLADE_DESIGN_LAYOUT (widget), x, y);
+ /* Check if we are in margin edit mode */
+ if (priv->selection)
+ {
+ if (priv->activity == ACTIVITY_NONE)
+ {
+ priv->selection = NULL;
+ gdl_set_cursor (priv, NULL);
+ glade_project_set_pointer_mode (priv->project, GLADE_POINTER_SELECT);
+ gtk_widget_queue_draw (widget);
+ return FALSE;
+ }
+ else if (priv->activity == ACTIVITY_MARGINS)
+ gdl_set_cursor (priv, priv->cursors[gdl_margin_get_activity (priv->margin)]);
+ else
+ gdl_set_cursor (priv, priv->cursors[priv->activity]);
+
+ priv->m_dx = x + ((priv->margin & MARGIN_LEFT) ?
+ gtk_widget_get_margin_left (priv->selection) :
+ gtk_widget_get_margin_right (priv->selection) * -1);
+ priv->m_dy = y + ((priv->margin & MARGIN_TOP) ?
+ gtk_widget_get_margin_top (priv->selection) :
+ gtk_widget_get_margin_bottom (priv->selection) * -1);
+
+ return FALSE;
+ }
+
gtk_widget_get_allocation (child, &child_allocation);
+
priv->dx = x - (child_allocation.x + child_allocation.width + priv->child_offset);
priv->dy = y - (child_allocation.y + child_allocation.height + priv->child_offset);
-
- priv->activity = gdl_get_activity_from_pointer (GLADE_DESIGN_LAYOUT (widget), x, y);
- gdk_window_set_cursor (priv->window, priv->cursors[priv->activity]);
if (priv->activity != ACTIVITY_NONE &&
- (gchild = glade_widget_get_from_gobject (G_OBJECT (child))))
+ !glade_project_is_toplevel_active (priv->project, child))
{
- GladeProject *project = glade_widget_get_project (gchild);
-
- if (project && !glade_project_is_toplevel_active (project, child))
- {
- _glade_design_view_freeze (priv->view);
- glade_project_selection_set (project, G_OBJECT (gtk_bin_get_child (GTK_BIN (widget))), TRUE);
- _glade_design_view_thaw (priv->view);
- }
+ _glade_design_view_freeze (priv->view);
+ glade_project_selection_set (priv->project, G_OBJECT (child), TRUE);
+ _glade_design_view_thaw (priv->view);
}
}
@@ -300,7 +455,7 @@ glade_design_layout_button_release_event (GtkWidget *widget,
priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
priv->activity = ACTIVITY_NONE;
- gdk_window_set_cursor (priv->window, NULL);
+ gdl_set_cursor (priv, NULL);
return FALSE;
}
@@ -519,12 +674,6 @@ glade_design_layout_remove (GtkContainer *container, GtkWidget *widget)
gtk_widget_queue_draw (GTK_WIDGET (container));
}
-static void
-glade_design_layout_finalize (GObject *object)
-{
- G_OBJECT_CLASS (glade_design_layout_parent_class)->finalize (object);
-}
-
static gboolean
glade_design_layout_damage (GtkWidget *widget, GdkEventExpose *event)
{
@@ -596,13 +745,41 @@ draw_frame (cairo_t *cr, GladeDesignLayoutPrivate *priv, gboolean selected,
cairo_restore (cr);
}
+static void
+draw_margin_selection (cairo_t *cr,
+ gint x1, gint x2, gint x3, gint x4,
+ gint y1, gint y2, gint y3, gint y4,
+ gdouble r, gdouble g, gdouble b,
+ gint x5, gint y5)
+{
+ cairo_pattern_t *gradient = cairo_pattern_create_linear (x1, y1, x5, y5);
+
+ cairo_pattern_add_color_stop_rgba (gradient, 0, r+.24, g+.24, b+.24, .08);
+ cairo_pattern_add_color_stop_rgba (gradient, 1, r, g, b, .16);
+
+ cairo_set_source (cr, gradient);
+
+ cairo_move_to (cr, x1, y1);
+ cairo_line_to (cr, x2, y2);
+ cairo_line_to (cr, x3, y3);
+ cairo_line_to (cr, x4, y4);
+ cairo_close_path (cr);
+ cairo_fill (cr);
+
+ cairo_pattern_destroy (gradient);
+}
+
static inline void
-draw_selection (cairo_t *cr, GtkWidget *parent, GtkWidget *widget, GdkRGBA *color)
+draw_selection (cairo_t *cr,
+ GtkWidget *parent,
+ GtkWidget *widget,
+ GdkRGBA *color)
{
+ gint x, y, w, h, xw, yh, y_top, yh_bottom, x_left, xw_right;
+ gint top, bottom, left, right;
cairo_pattern_t *gradient;
gdouble r, g, b, cx, cy;
GtkAllocation alloc;
- gint x, y;
gtk_widget_get_allocation (widget, &alloc);
@@ -611,22 +788,120 @@ draw_selection (cairo_t *cr, GtkWidget *parent, GtkWidget *widget, GdkRGBA *colo
r = color->red; g = color->green; b = color->blue;
gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y);
- cx = x + alloc.width/2;
- cy = y + alloc.height/2;
- gradient = cairo_pattern_create_radial (cx, cy, MIN (alloc.width, alloc.height)/6,
- cx, cy, MAX (alloc.width, alloc.height)/2);
+ w = alloc.width;
+ h = alloc.height;
+ xw = x + w;
+ yh = y + h;
+
+ top = gtk_widget_get_margin_top (widget);
+ bottom = gtk_widget_get_margin_bottom (widget);
+ left = gtk_widget_get_margin_left (widget);
+ right = gtk_widget_get_margin_right (widget);
+
+ y_top = y - top;
+ yh_bottom = yh + bottom;
+ x_left = x - left;
+ xw_right = xw + right;
+
+ /* Draw widget area overlay */
+ cx = x + w/2;
+ cy = y + h/2;
+ gradient = cairo_pattern_create_radial (cx, cy, MIN (w, h)/6, cx, cy, MAX (w, h)/2);
cairo_pattern_add_color_stop_rgba (gradient, 0, r+.24, g+.24, b+.24, .16);
cairo_pattern_add_color_stop_rgba (gradient, 1, r, g, b, .28);
cairo_set_source (cr, gradient);
- cairo_rectangle (cr, x, y, alloc.width, alloc.height);
+ cairo_rectangle (cr, x, y, w, h);
cairo_fill (cr);
- cairo_rectangle (cr, x, y, alloc.width, alloc.height);
+ cairo_pattern_destroy (gradient);
+
+ /* Draw margins overlays */
+ if (top)
+ draw_margin_selection (cr, x, xw, xw_right, x_left, y, y, y_top, y_top,
+ r, g, b, x, y_top);
+
+ if (bottom)
+ draw_margin_selection (cr, x, xw, xw_right, x_left, yh, yh, yh_bottom, yh_bottom,
+ r, g, b, x, yh_bottom);
+
+ if (left)
+ draw_margin_selection (cr, x, x, x_left, x_left, y, yh, yh_bottom, y_top,
+ r, g, b, x_left, y);
+
+ if (right)
+ draw_margin_selection (cr, xw, xw, xw_right, xw_right, y, yh, yh_bottom, y_top,
+ r, g, b, xw_right, y);
+
+ /* Draw Boxes */
cairo_set_source_rgba (cr, r, g, b, .75);
+ if (top || bottom || left || right)
+ {
+ gdouble dashes[] = { 4.0, 4.0 };
+ cairo_rectangle (cr,
+ x - left,
+ y - top,
+ w + left + right,
+ h + top + bottom);
+ cairo_stroke (cr);
+ cairo_set_dash (cr, dashes, 2, 0);
+ }
+
+ /* Draw Widget allocation box */
+ cairo_rectangle (cr, x, y, w, h);
cairo_stroke (cr);
- cairo_pattern_destroy (gradient);
+ cairo_set_dash (cr, NULL, 0, 0);
+}
+
+static void
+draw_nodes (cairo_t *cr,
+ gint x1, gint x2, gint x3,
+ gint y1, gint y2, gint y3,
+ gint radius,
+ GdkRGBA *color)
+{
+ gdk_cairo_set_source_rgba (cr, color);
+
+ cairo_arc (cr, x2, y1, radius, 0, 2*G_PI);
+ cairo_fill (cr);
+ cairo_arc (cr, x2, y3, radius, 0, 2*G_PI);
+ cairo_fill (cr);
+ cairo_arc (cr, x1, y2, radius, 0, 2*G_PI);
+ cairo_fill (cr);
+ cairo_arc (cr, x3, y2, radius, 0, 2*G_PI);
+ cairo_fill (cr);
+}
+
+static inline void
+draw_selection_nodes (cairo_t *cr,
+ GtkWidget *parent,
+ GtkWidget *widget,
+ GdkRGBA *color,
+ GdkRGBA *bg_color)
+{
+ gint x1, x2, x3, y1, y2, y3;
+ GtkAllocation alloc;
+ gint x, y, w, h;
+
+ gtk_widget_get_allocation (widget, &alloc);
+ w = alloc.width;
+ h = alloc.height;
+
+ if (x < 0 || y < 0) return;
+
+ gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y);
+
+ /* Draw nodes */
+ x1 = x - gtk_widget_get_margin_left (widget);
+ x2 = x + w/2;
+ x3 = x + w + gtk_widget_get_margin_right (widget);
+ y1 = y - gtk_widget_get_margin_top (widget);
+ y2 = y + h/2;
+ y3 = y + h + gtk_widget_get_margin_bottom (widget);
+
+ draw_nodes (cr, x1, x2, x3, y1, y2, y3, OUTLINE_WIDTH + 2, bg_color);
+ draw_nodes (cr, x1, x2, x3, y1, y2, y3, OUTLINE_WIDTH, color);
}
static gboolean
@@ -637,19 +912,15 @@ glade_design_layout_draw (GtkWidget * widget, cairo_t * cr)
if (gtk_cairo_should_draw_window (cr, window))
{
- GladeProject *project;
- GladeWidget *gchild;
GtkWidget *child;
if ((child = gtk_bin_get_child (GTK_BIN (widget))) &&
- gtk_widget_get_visible (child) &&
- (gchild = glade_widget_get_from_gobject (G_OBJECT (child))) &&
- (project = glade_widget_get_project (gchild)))
+ gtk_widget_get_visible (child))
{
gint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
gboolean selected = FALSE;
GList *l;
-
+
/* draw offscreen widgets */
gdk_cairo_set_source_window (cr, priv->offscreen_window,
priv->child_offset, priv->child_offset);
@@ -661,7 +932,7 @@ glade_design_layout_draw (GtkWidget * widget, cairo_t * cr)
cairo_set_line_width (cr, OUTLINE_WIDTH/2);
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
- for (l = glade_project_selection_get (project); l; l = g_list_next (l))
+ for (l = glade_project_selection_get (priv->project); l; l = g_list_next (l))
{
GtkWidget *selection = l->data;
@@ -685,13 +956,19 @@ glade_design_layout_draw (GtkWidget * widget, cairo_t * cr)
border_width + PADDING,
priv->current_width + 2 * OUTLINE_WIDTH,
priv->current_height + 2 * OUTLINE_WIDTH);
+
+ /* Draw selection nodes if we are in margins edit mode */
+ if (priv->selection)
+ draw_selection_nodes (cr, widget, priv->selection,
+ &priv->frame_color_active[0],
+ &priv->frame_color_active[1]);
}
}
else if (gtk_cairo_should_draw_window (cr, priv->offscreen_window))
{
GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
- gtk_render_background (gtk_widget_get_style_context (widget),
+ gtk_render_background (gtk_widget_get_style_context (child),
cr,
0, 0,
gdk_window_get_width (priv->offscreen_window),
@@ -747,7 +1024,7 @@ pick_offscreen_child (GdkWindow *offscreen_window,
gtk_widget_get_allocation (child, &child_area);
if (x >= 0 && x < child_area.width && y >= 0 && y < child_area.height)
- return priv->offscreen_window;
+ return (priv->selection) ? NULL : priv->offscreen_window;
}
return NULL;
@@ -853,12 +1130,22 @@ glade_design_layout_realize (GtkWidget * widget)
gtk_style_context_set_background (context, priv->offscreen_window);
gdk_window_show (priv->offscreen_window);
+ gdk_window_set_cursor (priv->window, NULL);
+ gdk_window_set_cursor (priv->offscreen_window, NULL);
+
/* Allocate cursors */
display = gtk_widget_get_display (widget);
priv->cursors[ACTIVITY_RESIZE_HEIGHT] = gdk_cursor_new_for_display (display, GDK_BOTTOM_SIDE);
priv->cursors[ACTIVITY_RESIZE_WIDTH] = gdk_cursor_new_for_display (display, GDK_RIGHT_SIDE);
priv->cursors[ACTIVITY_RESIZE_WIDTH_AND_HEIGHT] = gdk_cursor_new_for_display (display, GDK_BOTTOM_RIGHT_CORNER);
+ priv->cursors[ACTIVITY_MARGINS_VERTICAL] = gdk_cursor_new_for_display (display, GDK_SB_V_DOUBLE_ARROW);
+ priv->cursors[ACTIVITY_MARGINS_HORIZONTAL] = gdk_cursor_new_for_display (display, GDK_SB_H_DOUBLE_ARROW);
+ priv->cursors[ACTIVITY_MARGINS_TOP_LEFT] = gdk_cursor_new_for_display (display, GDK_TOP_LEFT_CORNER);
+ priv->cursors[ACTIVITY_MARGINS_TOP_RIGHT] = gdk_cursor_new_for_display (display, GDK_TOP_RIGHT_CORNER);
+ priv->cursors[ACTIVITY_MARGINS_BOTTOM_LEFT] = gdk_cursor_new_for_display (display, GDK_BOTTOM_LEFT_CORNER);
+ priv->cursors[ACTIVITY_MARGINS_BOTTOM_RIGHT] = gdk_cursor_ref (priv->cursors[ACTIVITY_RESIZE_WIDTH_AND_HEIGHT]);
+
priv->widget_name = pango_layout_new (gtk_widget_get_pango_context (widget));
}
@@ -866,7 +1153,8 @@ static void
glade_design_layout_unrealize (GtkWidget * widget)
{
GladeDesignLayoutPrivate *priv;
-
+ gint i;
+
priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
if (priv->offscreen_window)
@@ -875,23 +1163,19 @@ glade_design_layout_unrealize (GtkWidget * widget)
gdk_window_destroy (priv->offscreen_window);
priv->offscreen_window = NULL;
}
-
- if (priv->cursors[ACTIVITY_RESIZE_HEIGHT])
- {
- gdk_cursor_unref (priv->cursors[ACTIVITY_RESIZE_HEIGHT]);
- priv->cursors[ACTIVITY_RESIZE_HEIGHT] = NULL;
- }
- if (priv->cursors[ACTIVITY_RESIZE_WIDTH])
- {
- gdk_cursor_unref (priv->cursors[ACTIVITY_RESIZE_WIDTH]);
- priv->cursors[ACTIVITY_RESIZE_WIDTH] = NULL;
- }
- if (priv->cursors[ACTIVITY_RESIZE_WIDTH_AND_HEIGHT])
+
+ /* Free cursors */
+ for (i = 0; i < N_ACTIVITY; i++)
{
- gdk_cursor_unref (priv->cursors[ACTIVITY_RESIZE_WIDTH_AND_HEIGHT]);
- priv->cursors[ACTIVITY_RESIZE_WIDTH_AND_HEIGHT] = NULL;
+ if (priv->cursors[i])
+ {
+ gdk_cursor_unref (priv->cursors[i]);
+ priv->cursors[i] = NULL;
+ }
}
+ priv->cursor = NULL;
+
if (priv->widget_name)
{
g_object_unref (priv->widget_name);
@@ -939,15 +1223,13 @@ static void
glade_design_layout_init (GladeDesignLayout *layout)
{
GladeDesignLayoutPrivate *priv;
-
+ gint i;
+
layout->priv = priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (layout);
priv->activity = ACTIVITY_NONE;
- priv->cursors[ACTIVITY_NONE] = NULL;
- priv->cursors[ACTIVITY_RESIZE_HEIGHT] = NULL;
- priv->cursors[ACTIVITY_RESIZE_WIDTH] = NULL;
- priv->cursors[ACTIVITY_RESIZE_WIDTH_AND_HEIGHT] = NULL;
+ for (i = 0; i < N_ACTIVITY; i++) priv->cursors[i] = NULL;
priv->new_width = -1;
priv->new_height = -1;
@@ -968,7 +1250,11 @@ glade_design_layout_set_property (GObject *object,
switch (prop_id)
{
case PROP_DESIGN_VIEW:
- GLADE_DESIGN_LAYOUT_GET_PRIVATE (object)->view = GLADE_DESIGN_VIEW (g_value_get_object (value));
+ {
+ GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (object);
+ priv->view = GLADE_DESIGN_VIEW (g_value_get_object (value));
+ priv->project = glade_design_view_get_project (priv->view);
+ }
break;
default:
@@ -996,6 +1282,48 @@ glade_design_layout_get_property (GObject * object,
}
static void
+on_project_selection_changed (GladeProject *project, GladeDesignLayout *layout)
+{
+ layout->priv->selection = NULL;
+ glade_project_set_pointer_mode (layout->priv->project, GLADE_POINTER_SELECT);
+ gtk_widget_queue_draw (GTK_WIDGET (layout));
+}
+
+static GObject *
+glade_design_layout_constructor (GType type,
+ guint n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ GladeDesignLayoutPrivate *priv;
+ GObject *object;
+
+ object = G_OBJECT_CLASS (glade_design_layout_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+
+ priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (object);
+
+ g_signal_connect (priv->project,
+ "selection-changed",
+ G_CALLBACK (on_project_selection_changed),
+ GLADE_DESIGN_LAYOUT (object));
+
+ return object;
+}
+
+static void
+glade_design_layout_finalize (GObject *object)
+{
+ GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (object);
+
+ g_signal_handlers_disconnect_by_func (priv->project,
+ on_project_selection_changed,
+ GLADE_DESIGN_LAYOUT (object));
+
+ G_OBJECT_CLASS (glade_design_layout_parent_class)->finalize (object);
+}
+
+static void
glade_design_layout_class_init (GladeDesignLayoutClass * klass)
{
GObjectClass *object_class;
@@ -1006,6 +1334,7 @@ glade_design_layout_class_init (GladeDesignLayoutClass * klass)
widget_class = GTK_WIDGET_CLASS (klass);
container_class = GTK_CONTAINER_CLASS (klass);
+ object_class->constructor = glade_design_layout_constructor;
object_class->finalize = glade_design_layout_finalize;
object_class->set_property = glade_design_layout_set_property;
object_class->get_property = glade_design_layout_get_property;
@@ -1060,27 +1389,47 @@ _glade_design_layout_new (GladeDesignView *view)
* Returns: true if the event was handled.
*/
gboolean
-_glade_design_layout_do_event (GladeDesignLayout * layout, GdkEvent * event)
+_glade_design_layout_do_event (GladeDesignLayout *layout, GdkEvent *event)
{
GladeFindInContainerData data = { 0, };
GladeDesignLayoutPrivate *priv;
GtkWidget *child;
gboolean retval;
-
+ GList *l;
+
if ((child = gtk_bin_get_child (GTK_BIN (layout))) == NULL)
return FALSE;
priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (layout);
- data.toplevel = GTK_WIDGET (layout);
- gtk_widget_get_pointer (GTK_WIDGET (layout), &data.x, &data.y);
+ data.toplevel = GTK_WIDGET (child);
+ gtk_widget_get_pointer (GTK_WIDGET (child), &data.x, &data.y);
- glade_design_layout_find_inside_container (child, &data);
+ /* Check if we want to enter in margin edit mode */
+ if (event->type == GDK_BUTTON_PRESS &&
+ (l = glade_project_selection_get (priv->project)) &&
+ g_list_next (l) == NULL && GTK_IS_WIDGET (l->data) &&
+ gtk_widget_is_ancestor (l->data, child))
+ {
+ if (gdl_get_margins_from_pointer (l->data, data.x, data.y))
+ {
+ if (priv->selection == NULL)
+ {
+ priv->selection = l->data;
+ glade_project_set_pointer_mode (priv->project, GLADE_POINTER_MARGIN_MODE);
+ gtk_widget_queue_draw (GTK_WIDGET (layout));
+ return TRUE;
+ }
+ return FALSE;
+ }
+ }
_glade_design_view_freeze (priv->view);
-
+
+ glade_design_layout_find_inside_container (child, &data);
+
/* Try the placeholder first */
- if (data.placeholder && gtk_widget_event (data.placeholder, event))
+ if (data.placeholder && gtk_widget_event (data.placeholder, event))
retval = TRUE;
else if (data.gwidget) /* Then we try a GladeWidget */
retval = glade_widget_event (data.gwidget, event);
diff --git a/gladeui/glade-placeholder.c b/gladeui/glade-placeholder.c
index 4b16cd4d..beaf23c5 100644
--- a/gladeui/glade-placeholder.c
+++ b/gladeui/glade-placeholder.c
@@ -50,31 +50,32 @@
#define WIDTH_REQUISITION 20
#define HEIGHT_REQUISITION 20
-static void glade_placeholder_finalize (GObject * object);
-static void glade_placeholder_set_property (GObject * object,
+static void glade_placeholder_finalize (GObject *object);
+static void glade_placeholder_set_property (GObject *object,
guint prop_id,
- const GValue * value,
- GParamSpec * pspec);
-static void glade_placeholder_get_property (GObject * object,
+ const GValue *value,
+ GParamSpec *pspec);
+static void glade_placeholder_get_property (GObject *object,
guint prop_id,
- GValue * value, GParamSpec * pspec);
-static void glade_placeholder_realize (GtkWidget * widget);
-static void glade_placeholder_unrealize (GtkWidget * widget);
-static void glade_placeholder_map (GtkWidget * widget);
-static void glade_placeholder_unmap (GtkWidget * widget);
+ GValue *value,
+ GParamSpec *pspec);
+static void glade_placeholder_realize (GtkWidget *widget);
+static void glade_placeholder_unrealize (GtkWidget *widget);
+static void glade_placeholder_map (GtkWidget *widget);
+static void glade_placeholder_unmap (GtkWidget *widget);
-static void glade_placeholder_size_allocate (GtkWidget * widget,
- GtkAllocation * allocation);
+static void glade_placeholder_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
-static gboolean glade_placeholder_draw (GtkWidget * widget, cairo_t * cr);
+static gboolean glade_placeholder_draw (GtkWidget *widget, cairo_t *cr);
-static gboolean glade_placeholder_motion_notify_event (GtkWidget * widget,
- GdkEventMotion * event);
+static gboolean glade_placeholder_motion_notify_event (GtkWidget *widget,
+ GdkEventMotion *event);
-static gboolean glade_placeholder_button_press (GtkWidget * widget,
- GdkEventButton * event);
+static gboolean glade_placeholder_button_press (GtkWidget *widget,
+ GdkEventButton *event);
-static gboolean glade_placeholder_popup_menu (GtkWidget * widget);
+static gboolean glade_placeholder_popup_menu (GtkWidget *widget);
static cairo_pattern_t *placeholder_pattern = NULL;
@@ -95,10 +96,14 @@ enum
PROP_VSCROLL_POLICY
};
+#define GLADE_PLACEHOLDER_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
+ GLADE_TYPE_PLACEHOLDER, \
+ GladePlaceholderPrivate))
+
G_DEFINE_TYPE_WITH_CODE (GladePlaceholder, glade_placeholder, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
-static void glade_placeholder_class_init (GladePlaceholderClass * klass)
+static void glade_placeholder_class_init (GladePlaceholderClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -146,8 +151,9 @@ static void glade_placeholder_class_init (GladePlaceholderClass * klass)
}
static void
-glade_placeholder_notify_parent (GObject * gobject,
- GParamSpec * arg1, gpointer user_data)
+glade_placeholder_notify_parent (GObject *gobject,
+ GParamSpec *arg1,
+ gpointer user_data)
{
GladePlaceholder *placeholder = GLADE_PLACEHOLDER (gobject);
GladeWidgetAdaptor *parent_adaptor = NULL;
@@ -170,12 +176,9 @@ glade_placeholder_notify_parent (GObject * gobject,
}
static void
-glade_placeholder_init (GladePlaceholder * placeholder)
+glade_placeholder_init (GladePlaceholder *placeholder)
{
- placeholder->priv =
- G_TYPE_INSTANCE_GET_PRIVATE (placeholder,
- GLADE_TYPE_PLACEHOLDER,
- GladePlaceholderPrivate);
+ placeholder->priv = GLADE_PLACEHOLDER_GET_PRIVATE (placeholder);
placeholder->priv->packing_actions = NULL;
@@ -194,7 +197,7 @@ glade_placeholder_init (GladePlaceholder * placeholder)
}
static void
-glade_placeholder_finalize (GObject * object)
+glade_placeholder_finalize (GObject *object)
{
GladePlaceholder *placeholder;
@@ -211,9 +214,10 @@ glade_placeholder_finalize (GObject * object)
}
static void
-glade_placeholder_set_property (GObject * object,
+glade_placeholder_set_property (GObject *object,
guint prop_id,
- const GValue * value, GParamSpec * pspec)
+ const GValue *value,
+ GParamSpec *pspec)
{
switch (prop_id)
@@ -230,9 +234,10 @@ glade_placeholder_set_property (GObject * object,
}
static void
-glade_placeholder_get_property (GObject * object,
+glade_placeholder_get_property (GObject *object,
guint prop_id,
- GValue * value, GParamSpec * pspec)
+ GValue *value,
+ GParamSpec *pspec)
{
switch (prop_id)
{
@@ -251,7 +256,7 @@ glade_placeholder_get_property (GObject * object,
}
static void
-glade_placeholder_realize (GtkWidget * widget)
+glade_placeholder_realize (GtkWidget *widget)
{
GladePlaceholder *placeholder;
GtkAllocation allocation;
@@ -291,7 +296,7 @@ glade_placeholder_realize (GtkWidget * widget)
}
static void
-glade_placeholder_unrealize (GtkWidget * widget)
+glade_placeholder_unrealize (GtkWidget *widget)
{
GladePlaceholder *placeholder;
@@ -308,7 +313,7 @@ glade_placeholder_unrealize (GtkWidget * widget)
}
static void
-glade_placeholder_map (GtkWidget * widget)
+glade_placeholder_map (GtkWidget *widget)
{
GladePlaceholder *placeholder;
@@ -323,7 +328,7 @@ glade_placeholder_map (GtkWidget * widget)
}
static void
-glade_placeholder_unmap (GtkWidget * widget)
+glade_placeholder_unmap (GtkWidget *widget)
{
GladePlaceholder *placeholder;
@@ -338,7 +343,7 @@ glade_placeholder_unmap (GtkWidget * widget)
}
static void
-glade_placeholder_size_allocate (GtkWidget * widget, GtkAllocation * allocation)
+glade_placeholder_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
{
GladePlaceholder *placeholder;
@@ -355,7 +360,7 @@ glade_placeholder_size_allocate (GtkWidget * widget, GtkAllocation * allocation)
}
static gboolean
-glade_placeholder_draw (GtkWidget * widget, cairo_t * cr)
+glade_placeholder_draw (GtkWidget *widget, cairo_t *cr)
{
GtkStyle *style;
GdkColor *light;
@@ -389,9 +394,9 @@ glade_placeholder_draw (GtkWidget * widget, cairo_t * cr)
}
static gboolean
-glade_placeholder_motion_notify_event (GtkWidget * widget,
- GdkEventMotion * event)
+glade_placeholder_motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
{
+ GladePlaceholder *placeholder = GLADE_PLACEHOLDER (widget);
GladePointerMode pointer_mode;
GladeProject *project;
@@ -409,7 +414,7 @@ glade_placeholder_motion_notify_event (GtkWidget * widget,
}
static gboolean
-glade_placeholder_button_press (GtkWidget * widget, GdkEventButton * event)
+glade_placeholder_button_press (GtkWidget *widget, GdkEventButton *event)
{
GladePlaceholder *placeholder;
GladeProject *project;
@@ -458,7 +463,7 @@ glade_placeholder_button_press (GtkWidget * widget, GdkEventButton * event)
}
static gboolean
-glade_placeholder_popup_menu (GtkWidget * widget)
+glade_placeholder_popup_menu (GtkWidget *widget)
{
g_return_val_if_fail (GLADE_IS_PLACEHOLDER (widget), FALSE);
@@ -480,7 +485,7 @@ glade_placeholder_new (void)
}
GladeProject *
-glade_placeholder_get_project (GladePlaceholder * placeholder)
+glade_placeholder_get_project (GladePlaceholder *placeholder)
{
GladeWidget *parent;
parent = glade_placeholder_get_parent (placeholder);
@@ -488,7 +493,7 @@ glade_placeholder_get_project (GladePlaceholder * placeholder)
}
GladeWidget *
-glade_placeholder_get_parent (GladePlaceholder * placeholder)
+glade_placeholder_get_parent (GladePlaceholder *placeholder)
{
GtkWidget *widget;
GladeWidget *parent = NULL;
diff --git a/gladeui/glade-project.h b/gladeui/glade-project.h
index ab589b00..1fa7b86e 100644
--- a/gladeui/glade-project.h
+++ b/gladeui/glade-project.h
@@ -34,6 +34,7 @@ typedef enum
GLADE_POINTER_SELECT = 0,
GLADE_POINTER_ADD_WIDGET,
GLADE_POINTER_DRAG_RESIZE
+ GLADE_POINTER_MARGIN_MODE
} GladePointerMode;
typedef enum