diff options
-rw-r--r-- | widgets/misc/e-canvas-background.c | 464 | ||||
-rw-r--r-- | widgets/misc/e-canvas-background.h | 82 |
2 files changed, 546 insertions, 0 deletions
diff --git a/widgets/misc/e-canvas-background.c b/widgets/misc/e-canvas-background.c new file mode 100644 index 0000000000..36b84635ed --- /dev/null +++ b/widgets/misc/e-canvas-background.c @@ -0,0 +1,464 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-canvas-background.c - background color for canvas. + * Copyright 2001, Ximian, Inc. + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * 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 <config.h> + +#include "e-canvas-background.h" + +#include <math.h> +#include <stdio.h> +#include <gtk/gtksignal.h> +#include <gdk/gdkkeysyms.h> +#include "gal/widgets/e-hsv-utils.h" +#include "gal/widgets/e-canvas.h" +#include "gal/widgets/e-canvas-utils.h" +#include "gal/util/e-util.h" +#include <string.h> + +#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type () + +#define d(x) + +struct _ECanvasBackgroundPrivate { + guint rgba; /* Fill color, RGBA */ + GdkColor color; /* Fill color */ + GdkBitmap *stipple; /* Stipple for fill */ + GdkGC *gc; /* GC for filling */ + double x1; + double x2; + double y1; + double y2; + + guint needs_redraw : 1; +}; + +static GnomeCanvasItemClass *parent_class; + +enum { + ARG_0, + ARG_FILL_COLOR, + ARG_FILL_COLOR_GDK, + ARG_FILL_COLOR_RGBA, + ARG_FILL_STIPPLE, + ARG_X1, + ARG_X2, + ARG_Y1, + ARG_Y2, +}; + +static void +get_color(ECanvasBackground *ecb) +{ + int n; + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (ecb); + + n = 0; + gdk_color_context_get_pixels (item->canvas->cc, + &ecb->priv->color.red, + &ecb->priv->color.green, + &ecb->priv->color.blue, + 1, + &ecb->priv->color.pixel, + &n); +} + +static void +ecb_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2) +{ + double i2c [6]; + ArtPoint c1, c2, i1, i2; + ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item); + + /* Wrong BBox's are the source of redraw nightmares */ + + gnome_canvas_item_i2c_affine (GNOME_CANVAS_ITEM (ecb), i2c); + + i1.x = ecb->priv->x1; + i1.y = ecb->priv->y1; + i2.x = ecb->priv->x2; + i2.y = ecb->priv->y2; + art_affine_point (&c1, &i1, i2c); + art_affine_point (&c2, &i2, i2c); + + if (ecb->priv->x1 < 0) + c1.x = -(double)UINT_MAX; + + if (ecb->priv->y1 < 0) + c1.y = -(double)UINT_MAX; + + if (ecb->priv->x2 < 0) + c2.x = (double)UINT_MAX; + + if (ecb->priv->y2 < 0) + c2.y = (double)UINT_MAX; + + *x1 = c1.x; + *y1 = c1.y; + *x2 = c2.x + 1; + *y2 = c2.y + 1; +} + +/* + * GnomeCanvasItem::update method + */ +static void +ecb_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + ArtPoint o1, o2; + ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item); + + if (GNOME_CANVAS_ITEM_CLASS (parent_class)->update) + GNOME_CANVAS_ITEM_CLASS (parent_class)->update (item, affine, clip_path, flags); + + o1.x = item->x1; + o1.y = item->y1; + o2.x = item->x2; + o2.y = item->y2; + + ecb_bounds (item, &item->x1, &item->y1, &item->x2, &item->y2); + if (item->x1 != o1.x || + item->y1 != o1.y || + item->x2 != o2.x || + item->y2 != o2.y) { + gnome_canvas_request_redraw (item->canvas, o1.x, o1.y, o2.x, o2.y); + ecb->priv->needs_redraw = 1; + } + + if (ecb->priv->needs_redraw) { + gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, + item->x2, item->y2); + ecb->priv->needs_redraw = 0; + } +} + +/* Sets the stipple pattern for the text */ +static void +set_stipple (ECanvasBackground *ecb, GdkBitmap *stipple, int use_value) +{ + if (use_value) { + if (ecb->priv->stipple) + gdk_bitmap_unref (ecb->priv->stipple); + + ecb->priv->stipple = stipple; + if (stipple) + gdk_bitmap_ref (stipple); + } + + if (ecb->priv->gc) { + if (stipple) { + gdk_gc_set_stipple (ecb->priv->gc, stipple); + gdk_gc_set_fill (ecb->priv->gc, GDK_STIPPLED); + } else + gdk_gc_set_fill (ecb->priv->gc, GDK_SOLID); + } +} + +static void +ecb_destroy (GtkObject *object) +{ + ECanvasBackground *ecb = E_CANVAS_BACKGROUND (object); + + if (ecb->priv->stipple) + gdk_bitmap_unref (ecb->priv->stipple); + ecb->priv->stipple = NULL; + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +ecb_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + ECanvasBackground *ecb; + + GdkColor color = { 0, 0, 0, 0, }; + GdkColor *pcolor; + gboolean color_changed = FALSE; + + item = GNOME_CANVAS_ITEM (o); + ecb = E_CANVAS_BACKGROUND (o); + + switch (arg_id){ + case ARG_FILL_COLOR: + if (GTK_VALUE_STRING (*arg)) + gdk_color_parse (GTK_VALUE_STRING (*arg), &color); + + ecb->priv->rgba = ((color.red & 0xff00) << 16 | + (color.green & 0xff00) << 8 | + (color.blue & 0xff00) | + 0xff); + color_changed = TRUE; + break; + + case ARG_FILL_COLOR_GDK: + pcolor = GTK_VALUE_BOXED (*arg); + if (pcolor) { + color = *pcolor; + } + + ecb->priv->rgba = ((color.red & 0xff00) << 16 | + (color.green & 0xff00) << 8 | + (color.blue & 0xff00) | + 0xff); + color_changed = TRUE; + break; + + case ARG_FILL_COLOR_RGBA: + ecb->priv->rgba = GTK_VALUE_UINT (*arg); + color.red = ((ecb->priv->rgba >> 24) & 0xff) * 0x101; + color.green = ((ecb->priv->rgba >> 16) & 0xff) * 0x101; + color.blue = ((ecb->priv->rgba >> 8) & 0xff) * 0x101; + color_changed = TRUE; + break; + + case ARG_FILL_STIPPLE: + set_stipple (ecb, GTK_VALUE_BOXED (*arg), TRUE); + break; + + case ARG_X1: + ecb->priv->x1 = GTK_VALUE_DOUBLE (*arg); + break; + case ARG_X2: + ecb->priv->x2 = GTK_VALUE_DOUBLE (*arg); + break; + case ARG_Y1: + ecb->priv->y1 = GTK_VALUE_DOUBLE (*arg); + break; + case ARG_Y2: + ecb->priv->y2 = GTK_VALUE_DOUBLE (*arg); + break; + } + + if (color_changed) { + ecb->priv->color = color; + + if (GNOME_CANVAS_ITEM_REALIZED & GTK_OBJECT_FLAGS(item)) { + get_color (ecb); + if (!item->canvas->aa) { + gdk_gc_set_foreground (ecb->priv->gc, &ecb->priv->color); + } + } + } + + ecb->priv->needs_redraw = 1; + gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(ecb)); +} + +static void +ecb_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + ECanvasBackground *ecb; + + item = GNOME_CANVAS_ITEM (o); + ecb = E_CANVAS_BACKGROUND (o); + + switch (arg_id){ + case ARG_FILL_COLOR_GDK: + GTK_VALUE_BOXED (*arg) = gdk_color_copy (&ecb->priv->color); + break; + case ARG_FILL_COLOR_RGBA: + GTK_VALUE_UINT (*arg) = ecb->priv->rgba; + break; + case ARG_FILL_STIPPLE: + GTK_VALUE_BOXED (*arg) = ecb->priv->stipple; + break; + case ARG_X1: + GTK_VALUE_DOUBLE (*arg) = ecb->priv->x1; + break; + case ARG_X2: + GTK_VALUE_DOUBLE (*arg) = ecb->priv->x2; + break; + case ARG_Y1: + GTK_VALUE_DOUBLE (*arg) = ecb->priv->y1; + break; + case ARG_Y2: + GTK_VALUE_DOUBLE (*arg) = ecb->priv->y2; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +ecb_init (GnomeCanvasItem *item) +{ + ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item); + + ecb->priv = g_new (ECanvasBackgroundPrivate, 1); + + ecb->priv->color = (GdkColor) {0,}; + ecb->priv->stipple = NULL; + ecb->priv->gc = NULL; + ecb->priv->x1 = -1.0; + ecb->priv->x2 = -1.0; + ecb->priv->y1 = -1.0; + ecb->priv->y2 = -1.0; +} + +static void +ecb_realize (GnomeCanvasItem *item) +{ + ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item); + + if (GNOME_CANVAS_ITEM_CLASS (parent_class)->realize) + GNOME_CANVAS_ITEM_CLASS (parent_class)->realize (item); + + ecb->priv->gc = gdk_gc_new (item->canvas->layout.bin_window); + get_color (ecb); + if (!item->canvas->aa) + gdk_gc_set_foreground (ecb->priv->gc, &ecb->priv->color); + + set_stipple (ecb, NULL, FALSE); + + ecb->priv->needs_redraw = 1; + gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (ecb)); +} + +static void +ecb_unrealize (GnomeCanvasItem *item) +{ + ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item); + + gdk_gc_unref (ecb->priv->gc); + ecb->priv->gc = NULL; + + if (GNOME_CANVAS_ITEM_CLASS (parent_class)->unrealize) + GNOME_CANVAS_ITEM_CLASS (parent_class)->unrealize (item); +} + +static void +ecb_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) +{ + ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item); + int x1, x2, y1, y2; + double i2c [6]; + ArtPoint upper_left, lower_right, ecb_base_point; + + /* + * Find out our real position after grouping + */ + gnome_canvas_item_i2c_affine (item, i2c); + ecb_base_point.x = ecb->priv->x1; + ecb_base_point.y = ecb->priv->y1; + art_affine_point (&upper_left, &ecb_base_point, i2c); + + ecb_base_point.x = ecb->priv->x2; + ecb_base_point.y = ecb->priv->y2; + art_affine_point (&lower_right, &ecb_base_point, i2c); + + x1 = 0; + y1 = 0; + x2 = width; + y2 = height; + if (ecb->priv->x1 >= 0 && upper_left.x > x1) + x1 = upper_left.x; + if (ecb->priv->y1 >= 0 && upper_left.y > y1) + y1 = upper_left.y; + if (ecb->priv->x2 >= 0 && lower_right.x < x2) + x2 = lower_right.x; + if (ecb->priv->y2 >= 0 && lower_right.y < y2) + y2 = lower_right.y; + + gdk_draw_rectangle (drawable, ecb->priv->gc, TRUE, + x1, y1, x2 - x1, y2 - y1); +} + +static double +ecb_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, + GnomeCanvasItem **actual_item) +{ + ECanvasBackground *ecb = E_CANVAS_BACKGROUND (item); + + if (ecb->priv->x1 >= 0 && ecb->priv->x1 > x) + return 1.0; + if (ecb->priv->x2 >= 0 && ecb->priv->x2 < x) + return 1.0; + if (ecb->priv->y1 >= 0 && ecb->priv->y1 > y) + return 1.0; + if (ecb->priv->y2 >= 0 && ecb->priv->y2 < y) + return 1.0; + *actual_item = item; + + return 0.0; +} + +static void +ecb_class_init (GtkObjectClass *object_class) +{ + GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + + parent_class = gtk_type_class (PARENT_OBJECT_TYPE); + + object_class->destroy = ecb_destroy; + object_class->set_arg = ecb_set_arg; + object_class->get_arg = ecb_get_arg; + + item_class->update = ecb_update; + item_class->realize = ecb_realize; + item_class->unrealize = ecb_unrealize; + item_class->draw = ecb_draw; + item_class->point = ecb_point; + + gtk_object_add_arg_type ("ECanvasBackground::fill_color", GTK_TYPE_STRING, + GTK_ARG_WRITABLE, ARG_FILL_COLOR); + gtk_object_add_arg_type ("ECanvasBackground::fill_color_gdk", GTK_TYPE_GDK_COLOR, + GTK_ARG_READWRITE, ARG_FILL_COLOR_GDK); + gtk_object_add_arg_type ("ECanvasBackground::fill_color_rgba", GTK_TYPE_UINT, + GTK_ARG_READWRITE, ARG_FILL_COLOR_RGBA); + gtk_object_add_arg_type ("ECanvasBackground::fill_stipple", GTK_TYPE_GDK_WINDOW, + GTK_ARG_READWRITE, ARG_FILL_STIPPLE); + gtk_object_add_arg_type ("ECanvasBackground::x1", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_X1); + gtk_object_add_arg_type ("ECanvasBackground::x2", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_X2); + gtk_object_add_arg_type ("ECanvasBackground::y1", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_Y1); + gtk_object_add_arg_type ("ECanvasBackground::y2", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_Y2); +} + +GtkType +e_canvas_background_get_type (void) +{ + static GtkType type = 0; + + if (!type){ + GtkTypeInfo info = { + "ECanvasBackground", + sizeof (ECanvasBackground), + sizeof (ECanvasBackgroundClass), + (GtkClassInitFunc) ecb_class_init, + (GtkObjectInitFunc) ecb_init, + NULL, /* reserved 1 */ + NULL, /* reserved 2 */ + (GtkClassInitFunc) NULL + }; + + type = gtk_type_unique (PARENT_OBJECT_TYPE, &info); + } + + return type; +} diff --git a/widgets/misc/e-canvas-background.h b/widgets/misc/e-canvas-background.h new file mode 100644 index 0000000000..b0c28e099f --- /dev/null +++ b/widgets/misc/e-canvas-background.h @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-canvas-background.h - background color for canvas. + * Copyright 2001, Ximian, Inc. + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * 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. + */ + +#ifndef E_CANVAS_BACKGROUND_H +#define E_CANVAS_BACKGROUND_H + +#include <libgnome/gnome-defs.h> +#include <libgnomeui/gnome-canvas.h> + +BEGIN_GNOME_DECLS + +/* + * name type read/write description + * ------------------------------------------------------------------------------------------ + * fill_color string W X color specification for fill color, + * or NULL pointer for no color (transparent) + * fill_color_gdk GdkColor* RW Allocated GdkColor for fill + * fill_stipple GdkBitmap* RW Stipple pattern for fill + * x1 double RW Coordinates for edges of background rectangle + * x2 double RW Default is all of them = -1. + * y1 double RW Which means that the entire space is shown. + * y2 double RW If you need the rectangle to have negative coordinates, use an affine. + */ + + +#define E_CANVAS_BACKGROUND_TYPE (e_canvas_background_get_type ()) +#define E_CANVAS_BACKGROUND(obj) (GTK_CHECK_CAST ((obj), E_CANVAS_BACKGROUND_TYPE, ECanvasBackground)) +#define E_CANVAS_BACKGROUND_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_CANVAS_BACKGROUND_TYPE, ECanvasBackgroundClass)) +#define E_IS_CANVAS_BACKGROUND(obj) (GTK_CHECK_TYPE ((obj), E_CANVAS_BACKGROUND_TYPE)) +#define E_IS_CANVAS_BACKGROUND_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_CANVAS_BACKGROUND_TYPE)) + +typedef struct _ECanvasBackground ECanvasBackground; +typedef struct _ECanvasBackgroundClass ECanvasBackgroundClass; +typedef struct _ECanvasBackgroundPrivate ECanvasBackgroundPrivate; + +struct _ECanvasBackground { + GnomeCanvasItem item; + + ECanvasBackgroundPrivate *priv; +}; + +struct _ECanvasBackgroundClass { + GnomeCanvasItemClass parent_class; +}; + + +/* Standard Gtk function */ +GtkType e_canvas_background_get_type (void); + +END_GNOME_DECLS + +#endif + + + + + + + + + + |