aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/table/e-table-field-chooser-item.c
diff options
context:
space:
mode:
Diffstat (limited to 'widgets/table/e-table-field-chooser-item.c')
-rw-r--r--widgets/table/e-table-field-chooser-item.c567
1 files changed, 567 insertions, 0 deletions
diff --git a/widgets/table/e-table-field-chooser-item.c b/widgets/table/e-table-field-chooser-item.c
new file mode 100644
index 0000000000..fd08af3307
--- /dev/null
+++ b/widgets/table/e-table-field-chooser-item.c
@@ -0,0 +1,567 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * E-table-column-view.c: A canvas item based view of the ETableColumn.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * Copyright 1999, 2000 Helix Code, Inc.
+ */
+#include <config.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkdnd.h>
+#include <libgnomeui/gnome-canvas.h>
+#include <libgnomeui/gnome-canvas-util.h>
+#include <libgnomeui/gnome-canvas-polygon.h>
+#include <libgnomeui/gnome-canvas-rect-ellipse.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "e-util/e-xml-utils.h"
+#include "e-util/e-canvas.h"
+
+#include "e-table-header.h"
+#include "e-table-col-dnd.h"
+#include "e-table-defines.h"
+
+#include "e-table-field-chooser-item.h"
+
+#if 0
+enum {
+ BUTTON_PRESSED,
+ LAST_SIGNAL
+};
+
+static guint etfci_signals [LAST_SIGNAL] = { 0, };
+#endif
+
+#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
+
+#define ELEMENTS(x) (sizeof (x) / sizeof (x[0]))
+
+static GnomeCanvasItemClass *etfci_parent_class;
+
+static void etfci_drop_table_header (ETableFieldChooserItem *etfci);
+
+enum {
+ ARG_0,
+ ARG_TABLE_HEADER,
+ ARG_DND_CODE,
+ ARG_TABLE_FONTSET,
+ ARG_WIDTH,
+ ARG_HEIGHT,
+};
+
+static void
+etfci_destroy (GtkObject *object){
+ ETableFieldChooserItem *etfci = E_TABLE_FIELD_CHOOSER_ITEM (object);
+
+ etfci_drop_table_header (etfci);
+
+ gdk_font_unref(etfci->font);
+
+ if (GTK_OBJECT_CLASS (etfci_parent_class)->destroy)
+ (*GTK_OBJECT_CLASS (etfci_parent_class)->destroy) (object);
+}
+
+static void
+etfci_reflow (GnomeCanvasItem *item, gint flags)
+{
+ ETableFieldChooserItem *etfci = E_TABLE_FIELD_CHOOSER_ITEM (item);
+ double old_height;
+
+ old_height = etfci->height;
+
+ etfci->height = e_table_header_count (etfci->full_header) * etfci->button_height;
+
+ if (old_height != etfci->height)
+ e_canvas_item_request_parent_reflow(item);
+
+ gnome_canvas_item_request_update(item);
+}
+
+static void
+etfci_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ ETableFieldChooserItem *etfci = E_TABLE_FIELD_CHOOSER_ITEM (item);
+ double i2c [6];
+ ArtPoint c1, c2, i1, i2;
+
+ if (GNOME_CANVAS_ITEM_CLASS (etfci_parent_class)->update)
+ (*GNOME_CANVAS_ITEM_CLASS (etfci_parent_class)->update)(item, affine, clip_path, flags);
+
+ i1.x = i1.y = 0;
+ i2.x = etfci->width;
+ i2.y = etfci->height;
+
+ gnome_canvas_item_i2c_affine (item, i2c);
+ art_affine_point (&c1, &i1, i2c);
+ art_affine_point (&c2, &i2, i2c);
+
+ if (item->x1 != c1.x ||
+ item->y1 != c1.y ||
+ item->x2 != c2.x ||
+ item->y2 != c2.y)
+ {
+ gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2);
+ item->x1 = c1.x;
+ item->y1 = c1.y;
+ item->x2 = c2.x;
+ item->y2 = c2.y;
+
+ gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
+ }
+ gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2);
+}
+
+static void
+etfci_font_load (ETableFieldChooserItem *etfci, char *font)
+{
+ if (etfci->font)
+ gdk_font_unref (etfci->font);
+ etfci->font = NULL;
+
+ if (font)
+ etfci->font = gdk_fontset_load (font);
+
+ if (etfci->font == NULL) {
+ etfci->font = GTK_WIDGET(GNOME_CANVAS_ITEM(etfci)->canvas)->style->font;
+ gdk_font_ref(etfci->font);
+ }
+
+ etfci->button_height = etfci->font->ascent + etfci->font->descent + HEADER_PADDING;
+}
+
+static void
+etfci_drop_table_header (ETableFieldChooserItem *etfci)
+{
+ GtkObject *header;
+
+ if (!etfci->full_header)
+ return;
+
+ header = GTK_OBJECT (etfci->full_header);
+ gtk_signal_disconnect (header, etfci->structure_change_id);
+ gtk_signal_disconnect (header, etfci->dimension_change_id);
+
+ gtk_object_unref (header);
+ etfci->full_header = NULL;
+ etfci->height = 0;
+}
+
+static void
+structure_changed (ETableHeader *header, ETableFieldChooserItem *etfci)
+{
+ e_canvas_item_request_reflow(GNOME_CANVAS_ITEM(etfci));
+}
+
+static void
+dimension_changed (ETableHeader *header, int col, ETableFieldChooserItem *etfci)
+{
+ e_canvas_item_request_reflow(GNOME_CANVAS_ITEM(etfci));
+}
+
+static void
+etfci_add_table_header (ETableFieldChooserItem *etfci, ETableHeader *header)
+{
+ etfci->full_header = header;
+ gtk_object_ref (GTK_OBJECT (etfci->full_header));
+
+ etfci->structure_change_id = gtk_signal_connect (
+ GTK_OBJECT (header), "structure_change",
+ GTK_SIGNAL_FUNC(structure_changed), etfci);
+ etfci->dimension_change_id = gtk_signal_connect (
+ GTK_OBJECT (header), "dimension_change",
+ GTK_SIGNAL_FUNC(dimension_changed), etfci);
+ e_canvas_item_request_reflow(GNOME_CANVAS_ITEM(etfci));
+}
+
+static void
+etfci_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+{
+ GnomeCanvasItem *item;
+ ETableFieldChooserItem *etfci;
+
+ item = GNOME_CANVAS_ITEM (o);
+ etfci = E_TABLE_FIELD_CHOOSER_ITEM (o);
+
+ switch (arg_id){
+ case ARG_TABLE_HEADER:
+ etfci_drop_table_header (etfci);
+ etfci_add_table_header (etfci, E_TABLE_HEADER(GTK_VALUE_OBJECT (*arg)));
+ break;
+
+ case ARG_DND_CODE:
+ g_free(etfci->dnd_code);
+ etfci->dnd_code = g_strdup(GTK_VALUE_STRING (*arg));
+ break;
+
+ case ARG_TABLE_FONTSET:
+ etfci_font_load (etfci, GTK_VALUE_STRING (*arg));
+ e_canvas_item_request_reflow(item);
+ break;
+
+ case ARG_WIDTH:
+ etfci->width = GTK_VALUE_DOUBLE (*arg);
+ gnome_canvas_item_request_update(item);
+ break;
+ }
+}
+
+static void
+etfci_get_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+{
+ GnomeCanvasItem *item;
+ ETableFieldChooserItem *etfci;
+
+ item = GNOME_CANVAS_ITEM (o);
+ etfci = E_TABLE_FIELD_CHOOSER_ITEM (o);
+
+ switch (arg_id){
+
+ case ARG_DND_CODE:
+ GTK_VALUE_STRING (*arg) = g_strdup (etfci->dnd_code);
+ break;
+ case ARG_WIDTH:
+ GTK_VALUE_DOUBLE (*arg) = etfci->width;
+ break;
+ case ARG_HEIGHT:
+ GTK_VALUE_DOUBLE (*arg) = etfci->height;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void
+etfci_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ ETableFieldChooserItem *etfci)
+{
+ if (etfci->drag_col != -1) {
+ gchar *string = g_strdup_printf("%d", etfci->drag_col);
+ gtk_selection_data_set(selection_data,
+ GDK_SELECTION_TYPE_STRING,
+ sizeof(string[0]),
+ string,
+ strlen(string));
+ g_free(string);
+ }
+}
+
+static void
+etfci_drag_end (GtkWidget *canvas,
+ GdkDragContext *context,
+ ETableFieldChooserItem *etfci)
+{
+ etfci->drag_col = -1;
+}
+
+static void
+etfci_realize (GnomeCanvasItem *item)
+{
+ ETableFieldChooserItem *etfci = E_TABLE_FIELD_CHOOSER_ITEM (item);
+ GdkWindow *window;
+
+ if (GNOME_CANVAS_ITEM_CLASS (etfci_parent_class)-> realize)
+ (*GNOME_CANVAS_ITEM_CLASS (etfci_parent_class)->realize)(item);
+
+ window = GTK_WIDGET (item->canvas)->window;
+
+ if (!etfci->font)
+ etfci_font_load (etfci, NULL);
+
+ etfci->drag_end_id = gtk_signal_connect (
+ GTK_OBJECT (item->canvas), "drag_end",
+ GTK_SIGNAL_FUNC (etfci_drag_end), etfci);
+ etfci->drag_data_get_id = gtk_signal_connect (
+ GTK_OBJECT (item->canvas), "drag_data_get",
+ GTK_SIGNAL_FUNC (etfci_drag_data_get), etfci);
+}
+
+static void
+etfci_unrealize (GnomeCanvasItem *item)
+{
+ ETableFieldChooserItem *etfci = E_TABLE_FIELD_CHOOSER_ITEM (item);
+
+ if (etfci->font)
+ gdk_font_unref (etfci->font);
+ etfci->font = NULL;
+
+ gtk_signal_disconnect (GTK_OBJECT (item->canvas), etfci->drag_end_id);
+ etfci->drag_end_id = 0;
+ gtk_signal_disconnect (GTK_OBJECT (item->canvas), etfci->drag_data_get_id);
+ etfci->drag_data_get_id = 0;
+
+ if (GNOME_CANVAS_ITEM_CLASS (etfci_parent_class)->unrealize)
+ (*GNOME_CANVAS_ITEM_CLASS (etfci_parent_class)->unrealize)(item);
+}
+
+static void
+draw_button (ETableFieldChooserItem *etfci, ETableCol *col,
+ GdkDrawable *drawable, GtkStyle *style,
+ int x, int y, int width, int height)
+{
+ GdkRectangle clip;
+ int xtra;
+ GdkRectangle area;
+
+ GtkWidget *widget = GTK_WIDGET(GNOME_CANVAS_ITEM(etfci)->canvas);
+
+ gdk_window_clear_area (drawable, x, y, width, height);
+
+ area.x = x;
+ area.y = y;
+ area.width = width;
+ area.height = height;
+
+ gtk_paint_box (style, drawable,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ &area, widget, "button",
+ x, y, width, height);
+
+ clip.x = x + HEADER_PADDING / 2;
+ clip.y = y + HEADER_PADDING / 2;
+ clip.width = width - HEADER_PADDING;
+ clip.height = etfci->button_height;
+
+ if (col->is_pixbuf){
+ xtra = (clip.width - gdk_pixbuf_get_width (col->pixbuf))/2;
+
+ xtra += HEADER_PADDING / 2;
+
+ gdk_pixbuf_render_to_drawable_alpha (col->pixbuf,
+ drawable,
+ 0, 0,
+ x + xtra, y + (clip.height - gdk_pixbuf_get_height (col->pixbuf)) / 2,
+ gdk_pixbuf_get_width (col->pixbuf), gdk_pixbuf_get_height(col->pixbuf),
+ GDK_PIXBUF_ALPHA_FULL, 128,
+ GDK_RGB_DITHER_NORMAL,
+ 0, 0);
+ } else {
+ /* Center the thing */
+ xtra = (clip.width - gdk_string_measure (etfci->font, col->text))/2;
+
+ /* Skip over border */
+ if (xtra < 0)
+ xtra = 0;
+
+ xtra += HEADER_PADDING / 2;
+
+ gdk_draw_text (
+ drawable, etfci->font,
+ style->text_gc[GTK_STATE_NORMAL], x + xtra, y + etfci->button_height - etfci->font->descent - HEADER_PADDING / 2,
+ col->text, strlen (col->text));
+ }
+}
+
+static void
+etfci_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height)
+{
+ ETableFieldChooserItem *etfci = E_TABLE_FIELD_CHOOSER_ITEM (item);
+ GnomeCanvas *canvas = item->canvas;
+ const int rows = e_table_header_count (etfci->full_header);
+ int y1, y2;
+ int row;
+
+ y1 = y2 = 0;
+ for (row = 0; row < rows; row++, y1 = y2){
+ ETableCol *ecol = e_table_header_get_column (etfci->full_header, row);
+
+ y2 += etfci->button_height;
+
+ if (y1 > (y + height))
+ break;
+
+ if (y2 < y)
+ continue;
+
+ draw_button (etfci, ecol, drawable,
+ GTK_WIDGET (canvas)->style,
+ - x, y1 - y, etfci->width, y2 - y1);
+ }
+}
+
+static double
+etfci_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
+ GnomeCanvasItem **actual_item)
+{
+ *actual_item = item;
+ return 0.0;
+}
+
+static gboolean
+etfci_maybe_start_drag (ETableFieldChooserItem *etfci, double x, double y)
+{
+ if (!etfci->maybe_drag)
+ return FALSE;
+
+ if (MAX (abs (etfci->click_x - x),
+ abs (etfci->click_y - y)) <= 3)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+etfci_start_drag (ETableFieldChooserItem *etfci, GdkEvent *event)
+{
+ GtkWidget *widget = GTK_WIDGET (GNOME_CANVAS_ITEM (etfci)->canvas);
+ GtkTargetList *list;
+ GdkDragContext *context;
+ ETableCol *ecol;
+ GdkPixmap *pixmap;
+ int drag_col;
+
+ GtkTargetEntry etfci_drag_types [] = {
+ { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER },
+ };
+
+ drag_col = event->motion.x / etfci->button_height;
+
+ if (drag_col < 0 || drag_col > e_table_header_count(etfci->full_header))
+ return;
+
+ ecol = e_table_header_get_column (etfci->full_header, drag_col);
+
+ etfci->drag_col = ecol->col_idx;
+
+ etfci_drag_types[0].target = g_strdup_printf("%s-%s", etfci_drag_types[0].target, etfci->dnd_code);
+ list = gtk_target_list_new (etfci_drag_types, ELEMENTS (etfci_drag_types));
+ context = gtk_drag_begin (widget, list, GDK_ACTION_MOVE, 1, event);
+ g_free(etfci_drag_types[0].target);
+
+
+ pixmap = gdk_pixmap_new (widget->window, etfci->width, etfci->button_height, -1);
+ draw_button (etfci, ecol, pixmap,
+ widget->style,
+ 0, 0, etfci->width, etfci->button_height);
+ gtk_drag_set_icon_pixmap (context,
+ gdk_window_get_colormap (widget->window),
+ pixmap,
+ NULL,
+ etfci->width / 2,
+ etfci->button_height / 2);
+ gdk_pixmap_unref (pixmap);
+ etfci->maybe_drag = FALSE;
+}
+
+/*
+ * Handles the events on the ETableFieldChooserItem
+ */
+static int
+etfci_event (GnomeCanvasItem *item, GdkEvent *e)
+{
+ ETableFieldChooserItem *etfci = E_TABLE_FIELD_CHOOSER_ITEM (item);
+ GnomeCanvas *canvas = item->canvas;
+ int x, y;
+
+ switch (e->type){
+ case GDK_MOTION_NOTIFY:
+ gnome_canvas_w2c (canvas, e->motion.x, e->motion.y, &x, &y);
+
+ if (etfci_maybe_start_drag (etfci, x, y))
+ etfci_start_drag (etfci, e);
+ break;
+
+ case GDK_BUTTON_PRESS:
+ gnome_canvas_w2c (canvas, e->button.x, e->button.y, &x, &y);
+
+ if (e->button.button == 1){
+ etfci->click_x = x;
+ etfci->click_y = y;
+ etfci->maybe_drag = TRUE;
+ }
+ break;
+
+ case GDK_BUTTON_RELEASE: {
+ etfci->maybe_drag = FALSE;
+ break;
+ }
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+etfci_class_init (GtkObjectClass *object_class)
+{
+ GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
+
+ etfci_parent_class = gtk_type_class (PARENT_OBJECT_TYPE);
+
+ object_class->destroy = etfci_destroy;
+ object_class->set_arg = etfci_set_arg;
+ object_class->get_arg = etfci_get_arg;
+
+ item_class->update = etfci_update;
+ item_class->realize = etfci_realize;
+ item_class->unrealize = etfci_unrealize;
+ item_class->draw = etfci_draw;
+ item_class->point = etfci_point;
+ item_class->event = etfci_event;
+
+ gtk_object_add_arg_type ("ETableFieldChooserItem::ETableHeader", GTK_TYPE_OBJECT,
+ GTK_ARG_WRITABLE, ARG_TABLE_HEADER);
+ gtk_object_add_arg_type ("ETableFieldChooserItem::dnd_code", GTK_TYPE_STRING,
+ GTK_ARG_READWRITE, ARG_DND_CODE);
+ gtk_object_add_arg_type ("ETableFieldChooserItem::fontset", GTK_TYPE_STRING,
+ GTK_ARG_WRITABLE, ARG_TABLE_FONTSET);
+ gtk_object_add_arg_type ("ETableFieldChooserItem::width", GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE, ARG_WIDTH);
+ gtk_object_add_arg_type ("ETableFieldChooserItem::height", GTK_TYPE_DOUBLE,
+ GTK_ARG_READABLE, ARG_HEIGHT);
+
+}
+
+static void
+etfci_init (GnomeCanvasItem *item)
+{
+ ETableFieldChooserItem *etfci = E_TABLE_FIELD_CHOOSER_ITEM (item);
+
+ etfci->full_header = NULL;
+
+ etfci->height = etfci->width = 0;
+ etfci->button_height = 0;
+
+ etfci->font = NULL;
+
+ etfci->structure_change_id = 0;
+ etfci->dimension_change_id = 0;
+
+ etfci->dnd_code = NULL;
+
+ etfci->maybe_drag = 0;
+ etfci->drag_end_id = 0;
+
+ e_canvas_item_set_reflow_callback(item, etfci_reflow);
+}
+
+GtkType
+e_table_field_chooser_item_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableFieldChooserItem",
+ sizeof (ETableFieldChooserItem),
+ sizeof (ETableFieldChooserItemClass),
+ (GtkClassInitFunc) etfci_class_init,
+ (GtkObjectInitFunc) etfci_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
+ }
+
+ return type;
+}
+