You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnucash/lib/goffice/graph/gog-control-foocanvas.c

266 lines
8.9 KiB

/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* gog-control-foocanvas.c :
*
* Copyright (C) 2003-2004 Jody Goldberg (jody@gnome.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 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 <goffice/goffice-config.h>
#include <goffice/graph/gog-control-foocanvas.h>
#include <goffice/graph/gog-graph.h>
#include <goffice/graph/gog-object.h>
#include <libfoocanvas/foo-canvas-util.h>
#include <gsf/gsf-impl-utils.h>
#include <glib/gi18n.h>
#include <math.h>
enum {
CTRL_FOO_PROP_0,
CTRL_FOO_PROP_H,
CTRL_FOO_PROP_W,
CTRL_FOO_PROP_MODEL,
CTRL_FOO_PROP_RENDERER,
CTRL_FOO_PROP_LOGICAL_WIDTH_PTS,
CTRL_FOO_PROP_LOGICAL_HEIGHT_PTS
};
static GObjectClass *parent_klass;
#define GOG_CONTROL_FOOCANVAS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GOG_CONTROL_FOOCANVAS_TYPE, GogControlFooCanvasClass))
#define IS_GOG_CONTROL_FOOCANVAS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GOG_CONTROL_FOOCANVAS_TYPE))
#define GOG_CONTROL_FOOCANVAS_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((k), GOG_CONTROL_FOOCANVAS_TYPE, GogControlFooCanvasClass))
static void
gog_control_foocanvas_set_property (GObject *gobject, guint param_id,
GValue const *value, GParamSpec *pspec)
{
GogControlFooCanvas *ctrl = GOG_CONTROL_FOOCANVAS (gobject);
gboolean setup_renderer = (ctrl->renderer == NULL);
switch (param_id) {
case CTRL_FOO_PROP_H: ctrl->new_h = g_value_get_double (value); break;
case CTRL_FOO_PROP_W: ctrl->new_w = g_value_get_double (value); break;
case CTRL_FOO_PROP_MODEL:
if (ctrl->renderer != NULL)
g_object_unref (ctrl->renderer);
ctrl->renderer = g_object_new (GOG_RENDERER_PIXBUF_TYPE,
"model", g_value_get_object (value),
NULL);
break;
case CTRL_FOO_PROP_RENDERER:
if (ctrl->renderer != NULL)
g_object_unref (ctrl->renderer);
ctrl->renderer = GOG_RENDERER_PIXBUF (g_value_get_object (value));
if (ctrl->renderer != NULL)
g_object_ref (ctrl->renderer);
break;
case CTRL_FOO_PROP_LOGICAL_WIDTH_PTS :
g_object_set_property (G_OBJECT (ctrl->renderer),
"logical_width_pts", value);
break;
case CTRL_FOO_PROP_LOGICAL_HEIGHT_PTS :
g_object_set_property (G_OBJECT (ctrl->renderer),
"logical_height_pts", value);
break;
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec);
return; /* NOTE : RETURN */
}
if (setup_renderer && ctrl->renderer != NULL)
g_signal_connect_object (G_OBJECT (ctrl->renderer),
"request_update",
G_CALLBACK (foo_canvas_item_request_update),
ctrl, G_CONNECT_SWAPPED);
foo_canvas_item_request_update (FOO_CANVAS_ITEM (ctrl));
}
static void
gog_control_foocanvas_get_property (GObject *gobject, guint param_id,
GValue *value, GParamSpec *pspec)
{
GogControlFooCanvas *ctrl = GOG_CONTROL_FOOCANVAS (gobject);
switch (param_id) {
case CTRL_FOO_PROP_H: g_value_set_double (value, ctrl->new_h); break;
case CTRL_FOO_PROP_W: g_value_set_double (value, ctrl->new_w); break;
case CTRL_FOO_PROP_RENDERER : g_value_set_object (value, ctrl->renderer); break;
case CTRL_FOO_PROP_LOGICAL_WIDTH_PTS :
g_object_get_property (G_OBJECT (ctrl->renderer),
"logical_width_pts", value);
break;
case CTRL_FOO_PROP_LOGICAL_HEIGHT_PTS :
g_object_get_property (G_OBJECT (ctrl->renderer),
"logical_height_pts", value);
break;
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec);
break;
}
}
static void
gog_control_foocanvas_finalize (GObject *obj)
{
GogControlFooCanvas *ctrl = GOG_CONTROL_FOOCANVAS (obj);
if (ctrl->model != NULL) {
g_object_unref (ctrl->model);
ctrl->model = NULL;
}
if (ctrl->renderer != NULL) {
g_object_unref (ctrl->renderer);
ctrl->renderer = NULL;
}
(*parent_klass->finalize) (obj);
}
static void
gog_control_foocanvas_draw (FooCanvasItem *item, GdkDrawable *drawable,
GdkEventExpose *ev)
{
GogControlFooCanvas *ctrl = GOG_CONTROL_FOOCANVAS (item);
GdkPixbuf *buffer = gog_renderer_pixbuf_get (ctrl->renderer);
GdkRectangle display_rect, draw_rect;
GdkRegion *draw_region;
if (buffer) {
display_rect.x = item->x1;
display_rect.y = item->y1;
display_rect.width = item->x2 - item->x1;
display_rect.height = item->y2 - item->y1;
draw_region = gdk_region_rectangle (&display_rect);
gdk_region_intersect (draw_region, ev->region);
if (!gdk_region_empty (draw_region)) {
gdk_region_get_clipbox (draw_region, &draw_rect);
gdk_draw_pixbuf (drawable, NULL, buffer,
/* pixbuf 0, 0 is at pix_rect.x, pix_rect.y */
draw_rect.x - display_rect.x,
draw_rect.y - display_rect.y,
draw_rect.x,
draw_rect.y,
draw_rect.width,
draw_rect.height,
GDK_RGB_DITHER_NORMAL, 0, 0);
}
gdk_region_destroy (draw_region);
}
/* we are a canvas group, there could be some children */
if (FOO_CANVAS_ITEM_CLASS (parent_klass)->draw)
(FOO_CANVAS_ITEM_CLASS (parent_klass)->draw) (item, drawable, ev);
}
static void
gog_control_foocanvas_update (FooCanvasItem *item,
double i2w_dx, double i2w_dy, gint flags)
{
GogControlFooCanvas *ctrl = GOG_CONTROL_FOOCANVAS (item);
gboolean redraw;
int x1, x2, y1, y2;
int orig_x1 = item->x1, orig_x2 = item->x2, orig_y1 = item->y1, orig_y2 = item->y2;
if (FOO_CANVAS_ITEM_CLASS (parent_klass)->update)
(FOO_CANVAS_ITEM_CLASS (parent_klass)->update) (item, i2w_dx, i2w_dy, flags);
/* foo_canvas_group_update wipes the bbox */
item->x1 = orig_x1; item->x2 = orig_x2;
item->y1 = orig_y1; item->y2 = orig_y2;
foo_canvas_w2c (item->canvas, ctrl->base.xpos, ctrl->base.ypos, &x1, &y1);
foo_canvas_w2c (item->canvas, ctrl->base.xpos + ctrl->new_w, ctrl->base.ypos + ctrl->new_h, &x2, &y2);
redraw = gog_renderer_pixbuf_update (ctrl->renderer, x2-x1, y2-y1,
item->canvas->pixels_per_unit);
if (item->x1 != x1 || item->y1 != y1 || item->x2 != x2 || item->y2 != y2)
foo_canvas_update_bbox (FOO_CANVAS_ITEM (ctrl), x1, y1, x2, y2);
else if (redraw)
foo_canvas_item_request_redraw (FOO_CANVAS_ITEM (ctrl));
}
static void
gog_control_foocanvas_bounds (FooCanvasItem *item,
double *x1, double *y1, double *x2, double *y2)
{
*x1 = item->x1;
*x2 = item->x2;
*y1 = item->y1;
*y2 = item->y2;
}
static double
gog_control_foocanvas_point (FooCanvasItem *item, double x, double y, int cx, int cy,
FooCanvasItem **actual_item)
{
*actual_item = item;
return 0.;
}
static void
gog_control_foocanvas_class_init (GogControlFooCanvasClass *klass)
{
GObjectClass *gobject_klass = (GObjectClass *) klass;
FooCanvasItemClass *item_klass = (FooCanvasItemClass *) klass;
parent_klass = g_type_class_peek_parent (klass);
gobject_klass->set_property = gog_control_foocanvas_set_property;
gobject_klass->get_property = gog_control_foocanvas_get_property;
gobject_klass->finalize = gog_control_foocanvas_finalize;
item_klass->draw = gog_control_foocanvas_draw;
item_klass->update = gog_control_foocanvas_update;
item_klass->bounds = gog_control_foocanvas_bounds;
item_klass->point = gog_control_foocanvas_point;
g_object_class_install_property (gobject_klass, CTRL_FOO_PROP_H,
g_param_spec_double ("h", _("H"), _("Height"),
0, G_MAXDOUBLE, 100., G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, CTRL_FOO_PROP_W,
g_param_spec_double ("w", _("W"), _("Width"),
0, G_MAXDOUBLE, 100., G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, CTRL_FOO_PROP_MODEL,
g_param_spec_object ("model", "model",
"the GogObject this object displays",
GOG_OBJECT_TYPE, G_PARAM_WRITABLE));
g_object_class_install_property (gobject_klass, CTRL_FOO_PROP_RENDERER,
g_param_spec_object ("renderer", "renderer",
"the GogRendererPixbuf being displayed",
GOG_RENDERER_PIXBUF_TYPE, G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, CTRL_FOO_PROP_LOGICAL_WIDTH_PTS,
g_param_spec_double ("logical_width_pts", "Logical Width Pts",
"Logical width of the drawing area in pts",
0, G_MAXDOUBLE, 0, G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, CTRL_FOO_PROP_LOGICAL_HEIGHT_PTS,
g_param_spec_double ("logical_height_pts", "Logical Height Pts",
"Logical height of the drawing area in pts",
0, G_MAXDOUBLE, 0, G_PARAM_READWRITE));
}
static void
gog_control_foocanvas_init (GogControlFooCanvas *ctrl)
{
ctrl->new_h = ctrl->new_w = 0.;
}
GSF_CLASS (GogControlFooCanvas, gog_control_foocanvas,
gog_control_foocanvas_class_init, gog_control_foocanvas_init,
FOO_TYPE_CANVAS_GROUP)