/*
 * DiaCanvasImage
 *
 * This is LGPL'ed code.
 */

#include "dia-canvas-image.h"
#include "dia-handle.h"
#include "dia-shape.h"
#include <libart_lgpl/art_affine.h>
#include "dia-canvas-i18n.h"

//#define D(s) g_message s;
#define D(s)

enum {
	PROP_IMAGE = 1
};

static void dia_canvas_image_class_init (DiaCanvasImageClass *klass);
static void dia_canvas_image_init (DiaCanvasImage *item);
static void dia_canvas_image_dispose (GObject *object);
static void dia_canvas_image_set_property (GObject *object,
					     guint property_id,
					     const GValue *value,
					     GParamSpec *pspec);
static void dia_canvas_image_get_property (GObject *object,
					     guint property_id,
					     GValue *value,
					     GParamSpec *pspec);
static void dia_canvas_image_update (DiaCanvasItem *item, gdouble affine[6]);
static gboolean dia_canvas_image_get_shape_iter	(DiaCanvasItem *item,
						 DiaCanvasIter *iter);
static gboolean dia_canvas_image_shape_next	(DiaCanvasItem *item,
						 DiaCanvasIter *iter);
static DiaShape* dia_canvas_image_shape_value	(DiaCanvasItem *item,
						 DiaCanvasIter *iter);

static DiaCanvasElementClass *parent_class = NULL;

GType
dia_canvas_image_get_type (void)
{
	static GType object_type = 0;

	if (!object_type) {
		static const GTypeInfo object_info = {
			sizeof (DiaCanvasImageClass),
			(GBaseInitFunc) NULL,
			(GBaseFinalizeFunc) NULL,
			(GClassInitFunc) dia_canvas_image_class_init,
			(GClassFinalizeFunc) NULL,
			(gconstpointer) NULL, /* class_data */
			sizeof (DiaCanvasImage),
			(guint16) 0, /* n_preallocs */
			(GInstanceInitFunc) dia_canvas_image_init,
		};

		object_type = g_type_register_static (DIA_TYPE_CANVAS_ELEMENT,
						      "DiaCanvasImage",
						      &object_info, 0);
	}

	return object_type;
}


static void
dia_canvas_image_class_init (DiaCanvasImageClass *klass)
{
	GObjectClass *object_class;
	DiaCanvasItemClass *item_class;
	
	object_class = (GObjectClass*) klass;
	item_class = DIA_CANVAS_ITEM_CLASS (klass);
	
	parent_class = g_type_class_peek_parent (klass);

	object_class->dispose = dia_canvas_image_dispose;
	object_class->get_property = dia_canvas_image_get_property;
	object_class->set_property = dia_canvas_image_set_property;
	
	item_class->update = dia_canvas_image_update;
	item_class->get_shape_iter = dia_canvas_image_get_shape_iter;
	item_class->shape_next = dia_canvas_image_shape_next;
	item_class->shape_value = dia_canvas_image_shape_value;

	g_object_class_install_property (object_class,
					 PROP_IMAGE,
					 g_param_spec_object ("image",
						_("Image"),
						_("Image to be displayed"),
						GDK_TYPE_PIXBUF,
						G_PARAM_READWRITE));
}


static void
dia_canvas_image_init (DiaCanvasImage *item)
{
	item->pixbuf = NULL;

	item->image = dia_shape_new (DIA_SHAPE_IMAGE);
}


static void
dia_canvas_image_set_property (GObject *object, guint property_id,
				 const GValue *value, GParamSpec *pspec)
{
	DiaCanvasImage *image = (DiaCanvasImage*) (object);
	
	switch (property_id) {
	case PROP_IMAGE:
		dia_canvas_item_preserve_property (DIA_CANVAS_ITEM (object), "image");

		if (image->pixbuf)
			g_object_unref (image->pixbuf);

		if (g_value_get_object (value)) {
			image->pixbuf = GDK_PIXBUF (g_value_get_object (value));
			g_object_ref (image->pixbuf);
		} else
			image->pixbuf = NULL;
		dia_canvas_item_request_update (DIA_CANVAS_ITEM (image));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
dia_canvas_image_get_property (GObject *object, guint property_id,
				 GValue *value, GParamSpec *pspec)
{
	switch (property_id) {
	case PROP_IMAGE:
		g_value_set_object (value, DIA_CANVAS_IMAGE (object)->pixbuf);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
dia_canvas_image_dispose (GObject *object)
{
	DiaCanvasImage *image = (DiaCanvasImage *) object;
	if (image->pixbuf) {
		g_object_unref (image->pixbuf);
		image->pixbuf = NULL;
	}
	if (image->image) {
		dia_shape_free (image->image);
		image->image = NULL;
	}
	G_OBJECT_CLASS (parent_class)->dispose (object);
}

static void
dia_canvas_image_update (DiaCanvasItem *item, gdouble affine[6])
{
	DiaShape *image_shape;
	DiaCanvasElement *elem = (DiaCanvasElement*) item;
	DiaCanvasImage *image = (DiaCanvasImage*) item;
	gdouble pixbuf_affine[6];

        if (DIA_CANVAS_ITEM_CLASS (parent_class)->update)
		DIA_CANVAS_ITEM_CLASS (parent_class)->update (item, affine);
	
	image_shape = image->image;

	art_affine_scale (pixbuf_affine,
			  elem->width / gdk_pixbuf_get_width (image->pixbuf),
			  elem->height / gdk_pixbuf_get_height (image->pixbuf)); 

	dia_shape_image (image_shape, image->pixbuf);
	dia_shape_image_set_affine (image_shape, pixbuf_affine);
}

static gboolean
dia_canvas_image_get_shape_iter (DiaCanvasItem *item, DiaCanvasIter *iter)
{
	iter->data[0] = DIA_CANVAS_IMAGE (item)->image;
	return TRUE;
}

static gboolean
dia_canvas_image_shape_next (DiaCanvasItem *item, DiaCanvasIter *iter)
{
	return FALSE;
}

static DiaShape*
dia_canvas_image_shape_value (DiaCanvasItem *item, DiaCanvasIter *iter)
{
	return iter->data[0];
}

