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

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

enum {
	PROP_COLOR = 1,
	PROP_FILL_COLOR,
	PROP_BORDER_WIDTH,
	/* Depricated: */
	PROP_BG_COLOR,
	PROP_LINE_WIDTH
};

static void dia_canvas_box_class_init (DiaCanvasBoxClass *klass);
static void dia_canvas_box_init (DiaCanvasBox *item);
static void dia_canvas_box_set_property (GObject *object,
					 guint property_id,
					 const GValue *value,
					 GParamSpec *pspec);
static void dia_canvas_box_get_property (GObject *object,
					 guint property_id,
					 GValue *value,
					 GParamSpec *pspec);
static void dia_canvas_box_dispose	(GObject *object);
static void dia_canvas_box_update	(DiaCanvasItem *item,
					 gdouble affine[6]);
static gboolean dia_canvas_box_get_shape_iter	(DiaCanvasItem *item,
						 DiaCanvasIter *iter);
static gboolean dia_canvas_box_shape_next	(DiaCanvasItem *item,
						 DiaCanvasIter *iter);
static DiaShape* dia_canvas_box_shape_value	(DiaCanvasItem *item,
						 DiaCanvasIter *iter);
static DiaCanvasElementClass *parent_class = NULL;

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

	if (!object_type) {
		static const GTypeInfo object_info = {
			sizeof (DiaCanvasBoxClass),
			(GBaseInitFunc) NULL,
			(GBaseFinalizeFunc) NULL,
			(GClassInitFunc) dia_canvas_box_class_init,
			(GClassFinalizeFunc) NULL,
			(gconstpointer) NULL, /* class_data */
			sizeof (DiaCanvasBox),
			(guint16) 0, /* n_preallocs */
			(GInstanceInitFunc) dia_canvas_box_init,
		};

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

	return object_type;
}


static void
dia_canvas_box_class_init (DiaCanvasBoxClass *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->get_property = dia_canvas_box_get_property;
	object_class->set_property = dia_canvas_box_set_property;
	object_class->dispose = dia_canvas_box_dispose;

	item_class->update = dia_canvas_box_update;
	item_class->get_shape_iter = dia_canvas_box_get_shape_iter;
	item_class->shape_next = dia_canvas_box_shape_next;
	item_class->shape_value = dia_canvas_box_shape_value;

	g_object_class_install_property (object_class,
					 PROP_COLOR,
					 g_param_spec_ulong ("color",
						_("Color"),
						_("Color of the line in RGBA"),
						0, G_MAXULONG, 0,
						G_PARAM_READWRITE));
	g_object_class_install_property (object_class,
					 PROP_FILL_COLOR,
					 g_param_spec_ulong ("fill_color",
						_("Fill color"),
						_("Fill color"),
						0, G_MAXULONG, 0,
						G_PARAM_READWRITE));
	g_object_class_install_property (object_class,
					 PROP_BORDER_WIDTH,
					 g_param_spec_double ("border_width",
						_("Border width"),
						_("width of the border"),
						-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
						G_PARAM_READWRITE));
	/* Depricated: */
	g_object_class_install_property (object_class,
					 PROP_BG_COLOR,
					 g_param_spec_ulong ("bg_color",
						_("Background color"),
						_("Background color"),
						0, G_MAXULONG, 0,
						G_PARAM_READWRITE));
	g_object_class_install_property (object_class,
					 PROP_LINE_WIDTH,
					 g_param_spec_double ("line_width",
						_("Line width"),
						_("width of the border"),
						-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
						G_PARAM_READWRITE));
}


static void
dia_canvas_box_init (DiaCanvasBox *item)
{
	item->color = DIA_COLOR (0, 0, 0);
	item->fill_color = 0; /* fully transparent */
	item->border_width = 1.0;
	item->border = dia_shape_new (DIA_SHAPE_PATH);
}


static void
dia_canvas_box_set_property (GObject *object, guint property_id,
			     const GValue *value, GParamSpec *pspec)
{
	DiaCanvasBox *box = (DiaCanvasBox*) object;

	switch (property_id) {
	case PROP_COLOR:
		dia_canvas_item_preserve_property (DIA_CANVAS_ITEM (box), "color");
		box->color = g_value_get_ulong (value);
		dia_canvas_item_request_update (DIA_CANVAS_ITEM (object));
		break;
	case PROP_BG_COLOR:
		g_warning("Depricated property: bg_color, use fill_color instead");
	case PROP_FILL_COLOR:
		dia_canvas_item_preserve_property (DIA_CANVAS_ITEM(box), "fill_color");
		box->fill_color = g_value_get_ulong (value);
		dia_canvas_item_request_update (DIA_CANVAS_ITEM (object));
		break;
	case PROP_LINE_WIDTH:
		g_warning("Depricated property: line_width, use border_width instead");
	case PROP_BORDER_WIDTH:
		dia_canvas_item_preserve_property (DIA_CANVAS_ITEM(box), "border_width");
		box->border_width = g_value_get_double (value);
		dia_canvas_item_request_update (DIA_CANVAS_ITEM (object));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
dia_canvas_box_get_property (GObject *object, guint property_id,
			     GValue *value, GParamSpec *pspec)
{
	switch (property_id) {
	case PROP_COLOR:
		g_value_set_ulong (value, DIA_CANVAS_BOX (object)->color);
		break;
	case PROP_BG_COLOR:
	case PROP_FILL_COLOR:
		g_value_set_ulong (value, DIA_CANVAS_BOX (object)->fill_color);
		break;
	case PROP_LINE_WIDTH:
	case PROP_BORDER_WIDTH:
		g_value_set_double (value, DIA_CANVAS_BOX (object)->border_width);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
dia_canvas_box_dispose (GObject *object)
{
	DiaCanvasBox *box = (DiaCanvasBox*) object;

	if (box->border) {
		dia_shape_free (box->border);
		box->border = NULL;
	}

	G_OBJECT_CLASS (parent_class)->dispose (object);
}


static void
dia_canvas_box_update (DiaCanvasItem *item, gdouble affine[6])
{
	DiaShape *border;
	DiaPoint p1 = { 0.0, 0.0 }, p2;
	gdouble half_w;

	p2.x = DIA_CANVAS_ELEMENT (item)->width;
	p2.y = DIA_CANVAS_ELEMENT (item)->height;

        if (DIA_CANVAS_ITEM_CLASS (parent_class)->update)
		DIA_CANVAS_ITEM_CLASS (parent_class)->update (item, affine);
	
	border = DIA_CANVAS_BOX (item)->border;

	half_w = DIA_CANVAS_BOX (item)->border_width / 2.0;
	item->bounds.top -= half_w;
	item->bounds.left -= half_w;
	item->bounds.bottom += half_w;
	item->bounds.right += half_w;

	/* Create the border */
	dia_shape_rectangle (border, &p1, &p2);
	dia_shape_set_color (border, DIA_CANVAS_BOX (item)->color);
	dia_shape_path_set_fill (border, DIA_FILL_SOLID);
	dia_shape_path_set_fill_color (border, DIA_CANVAS_BOX (item)->fill_color);
	dia_shape_path_set_line_width (border, DIA_CANVAS_BOX (item)->border_width);
}

static gboolean
dia_canvas_box_get_shape_iter (DiaCanvasItem *item, DiaCanvasIter *iter)
{
	iter->data[0] = DIA_CANVAS_BOX (item)->border;
	return TRUE;
}

static gboolean
dia_canvas_box_shape_next (DiaCanvasItem *item, DiaCanvasIter *iter)
{
	iter->data[0] = NULL;
	return FALSE;
}

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

