/* $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 and * Havoc Pennington . * * 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 #include #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 $ */