/* $Id: guppi-scatter-item.c,v 1.33 2001/11/08 06:13:40 trow Exp $ */

/*
 * guppi-scatter-item.c
 *
 * Copyright (C) 1999 EMC Capital Management, Inc.
 *
 * Developed by Jon Trowbridge <trow@gnu.org> and
 * Havoc Pennington <hp@pobox.com>.
 *
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#include <config.h>
#include <guppi-useful.h>
#include "guppi-scatter-tools.h"
#include "guppi-scatter-item.h"

static GtkObjectClass *parent_class = NULL;

static void
guppi_scatter_item_destroy (GtkObject * obj)
{
  if (parent_class->destroy)
    parent_class->destroy (obj);
}

static void
guppi_scatter_item_finalize (GtkObject * obj)
{
  GuppiScatterItem *item = GUPPI_SCATTER_ITEM (obj);

  guppi_unref0 (item->local_x_visibility_mask);
  guppi_unref0 (item->local_y_visibility_mask);

  if (parent_class->finalize)
    parent_class->finalize (obj);
}


/***************************************************************************/

static gint
query_slack (GuppiCanvasItem *gci)
{
  /* We make the implicit assumption that size1 is the radius in points of a bounding
     circle around the markers.  In general, this isn't a bad assumption. */

  GuppiElementState *state = guppi_canvas_item_state (gci);
  double sz, sz_scale;
  GuppiSeqScalar *sz_data;
  GuppiMarker marker;
  const GuppiMarkerInfo *info;
  gint slack_x, slack_y;

  guppi_element_state_get (state,
			   "marker", &marker,
			   "size1", &sz,
			   "data_size1", &sz_data,
			   "size1_gradient_scale", &sz_scale,
			   NULL);

  info = guppi_marker_info (marker);

  if (sz_data) {
    sz = guppi_seq_scalar_max (sz_data) * sz_scale;
  } else {
    sz *= info->size1_default;
  }

  guppi_canvas_item_pt2c (gci, sz, sz, &slack_x, &slack_y);
  
  return MAX (slack_x, slack_y);
}

static void
update (GuppiCanvasItem *gci, double aff[6], ArtSVP *svp, gint flags)
{

}

typedef struct _GatherInfo GatherInfo;
struct _GatherInfo {
  GuppiCanvasItem *item;
  GnomeCanvasBuf *buf;
};

static void
gather_pairs_cb (GuppiIndexedPair *pair, gsize N, gpointer closure)
{
  GatherInfo *info = closure;
  GuppiScatterState *state = GUPPI_SCATTER_STATE (guppi_canvas_item_state (info->item));
  GuppiPixbuf *pixbuf;
  double scale;
  gint x, y;
  gsize i = 0;
  guint32 color;

  scale = guppi_canvas_item_scale (info->item);

  for (i = 0; i < N; ++i) {
    if (guppi_element_view_valid_vp (guppi_canvas_item_view (info->item), pair[i].x, pair[i].y)) {
      pixbuf = guppi_scatter_state_get_point_pixbuf (state, pair[i].i, scale, &color);
      if (pixbuf != NULL) {
	guppi_canvas_item_vp2c (info->item, pair[i].x, pair[i].y, &x, &y);

	/* FIXME: hardwired colormap colors */
	guppi_pixbuf_color_mapped_paste (pixbuf, x, y, color, 0xff0000ff, 0x000000ff, 0xff, info->buf);

	guppi_pixbuf_unref (pixbuf);
      }
    }
  }
}

static void
render (GuppiCanvasItem *gci, GnomeCanvasBuf *buf)
{
  GuppiScatterItem *item;
  GuppiScatterState *state;
  GuppiElementView *gev;

  GuppiSeqScalar *x_data;
  GuppiSeqScalar *y_data;

  GatherInfo info;

  double vx0, vy0, vx1, vy1;
  gint slack;

  item = GUPPI_SCATTER_ITEM (gci);
  state = GUPPI_SCATTER_STATE (guppi_canvas_item_state (gci));
  gev = guppi_canvas_item_view (gci);

  x_data = guppi_scatter_state_get_x_data (state);
  y_data = guppi_scatter_state_get_y_data (state);

  if (x_data == NULL || y_data == NULL)
    return;

  /*
     Find the bounding box for the area we are viewing, in plot/view
     coordinates.  We allow some slack that is based on our estimate of
     how big our largest marker can be.
   */

  slack = query_slack (gci);
  guppi_canvas_item_c2vp (gci, buf->rect.x0 - slack, buf->rect.y0 - slack,
			  &vx0, &vy0);
  guppi_canvas_item_c2vp (gci, buf->rect.x1 + slack, buf->rect.y1 + slack,
			  &vx1, &vy1);

  
  info.item = gci;
  info.buf  = buf;
  guppi_seq_scalar_gather_pairs (x_data, y_data, vx0, vy0, vx1, vy1, gather_pairs_cb, &info);
}

static void
foreach_class_toolkit (GuppiCanvasItem * item,
		       void (*fn) (GuppiPlotToolkit *, gpointer),
		       gpointer user_data)
{
  GuppiPlotToolkit *tk;

  tk = guppi_scatter_toolkit_drag ();
  fn (tk, user_data);
  guppi_unref (tk);

  tk = guppi_scatter_toolkit_brush ();
  fn (tk, user_data);
  guppi_unref (tk);
}

/***************************************************************************/

static void
guppi_scatter_item_class_init (GuppiScatterItemClass * klass)
{
  GtkObjectClass *object_class;
  GuppiCanvasItemClass *gci_class;
  GnomeCanvasItemClass *item_class;

  object_class = (GtkObjectClass *) klass;
  gci_class = GUPPI_CANVAS_ITEM_CLASS (klass);
  item_class = GNOME_CANVAS_ITEM_CLASS (klass);
  parent_class = gtk_type_class (GUPPI_TYPE_CANVAS_ITEM);

  object_class->destroy = guppi_scatter_item_destroy;
  object_class->finalize = guppi_scatter_item_finalize;

  gci_class->guppi_update = update;
  gci_class->guppi_render = render;
  gci_class->uses_vp_coordinates = TRUE;
  gci_class->foreach_class_toolkit = foreach_class_toolkit;

  guppi_canvas_item_class_set_item_class_toolkit (gci_class,
						  guppi_scatter_toolkit_default ());
}

static void
guppi_scatter_item_init (GuppiScatterItem * si)
{

}

GtkType guppi_scatter_item_get_type (void)
{
  static GtkType scatter_item_type = 0;

  if (!scatter_item_type) {
    static const GtkTypeInfo scatter_item_info = {
      "GuppiScatterItem",
      sizeof (GuppiScatterItem),
      sizeof (GuppiScatterItemClass),
      (GtkClassInitFunc) guppi_scatter_item_class_init,
      (GtkObjectInitFunc) guppi_scatter_item_init,
      NULL, NULL,
      (GtkClassInitFunc) NULL
    };
    scatter_item_type = gtk_type_unique (GUPPI_TYPE_CANVAS_ITEM,
					 &scatter_item_info);
  }

  return scatter_item_type;
}




/* $Id: guppi-scatter-item.c,v 1.33 2001/11/08 06:13:40 trow Exp $ */


syntax highlighted by Code2HTML, v. 0.9.1