/* dia-selector.c
 * Copyright (C) 2001  Arjan Molenaar
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "dia-canvas-view.h"
#include "dia-selector.h"
#include "dia-geometry.h"
#include "dia-canvas-i18n.h"

enum {
	PROP_X1 = 1,
	PROP_Y1,
	PROP_X2,
	PROP_Y2
};

static void dia_selector_class_init		(DiaSelectorClass *class);
static void dia_selector_init			(DiaSelector *selector);
static void dia_selector_set_property		(GObject	*object,
						 guint		 param_id,
						 const GValue	*value,
						 GParamSpec	*pspec);
static void dia_selector_get_property		(GObject	*object,
						 guint		 param_id,
						 GValue		*value,
						 GParamSpec	*pspec);
static void dia_selector_dispose		(GObject	*object);
static double dia_selector_point		(GnomeCanvasItem *item,
						 double x, double y,
						 int cx, int cy,
						 GnomeCanvasItem **actual_item);
static void dia_selector_update			(GnomeCanvasItem *item,
						 double *affine,
						 ArtSVP *clip_path, int flags);
static void dia_selector_draw			(GnomeCanvasItem *item,
						 GdkDrawable *drawable,
						 int x, int y,
						 int width, int height);
static void dia_selector_render			(GnomeCanvasItem *item,
						 GnomeCanvasBuf *buf);

static void request_redraw			(DiaSelector *sel);

static GnomeCanvasItemClass *parent_class;


GtkType
dia_selector_get_type (void)
{
	static GtkType selector_type = 0;

	if (!selector_type) {
		GtkTypeInfo selector_info = {
			"DiaSelector",
			sizeof (DiaSelector),
			sizeof (DiaSelectorClass),
			(GtkClassInitFunc) dia_selector_class_init,
			(GtkObjectInitFunc) dia_selector_init,
			NULL, /* reserved_1 */
			NULL, /* reserved_2 */
			(GtkClassInitFunc) NULL
		};

		selector_type = gtk_type_unique (gnome_canvas_item_get_type (),
						 &selector_info);
	}

	return selector_type;
}

static void
dia_selector_class_init (DiaSelectorClass *class)
{
	GObjectClass *object_class;
	GnomeCanvasItemClass *item_class;

	object_class = (GObjectClass *) class;
	item_class = (GnomeCanvasItemClass *) class;

	parent_class = gtk_type_class (gnome_canvas_item_get_type ());
	object_class->dispose = dia_selector_dispose;
	object_class->set_property = dia_selector_set_property;
	object_class->get_property = dia_selector_get_property;

	g_object_class_install_property (object_class,
					 PROP_X1,
					 g_param_spec_int ("x1",
					 _("X1"),
					 _("Selector upper left X."),
					 -G_MAXINT, G_MAXINT, 0,
					 G_PARAM_READWRITE));

	g_object_class_install_property (object_class,
					 PROP_Y1,
					 g_param_spec_int ("y1",
					 _("Y1"),
					 _("Selector upper left Y."),
					 -G_MAXINT, G_MAXINT, 0,
					 G_PARAM_READWRITE));

	g_object_class_install_property (object_class,
					 PROP_X2,
					 g_param_spec_int ("x2",
					 _("X2"),
					 _("Selector lower right X."),
					 -G_MAXINT, G_MAXINT, 0,
					 G_PARAM_READWRITE));

	g_object_class_install_property (object_class,
					 PROP_Y2,
					 g_param_spec_int ("y2",
					 _("Y2"),
					 _("Selector lower right Y."),
					 -G_MAXINT, G_MAXINT, 0,
					 G_PARAM_READWRITE));

	item_class->point = dia_selector_point;
	item_class->update = dia_selector_update;
	item_class->draw = dia_selector_draw;
	item_class->render = dia_selector_render;
}

static void
dia_selector_init (DiaSelector *selector)
{
	selector->x1 = 0;
	selector->y1 = 0;
	selector->x2 = 0;
	selector->y2 = 0;
}

static void
dia_selector_set_property (GObject *object, guint property_id,
			   const GValue *value, GParamSpec *pspec)
{
	DiaSelector *sel = (DiaSelector*) object;

	switch (property_id) {
	case PROP_X1:
		request_redraw (sel);
		sel->x1 = g_value_get_int (value);
		request_redraw (sel);
		break;
	case PROP_Y1:
		request_redraw (sel);
		sel->y1 = g_value_get_int (value);
		request_redraw (sel);
		break;
	case PROP_X2:
		request_redraw (sel);
		sel->x2 = g_value_get_int (value);
		request_redraw (sel);
		break;
	case PROP_Y2:
		request_redraw (sel);
		sel->y2 = g_value_get_int (value);
		request_redraw (sel);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
dia_selector_get_property (GObject *object, guint property_id,
			   GValue *value, GParamSpec *pspec)
{
	DiaSelector *sel = (DiaSelector*) object;

	switch (property_id) {
	case PROP_X1:
		g_value_set_int (value, sel->x1);
		break;
	case PROP_Y1:
		g_value_set_int (value, sel->y1);
		break;
	case PROP_X2:
		g_value_set_int (value, sel->x2);
		break;
	case PROP_Y2:
		g_value_set_int (value, sel->y2);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
dia_selector_dispose (GObject *object)
{
	request_redraw ((DiaSelector*) object);

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

static void
request_redraw (DiaSelector *sel)
{
	gint minx, miny, maxx, maxy;

	if (!sel->item.canvas)
		return;

	minx = MIN (sel->x1, sel->x2);
	miny = MIN (sel->y1, sel->y2);
	maxx = MAX (sel->x1, sel->x2) + 1;
	maxy = MAX (sel->y1, sel->y2) + 1;
	gnome_canvas_request_redraw (sel->item.canvas, minx, miny,
				     maxx, maxy);
}

static double
dia_selector_point (GnomeCanvasItem *item, double x, double y,
		    int cx, int cy, GnomeCanvasItem **actual_item)
{
	*actual_item = item;
	return 0.0;
}

static void
dia_selector_update (GnomeCanvasItem *item, double *affine,
		     ArtSVP *clip_path, int flags)
{
	DiaSelector *sel = (DiaSelector*) item;

	parent_class->update (item, affine, clip_path, flags);

	//g_message (__FUNCTION__": ");

	item->x1 = G_MINDOUBLE;
	item->y1 = G_MINDOUBLE;
	item->x2 = G_MAXDOUBLE;
	item->y2 = G_MAXDOUBLE;

	request_redraw (sel);
}

static void
dia_selector_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
		   int x, int y, int width, int height)
{
}

static void
dia_selector_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf)
{
	DiaSelector *sel = (DiaSelector*) item;
	gint minx, miny, maxx, maxy;
	gint i, start, end;
	guchar *p;

	minx = MIN (sel->x1, sel->x2);
	miny = MIN (sel->y1, sel->y2);
	maxx = MAX (sel->x1, sel->x2);
	maxy = MAX (sel->y1, sel->y2);
	/*minx = MIN (sel->x1, sel->x2) - item->canvas->zoom_xofs;
	miny = MIN (sel->y1, sel->y2) - item->canvas->zoom_yofs;
	maxx = MAX (sel->x1, sel->x2) - item->canvas->zoom_xofs;
	maxy = MAX (sel->y1, sel->y2) - item->canvas->zoom_yofs;*/

	//g_message (__FUNCTION__": %d %d %d %d", minx, miny, maxx, maxy);

	/* Render a rectangle on the canvas */
	if ((minx < buf->rect.x1) && (maxx >= buf->rect.x0)
	    && (miny < buf->rect.y1) && (maxy >= buf->rect.y0)) {
		/* Top line */
		if ((miny >= buf->rect.y0) && (miny < buf->rect.y1)) {
			start = MAX (minx, buf->rect.x0);
			end = MIN (maxx, buf->rect.x1);
			p = &buf->buf[(miny - buf->rect.y0) * buf->buf_rowstride + (start - buf->rect.x0) * 3];
			for (i = start; i < end; i++) {
				if (i & 4) {
					*p++ = 0x0;
					*p++ = 0x0;
					*p++ = 0x0;
				} else
					p += 3;
			}
		}
		/* Bottom line */
		if ((maxy >= buf->rect.y0) && (maxy < buf->rect.y1)) {
			start = MAX (minx, buf->rect.x0);
			end = MIN (maxx, buf->rect.x1);
			p = &buf->buf[(maxy - buf->rect.y0) * buf->buf_rowstride + (start - buf->rect.x0) * 3];
			for (i = start; i < end; i++) {
				if (i & 4) {
					*p++ = 0x0;
					*p++ = 0x0;
					*p++ = 0x0;
				} else
					p += 3;
			}
		}
		/* Left line */
		if ((minx >= buf->rect.x0) && (minx < buf->rect.x1)) {
			start = MAX (miny, buf->rect.y0);
			end = MIN (maxy, buf->rect.y1);
			p = &buf->buf[(start - buf->rect.y0) * buf->buf_rowstride + (minx - buf->rect.x0) * 3];
			for (i = start; i < end; i++) {
				if (i & 4) {
					p[0] = 0x0;
					p[1] = 0x0;
					p[2] = 0x0;
				}
				p += buf->buf_rowstride;
			}
		}
		/* Right line */
		if ((maxx >= buf->rect.x0) && (maxx < buf->rect.x1)) {
			start = MAX (miny, buf->rect.y0);
			end = MIN (maxy, buf->rect.y1);
			p = &buf->buf[(start - buf->rect.y0) * buf->buf_rowstride + (maxx - buf->rect.x0) * 3];
			for (i = start; i < end; i++) {
				if (i & 4) {
					p[0] = 0x0;
					p[1] = 0x0;
					p[2] = 0x0;
				}
				p += buf->buf_rowstride;
			}
		}
	}
}

