[accounts-dialog] Split the "crop area" work from the photo dialogue



commit 4087f3b3b5c27c685458ddd39954de80e5da8276
Author: Bastien Nocera <hadess hadess net>
Date:   Tue Jan 12 21:28:48 2010 +0000

    Split the "crop area" work from the photo dialogue
    
    So it can be reused.

 src/Makefile.am       |    2 +
 src/um-crop-area.c    |  643 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/um-crop-area.h    |   62 +++++
 src/um-photo-dialog.c |  575 ++------------------------------------------
 4 files changed, 723 insertions(+), 559 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index fc12806..7493cbd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,6 +35,8 @@ accounts_dialog_SOURCES = \
 	um-password-dialog.c		\
 	um-photo-dialog.h		\
 	um-photo-dialog.c		\
+	um-crop-area.h			\
+	um-crop-area.c			\
 	um-utils.h			\
 	um-utils.c			\
 	main.c
diff --git a/src/um-crop-area.c b/src/um-crop-area.c
new file mode 100644
index 0000000..a10340c
--- /dev/null
+++ b/src/um-crop-area.c
@@ -0,0 +1,643 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009  Red Hat, Inc,
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Written by: Matthias Clasen <mclasen redhat com>
+ */
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "um-crop-area.h"
+
+struct _UmCropAreaPrivate {
+	GdkPixbuf *browse_pixbuf;
+	GdkPixbuf *pixbuf;
+	GdkPixbuf *color_shifted;
+	gdouble scale;
+	GdkRectangle image;
+	GdkCursorType current_cursor;
+	GdkRectangle crop;
+	gint active_region;
+	gint last_press_x;
+	gint last_press_y;
+};
+
+G_DEFINE_TYPE (UmCropArea, um_crop_area, GTK_TYPE_DRAWING_AREA);
+
+static inline guchar
+shift_color_byte (guchar b,
+                  int    shift)
+{
+	return CLAMP(b + shift, 0, 255);
+}
+
+static void
+shift_colors (GdkPixbuf *pixbuf,
+	      gint       red,
+	      gint       green,
+	      gint       blue,
+	      gint       alpha)
+{
+	gint x, y, offset, y_offset, rowstride, width, height;
+	guchar *pixels;
+	gint channels;
+
+	width = gdk_pixbuf_get_width (pixbuf);
+	height = gdk_pixbuf_get_height (pixbuf);
+	rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+	pixels = gdk_pixbuf_get_pixels (pixbuf);
+	channels = gdk_pixbuf_get_n_channels (pixbuf);
+
+	for (y = 0; y < height; y++) {
+		y_offset = y * rowstride;
+		for (x = 0; x < width; x++) {
+			offset = y_offset + x * channels;
+			if (red != 0)
+				pixels[offset] = shift_color_byte (pixels[offset], red);
+			if (green != 0)
+				pixels[offset + 1] = shift_color_byte (pixels[offset + 1], green);
+			if (blue != 0)
+				pixels[offset + 2] = shift_color_byte (pixels[offset + 2], blue);
+			if (alpha != 0 && channels >= 4)
+				pixels[offset + 3] = shift_color_byte (pixels[offset + 3], blue);
+		}
+	}
+}
+
+static void
+update_pixbufs (UmCropArea *area)
+{
+	gint width;
+	gint height;
+	GtkAllocation allocation;
+	gdouble scale;
+	GdkColor *color;
+	guint32 pixel;
+	gint dest_x, dest_y, dest_width, dest_height;
+	GtkWidget *widget;
+
+	widget = GTK_WIDGET (area);
+	gtk_widget_get_allocation (widget, &allocation);
+
+	if (area->priv->pixbuf == NULL ||
+	    gdk_pixbuf_get_width (area->priv->pixbuf) != allocation.width ||
+	    gdk_pixbuf_get_height (area->priv->pixbuf) != allocation.height) {
+		if (area->priv->pixbuf != NULL)
+			g_object_unref (area->priv->pixbuf);
+		area->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+					     allocation.width, allocation.height);
+
+		color = &widget->style->bg[GTK_WIDGET_STATE (widget)];
+  		pixel = ((color->red & 0xff00) << 16) |
+       			((color->green & 0xff00) << 8) |
+         		 (color->blue & 0xff00);
+		gdk_pixbuf_fill (area->priv->pixbuf, pixel);
+
+		width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
+		height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
+
+		scale = allocation.height / (gdouble)height;
+		if (scale * width > allocation.width)
+		    scale = allocation.width / (gdouble)width;
+
+		dest_width = width * scale;
+		dest_height = height * scale;
+		dest_x = (allocation.width - dest_width) / 2;
+		dest_y = (allocation.height - dest_height) / 2,
+
+		gdk_pixbuf_scale (area->priv->browse_pixbuf,
+				  area->priv->pixbuf,
+				  dest_x, dest_y,
+				  dest_width, dest_height,
+				  dest_x, dest_y,
+				  scale, scale,
+				  GDK_INTERP_BILINEAR);
+
+		if (area->priv->color_shifted)
+			g_object_unref (area->priv->color_shifted);
+		area->priv->color_shifted = gdk_pixbuf_copy (area->priv->pixbuf);
+		shift_colors (area->priv->color_shifted, -32, -32, -32, 0);
+
+		if (area->priv->scale == 0.0) {
+			area->priv->crop.width = 96.0 / scale;
+			area->priv->crop.height = 96.0 / scale;
+			area->priv->crop.x = (gdk_pixbuf_get_width (area->priv->browse_pixbuf) - area->priv->crop.width) / 2;
+			area->priv->crop.y = (gdk_pixbuf_get_height (area->priv->browse_pixbuf) - area->priv->crop.height) / 2;
+		}
+
+		area->priv->scale = scale;
+		area->priv->image.x = dest_x;
+		area->priv->image.y = dest_y;
+		area->priv->image.width = dest_width;
+		area->priv->image.height = dest_height;
+	}
+}
+
+static void
+crop_to_widget (UmCropArea    *area,
+                GdkRectangle  *crop)
+{
+	crop->x = area->priv->image.x + area->priv->crop.x * area->priv->scale;
+	crop->y = area->priv->image.y + area->priv->crop.y * area->priv->scale;
+	crop->width = area->priv->crop.width * area->priv->scale;
+	crop->height = area->priv->crop.height * area->priv->scale;
+}
+
+typedef enum {
+	OUTSIDE,
+	INSIDE,
+	TOP,
+	TOP_LEFT,
+	TOP_RIGHT,
+	BOTTOM,
+	BOTTOM_LEFT,
+	BOTTOM_RIGHT,
+	LEFT,
+	RIGHT
+} Location;
+
+static gboolean
+um_crop_area_expose (GtkWidget      *widget,
+		     GdkEventExpose *event)
+{
+	cairo_t *cr;
+	GdkRectangle area;
+	GdkRectangle crop;
+	gint width, height;
+	UmCropArea *uarea = UM_CROP_AREA (widget);
+
+	if (uarea->priv->browse_pixbuf == NULL)
+		return FALSE;
+
+	update_pixbufs (uarea);
+
+	width = gdk_pixbuf_get_width (uarea->priv->pixbuf);
+	height = gdk_pixbuf_get_height (uarea->priv->pixbuf);
+	crop_to_widget (uarea, &crop);
+
+	area.x = 0;
+	area.y = 0;
+	area.width = width;
+	area.height = crop.y;
+	gdk_rectangle_intersect (&area, &event->area, &area);
+	gdk_draw_pixbuf (widget->window,
+		 	 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+			 uarea->priv->color_shifted,
+		 	 area.x, area.y,
+		 	 area.x, area.y,
+		 	 area.width, area.height,
+		 	 GDK_RGB_DITHER_NONE, 0, 0);
+
+	area.x = 0;
+	area.y = crop.y;
+	area.width = crop.x;
+	area.height = crop.height;
+	gdk_rectangle_intersect (&area, &event->area, &area);
+	gdk_draw_pixbuf (widget->window,
+		 	 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+			 uarea->priv->color_shifted,
+		 	 area.x, area.y,
+		 	 area.x, area.y,
+		 	 area.width, area.height,
+		 	 GDK_RGB_DITHER_NONE, 0, 0);
+
+	area.x = crop.x;
+	area.y = crop.y;
+	area.width = crop.width;
+	area.height = crop.height;
+	gdk_rectangle_intersect (&area, &event->area, &area);
+	gdk_draw_pixbuf (widget->window,
+			 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+			 uarea->priv->pixbuf,
+			 area.x, area.y,
+			 area.x, area.y,
+			 area.width, area.height,
+			 GDK_RGB_DITHER_NONE, 0, 0);
+
+	area.x = crop.x + crop.width;
+	area.y = crop.y;
+	area.width = width - area.x;
+	area.height = crop.height;
+	gdk_rectangle_intersect (&area, &event->area, &area);
+	gdk_draw_pixbuf (widget->window,
+		 	 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+			 uarea->priv->color_shifted,
+		 	 area.x, area.y,
+		 	 area.x, area.y,
+		 	 area.width, area.height,
+		 	 GDK_RGB_DITHER_NONE, 0, 0);
+
+	area.x = 0;
+	area.y = crop.y + crop.width;
+	area.width = width;
+	area.height = height - area.y;
+	gdk_rectangle_intersect (&area, &event->area, &area);
+	gdk_draw_pixbuf (widget->window,
+		 	 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+			 uarea->priv->color_shifted,
+		 	 area.x, area.y,
+		 	 area.x, area.y,
+		 	 area.width, area.height,
+		 	 GDK_RGB_DITHER_NONE, 0, 0);
+
+	cr = gdk_cairo_create (widget->window);
+	gdk_cairo_rectangle (cr, &event->area);
+	cairo_clip (cr);
+
+	if (uarea->priv->active_region != OUTSIDE) {
+		gint x1, x2, y1, y2;
+		gdk_cairo_set_source_color (cr, &widget->style->white);
+		cairo_set_line_width (cr, 1.0);
+		x1 = crop.x + crop.width / 3.0;
+		x2 = crop.x + 2 * crop.width / 3.0;
+		y1 = crop.y + crop.height / 3.0;
+		y2 = crop.y + 2 * crop.height / 3.0;
+
+		cairo_move_to (cr, x1 + 0.5, crop.y);
+		cairo_line_to (cr, x1 + 0.5, crop.y + crop.height);
+
+		cairo_move_to (cr, x2 + 0.5, crop.y);
+		cairo_line_to (cr, x2 + 0.5, crop.y + crop.height);
+
+		cairo_move_to (cr, crop.x, y1 + 0.5);
+		cairo_line_to (cr, crop.x + crop.width, y1 + 0.5);
+
+		cairo_move_to (cr, crop.x, y2 + 0.5);
+		cairo_line_to (cr, crop.x + crop.width, y2 + 0.5);
+		cairo_stroke (cr);
+	}
+
+	gdk_cairo_set_source_color (cr, &widget->style->black);
+	cairo_set_line_width (cr, 1.0);
+	cairo_rectangle (cr,
+                         crop.x + 0.5,
+                         crop.y + 0.5,
+                         crop.width - 1.0,
+                         crop.height - 1.0);
+        cairo_stroke (cr);
+
+	gdk_cairo_set_source_color (cr, &widget->style->white);
+	cairo_set_line_width (cr, 2.0);
+	cairo_rectangle (cr,
+                         crop.x + 2.0,
+                         crop.y + 2.0,
+                         crop.width - 4.0,
+                         crop.height - 4.0);
+        cairo_stroke (cr);
+
+	cairo_destroy (cr);
+
+	return FALSE;
+}
+
+typedef enum {
+	BELOW,
+	LOWER,
+	BETWEEN,
+	UPPER,
+	ABOVE
+} Range;
+
+static Range
+find_range (gint x,
+            gint min,
+            gint max)
+{
+	gint tolerance = 12;
+
+	if (x < min - tolerance)
+		return BELOW;
+	if (x <= min + tolerance)
+		return LOWER;
+	if (x < max - tolerance)
+		return BETWEEN;
+	if (x <= max + tolerance)
+		return UPPER;
+	return ABOVE;
+}
+
+static Location
+find_location (GdkRectangle *rect,
+	       gint          x,
+	       gint          y)
+{
+	Range x_range, y_range;
+	Location location[5][5] = {
+		{ OUTSIDE, OUTSIDE,     OUTSIDE, OUTSIDE,      OUTSIDE },
+		{ OUTSIDE, TOP_LEFT,    TOP,     TOP_RIGHT,    OUTSIDE },
+		{ OUTSIDE, LEFT,        INSIDE,  RIGHT,        OUTSIDE },
+		{ OUTSIDE, BOTTOM_LEFT, BOTTOM,  BOTTOM_RIGHT, OUTSIDE },
+		{ OUTSIDE, OUTSIDE,     OUTSIDE, OUTSIDE,      OUTSIDE }
+	};
+
+	x_range = find_range (x, rect->x, rect->x + rect->width);
+	y_range = find_range (y, rect->y, rect->y + rect->height);
+
+	return location[y_range][x_range];
+}
+
+static void
+update_cursor (UmCropArea *area,
+               gint           x,
+               gint           y)
+{
+	gint cursor_type;
+	GdkRectangle crop;
+
+	crop_to_widget (area, &crop);
+
+	switch (find_location (&crop, x, y)) {
+	case OUTSIDE:
+		cursor_type = GDK_LEFT_PTR;
+		break;
+	case TOP_LEFT:
+		cursor_type = GDK_TOP_LEFT_CORNER;
+		break;
+	case TOP:
+		cursor_type = GDK_TOP_SIDE;
+		break;
+	case TOP_RIGHT:
+		cursor_type = GDK_TOP_RIGHT_CORNER;
+		break;
+	case LEFT:
+		cursor_type = GDK_LEFT_SIDE;
+		break;
+	case INSIDE:
+		cursor_type = GDK_FLEUR;
+		break;
+	case RIGHT:
+		cursor_type = GDK_RIGHT_SIDE;
+		break;
+	case BOTTOM_LEFT:
+		cursor_type = GDK_BOTTOM_LEFT_CORNER;
+		break;
+	case BOTTOM:
+		cursor_type = GDK_BOTTOM_SIDE;
+		break;
+	case BOTTOM_RIGHT:
+		cursor_type = GDK_BOTTOM_RIGHT_CORNER;
+		break;
+	}
+
+	if (cursor_type != area->priv->current_cursor) {
+		GdkCursor *cursor = gdk_cursor_new (cursor_type);
+		gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (area)), cursor);
+		gdk_cursor_unref (cursor);
+		area->priv->current_cursor = cursor_type;
+	}
+}
+
+static gboolean 
+um_crop_area_motion_notify_event (GtkWidget      *widget,
+				  GdkEventMotion *event)
+{
+	gint x, y;
+	gint x2, y2;
+	gint delta_x, delta_y;
+	gint width, height, d;
+	UmCropArea *area = UM_CROP_AREA (widget);
+
+	width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
+	height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
+
+	x = (event->x - area->priv->image.x) / area->priv->scale;
+	y = (event->y - area->priv->image.y) / area->priv->scale;
+	x = CLAMP (x, 0, width);
+	y = CLAMP (y, 0, height);
+
+	delta_x = x - area->priv->last_press_x;
+	delta_y = y - area->priv->last_press_y;
+	area->priv->last_press_x = x;
+	area->priv->last_press_y = y;
+
+	x2 = area->priv->crop.x + area->priv->crop.width;
+	y2 = area->priv->crop.y + area->priv->crop.height;
+
+	switch (area->priv->active_region) {
+ 	case INSIDE:
+		area->priv->crop.x = CLAMP (area->priv->crop.x + delta_x, 0, width - area->priv->crop.width);
+		area->priv->crop.y = CLAMP (area->priv->crop.y + delta_y, 0, height - area->priv->crop.height);
+		break;
+
+	case TOP_LEFT:
+		d = MAX (x2 - x, y2 - y);
+		if (d < 48 / area->priv->scale)
+			d = 48 / area->priv->scale;
+		if (x2 - d < 0)
+			d = x2;
+		if (y2 - d < 0)
+			d = y2;
+		area->priv->crop.x = x2 - d;
+		area->priv->crop.y = y2 - d;
+		area->priv->crop.width = area->priv->crop.height = d;
+		break;
+
+	case TOP:
+	case TOP_RIGHT:
+		d = MAX (y2 - y, x - area->priv->crop.x);
+		if (d < 48 / area->priv->scale)
+			d = 48 / area->priv->scale;
+		if (area->priv->crop.x + d > width)
+			d = width - area->priv->crop.x;
+		if (y2 - d < 0)
+			d = y2;
+		area->priv->crop.y = y2 - d;
+		area->priv->crop.width = area->priv->crop.height = d;
+		break;
+
+	case LEFT:
+	case BOTTOM_LEFT:
+		d = MAX (x2 - x, y - area->priv->crop.y);
+		if (d < 48 / area->priv->scale)
+			d = 48 / area->priv->scale;
+		if (area->priv->crop.y + d > height)
+			d = height - area->priv->crop.y;
+		if (x2 - d < 0)
+			d = x2;
+		area->priv->crop.x = x2 - d;
+		area->priv->crop.width = area->priv->crop.height = d;
+		break;
+
+	case RIGHT:
+	case BOTTOM_RIGHT:
+	case BOTTOM:
+		area->priv->crop.width = MAX (x - area->priv->crop.x, y - area->priv->crop.y);
+		if (area->priv->crop.width < 48 / area->priv->scale)
+			area->priv->crop.width = 48 / area->priv->scale;
+		if (area->priv->crop.x + area->priv->crop.width > width)
+			area->priv->crop.width = width - area->priv->crop.x;
+		area->priv->crop.height = area->priv->crop.width;
+		if (area->priv->crop.y + area->priv->crop.height > height)
+			area->priv->crop.height = height - area->priv->crop.y;
+		area->priv->crop.width = area->priv->crop.height;
+		break;
+
+	case OUTSIDE:
+		break;
+	default: ;
+	}
+
+	update_cursor (area, event->x, event->y);
+	gtk_widget_queue_draw (widget);
+
+	return FALSE;
+}
+
+static gboolean
+um_crop_area_button_press_event (GtkWidget      *widget,
+				 GdkEventButton *event)
+{
+	GdkRectangle crop;
+	UmCropArea *area = UM_CROP_AREA (widget);
+
+	crop_to_widget (area, &crop);
+
+	area->priv->last_press_x = (event->x - area->priv->image.x) / area->priv->scale;
+	area->priv->last_press_y = (event->y - area->priv->image.y) / area->priv->scale;
+	area->priv->active_region = find_location (&crop, event->x, event->y);
+
+	gtk_widget_queue_draw (widget);
+
+	return FALSE;
+}
+
+static gboolean
+um_crop_area_button_release_event (GtkWidget      *widget,
+				   GdkEventButton *event)
+{
+	UmCropArea *area = UM_CROP_AREA (widget);
+
+	area->priv->last_press_x = -1;
+	area->priv->last_press_y = -1;
+	area->priv->active_region = OUTSIDE;
+
+	gtk_widget_queue_draw (widget);
+
+	return FALSE;
+}
+
+static void
+um_crop_area_finalize (GObject *object)
+{
+	UmCropArea *area = UM_CROP_AREA (object);
+
+	if (area->priv->browse_pixbuf) {
+		g_object_unref (area->priv->browse_pixbuf);
+		area->priv->browse_pixbuf = NULL;
+	}
+	if (area->priv->pixbuf) {
+		g_object_unref (area->priv->pixbuf);
+		area->priv->pixbuf = NULL;
+	}
+	if (area->priv->color_shifted) {
+		g_object_unref (area->priv->color_shifted);
+		area->priv->color_shifted = NULL;
+	}
+}
+
+static void
+um_crop_area_class_init (UmCropAreaClass *klass)
+{
+	GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+	object_class->finalize     = um_crop_area_finalize;
+	widget_class->expose_event = um_crop_area_expose;
+	widget_class->button_press_event = um_crop_area_button_press_event;
+	widget_class->button_release_event = um_crop_area_button_release_event;
+	widget_class->motion_notify_event = um_crop_area_motion_notify_event;
+
+	g_type_class_add_private (klass, sizeof (UmCropAreaPrivate));
+}
+
+static void
+um_crop_area_init (UmCropArea *area)
+{
+	area->priv = (G_TYPE_INSTANCE_GET_PRIVATE ((area), UM_TYPE_CROP_AREA,
+						   UmCropAreaPrivate));
+
+	gtk_widget_add_events (GTK_WIDGET (area), GDK_POINTER_MOTION_MASK |
+			       GDK_BUTTON_PRESS_MASK |
+			       GDK_BUTTON_RELEASE_MASK);
+
+	area->priv->scale = 0.0;
+	area->priv->image.x = 0;
+	area->priv->image.y = 0;
+	area->priv->image.width = 0;
+	area->priv->image.height = 0;
+	area->priv->active_region = OUTSIDE;
+}
+
+GtkWidget *
+um_crop_area_new (void)
+{
+	return g_object_new (UM_TYPE_CROP_AREA, NULL);
+}
+
+GdkPixbuf *
+um_crop_area_get_picture (UmCropArea *area)
+{
+	return gdk_pixbuf_new_subpixbuf (area->priv->browse_pixbuf,
+					 area->priv->crop.x, area->priv->crop.y,
+					 area->priv->crop.width, area->priv->crop.height);
+}
+
+void
+um_crop_area_set_picture (UmCropArea *area,
+			  GdkPixbuf  *pixbuf)
+{
+	int width;
+	int height;
+
+	if (area->priv->browse_pixbuf) {
+		g_object_unref (area->priv->browse_pixbuf);
+		area->priv->browse_pixbuf = NULL;
+	}
+	if (pixbuf) {
+		area->priv->browse_pixbuf = g_object_ref (pixbuf);
+		width = gdk_pixbuf_get_width (pixbuf);
+		height = gdk_pixbuf_get_height (pixbuf);
+	} else {
+		width = 0;
+		height = 0;
+	}
+
+#if 0
+	gtk_widget_get_allocation (um->browse_drawing_area, &allocation);
+	um->priv->crop.width = 96;
+	um->priv->crop.height = 96;
+	um->priv->crop.x = (allocation.width - um->priv->crop.width) / 2;
+	um->priv->crop.y = (allocation.height - um->priv->crop.height) / 2;
+#else
+	area->priv->crop.width = 96;
+	area->priv->crop.height = 96;
+	area->priv->crop.x = (width - area->priv->crop.width) / 2;
+	area->priv->crop.y = (height - area->priv->crop.height) / 2;
+#endif
+	area->priv->scale = 0.0;
+	area->priv->image.x = 0;
+	area->priv->image.y = 0;
+	area->priv->image.width = 0;
+	area->priv->image.height = 0;
+
+	gtk_widget_queue_draw (GTK_WIDGET (area));
+}
+
diff --git a/src/um-crop-area.h b/src/um-crop-area.h
new file mode 100644
index 0000000..c1767ad
--- /dev/null
+++ b/src/um-crop-area.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2009 Bastien Nocera <hadess hadess net>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _UM_CROP_AREA_H_
+#define _UM_CROP_AREA_H_
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define UM_TYPE_CROP_AREA (um_crop_area_get_type ())
+#define UM_CROP_AREA(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), UM_TYPE_CROP_AREA, \
+                                                                           UmCropArea))
+#define UM_CROP_AREA_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), UM_TYPE_CROP_AREA, \
+                                                                        UmCropAreaClass))
+#define UM_IS_CROP_AREA(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UM_TYPE_CROP_AREA))
+#define UM_IS_CROP_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UM_TYPE_CROP_AREA))
+#define UM_CROP_AREA_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), UM_TYPE_CROP_AREA, \
+                                                                          UmCropAreaClass))
+
+typedef struct _UmCropAreaClass UmCropAreaClass;
+typedef struct _UmCropArea UmCropArea;
+typedef struct _UmCropAreaPrivate UmCropAreaPrivate;
+
+struct _UmCropAreaClass
+{
+  GtkDrawingAreaClass parent_class;
+};
+
+struct _UmCropArea
+{
+  GtkDrawingArea parent_instance;
+  UmCropAreaPrivate *priv;
+};
+
+GType um_crop_area_get_type (void) G_GNUC_CONST;
+
+GtkWidget *um_crop_area_new (void);
+GdkPixbuf *um_crop_area_get_picture (UmCropArea *area);
+void um_crop_area_set_picture (UmCropArea *area,
+			       GdkPixbuf  *pixbuf);
+
+G_END_DECLS
+
+#endif /* _UM_CROP_AREA_H_ */
diff --git a/src/um-photo-dialog.c b/src/um-photo-dialog.c
index 5431cbf..a206767 100644
--- a/src/um-photo-dialog.c
+++ b/src/um-photo-dialog.c
@@ -29,6 +29,7 @@
 
 #include "um-photo-dialog.h"
 #include "um-user-manager.h"
+#include "um-crop-area.h"
 
 struct _UmPhotoDialog {
         GtkWidget *dialog;
@@ -46,15 +47,6 @@ struct _UmPhotoDialog {
 
         GnomeDesktopThumbnailFactory *thumb_factory;
         GdkPixbuf *browse_pixbuf;
-        GdkPixbuf *pixbuf;
-        GdkPixbuf *color_shifted;
-        gdouble scale;
-        GdkRectangle image;
-        GdkCursorType current_cursor;
-        GdkRectangle crop;
-        gint active_region;
-        gint last_press_x;
-        gint last_press_y;
 
         UmUser *user;
 };
@@ -96,9 +88,7 @@ accept_photo_dialog (GtkButton     *button,
                 break;
 
         case 1:
-                pb = gdk_pixbuf_new_subpixbuf (um->browse_pixbuf,
-                                               um->crop.x, um->crop.y,
-                                               um->crop.width, um->crop.height);
+                pb = um_crop_area_get_picture (UM_CROP_AREA (um->browse_drawing_area));
                 pb2 = gdk_pixbuf_scale_simple (pb, 96, 96, GDK_INTERP_BILINEAR);
 
                 um_user_set_icon_data (um->user, pb2);
@@ -143,22 +133,8 @@ file_chooser_response (GtkDialog     *chooser,
                 if (um->browse_pixbuf)
                         g_object_unref (um->browse_pixbuf);
                 um->browse_pixbuf = pixbuf;
-                if (um->pixbuf) {
-                        g_object_unref (um->pixbuf);
-                        um->pixbuf = NULL;
-                }
 
-                um->crop.width = 96;
-                um->crop.height = 96;
-                um->crop.x = (gdk_pixbuf_get_width (pixbuf) - um->crop.width) / 2;
-                um->crop.y = (gdk_pixbuf_get_height (pixbuf) - um->crop.height) / 2;
-                um->scale = 0.0;
-                um->image.x = 0;
-                um->image.y = 0;
-                um->image.width = 0;
-                um->image.height = 0;
-
-                gtk_widget_queue_draw (um->browse_drawing_area);
+                um_crop_area_set_picture (UM_CROP_AREA (um->browse_drawing_area), pixbuf);
 
                 g_free (filename);
 
@@ -362,508 +338,6 @@ gallery_item_activated (GtkIconView   *gallery,
         um_photo_dialog_set_user (um, NULL);
 }
 
-static inline guchar
-shift_color_byte (guchar b,
-                  int    shift)
-{
-        return CLAMP(b + shift, 0, 255);
-}
-
-
-static void
-shift_colors (GdkPixbuf *pixbuf,
-              gint       red,
-              gint       green,
-              gint       blue,
-              gint       alpha)
-{
-        gint x, y, offset, y_offset, rowstride, width, height;
-        guchar *pixels;
-        gint channels;
-
-        width = gdk_pixbuf_get_width (pixbuf);
-        height = gdk_pixbuf_get_height (pixbuf);
-        rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-        pixels = gdk_pixbuf_get_pixels (pixbuf);
-        channels = gdk_pixbuf_get_n_channels (pixbuf);
-
-        for (y = 0; y < height; y++) {
-                y_offset = y * rowstride;
-                for (x = 0; x < width; x++) {
-                        offset = y_offset + x * channels;
-                        if (red != 0)
-                                pixels[offset] = shift_color_byte (pixels[offset], red);
-                        if (green != 0)
-                                pixels[offset + 1] = shift_color_byte (pixels[offset + 1], green);
-                        if (blue != 0)
-                                pixels[offset + 2] = shift_color_byte (pixels[offset + 2], blue);
-                        if (alpha != 0 && channels >= 4)
-                                pixels[offset + 3] = shift_color_byte (pixels[offset + 3], blue);
-                }
-        }
-}
-
-static void
-update_pixbufs (UmPhotoDialog *um)
-{
-        gint width;
-        gint height;
-        GtkAllocation allocation;
-        gdouble scale;
-        GdkPixbuf *pixbuf;
-        GdkColor *color;
-        guint32 pixel;
-        gint dest_x, dest_y, dest_width, dest_height;
-        GtkWidget *widget;
-
-        widget = um->browse_drawing_area;
-        gtk_widget_get_allocation (widget, &allocation);
-
-        if (um->pixbuf == NULL ||
-            gdk_pixbuf_get_width (um->pixbuf) != allocation.width ||
-            gdk_pixbuf_get_height (um->pixbuf) != allocation.height) {
-                if (um->pixbuf != NULL)
-                        g_object_unref (um->pixbuf);
-                um->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
-                                             allocation.width, allocation.height);
-
-                color = &widget->style->bg[GTK_WIDGET_STATE (widget)];
-                pixel = ((color->red & 0xff00) << 16) |
-                        ((color->green & 0xff00) << 8) |
-                         (color->blue & 0xff00);
-                gdk_pixbuf_fill (um->pixbuf, pixel);
-
-                width = gdk_pixbuf_get_width (um->browse_pixbuf);
-                height = gdk_pixbuf_get_height (um->browse_pixbuf);
-
-                scale = allocation.height / (gdouble)height;
-                if (scale * width > allocation.width)
-                    scale = allocation.width / (gdouble)width;
-
-                dest_width = width * scale;
-                dest_height = height * scale;
-                dest_x = (allocation.width - dest_width) / 2;
-                dest_y = (allocation.height - dest_height) / 2,
-
-                gdk_pixbuf_scale (um->browse_pixbuf,
-                                  um->pixbuf,
-                                  dest_x, dest_y,
-                                  dest_width, dest_height,
-                                  dest_x, dest_y,
-                                  scale, scale,
-                                  GDK_INTERP_BILINEAR);
-
-                if (um->color_shifted)
-                        g_object_unref (um->color_shifted);
-                um->color_shifted = gdk_pixbuf_copy (um->pixbuf);
-                shift_colors (um->color_shifted, -32, -32, -32, 0);
-
-                if (um->scale == 0.0) {
-                        um->crop.width = 96.0 / scale;
-                        um->crop.height = 96.0 / scale;
-                        um->crop.x = (gdk_pixbuf_get_width (um->browse_pixbuf) - um->crop.width) / 2;
-                        um->crop.y = (gdk_pixbuf_get_height (um->browse_pixbuf) - um->crop.height) / 2;
-                }
-
-                um->scale = scale;
-                um->image.x = dest_x;
-                um->image.y = dest_y;
-                um->image.width = dest_width;
-                um->image.height = dest_height;
-        }
-}
-
-static void
-crop_to_widget (UmPhotoDialog *um,
-                GdkRectangle  *crop)
-{
-        crop->x = um->image.x + um->crop.x * um->scale;
-        crop->y = um->image.y + um->crop.y * um->scale;
-        crop->width = um->crop.width * um->scale;
-        crop->height = um->crop.height * um->scale;
-}
-
-typedef enum {
-        OUTSIDE,
-        INSIDE,
-        TOP,
-        TOP_LEFT,
-        TOP_RIGHT,
-        BOTTOM,
-        BOTTOM_LEFT,
-        BOTTOM_RIGHT,
-        LEFT,
-        RIGHT
-} Location;
-
-static gboolean
-drawing_area_expose (GtkWidget      *widget,
-                     GdkEventExpose *event,
-                     UmPhotoDialog  *um)
-{
-        cairo_t *cr;
-        GdkRectangle area;
-        GdkRectangle crop;
-        gint width, height;
-
-        if (um->browse_pixbuf == NULL)
-                return FALSE;
-
-        update_pixbufs (um);
-
-        width = gdk_pixbuf_get_width (um->pixbuf);
-        height = gdk_pixbuf_get_height (um->pixbuf);
-        crop_to_widget (um, &crop);
-
-        area.x = 0;
-        area.y = 0;
-        area.width = width;
-        area.height = crop.y;
-        gdk_rectangle_intersect (&area, &event->area, &area);
-        gdk_draw_pixbuf (widget->window,
-                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
-                         um->color_shifted,
-                         area.x, area.y,
-                         area.x, area.y,
-                         area.width, area.height,
-                         GDK_RGB_DITHER_NONE, 0, 0);
-
-        area.x = 0;
-        area.y = crop.y;
-        area.width = crop.x;
-        area.height = crop.height;
-        gdk_rectangle_intersect (&area, &event->area, &area);
-        gdk_draw_pixbuf (widget->window,
-                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
-                         um->color_shifted,
-                         area.x, area.y,
-                         area.x, area.y,
-                         area.width, area.height,
-                         GDK_RGB_DITHER_NONE, 0, 0);
-
-        area.x = crop.x;
-        area.y = crop.y;
-        area.width = crop.width;
-        area.height = crop.height;
-        gdk_rectangle_intersect (&area, &event->area, &area);
-        gdk_draw_pixbuf (widget->window,
-                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
-                         um->pixbuf,
-                         area.x, area.y,
-                         area.x, area.y,
-                         area.width, area.height,
-                         GDK_RGB_DITHER_NONE, 0, 0);
-
-        area.x = crop.x + crop.width;
-        area.y = crop.y;
-        area.width = width - area.x;
-        area.height = crop.height;
-        gdk_rectangle_intersect (&area, &event->area, &area);
-        gdk_draw_pixbuf (widget->window,
-                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
-                         um->color_shifted,
-                         area.x, area.y,
-                         area.x, area.y,
-                         area.width, area.height,
-                         GDK_RGB_DITHER_NONE, 0, 0);
-
-        area.x = 0;
-        area.y = crop.y + crop.width;
-        area.width = width;
-        area.height = height - area.y;
-        gdk_rectangle_intersect (&area, &event->area, &area);
-        gdk_draw_pixbuf (widget->window,
-                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
-                         um->color_shifted,
-                         area.x, area.y,
-                         area.x, area.y,
-                         area.width, area.height,
-                         GDK_RGB_DITHER_NONE, 0, 0);
-
-        cr = gdk_cairo_create (widget->window);
-        gdk_cairo_rectangle (cr, &event->area);
-        cairo_clip (cr);
-
-        if (um->active_region != OUTSIDE) {
-                gint x1, x2, y1, y2;
-                gdk_cairo_set_source_color (cr, &widget->style->white);
-                cairo_set_line_width (cr, 1.0);
-                x1 = crop.x + crop.width / 3.0;
-                x2 = crop.x + 2 * crop.width / 3.0;
-                y1 = crop.y + crop.height / 3.0;
-                y2 = crop.y + 2 * crop.height / 3.0;
-
-                cairo_move_to (cr, x1 + 0.5, crop.y);
-                cairo_line_to (cr, x1 + 0.5, crop.y + crop.height);
-
-                cairo_move_to (cr, x2 + 0.5, crop.y);
-                cairo_line_to (cr, x2 + 0.5, crop.y + crop.height);
-
-                cairo_move_to (cr, crop.x, y1 + 0.5);
-                cairo_line_to (cr, crop.x + crop.width, y1 + 0.5);
-
-                cairo_move_to (cr, crop.x, y2 + 0.5);
-                cairo_line_to (cr, crop.x + crop.width, y2 + 0.5);
-                cairo_stroke (cr);
-        }
-
-        gdk_cairo_set_source_color (cr, &widget->style->black);
-        cairo_set_line_width (cr, 1.0);
-        cairo_rectangle (cr,
-                         crop.x + 0.5,
-                         crop.y + 0.5,
-                         crop.width - 1.0,
-                         crop.height - 1.0);
-        cairo_stroke (cr);
-
-        gdk_cairo_set_source_color (cr, &widget->style->white);
-        cairo_set_line_width (cr, 2.0);
-        cairo_rectangle (cr,
-                         crop.x + 2.0,
-                         crop.y + 2.0,
-                         crop.width - 4.0,
-                         crop.height - 4.0);
-        cairo_stroke (cr);
-
-        cairo_destroy (cr);
-
-        return FALSE;
-}
-
-typedef enum {
-        BELOW,
-        LOWER,
-        BETWEEN,
-        UPPER,
-        ABOVE
-} Range;
-
-Range
-find_range (gint x,
-            gint min,
-            gint max)
-{
-        gint tolerance = 12;
-
-        if (x < min - 12)
-                return BELOW;
-        if (x <= min + 12)
-                return LOWER;
-        if (x < max - 12)
-                return BETWEEN;
-        if (x <= max + 12)
-                return UPPER;
-        return ABOVE;
-}
-
-Location
-find_location (GdkRectangle *rect,
-               gint          x,
-               gint          y)
-{
-        Range x_range, y_range;
-        Location location[5][5] = {
-                { OUTSIDE, OUTSIDE,     OUTSIDE, OUTSIDE,      OUTSIDE },
-                { OUTSIDE, TOP_LEFT,    TOP,     TOP_RIGHT,    OUTSIDE },
-                { OUTSIDE, LEFT,        INSIDE,  RIGHT,        OUTSIDE },
-                { OUTSIDE, BOTTOM_LEFT, BOTTOM,  BOTTOM_RIGHT, OUTSIDE },
-                { OUTSIDE, OUTSIDE,     OUTSIDE, OUTSIDE,      OUTSIDE }
-        };
-
-        x_range = find_range (x, rect->x, rect->x + rect->width);
-        y_range = find_range (y, rect->y, rect->y + rect->height);
-
-        return location[y_range][x_range];
-}
-
-static void
-update_cursor (UmPhotoDialog *um,
-               gint           x,
-               gint           y)
-{
-        gint cursor_type;
-        GdkRectangle crop;
-
-        crop_to_widget (um, &crop);
-
-        switch (find_location (&crop, x, y)) {
-        case OUTSIDE:
-                cursor_type = GDK_LEFT_PTR;
-                break;
-        case TOP_LEFT:
-                cursor_type = GDK_TOP_LEFT_CORNER;
-                break;
-        case TOP:
-                cursor_type = GDK_TOP_SIDE;
-                break;
-        case TOP_RIGHT:
-                cursor_type = GDK_TOP_RIGHT_CORNER;
-                break;
-        case LEFT:
-                cursor_type = GDK_LEFT_SIDE;
-                break;
-        case INSIDE:
-                cursor_type = GDK_FLEUR;
-                break;
-        case RIGHT:
-                cursor_type = GDK_RIGHT_SIDE;
-                break;
-        case BOTTOM_LEFT:
-                cursor_type = GDK_BOTTOM_LEFT_CORNER;
-                break;
-        case BOTTOM:
-                cursor_type = GDK_BOTTOM_SIDE;
-                break;
-        case BOTTOM_RIGHT:
-                cursor_type = GDK_BOTTOM_RIGHT_CORNER;
-                break;
-        }
-
-        if (cursor_type != um->current_cursor) {
-                GdkCursor *cursor = gdk_cursor_new (cursor_type);
-                gdk_window_set_cursor (gtk_widget_get_window (um->browse_drawing_area), cursor);
-                gdk_cursor_unref (cursor);
-                um->current_cursor = cursor_type;
-        }
-}
-
-static gboolean
-drawing_area_motion (GtkWidget      *widget,
-                     GdkEventMotion *event,
-                     UmPhotoDialog  *um)
-{
-        gint x, y;
-        gint x2, y2;
-        gint delta_x, delta_y;
-        gint width, height, d;
-
-        if (um->browse_pixbuf == NULL)
-                return FALSE;
-
-        width = gdk_pixbuf_get_width (um->browse_pixbuf);
-        height = gdk_pixbuf_get_height (um->browse_pixbuf);
-
-        x = (event->x - um->image.x) / um->scale;
-        y = (event->y - um->image.y) / um->scale;
-        x = CLAMP (x, 0, width);
-        y = CLAMP (y, 0, height);
-
-        delta_x = x - um->last_press_x;
-        delta_y = y - um->last_press_y;
-        um->last_press_x = x;
-        um->last_press_y = y;
-
-        x2 = um->crop.x + um->crop.width;
-        y2 = um->crop.y + um->crop.height;
-
-        switch (um->active_region) {
-        case INSIDE:
-                um->crop.x = CLAMP (um->crop.x + delta_x, 0, width - um->crop.width);
-                um->crop.y = CLAMP (um->crop.y + delta_y, 0, height - um->crop.height);
-                break;
-
-        case TOP_LEFT:
-                d = MAX (x2 - x, y2 - y);
-                if (d < 48 / um->scale)
-                        d = 48 / um->scale;
-                if (x2 - d < 0)
-                        d = x2;
-                if (y2 - d < 0)
-                        d = y2;
-                um->crop.x = x2 - d;
-                um->crop.y = y2 - d;
-                um->crop.width = um->crop.height = d;
-                break;
-
-        case TOP:
-        case TOP_RIGHT:
-                d = MAX (y2 - y, x - um->crop.x);
-                if (d < 48 / um->scale)
-                        d = 48 / um->scale;
-                if (um->crop.x + d > width)
-                        d = width - um->crop.x;
-                if (y2 - d < 0)
-                        d = y2;
-                um->crop.y = y2 - d;
-                um->crop.width = um->crop.height = d;
-                break;
-
-        case LEFT:
-        case BOTTOM_LEFT:
-                d = MAX (x2 - x, y - um->crop.y);
-                if (d < 48 / um->scale)
-                        d = 48 / um->scale;
-                if (um->crop.y + d > height)
-                        d = height - um->crop.y;
-                if (x2 - d < 0)
-                        d = x2;
-                um->crop.x = x2 - d;
-                um->crop.width = um->crop.height = d;
-                break;
-
-        case RIGHT:
-        case BOTTOM_RIGHT:
-        case BOTTOM:
-                um->crop.width = MAX (x - um->crop.x, y - um->crop.y);
-                if (um->crop.width < 48 / um->scale)
-                        um->crop.width = 48 / um->scale;
-                if (um->crop.x + um->crop.width > width)
-                        um->crop.width = width - um->crop.x;
-                um->crop.height = um->crop.width;
-                if (um->crop.y + um->crop.height > height)
-                        um->crop.height = height - um->crop.y;
-                um->crop.width = um->crop.height;
-                break;
-
-        case OUTSIDE:
-                break;
-        default: ;
-        }
-
-        update_cursor (um, event->x, event->y);
-        gtk_widget_queue_draw (widget);
-
-        return FALSE;
-}
-
-static gboolean
-drawing_area_pressed (GtkWidget      *widget,
-                      GdkEventButton *event,
-                      UmPhotoDialog  *um)
-{
-        GdkRectangle crop;
-
-        if (um->browse_pixbuf == NULL)
-                return FALSE;
-
-        crop_to_widget (um, &crop);
-
-        um->last_press_x = (event->x - um->image.x) / um->scale;
-        um->last_press_y = (event->y - um->image.y) / um->scale;
-        um->active_region = find_location (&crop, event->x, event->y);
-
-        gtk_widget_queue_draw (um->browse_drawing_area);
-
-        return FALSE;
-}
-
-static gboolean
-drawing_area_released (GtkWidget      *widget,
-                       GdkEventButton *event,
-                       UmPhotoDialog  *um)
-{
-        um->last_press_x = -1;
-        um->last_press_y = -1;
-        um->active_region = OUTSIDE;
-
-        if (um->browse_pixbuf == NULL)
-                return FALSE;
-
-        gtk_widget_queue_draw (um->browse_drawing_area);
-
-        return FALSE;
-}
-
 static void
 scale_changed (GtkRange      *range,
                UmPhotoDialog *um)
@@ -946,19 +420,15 @@ um_photo_dialog_new (void)
         um->gallery = widget;
 
         um->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
-        widget = (GtkWidget *)gtk_builder_get_object (builder, "browse-drawing-area");
-        gtk_widget_add_events (widget, GDK_POINTER_MOTION_MASK |
-                                       GDK_BUTTON_PRESS_MASK |
-                                       GDK_BUTTON_RELEASE_MASK);
-        g_signal_connect (widget, "expose-event",
-                          G_CALLBACK (drawing_area_expose), um);
-        g_signal_connect (widget, "button-press-event",
-                          G_CALLBACK (drawing_area_pressed), um);
-        g_signal_connect (widget, "button-release-event",
-                          G_CALLBACK (drawing_area_released), um);
-        g_signal_connect (widget, "motion-notify-event",
-                          G_CALLBACK (drawing_area_motion), um);
-        um->browse_drawing_area = widget;
+
+        /* FIXME replace drawing area with UmCropArea */
+        widget = (GtkWidget *) gtk_builder_get_object (builder, "browse-drawing-area");
+        gtk_widget_destroy (widget);
+        um->browse_drawing_area = um_crop_area_new ();
+        widget = (GtkWidget *) gtk_builder_get_object (builder, "vbox1234");
+        gtk_box_pack_start (GTK_BOX (widget), um->browse_drawing_area, TRUE, TRUE, 0);
+        gtk_widget_show (um->browse_drawing_area);
+
         widget = (GtkWidget *) gtk_builder_get_object (builder, "browse-scale");
         g_signal_connect (widget, "value-changed",
                           G_CALLBACK (scale_changed), um);
@@ -966,13 +436,6 @@ um_photo_dialog_new (void)
 
         load_faces (um);
 
-        um->scale = 0.0;
-        um->image.x = 0;
-        um->image.y = 0;
-        um->image.width = 0;
-        um->image.height = 0;
-        um->active_region = OUTSIDE;
-
         return um;
 }
 
@@ -1029,6 +492,8 @@ um_photo_dialog_set_user (UmPhotoDialog *um,
         GIcon *icon, *icon2;
         GEmblem *emblem;
 
+        g_return_if_fail (um != NULL);
+
         if (um->user) {
                 g_object_unref (um->user);
                 um->user = NULL;
@@ -1038,8 +503,8 @@ um_photo_dialog_set_user (UmPhotoDialog *um,
                 g_object_ref (user);
 
                 pixbuf = um_user_render_icon (user, FALSE, 48);
-                gtk_image_set_from_pixbuf (GTK_IMAGE (um->user_icon), pixbuf);
-                g_object_unref (pixbuf);
+		gtk_image_set_from_pixbuf (GTK_IMAGE (um->user_icon), pixbuf);
+		g_object_unref (pixbuf);
 
                 name = um_user_get_real_name (user);
                 gtk_label_set_label (GTK_LABEL (um->user_name), name);
@@ -1102,14 +567,6 @@ um_photo_dialog_set_user (UmPhotoDialog *um,
                         g_object_unref (um->browse_pixbuf);
                         um->browse_pixbuf = NULL;
                 }
-                if (um->pixbuf) {
-                        g_object_unref (um->pixbuf);
-                        um->pixbuf = NULL;
-                }
-                if (um->color_shifted) {
-                        g_object_unref (um->color_shifted);
-                        um->color_shifted = NULL;
-                }
         }
 }
 



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