/* This is -*- C -*- */
/* $Id: guppi-legend-item.c,v 1.17 2001/10/18 21:47:15 jody Exp $ */
/*
* guppi-legend-item.c
*
* Copyright (C) 2000 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-raster-text.h>
#include "guppi-legend-item.h"
#include "guppi-legend-view.h"
#include "guppi-legend-state.h"
#include "guppi-legend-tool.h"
static GtkObjectClass *parent_class = NULL;
enum {
CLICKED_BOX,
LAST_SIGNAL
};
guint leg_signals[LAST_SIGNAL] = { 0 };
static void
guppi_legend_item_finalize (GtkObject * obj)
{
GuppiLegendItem *item = GUPPI_LEGEND_ITEM (obj);
GList *iter;
if (item->labels) {
iter = item->labels;
while (iter != NULL) {
guppi_unref (iter->data);
iter = g_list_next (iter);
}
g_list_free (item->labels);
item->labels = NULL;
}
if (parent_class->finalize)
parent_class->finalize (obj);
}
/***************************************************************************/
static void
update (GuppiCanvasItem * gci, double aff[6], ArtSVP * clip_path, gint flags)
{
GuppiLegendState *state;
GuppiLegendItem *item;
GnomeFont *font;
GList *new_labels = NULL;
GList *iter;
double sc;
gint i, i0, i1;
item = GUPPI_LEGEND_ITEM (gci);
state = GUPPI_LEGEND_STATE (guppi_canvas_item_state (gci));
sc = guppi_canvas_item_scale (gci);
guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
"label_font", &font,
NULL);
/* Rasterize our labels, re-using old rasterizations when possible. */
guppi_legend_state_entry_bounds (state, &i0, &i1);
for (i = i0; i <= i1; ++i) {
GuppiRasterText *rt = NULL;
const gchar *text = guppi_legend_state_entry_text (state, i);
iter = item->labels;
while (iter != NULL && rt == NULL) {
if (iter->data) {
GuppiRasterText *rt2 = GUPPI_RASTER_TEXT (iter->data);
char *tmp = guppi_raster_text_text (rt2);
if (text != NULL && tmp != NULL && strcmp (text, tmp) == 0) {
rt = rt2;
iter->data = NULL;
}
g_free (tmp);
}
iter = g_list_next (iter);
}
if (rt == NULL) {
rt = guppi_raster_text_new (NULL);
guppi_raster_text_set_text (rt, text);
}
guppi_raster_text_set_scale (rt, sc);
new_labels = g_list_append (new_labels, rt);
}
/* Clean up old labels */
iter = item->labels;
while (iter != NULL) {
guppi_unref (iter->data);
iter = g_list_next (iter);
}
g_list_free (item->labels);
item->labels = new_labels;
guppi_unref (font);
}
static void
render (GuppiCanvasItem * gci, GnomeCanvasBuf * buf)
{
GuppiLegendItem *item;
GuppiLegendState *state;
double sc;
gint i, i0, i1, N;
gint x0, y0, x1, y1;
double edge_margin, edge_thickness, label_offset, swatch_width, swatch_height;
double px_margin, px_label_offset, px_box_width, px_box_height, px_box_edge;
guint32 label_color, box_color, box_edge_color;
GList *iter;
double box_y_step, box_x0, box_y0, box_x1, box_y1, lab_x, lab_y;
guint r, g, b, a;
item = GUPPI_LEGEND_ITEM (gci);
state = GUPPI_LEGEND_STATE (guppi_canvas_item_state (gci));
sc = guppi_canvas_item_scale (gci);
guppi_canvas_item_get_bbox_c (gci, &x0, &y0, &x1, &y1);
guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
"edge_margin", &edge_margin,
"edge_thickness", &edge_thickness,
"label_offset", &label_offset,
"label_color", &label_color,
"swatch_width", &swatch_width,
"swatch_height", &swatch_height,
"edge_color", &box_edge_color,
NULL);
px_margin = guppi_pt2px (edge_margin * sc);
px_label_offset = guppi_x_pt2px (label_offset * sc);
px_box_width = guppi_x_pt2px (swatch_width * sc);
px_box_height = guppi_y_pt2px (swatch_height * sc);
px_box_edge = guppi_pt2px (edge_thickness * sc);
guppi_legend_state_entry_bounds (state, &i0, &i1);
N = i1 - i0 + 1;
box_y_step = N > 1 ? (y1 - y0 - 2 * px_margin - px_box_height) / (N - 1) : 0;
UINT_TO_RGBA (label_color, &r, &g, &b, &a);
iter = item->labels;
for (i = i0; i <= i1; ++i) {
GuppiAlphaTemplate *label_template;
double box_y_center;
box_y_center = y0 + px_margin + px_box_height / 2 + (i-i0) * box_y_step;
box_y0 = box_y_center - px_box_height / 2;
box_y1 = box_y_center + px_box_height / 2;
box_x0 = x0 + px_margin;
box_x1 = box_x0 + px_box_width;
box_color = guppi_legend_state_entry_color (state, i);
guppi_paint_soft_box (buf, box_x0, box_y0, box_x1, box_y1,
box_edge_color);
guppi_paint_soft_box (buf, box_x0 + px_box_edge, box_y0 + px_box_edge,
box_x1 - px_box_edge, box_y1 - px_box_edge,
box_color);
label_template =
guppi_raster_text_template (GUPPI_RASTER_TEXT (iter->data));
lab_x = box_x1 + px_label_offset;
if (label_template)
lab_y = box_y_center - label_template->height / 2;
if (label_template)
guppi_alpha_template_print (label_template,
(gint) rint (lab_x), (gint) rint (lab_y),
r, g, b, a, buf);
iter = g_list_next (iter);
}
}
/***************************************************************************/
static gboolean
double_click (GuppiCanvasItem * gci,
guint button, guint state, double pt_x, double pt_y)
{
gint box;
gint c_x, c_y;
guppi_canvas_item_pt2c (gci, pt_x, pt_y, &c_x, &c_y);
if (guppi_legend_item_in_box (GUPPI_LEGEND_ITEM (gci), c_x, c_y, &box)) {
gtk_signal_emit (GTK_OBJECT (gci), leg_signals[CLICKED_BOX],
box, button, state);
return TRUE;
}
return FALSE;
}
static void
guppi_marshal_NONE__INT_UINT_UINT (GtkObject * obj,
GtkSignalFunc func,
gpointer func_data, GtkArg * args)
{
((void (*)(GtkObject *,
gint, guint, guint,
gpointer)) func) (obj,
GTK_VALUE_INT (args[0]),
GTK_VALUE_UINT (args[1]),
GTK_VALUE_UINT (args[2]), func_data);
}
static void
guppi_legend_item_class_init (GuppiLegendItemClass * klass)
{
GtkObjectClass *object_class = (GtkObjectClass *) klass;
GuppiCanvasItemClass *gci_class = GUPPI_CANVAS_ITEM_CLASS (klass);
parent_class = gtk_type_class (GUPPI_TYPE_CANVAS_ITEM);
object_class->finalize = guppi_legend_item_finalize;
gci_class->guppi_update = update;
gci_class->guppi_render = render;
gci_class->double_click = double_click;
leg_signals[CLICKED_BOX] =
gtk_signal_new ("clicked_box",
GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET (GuppiLegendItemClass, clicked_box),
guppi_marshal_NONE__INT_UINT_UINT,
GTK_TYPE_NONE, 3,
GTK_TYPE_INT, GTK_TYPE_UINT, GTK_TYPE_UINT);
gtk_object_class_add_signals (object_class, leg_signals, LAST_SIGNAL);
}
static void
guppi_legend_item_init (GuppiLegendItem * obj)
{
}
GtkType guppi_legend_item_get_type (void)
{
static GtkType guppi_legend_item_type = 0;
if (!guppi_legend_item_type) {
static const GtkTypeInfo guppi_legend_item_info = {
"GuppiLegendItem",
sizeof (GuppiLegendItem),
sizeof (GuppiLegendItemClass),
(GtkClassInitFunc) guppi_legend_item_class_init,
(GtkObjectInitFunc) guppi_legend_item_init,
NULL, NULL, (GtkClassInitFunc) NULL
};
guppi_legend_item_type =
gtk_type_unique (GUPPI_TYPE_CANVAS_ITEM, &guppi_legend_item_info);
}
return guppi_legend_item_type;
}
/***************************************************************************/
gboolean
guppi_legend_item_in_box (GuppiLegendItem * item, gint x, gint y, gint * box)
{
GuppiCanvasItem *gci;
GuppiLegendState *state;
gint x0, y0, x1, y1, i, i0, i1, N;
double edge_margin, label_offset, swatch_width, swatch_height;
double px_margin, px_label_offset, px_box_width, px_box_height, sc;
double box_y_step, box_x0, box_x1, box_y0, box_y1;
g_return_val_if_fail (item != NULL, FALSE);
g_return_val_if_fail (GUPPI_IS_LEGEND_ITEM (item), FALSE);
g_return_val_if_fail (box != NULL, FALSE);
gci = GUPPI_CANVAS_ITEM (item);
state = GUPPI_LEGEND_STATE (guppi_canvas_item_state (gci));
guppi_element_state_get (GUPPI_ELEMENT_STATE (state),
"edge_margin", &edge_margin,
"label_offset", &label_offset,
"swatch_width", &swatch_width,
"swatch_height", &swatch_height,
NULL);
/* *Very* Hacky: a lot of code cut&paste from above. */
sc = guppi_canvas_item_scale (gci);
guppi_canvas_item_get_bbox_c (gci, &x0, &y0, &x1, &y1);
px_margin = guppi_pt2px (edge_margin * sc);
px_label_offset = guppi_x_pt2px (label_offset * sc);
px_box_width = guppi_x_pt2px (swatch_width * sc);
px_box_height = guppi_y_pt2px (swatch_height * sc);
guppi_legend_state_entry_bounds (state, &i0, &i1);
N = i1 - i0 + 1;
box_y_step =
N > 1 ? (y1 - y0 - 2 * px_margin - px_box_height) / (N - 1) : 0;
for (i = i0; i <= i1; ++i) {
double box_y_center;
box_y_center = y0 + px_margin + px_box_height / 2 + (i-i0) * box_y_step;
box_y0 = box_y_center - px_box_height / 2;
box_y1 = box_y_center + px_box_height / 2;
box_x0 = x0 + px_margin;
box_x1 = box_x0 + px_box_width;
if (box_x0 <= x && x <= box_x1 && box_y0 <= y && y <= box_y1) {
*box = i;
return TRUE;
}
}
return FALSE;
}
/* $Id: guppi-legend-item.c,v 1.17 2001/10/18 21:47:15 jody Exp $ */
syntax highlighted by Code2HTML, v. 0.9.1