aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--widgets/ChangeLog9
-rw-r--r--widgets/Makefile.am7
-rw-r--r--widgets/e-table-column-item.c199
-rw-r--r--widgets/e-table-column-item.h20
-rw-r--r--widgets/e-table-column-model.h5
-rw-r--r--widgets/e-table-column.c293
-rw-r--r--widgets/e-table-group.c98
-rw-r--r--widgets/e-table-group.h23
-rw-r--r--widgets/e-table-model.c152
-rw-r--r--widgets/e-table-simple.c120
-rw-r--r--widgets/e-table-simple.h38
-rw-r--r--widgets/e-table.c36
-rw-r--r--widgets/e-table/ChangeLog9
-rw-r--r--widgets/e-table/Makefile.am7
-rw-r--r--widgets/e-table/e-table-column-item.c199
-rw-r--r--widgets/e-table/e-table-column-item.h20
-rw-r--r--widgets/e-table/e-table-column-model.h5
-rw-r--r--widgets/e-table/e-table-column.c293
-rw-r--r--widgets/e-table/e-table-group.c98
-rw-r--r--widgets/e-table/e-table-group.h23
-rw-r--r--widgets/e-table/e-table-model.c152
-rw-r--r--widgets/e-table/e-table-simple.c120
-rw-r--r--widgets/e-table/e-table-simple.h38
-rw-r--r--widgets/e-table/e-table.c36
-rw-r--r--widgets/table/e-table-column-item.c199
-rw-r--r--widgets/table/e-table-column-item.h20
-rw-r--r--widgets/table/e-table-column-model.h5
-rw-r--r--widgets/table/e-table-column.c293
-rw-r--r--widgets/table/e-table-group.c98
-rw-r--r--widgets/table/e-table-group.h23
-rw-r--r--widgets/table/e-table-model.c152
-rw-r--r--widgets/table/e-table-simple.c120
-rw-r--r--widgets/table/e-table-simple.h38
-rw-r--r--widgets/table/e-table.c36
34 files changed, 2984 insertions, 0 deletions
diff --git a/widgets/ChangeLog b/widgets/ChangeLog
new file mode 100644
index 0000000000..e8d0c8e9ed
--- /dev/null
+++ b/widgets/ChangeLog
@@ -0,0 +1,9 @@
+1999-10-31 Miguel de Icaza <miguel@gnu.org>
+
+ * widgets/e-table-column.c, e-table-column.h: New file, implements the
+ e-table-column object.
+
+ * widget/e-table-model.h, e-table-model.c, e-table-simple.c,
+ e-table-simple.h: New files. Implements the column model and
+ a simple table wrapper.
+
diff --git a/widgets/Makefile.am b/widgets/Makefile.am
new file mode 100644
index 0000000000..d6aa94fb90
--- /dev/null
+++ b/widgets/Makefile.am
@@ -0,0 +1,7 @@
+noinst_LIBRARIES = \
+ e-table-simple.c \
+ e-table-simple.h \
+ e-table-model.c \
+ e-table-model.h \
+ e-table-column-model.c \
+ e-table-column-model.h \
diff --git a/widgets/e-table-column-item.c b/widgets/e-table-column-item.c
new file mode 100644
index 0000000000..dc0da16c11
--- /dev/null
+++ b/widgets/e-table-column-item.c
@@ -0,0 +1,199 @@
+/*
+ * E-table-column-view.c: A canvas view of the TableColumn.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * Copyright 1999, International GNOME Support.
+ */
+#include <config.h>
+#include "e-table-column.h"
+#include "e-table-column-view.h"
+
+#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
+
+static GnomeCanvasItemClass *etci_parent_class;
+
+enum {
+ ARG_0,
+ ARG_TABLE_COLUMN
+};
+
+static void
+etci_destroy (GtkObject *object)
+{
+ ETableColumnItem *etcv = E_TABLE_COLUMN_VIEW (object);
+
+ gtk_object_unref (GTK_OBJECT (etcv));
+
+ if (GTK_OBJECT_CLASS (etcv_parent_class)->destroy)
+ (*GTK_OBJECT_CLASS (etcv_parent_class)->destroy) (object);
+}
+
+static void
+etci_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ if (GNOME_CANVAS_ITEM_CLASS(item_bar_parent_class)->update)
+ (*GNOME_CANVAS_ITEM_CLASS(item_bar_parent_class)->update)(item, affine, clip_path, flags);
+
+ item->x1 = 0;
+ item->y1 = 0;
+ item->x2 = INT_MAX;
+ item->y2 = INT_MAX;
+ gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
+}
+
+static void
+etci_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+{
+ GnomeCanvasItem *item;
+ ETableColumnItem *etci;
+ int v;
+
+ item = GNOME_CANVAS_ITEM (o);
+ etci = E_TABLE_COLUMN_ITEM (o);
+
+ switch (arg_id){
+ case ARG_TABLE_COLUMN:
+ etci->etci = GTK_VALUE_POINTER (*arg);
+ break;
+ }
+ etci_update (item, NULL, NULL, 0);
+}
+
+static void
+etci_realize (GnomeCanvasItem *item)
+{
+ ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
+ GdkWindow *window;
+ GdkColor c;
+
+ if (GNOME_CANVAS_ITEM_CLASS (etci_parent_class)-> realize)
+ (*GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->realize)(item);
+
+ window = GTK_WIDGET (item->canvas)->window;
+
+ etci->gc = gdk_gc_new (window);
+ gnome_canvas_get_color (item->canvas, "black", &c);
+ gdk_gc_set_foreground (etci->gc, &c);
+
+ etci->normal_cursor = gdk_cursor_new (GDK_ARROW);
+}
+
+static void
+etci_unrealize (GnomeCanvasItem *item)
+{
+ ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
+
+ gdk_gc_unref (etci->gc);
+ etci->gc = NULL;
+
+ gdk_cursor_destroy (etci->change_cursor);
+ etci->change_cursor = NULL;
+
+ gdk_cursor_destroy (etci->normal_cursor);
+ etci->normal_cursor = NULL;
+
+ if (GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->unrealize)
+ (*GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->unrealize)(item);
+}
+
+static void
+etci_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height)
+{
+ ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
+ GnomeCanvas *canvas = item->canvas;
+ GdkGC *gc;
+ const int cols = e_table_column_count (etci->etc);
+ int x2 = x1 + width;
+ int col, total;
+
+ total = 0;
+ for (col = 0; col < cols; col++){
+ ETableCol *col = e_table_column_get_column (etci->etc, col);
+ const int col_width = col->width;
+
+ if (x1 > total + col_width)
+ continue;
+
+ if (x2 < total)
+ return;
+
+ gc = canvas->style->bg_gc [GTK_STATE_ACTIVE];
+ gdk_draw_rectangle (drawble, gc, TRUE,
+ gtk_draw_shadow (canvas->style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ x, y, width, height
+ }
+}
+
+static double
+etci_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
+ GnomeCanvasItem **actual_item)
+{
+ *actual_item = *item;
+ return 0.0;
+}
+
+static void
+etci_event (GnomeCanvasItem *item, GdkEvent *e)
+{
+ switch (e->type){
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+etci_class_init (GtkObjectClass *object_class)
+{
+ GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
+
+ object_class->destroy = etci_destroy;
+ object_class->set_arg = etci_set_arg;
+
+ item_class->update = etci_update;
+ item_class->realize = etci_realize;
+ item_class->unrealize = etci_unrealize;
+ item_class->draw = etci_draw;
+ item_class->point = etci_point;
+ item_class->event = etci_event;
+
+ gtk_object_add_arg_type ("ETableColumnItem::ETableColumn", GTK_TYPE_POINTER,
+ GTK_ARG_WRITABLE, ARG_TABLE_COLUMN);
+}
+
+static void
+etci_init (GnomeCanvasItem *item)
+{
+ item->x1 = 0;
+ item->y1 = 0;
+ item->x2 = 0;
+ item->y2 = 0;
+}
+
+GtkType
+e_table_column_view_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableColumnItem",
+ sizeof (ETableColumnItem),
+ sizeof (ETableColumnItemClass),
+ (GtkClassInitFunc) etci_class_init,
+ (GtkObjectInitFunc) etci_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
+ }
+
+ return type;
+}
+
+
+
diff --git a/widgets/e-table-column-item.h b/widgets/e-table-column-item.h
new file mode 100644
index 0000000000..fd38681a73
--- /dev/null
+++ b/widgets/e-table-column-item.h
@@ -0,0 +1,20 @@
+#ifndef _E_TABLE_COLUMN_VIEW_H
+#defein _E_TABLE_COLUMN_VIEW_H
+
+#include "e-table-column.h"
+
+typedef struct {
+ GnomeCanvasItem parent;
+ ETableColumn *etc;
+
+ GdkGC *gc;
+ GdkCursor *change_cursor, *normal_cursor;
+} ETableColumnView;
+
+typedef struct {
+ GnomeCanvasItemClass parent_class;
+} ETableColumnViewClass;
+
+GtkType e_table_column_item_get_type (void);
+
+#endif /* _E_TABLE_COLUMN_VIEW_H */
diff --git a/widgets/e-table-column-model.h b/widgets/e-table-column-model.h
new file mode 100644
index 0000000000..043dd783ca
--- /dev/null
+++ b/widgets/e-table-column-model.h
@@ -0,0 +1,5 @@
+
+class ETableColumnModel {
+ virtual void add_column (ETableCol *et) = 0;
+ virtual ETableCol *get_column (int column);
+ virtual
diff --git a/widgets/e-table-column.c b/widgets/e-table-column.c
new file mode 100644
index 0000000000..851ebc4532
--- /dev/null
+++ b/widgets/e-table-column.c
@@ -0,0 +1,293 @@
+/*
+ * e-table-column.c: TableColumn implementation
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 International GNOME Support
+ */
+#include <config.h>
+#include "e-table-column.h"
+
+enum {
+ STRUCTURE_CHANGE,
+ DIMENSION_CHANGE,
+ LAST_SIGNAL
+};
+
+static guint etc_signals [LAST_SIGNAL] = { 0, };
+
+static GtkObjectClass *e_table_column_parent_class;
+
+static void
+e_table_column_destroy (GtkObject *object)
+{
+ ETableColumn *etc = E_TABLE_COLUMN (object);
+ const int cols = etc->col_count;
+
+ /*
+ * Destroy listeners
+ */
+ for (l = etc->listeners; l; l = l->next)
+ g_free (l->data);
+ g_slist_free (etc->listeners);
+ etc->listeners = NULL;
+
+ /*
+ * Destroy columns
+ */
+ for (i = 0; i < cols; i++)
+ e_table_column_remove (etc, i);
+
+ if (e_table_column_parent_class->destroy)
+ e_table_column_parent_class->destroy (object);
+}
+
+static void
+e_table_column_class_init (GtkObjectClass *object_class)
+{
+ object_class->destroy = e_table_column_destroy;
+
+ e_table_column_parent_class = (gtk_type_class (gtk_object_get_type ()));
+
+ etc_signals [STRUCTURE_CHANGE] =
+ gtk_signal_new ("structure_change",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableColumn, structure_change),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+ etc_signals [DIMENSION_CHANGE] =
+ gtk_signal_new ("dimension_change",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableColumn, dimension_change),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, etc_signals, LAST_SIGNAL);
+}
+
+GtkType
+e_table_column_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableColumn",
+ sizeof (ETableColumn),
+ sizeof (ETableColumnClass),
+ (GtkClassInitFunc) e_table_column_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (gtk_object_get_type (), &info);
+ }
+
+ return type;
+}
+
+static void
+etc_do_insert (ETableColumn *etc, int pos, ETableCol *val)
+{
+ memcpy (&etc->columns [pos+1], &etc->columns [pos],
+ sizeof (ETableCol *) * (etc->col_count - pos));
+ etc->columns [pos] = val;
+}
+
+void
+e_table_column_add_column (ETableColumn *etc, ETableCol *tc, int pos)
+{
+ ETableCol **new_ptr;
+
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (tc != NULL);
+ g_return_if_fail (pos >= 0 && pos < etc->col_count);
+
+ if (pos == -1)
+ pos = etc->col_count;
+ etc->columns = g_realloc (etc->columns, sizeof (ETableCol *) * (etc->col_count + 1));
+ etc_do_insert (etc, pos, tc);
+ etc->col_count++;
+
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
+}
+
+ETableCol *
+e_table_column_get_column (ETableColumn *etc, int column)
+{
+ g_return_val_if_fail (etc != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), NULL);
+
+ if (column < 0)
+ return NULL;
+
+ if (column >= etc->col_count)
+ return NULL;
+
+ return etc->columns [column];
+}
+
+int
+e_table_column_count (ETableColumn *etc)
+{
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ return etc->col_count;
+}
+
+int
+e_table_column_index (ETableColumn *etc, const char *identifier)
+{
+ int i;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+ g_return_val_if_fail (identifier != NULL, 0);
+
+ for (i = 0; i < etc->col_count; i++){
+ ETableCol *tc = etc->columns [i];
+
+ if (strcmp (i->id, identifier) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+int
+e_table_column_get_index_at (ETableColumn *etc, int x_offset)
+{
+ int i, total;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+ g_return_val_if_fail (identifier != NULL, 0);
+
+ total = 0;
+ for (i = 0; i < etc->col_count; i++){
+ total += etc->columns [i]->width;
+
+ if (x_offset < total)
+ return i;
+ }
+
+ return -1;
+}
+
+ETableCol **
+e_table_column_get_columns (ETableColumn *etc)
+{
+ ETableCol **ret;
+ int i;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ ret = g_new (ETableCol *, etc->col_count + 1);
+ memcpy (ret, etc->columns, sizeof (ETableCol *) * etc->col_count);
+ ret [etc->col_count] = NULL;
+
+ return ret;
+}
+
+gboolean
+e_table_column_selection_ok (ETableColumn *etc)
+{
+ g_return_val_if_fail (etc != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), FALSE);
+
+ return etc->selectable;
+}
+
+int
+ve_table_column_get_selected (ETableColumn *etc)
+{
+ int i;
+ int selected = 0;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ for (i = 0; i < etc->col_count; i++){
+ if (etc->columns [i]->selected)
+ selected++;
+ }
+
+ return selected;
+}
+
+int
+e_table_column_total_width (ETableColumn *etc)
+{
+ int total;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ total = 0;
+ for (i = 0; i < etc->col_count; i++)
+ total += etc->columns [i].width;
+
+ return total;
+}
+
+static void
+etc_do_remove (ETableColumn *etc, int idx)
+{
+ memcpy (&etc->columns [idx], &etc->columns [idx+1],
+ sizeof (ETableCol *) * etc->col_count - idx);
+ etc->col_count--;
+}
+
+void
+e_table_column_move (ETableColumn *etc, int source_index, int target_index)
+{
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (source_index >= 0);
+ g_return_if_fail (target_index >= 0);
+ g_return_if_fail (source_index < etc->col_count);
+ g_return_if_fail (target_index < etc->col_count);
+
+ old = etc->columns [source_index];
+ etc_do_remove (etc, source_index);
+ etc_do_insert (etc, target_index, old);
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
+}
+
+void
+e_table_column_remove (ETableColumn *etc, int idx)
+{
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (idx >= 0);
+ g_return_if_fail (idx < etc->col_count);
+
+ etc_do_remove (etc, idx);
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
+}
+
+void
+e_table_column_set_selection (ETableColumn *etc, gboolean allow_selection);
+{
+}
+
+void
+e_table_column_set_size (ETableColumn *etc, int idx, int size)
+{
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (idx >= 0);
+ g_return_if_fail (idx < etc->col_count);
+ g_return_if_fail (size > 0);
+
+ etc->columns [idx]->width = size;
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [SIZE_CHANGE], idx);
+}
diff --git a/widgets/e-table-group.c b/widgets/e-table-group.c
new file mode 100644
index 0000000000..194bc6b235
--- /dev/null
+++ b/widgets/e-table-group.c
@@ -0,0 +1,98 @@
+/*
+ * E-Table-Group.c: Implements the grouping objects for elements on a table
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org()
+ *
+ * Copyright 1999, International GNOME Support.
+ */
+
+#include <config.h>
+#include "e-table-group.h"
+
+void
+e_table_group_destroy (ETableGroup *etg)
+{
+ g_return_val_if_fail (etg != NULL);
+
+ g_free (etg->title);
+
+ if (etg->is_leaf == 0){
+ GSList *l;
+
+ for (l = etg->u.children; l; l = l->next){
+ ETableGroup *child = l->data;
+
+ e_table_group_destroy (child);
+ }
+ g_slist_free (etg->u.children);
+ etg->u.children = NULL;
+ }
+ g_free (etg);
+}
+
+ETableGroup *
+e_table_group_new_leaf (const char *title, ETableModel *table)
+{
+ ETableGroup *etg;
+
+ g_return_val_if_fail (title != NULL, NULL);
+ g_return_val_if_fail (table != NULL, NULL);
+
+ etg = g_new (ETableGroup, 1);
+
+ etg->expanded = 0;
+ etg->is_leaf = 1;
+ etg->u.table = table;
+ etg->title = g_strdup (title);
+
+ return eg;
+}
+
+ETableGroup *
+e_table_group_new_leaf (const char *title)
+{
+ ETableGroup *etg;
+
+ g_return_val_if_fail (title != NULL, NULL);
+
+ etg = g_new (ETableGroup, 1);
+
+ etg->expanded = 0;
+ etg->is_leaf = 0;
+ etg->u.children = NULL;
+ etg->title = g_strdup (title);
+
+ return eg;
+}
+
+void
+e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
+{
+ g_return_val_if_fail (etg != NULL);
+ g_return_val_if_fail (child != NULL);
+ g_return_val_if_fail (etg->is_leaf != 0);
+
+ etg->u.children = g_slist_append (etg->u.children, child);
+}
+
+int
+e_table_group_size (ETableGroup *etg)
+{
+ g_return_val_if_fail (etg != NULL);
+
+ if (etg->is_leaf)
+ return e_table_model_height (etg->u.table);
+ else {
+ GSList *l;
+ int size = 0;
+
+ for (l = etg->u.children; l; l = l->next){
+ ETableGroup *child = l->data;
+
+ size += e_table_group_size (child);
+ }
+ return size;
+ }
+}
+
diff --git a/widgets/e-table-group.h b/widgets/e-table-group.h
new file mode 100644
index 0000000000..ab79d317e9
--- /dev/null
+++ b/widgets/e-table-group.h
@@ -0,0 +1,23 @@
+#ifndef _E_TABLE_TREE_H_
+#define _E_TABLE_TREE_H_
+
+typedef struct {
+ char *title;
+
+ union {
+ ETableModel *table;
+ GSList *children;
+ } u;
+
+ guint expanded :1;
+ guint is_leaf :1;
+} ETableGroup;
+
+ETableGroup *e_table_group_new (const char *title, ETableModel *table);
+ETableGroup *e_table_group_new_leaf (const char *title);
+void e_table_group_destroy (ETableGroup *etg);
+
+int e_table_group_size (ETableGroup *egroup);
+void e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
+
+#endif /* _E_TABLE_TREE_H_ */
diff --git a/widgets/e-table-model.c b/widgets/e-table-model.c
new file mode 100644
index 0000000000..23782e52c9
--- /dev/null
+++ b/widgets/e-table-model.c
@@ -0,0 +1,152 @@
+/*
+ * e-table-model.c: a Table Model
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 International GNOME Support.
+ */
+#include <config.h>
+#include "e-table-model.h"
+
+#define ETM_CLASS(e) ((ETableModelClass *)((GtkObject *)e)->klass)
+
+static GtkObjectClass *e_table_model_parent_class;
+
+int
+e_table_model_column_count (ETableModel *etable)
+{
+ return ETM_CLASS (etable)->column_count (etable);
+}
+
+const char *
+e_table_model_column_name (ETableModel *etable, int col)
+{
+ return ETM_CLASS (etable)->column_name (etable, col);
+}
+
+int
+e_table_model_row_count (ETableModel *etable)
+{
+ return ETM_CLASS (etable)->row_count (etable);
+}
+
+void *
+e_table_model_value_at (ETableModel *etable, int col, int row)
+{
+ return ETM_CLASS (etable)->value_at (etable, col, row);
+}
+
+void
+e_table_model_set_value_at (ETableModel *etable, int col, int row, void *data)
+{
+ return ETM_CLASS (etable)->set_value_at (etable, col, row, data);
+}
+
+gboolean
+e_table_model_is_cell_editable (ETableModel *etable, int col, int row)
+{
+ return ETM_CLASS (etable)->is_cell_editable (etable, col, row);
+}
+
+int
+e_table_model_row_height (ETableModel *etable, int row)
+{
+ return ETM_CLASS (etable)->row_height (etable, row);
+}
+
+typedef struct {
+ ETableModelListenerFn listener;
+ void *data;
+} listener_t;
+
+void
+e_table_model_add_listener (ETableModel *etable, ETableModelListenerFn listener, void *data)
+{
+ listener_t *lis;
+
+ lis = g_new (listener_t, 1);
+ lis->listener_t = listener;
+ lis->data = data;
+
+ etable->listeners = g_list_prepend (etable->listeners, lis);
+}
+
+void
+e_table_model_remove_listener (ETableModel *etable, ETableModelListenerFn listener, void *data)
+{
+ GSList *l;
+
+ for (l = etable->listeners; l; l = l->next){
+ listener_t *lis = l->data;
+
+ if (lis->listener == listener && lis->data == data){
+ etable->listeners = g_list_remove (etable->listeners, lis);
+ g_free (lis);
+ return;
+ }
+ }
+}
+
+static void
+e_table_model_destroy (GtkObject *object)
+{
+ GSList *l;
+
+ ETableModel *etable = (ETableModel *) object;
+
+ for (l = etable->listeners; l; l = l->next)
+ g_free (l->data);
+ g_list_free (etable->listeners);
+
+ if (e_table_model_parent_class->destroy)
+ (*e_table_model_parent_class->destroy)(object);
+}
+
+static void
+e_table_model_class_init (GtkObjectClass *class)
+{
+ e_table_model_parent_class = gtk_type_class (gtk_object_get_type ());
+
+ class->destroy = e_table_model_destroy;
+}
+
+GtkType
+e_table_model_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableModel",
+ sizeof (ETableModel),
+ sizeof (ETableModelClass),
+ (GtkClassInitFunc) e_table_model_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (gtk_object_get_type (), &info);
+ }
+
+ return type;
+}
+
+int
+e_table_model_height (ETableModel *etable)
+{
+ int rows;
+ int size;
+ g_return_val_if_fail (etable != NULL);
+
+ rows = e_table_model_row_count (etable);
+ size = 0;
+
+ for (i = 0; i < rows; i++)
+ size += e_table_model_row_height (etable, i);
+
+ return size;
+}
+
diff --git a/widgets/e-table-simple.c b/widgets/e-table-simple.c
new file mode 100644
index 0000000000..b586712942
--- /dev/null
+++ b/widgets/e-table-simple.c
@@ -0,0 +1,120 @@
+/*
+ * e-table-model.c: a simple table model implementation that uses function
+ * pointers to simplify the creation of new, exotic and colorful tables in
+ * no time.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 International GNOME Support.
+ */
+
+#include <config.h>
+#include "e-table-simple.h"
+
+static int
+simple_column_count (ETableModel *etm)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->col_count (etm)
+}
+
+static const char *
+simple_column_name (ETableModel *etm, int col)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->col_name (etm, col);
+}
+
+static int
+simple_row_count (ETableModel *etm)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->row_count (etm);
+}
+
+static void
+simple_value_at (ETableModel *etm, int col, int row)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->value_at (etm, col, row);
+}
+
+static void
+simple_set_value_at (ETableModel *etm, int col, int row, void *data)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->set_value_at (etm, col, row, data);
+}
+
+static gboolean
+simple_is_cell_editable (ETableModel *etm, int col, int row)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->is_cell_editable (etm, col, row, data);
+}
+
+static void
+e_table_simple_class_init (GtkObjectClass *object_class)
+{
+ ETableSimpleClass *simple_class = (ETableSimpleClass *) object_class;
+
+ simple_class->column_count = simple_column_count;
+ simple_class->column_name = simple_column_name;
+ simple_class->row_count = simple_row_count;
+ simple_class->value_at = simple_value_at;
+ simple_class->set_value_at = simple_set_value_at;
+ simple_class->is_cell_editable = simple_is_cell_editable;
+}
+
+GtkType
+e_table_simple_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableSimple",
+ sizeof (ETableSimple),
+ sizeof (ETableSimpleClass),
+ (GtkClassInitFunc) e_table_simple_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (e_table_model_get_type (), &info);
+ }
+
+ return type;
+}
+
+ETable *
+e_table_simple_new (ETableSimpleColumnCountFn col_count,
+ ETableSimpleColumnNameFn col_name,
+ ETableSimpleRowCountFn row_count,
+ ETableSimpleValueAtFn value_at,
+ ETableSimpleSetValueAtFn set_value_at,
+ ETableSimpleIsCellEditableFn is_cell_editable,
+ void *data)
+{
+ ETableSimple *et;
+
+ et = gtk_type_new (e_table_simple_get_type ());
+
+ et->col_count = col_count;
+ et->col_name = col_name;
+ et->row_count = row_count;
+ et->value_at = value_at;
+ et->set_value_at = set_value_at;
+ et->is_cell_editable = is_cell_editable;
+
+ return (ETable *) et;
+}
diff --git a/widgets/e-table-simple.h b/widgets/e-table-simple.h
new file mode 100644
index 0000000000..b5c549a440
--- /dev/null
+++ b/widgets/e-table-simple.h
@@ -0,0 +1,38 @@
+#ifndef _E_TABLE_SIMPLE_H_
+#define _E_TABLE_SIMPLE_H_
+
+#include "e-table-model.h"
+
+typedef int (*ETableSimpleColumnCountFn) (ETableModel *etm);
+typedef const char *(*ETableSimpleColumnNameFn) (ETableModel *etm, int col);
+typedef int (*ETableSimpleRowCountFn) (ETableModel *etm);
+typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row);
+typedef void (*ETableSimpleSetValueAtFn) (ETableModel *etm, int col, int row, void *data);
+typedef gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row);
+typedef int (*ETableSimpleRowHeightFn (ETableModel *etm, int row);
+
+typedef struct {
+ ETableModel parent;
+
+ ETableSimpleColumnCountFn col_count;
+ ETableSimpleColumnNameFn col_name;
+ ETableSimpleRowCountFn row_count;
+ ETableSimpleValueAtFn value_at;
+ ETableSimpleSetValueAtFn set_value_at;
+ ETableSimpleIsCellEditableFn is_cell_editable;
+ ETableSimpleRowHeightFn row_height;
+ void *data;
+} ETableSimple;
+
+GtkType e_table_simple_get_type (void);
+
+ETable *e_table_simple_new (ETableSimpleColumnCountFn col_count,
+ ETableSimpleColumnNameFn col_name,
+ ETableSimpleRowCountFn row_count,
+ ETableSimpleValueAtFn value_at,
+ ETableSimpleSetValueAtFn set_value_at,
+ ETableSimpleIsCellEditableFn is_cell_editable,
+ void *data);
+
+#endif /* _E_TABLE_SIMPLE_H_ */
+
diff --git a/widgets/e-table.c b/widgets/e-table.c
new file mode 100644
index 0000000000..427f527185
--- /dev/null
+++ b/widgets/e-table.c
@@ -0,0 +1,36 @@
+/*
+ * E-table-view.c: A graphical view of a Table.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * Copyright 1999, International GNOME Support
+ */
+#include <config.h>
+#include <libgnomeui/gnome-canvas.h>
+#include "e-table.h"
+
+#define PARENT_OBJECT_TYPE gnome_canvas_get_type ()
+
+GtkType
+e_table_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETable",
+ sizeof (ETable),
+ sizeof (ETableClass),
+ (GtkClassInitFunc) e_table_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
+ }
+
+ return type;
+}
diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog
new file mode 100644
index 0000000000..e8d0c8e9ed
--- /dev/null
+++ b/widgets/e-table/ChangeLog
@@ -0,0 +1,9 @@
+1999-10-31 Miguel de Icaza <miguel@gnu.org>
+
+ * widgets/e-table-column.c, e-table-column.h: New file, implements the
+ e-table-column object.
+
+ * widget/e-table-model.h, e-table-model.c, e-table-simple.c,
+ e-table-simple.h: New files. Implements the column model and
+ a simple table wrapper.
+
diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am
new file mode 100644
index 0000000000..d6aa94fb90
--- /dev/null
+++ b/widgets/e-table/Makefile.am
@@ -0,0 +1,7 @@
+noinst_LIBRARIES = \
+ e-table-simple.c \
+ e-table-simple.h \
+ e-table-model.c \
+ e-table-model.h \
+ e-table-column-model.c \
+ e-table-column-model.h \
diff --git a/widgets/e-table/e-table-column-item.c b/widgets/e-table/e-table-column-item.c
new file mode 100644
index 0000000000..dc0da16c11
--- /dev/null
+++ b/widgets/e-table/e-table-column-item.c
@@ -0,0 +1,199 @@
+/*
+ * E-table-column-view.c: A canvas view of the TableColumn.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * Copyright 1999, International GNOME Support.
+ */
+#include <config.h>
+#include "e-table-column.h"
+#include "e-table-column-view.h"
+
+#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
+
+static GnomeCanvasItemClass *etci_parent_class;
+
+enum {
+ ARG_0,
+ ARG_TABLE_COLUMN
+};
+
+static void
+etci_destroy (GtkObject *object)
+{
+ ETableColumnItem *etcv = E_TABLE_COLUMN_VIEW (object);
+
+ gtk_object_unref (GTK_OBJECT (etcv));
+
+ if (GTK_OBJECT_CLASS (etcv_parent_class)->destroy)
+ (*GTK_OBJECT_CLASS (etcv_parent_class)->destroy) (object);
+}
+
+static void
+etci_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ if (GNOME_CANVAS_ITEM_CLASS(item_bar_parent_class)->update)
+ (*GNOME_CANVAS_ITEM_CLASS(item_bar_parent_class)->update)(item, affine, clip_path, flags);
+
+ item->x1 = 0;
+ item->y1 = 0;
+ item->x2 = INT_MAX;
+ item->y2 = INT_MAX;
+ gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
+}
+
+static void
+etci_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+{
+ GnomeCanvasItem *item;
+ ETableColumnItem *etci;
+ int v;
+
+ item = GNOME_CANVAS_ITEM (o);
+ etci = E_TABLE_COLUMN_ITEM (o);
+
+ switch (arg_id){
+ case ARG_TABLE_COLUMN:
+ etci->etci = GTK_VALUE_POINTER (*arg);
+ break;
+ }
+ etci_update (item, NULL, NULL, 0);
+}
+
+static void
+etci_realize (GnomeCanvasItem *item)
+{
+ ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
+ GdkWindow *window;
+ GdkColor c;
+
+ if (GNOME_CANVAS_ITEM_CLASS (etci_parent_class)-> realize)
+ (*GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->realize)(item);
+
+ window = GTK_WIDGET (item->canvas)->window;
+
+ etci->gc = gdk_gc_new (window);
+ gnome_canvas_get_color (item->canvas, "black", &c);
+ gdk_gc_set_foreground (etci->gc, &c);
+
+ etci->normal_cursor = gdk_cursor_new (GDK_ARROW);
+}
+
+static void
+etci_unrealize (GnomeCanvasItem *item)
+{
+ ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
+
+ gdk_gc_unref (etci->gc);
+ etci->gc = NULL;
+
+ gdk_cursor_destroy (etci->change_cursor);
+ etci->change_cursor = NULL;
+
+ gdk_cursor_destroy (etci->normal_cursor);
+ etci->normal_cursor = NULL;
+
+ if (GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->unrealize)
+ (*GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->unrealize)(item);
+}
+
+static void
+etci_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height)
+{
+ ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
+ GnomeCanvas *canvas = item->canvas;
+ GdkGC *gc;
+ const int cols = e_table_column_count (etci->etc);
+ int x2 = x1 + width;
+ int col, total;
+
+ total = 0;
+ for (col = 0; col < cols; col++){
+ ETableCol *col = e_table_column_get_column (etci->etc, col);
+ const int col_width = col->width;
+
+ if (x1 > total + col_width)
+ continue;
+
+ if (x2 < total)
+ return;
+
+ gc = canvas->style->bg_gc [GTK_STATE_ACTIVE];
+ gdk_draw_rectangle (drawble, gc, TRUE,
+ gtk_draw_shadow (canvas->style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ x, y, width, height
+ }
+}
+
+static double
+etci_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
+ GnomeCanvasItem **actual_item)
+{
+ *actual_item = *item;
+ return 0.0;
+}
+
+static void
+etci_event (GnomeCanvasItem *item, GdkEvent *e)
+{
+ switch (e->type){
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+etci_class_init (GtkObjectClass *object_class)
+{
+ GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
+
+ object_class->destroy = etci_destroy;
+ object_class->set_arg = etci_set_arg;
+
+ item_class->update = etci_update;
+ item_class->realize = etci_realize;
+ item_class->unrealize = etci_unrealize;
+ item_class->draw = etci_draw;
+ item_class->point = etci_point;
+ item_class->event = etci_event;
+
+ gtk_object_add_arg_type ("ETableColumnItem::ETableColumn", GTK_TYPE_POINTER,
+ GTK_ARG_WRITABLE, ARG_TABLE_COLUMN);
+}
+
+static void
+etci_init (GnomeCanvasItem *item)
+{
+ item->x1 = 0;
+ item->y1 = 0;
+ item->x2 = 0;
+ item->y2 = 0;
+}
+
+GtkType
+e_table_column_view_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableColumnItem",
+ sizeof (ETableColumnItem),
+ sizeof (ETableColumnItemClass),
+ (GtkClassInitFunc) etci_class_init,
+ (GtkObjectInitFunc) etci_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
+ }
+
+ return type;
+}
+
+
+
diff --git a/widgets/e-table/e-table-column-item.h b/widgets/e-table/e-table-column-item.h
new file mode 100644
index 0000000000..fd38681a73
--- /dev/null
+++ b/widgets/e-table/e-table-column-item.h
@@ -0,0 +1,20 @@
+#ifndef _E_TABLE_COLUMN_VIEW_H
+#defein _E_TABLE_COLUMN_VIEW_H
+
+#include "e-table-column.h"
+
+typedef struct {
+ GnomeCanvasItem parent;
+ ETableColumn *etc;
+
+ GdkGC *gc;
+ GdkCursor *change_cursor, *normal_cursor;
+} ETableColumnView;
+
+typedef struct {
+ GnomeCanvasItemClass parent_class;
+} ETableColumnViewClass;
+
+GtkType e_table_column_item_get_type (void);
+
+#endif /* _E_TABLE_COLUMN_VIEW_H */
diff --git a/widgets/e-table/e-table-column-model.h b/widgets/e-table/e-table-column-model.h
new file mode 100644
index 0000000000..043dd783ca
--- /dev/null
+++ b/widgets/e-table/e-table-column-model.h
@@ -0,0 +1,5 @@
+
+class ETableColumnModel {
+ virtual void add_column (ETableCol *et) = 0;
+ virtual ETableCol *get_column (int column);
+ virtual
diff --git a/widgets/e-table/e-table-column.c b/widgets/e-table/e-table-column.c
new file mode 100644
index 0000000000..851ebc4532
--- /dev/null
+++ b/widgets/e-table/e-table-column.c
@@ -0,0 +1,293 @@
+/*
+ * e-table-column.c: TableColumn implementation
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 International GNOME Support
+ */
+#include <config.h>
+#include "e-table-column.h"
+
+enum {
+ STRUCTURE_CHANGE,
+ DIMENSION_CHANGE,
+ LAST_SIGNAL
+};
+
+static guint etc_signals [LAST_SIGNAL] = { 0, };
+
+static GtkObjectClass *e_table_column_parent_class;
+
+static void
+e_table_column_destroy (GtkObject *object)
+{
+ ETableColumn *etc = E_TABLE_COLUMN (object);
+ const int cols = etc->col_count;
+
+ /*
+ * Destroy listeners
+ */
+ for (l = etc->listeners; l; l = l->next)
+ g_free (l->data);
+ g_slist_free (etc->listeners);
+ etc->listeners = NULL;
+
+ /*
+ * Destroy columns
+ */
+ for (i = 0; i < cols; i++)
+ e_table_column_remove (etc, i);
+
+ if (e_table_column_parent_class->destroy)
+ e_table_column_parent_class->destroy (object);
+}
+
+static void
+e_table_column_class_init (GtkObjectClass *object_class)
+{
+ object_class->destroy = e_table_column_destroy;
+
+ e_table_column_parent_class = (gtk_type_class (gtk_object_get_type ()));
+
+ etc_signals [STRUCTURE_CHANGE] =
+ gtk_signal_new ("structure_change",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableColumn, structure_change),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+ etc_signals [DIMENSION_CHANGE] =
+ gtk_signal_new ("dimension_change",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableColumn, dimension_change),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, etc_signals, LAST_SIGNAL);
+}
+
+GtkType
+e_table_column_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableColumn",
+ sizeof (ETableColumn),
+ sizeof (ETableColumnClass),
+ (GtkClassInitFunc) e_table_column_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (gtk_object_get_type (), &info);
+ }
+
+ return type;
+}
+
+static void
+etc_do_insert (ETableColumn *etc, int pos, ETableCol *val)
+{
+ memcpy (&etc->columns [pos+1], &etc->columns [pos],
+ sizeof (ETableCol *) * (etc->col_count - pos));
+ etc->columns [pos] = val;
+}
+
+void
+e_table_column_add_column (ETableColumn *etc, ETableCol *tc, int pos)
+{
+ ETableCol **new_ptr;
+
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (tc != NULL);
+ g_return_if_fail (pos >= 0 && pos < etc->col_count);
+
+ if (pos == -1)
+ pos = etc->col_count;
+ etc->columns = g_realloc (etc->columns, sizeof (ETableCol *) * (etc->col_count + 1));
+ etc_do_insert (etc, pos, tc);
+ etc->col_count++;
+
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
+}
+
+ETableCol *
+e_table_column_get_column (ETableColumn *etc, int column)
+{
+ g_return_val_if_fail (etc != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), NULL);
+
+ if (column < 0)
+ return NULL;
+
+ if (column >= etc->col_count)
+ return NULL;
+
+ return etc->columns [column];
+}
+
+int
+e_table_column_count (ETableColumn *etc)
+{
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ return etc->col_count;
+}
+
+int
+e_table_column_index (ETableColumn *etc, const char *identifier)
+{
+ int i;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+ g_return_val_if_fail (identifier != NULL, 0);
+
+ for (i = 0; i < etc->col_count; i++){
+ ETableCol *tc = etc->columns [i];
+
+ if (strcmp (i->id, identifier) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+int
+e_table_column_get_index_at (ETableColumn *etc, int x_offset)
+{
+ int i, total;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+ g_return_val_if_fail (identifier != NULL, 0);
+
+ total = 0;
+ for (i = 0; i < etc->col_count; i++){
+ total += etc->columns [i]->width;
+
+ if (x_offset < total)
+ return i;
+ }
+
+ return -1;
+}
+
+ETableCol **
+e_table_column_get_columns (ETableColumn *etc)
+{
+ ETableCol **ret;
+ int i;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ ret = g_new (ETableCol *, etc->col_count + 1);
+ memcpy (ret, etc->columns, sizeof (ETableCol *) * etc->col_count);
+ ret [etc->col_count] = NULL;
+
+ return ret;
+}
+
+gboolean
+e_table_column_selection_ok (ETableColumn *etc)
+{
+ g_return_val_if_fail (etc != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), FALSE);
+
+ return etc->selectable;
+}
+
+int
+ve_table_column_get_selected (ETableColumn *etc)
+{
+ int i;
+ int selected = 0;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ for (i = 0; i < etc->col_count; i++){
+ if (etc->columns [i]->selected)
+ selected++;
+ }
+
+ return selected;
+}
+
+int
+e_table_column_total_width (ETableColumn *etc)
+{
+ int total;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ total = 0;
+ for (i = 0; i < etc->col_count; i++)
+ total += etc->columns [i].width;
+
+ return total;
+}
+
+static void
+etc_do_remove (ETableColumn *etc, int idx)
+{
+ memcpy (&etc->columns [idx], &etc->columns [idx+1],
+ sizeof (ETableCol *) * etc->col_count - idx);
+ etc->col_count--;
+}
+
+void
+e_table_column_move (ETableColumn *etc, int source_index, int target_index)
+{
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (source_index >= 0);
+ g_return_if_fail (target_index >= 0);
+ g_return_if_fail (source_index < etc->col_count);
+ g_return_if_fail (target_index < etc->col_count);
+
+ old = etc->columns [source_index];
+ etc_do_remove (etc, source_index);
+ etc_do_insert (etc, target_index, old);
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
+}
+
+void
+e_table_column_remove (ETableColumn *etc, int idx)
+{
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (idx >= 0);
+ g_return_if_fail (idx < etc->col_count);
+
+ etc_do_remove (etc, idx);
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
+}
+
+void
+e_table_column_set_selection (ETableColumn *etc, gboolean allow_selection);
+{
+}
+
+void
+e_table_column_set_size (ETableColumn *etc, int idx, int size)
+{
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (idx >= 0);
+ g_return_if_fail (idx < etc->col_count);
+ g_return_if_fail (size > 0);
+
+ etc->columns [idx]->width = size;
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [SIZE_CHANGE], idx);
+}
diff --git a/widgets/e-table/e-table-group.c b/widgets/e-table/e-table-group.c
new file mode 100644
index 0000000000..194bc6b235
--- /dev/null
+++ b/widgets/e-table/e-table-group.c
@@ -0,0 +1,98 @@
+/*
+ * E-Table-Group.c: Implements the grouping objects for elements on a table
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org()
+ *
+ * Copyright 1999, International GNOME Support.
+ */
+
+#include <config.h>
+#include "e-table-group.h"
+
+void
+e_table_group_destroy (ETableGroup *etg)
+{
+ g_return_val_if_fail (etg != NULL);
+
+ g_free (etg->title);
+
+ if (etg->is_leaf == 0){
+ GSList *l;
+
+ for (l = etg->u.children; l; l = l->next){
+ ETableGroup *child = l->data;
+
+ e_table_group_destroy (child);
+ }
+ g_slist_free (etg->u.children);
+ etg->u.children = NULL;
+ }
+ g_free (etg);
+}
+
+ETableGroup *
+e_table_group_new_leaf (const char *title, ETableModel *table)
+{
+ ETableGroup *etg;
+
+ g_return_val_if_fail (title != NULL, NULL);
+ g_return_val_if_fail (table != NULL, NULL);
+
+ etg = g_new (ETableGroup, 1);
+
+ etg->expanded = 0;
+ etg->is_leaf = 1;
+ etg->u.table = table;
+ etg->title = g_strdup (title);
+
+ return eg;
+}
+
+ETableGroup *
+e_table_group_new_leaf (const char *title)
+{
+ ETableGroup *etg;
+
+ g_return_val_if_fail (title != NULL, NULL);
+
+ etg = g_new (ETableGroup, 1);
+
+ etg->expanded = 0;
+ etg->is_leaf = 0;
+ etg->u.children = NULL;
+ etg->title = g_strdup (title);
+
+ return eg;
+}
+
+void
+e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
+{
+ g_return_val_if_fail (etg != NULL);
+ g_return_val_if_fail (child != NULL);
+ g_return_val_if_fail (etg->is_leaf != 0);
+
+ etg->u.children = g_slist_append (etg->u.children, child);
+}
+
+int
+e_table_group_size (ETableGroup *etg)
+{
+ g_return_val_if_fail (etg != NULL);
+
+ if (etg->is_leaf)
+ return e_table_model_height (etg->u.table);
+ else {
+ GSList *l;
+ int size = 0;
+
+ for (l = etg->u.children; l; l = l->next){
+ ETableGroup *child = l->data;
+
+ size += e_table_group_size (child);
+ }
+ return size;
+ }
+}
+
diff --git a/widgets/e-table/e-table-group.h b/widgets/e-table/e-table-group.h
new file mode 100644
index 0000000000..ab79d317e9
--- /dev/null
+++ b/widgets/e-table/e-table-group.h
@@ -0,0 +1,23 @@
+#ifndef _E_TABLE_TREE_H_
+#define _E_TABLE_TREE_H_
+
+typedef struct {
+ char *title;
+
+ union {
+ ETableModel *table;
+ GSList *children;
+ } u;
+
+ guint expanded :1;
+ guint is_leaf :1;
+} ETableGroup;
+
+ETableGroup *e_table_group_new (const char *title, ETableModel *table);
+ETableGroup *e_table_group_new_leaf (const char *title);
+void e_table_group_destroy (ETableGroup *etg);
+
+int e_table_group_size (ETableGroup *egroup);
+void e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
+
+#endif /* _E_TABLE_TREE_H_ */
diff --git a/widgets/e-table/e-table-model.c b/widgets/e-table/e-table-model.c
new file mode 100644
index 0000000000..23782e52c9
--- /dev/null
+++ b/widgets/e-table/e-table-model.c
@@ -0,0 +1,152 @@
+/*
+ * e-table-model.c: a Table Model
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 International GNOME Support.
+ */
+#include <config.h>
+#include "e-table-model.h"
+
+#define ETM_CLASS(e) ((ETableModelClass *)((GtkObject *)e)->klass)
+
+static GtkObjectClass *e_table_model_parent_class;
+
+int
+e_table_model_column_count (ETableModel *etable)
+{
+ return ETM_CLASS (etable)->column_count (etable);
+}
+
+const char *
+e_table_model_column_name (ETableModel *etable, int col)
+{
+ return ETM_CLASS (etable)->column_name (etable, col);
+}
+
+int
+e_table_model_row_count (ETableModel *etable)
+{
+ return ETM_CLASS (etable)->row_count (etable);
+}
+
+void *
+e_table_model_value_at (ETableModel *etable, int col, int row)
+{
+ return ETM_CLASS (etable)->value_at (etable, col, row);
+}
+
+void
+e_table_model_set_value_at (ETableModel *etable, int col, int row, void *data)
+{
+ return ETM_CLASS (etable)->set_value_at (etable, col, row, data);
+}
+
+gboolean
+e_table_model_is_cell_editable (ETableModel *etable, int col, int row)
+{
+ return ETM_CLASS (etable)->is_cell_editable (etable, col, row);
+}
+
+int
+e_table_model_row_height (ETableModel *etable, int row)
+{
+ return ETM_CLASS (etable)->row_height (etable, row);
+}
+
+typedef struct {
+ ETableModelListenerFn listener;
+ void *data;
+} listener_t;
+
+void
+e_table_model_add_listener (ETableModel *etable, ETableModelListenerFn listener, void *data)
+{
+ listener_t *lis;
+
+ lis = g_new (listener_t, 1);
+ lis->listener_t = listener;
+ lis->data = data;
+
+ etable->listeners = g_list_prepend (etable->listeners, lis);
+}
+
+void
+e_table_model_remove_listener (ETableModel *etable, ETableModelListenerFn listener, void *data)
+{
+ GSList *l;
+
+ for (l = etable->listeners; l; l = l->next){
+ listener_t *lis = l->data;
+
+ if (lis->listener == listener && lis->data == data){
+ etable->listeners = g_list_remove (etable->listeners, lis);
+ g_free (lis);
+ return;
+ }
+ }
+}
+
+static void
+e_table_model_destroy (GtkObject *object)
+{
+ GSList *l;
+
+ ETableModel *etable = (ETableModel *) object;
+
+ for (l = etable->listeners; l; l = l->next)
+ g_free (l->data);
+ g_list_free (etable->listeners);
+
+ if (e_table_model_parent_class->destroy)
+ (*e_table_model_parent_class->destroy)(object);
+}
+
+static void
+e_table_model_class_init (GtkObjectClass *class)
+{
+ e_table_model_parent_class = gtk_type_class (gtk_object_get_type ());
+
+ class->destroy = e_table_model_destroy;
+}
+
+GtkType
+e_table_model_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableModel",
+ sizeof (ETableModel),
+ sizeof (ETableModelClass),
+ (GtkClassInitFunc) e_table_model_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (gtk_object_get_type (), &info);
+ }
+
+ return type;
+}
+
+int
+e_table_model_height (ETableModel *etable)
+{
+ int rows;
+ int size;
+ g_return_val_if_fail (etable != NULL);
+
+ rows = e_table_model_row_count (etable);
+ size = 0;
+
+ for (i = 0; i < rows; i++)
+ size += e_table_model_row_height (etable, i);
+
+ return size;
+}
+
diff --git a/widgets/e-table/e-table-simple.c b/widgets/e-table/e-table-simple.c
new file mode 100644
index 0000000000..b586712942
--- /dev/null
+++ b/widgets/e-table/e-table-simple.c
@@ -0,0 +1,120 @@
+/*
+ * e-table-model.c: a simple table model implementation that uses function
+ * pointers to simplify the creation of new, exotic and colorful tables in
+ * no time.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 International GNOME Support.
+ */
+
+#include <config.h>
+#include "e-table-simple.h"
+
+static int
+simple_column_count (ETableModel *etm)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->col_count (etm)
+}
+
+static const char *
+simple_column_name (ETableModel *etm, int col)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->col_name (etm, col);
+}
+
+static int
+simple_row_count (ETableModel *etm)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->row_count (etm);
+}
+
+static void
+simple_value_at (ETableModel *etm, int col, int row)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->value_at (etm, col, row);
+}
+
+static void
+simple_set_value_at (ETableModel *etm, int col, int row, void *data)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->set_value_at (etm, col, row, data);
+}
+
+static gboolean
+simple_is_cell_editable (ETableModel *etm, int col, int row)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->is_cell_editable (etm, col, row, data);
+}
+
+static void
+e_table_simple_class_init (GtkObjectClass *object_class)
+{
+ ETableSimpleClass *simple_class = (ETableSimpleClass *) object_class;
+
+ simple_class->column_count = simple_column_count;
+ simple_class->column_name = simple_column_name;
+ simple_class->row_count = simple_row_count;
+ simple_class->value_at = simple_value_at;
+ simple_class->set_value_at = simple_set_value_at;
+ simple_class->is_cell_editable = simple_is_cell_editable;
+}
+
+GtkType
+e_table_simple_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableSimple",
+ sizeof (ETableSimple),
+ sizeof (ETableSimpleClass),
+ (GtkClassInitFunc) e_table_simple_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (e_table_model_get_type (), &info);
+ }
+
+ return type;
+}
+
+ETable *
+e_table_simple_new (ETableSimpleColumnCountFn col_count,
+ ETableSimpleColumnNameFn col_name,
+ ETableSimpleRowCountFn row_count,
+ ETableSimpleValueAtFn value_at,
+ ETableSimpleSetValueAtFn set_value_at,
+ ETableSimpleIsCellEditableFn is_cell_editable,
+ void *data)
+{
+ ETableSimple *et;
+
+ et = gtk_type_new (e_table_simple_get_type ());
+
+ et->col_count = col_count;
+ et->col_name = col_name;
+ et->row_count = row_count;
+ et->value_at = value_at;
+ et->set_value_at = set_value_at;
+ et->is_cell_editable = is_cell_editable;
+
+ return (ETable *) et;
+}
diff --git a/widgets/e-table/e-table-simple.h b/widgets/e-table/e-table-simple.h
new file mode 100644
index 0000000000..b5c549a440
--- /dev/null
+++ b/widgets/e-table/e-table-simple.h
@@ -0,0 +1,38 @@
+#ifndef _E_TABLE_SIMPLE_H_
+#define _E_TABLE_SIMPLE_H_
+
+#include "e-table-model.h"
+
+typedef int (*ETableSimpleColumnCountFn) (ETableModel *etm);
+typedef const char *(*ETableSimpleColumnNameFn) (ETableModel *etm, int col);
+typedef int (*ETableSimpleRowCountFn) (ETableModel *etm);
+typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row);
+typedef void (*ETableSimpleSetValueAtFn) (ETableModel *etm, int col, int row, void *data);
+typedef gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row);
+typedef int (*ETableSimpleRowHeightFn (ETableModel *etm, int row);
+
+typedef struct {
+ ETableModel parent;
+
+ ETableSimpleColumnCountFn col_count;
+ ETableSimpleColumnNameFn col_name;
+ ETableSimpleRowCountFn row_count;
+ ETableSimpleValueAtFn value_at;
+ ETableSimpleSetValueAtFn set_value_at;
+ ETableSimpleIsCellEditableFn is_cell_editable;
+ ETableSimpleRowHeightFn row_height;
+ void *data;
+} ETableSimple;
+
+GtkType e_table_simple_get_type (void);
+
+ETable *e_table_simple_new (ETableSimpleColumnCountFn col_count,
+ ETableSimpleColumnNameFn col_name,
+ ETableSimpleRowCountFn row_count,
+ ETableSimpleValueAtFn value_at,
+ ETableSimpleSetValueAtFn set_value_at,
+ ETableSimpleIsCellEditableFn is_cell_editable,
+ void *data);
+
+#endif /* _E_TABLE_SIMPLE_H_ */
+
diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c
new file mode 100644
index 0000000000..427f527185
--- /dev/null
+++ b/widgets/e-table/e-table.c
@@ -0,0 +1,36 @@
+/*
+ * E-table-view.c: A graphical view of a Table.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * Copyright 1999, International GNOME Support
+ */
+#include <config.h>
+#include <libgnomeui/gnome-canvas.h>
+#include "e-table.h"
+
+#define PARENT_OBJECT_TYPE gnome_canvas_get_type ()
+
+GtkType
+e_table_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETable",
+ sizeof (ETable),
+ sizeof (ETableClass),
+ (GtkClassInitFunc) e_table_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
+ }
+
+ return type;
+}
diff --git a/widgets/table/e-table-column-item.c b/widgets/table/e-table-column-item.c
new file mode 100644
index 0000000000..dc0da16c11
--- /dev/null
+++ b/widgets/table/e-table-column-item.c
@@ -0,0 +1,199 @@
+/*
+ * E-table-column-view.c: A canvas view of the TableColumn.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * Copyright 1999, International GNOME Support.
+ */
+#include <config.h>
+#include "e-table-column.h"
+#include "e-table-column-view.h"
+
+#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
+
+static GnomeCanvasItemClass *etci_parent_class;
+
+enum {
+ ARG_0,
+ ARG_TABLE_COLUMN
+};
+
+static void
+etci_destroy (GtkObject *object)
+{
+ ETableColumnItem *etcv = E_TABLE_COLUMN_VIEW (object);
+
+ gtk_object_unref (GTK_OBJECT (etcv));
+
+ if (GTK_OBJECT_CLASS (etcv_parent_class)->destroy)
+ (*GTK_OBJECT_CLASS (etcv_parent_class)->destroy) (object);
+}
+
+static void
+etci_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ if (GNOME_CANVAS_ITEM_CLASS(item_bar_parent_class)->update)
+ (*GNOME_CANVAS_ITEM_CLASS(item_bar_parent_class)->update)(item, affine, clip_path, flags);
+
+ item->x1 = 0;
+ item->y1 = 0;
+ item->x2 = INT_MAX;
+ item->y2 = INT_MAX;
+ gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
+}
+
+static void
+etci_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+{
+ GnomeCanvasItem *item;
+ ETableColumnItem *etci;
+ int v;
+
+ item = GNOME_CANVAS_ITEM (o);
+ etci = E_TABLE_COLUMN_ITEM (o);
+
+ switch (arg_id){
+ case ARG_TABLE_COLUMN:
+ etci->etci = GTK_VALUE_POINTER (*arg);
+ break;
+ }
+ etci_update (item, NULL, NULL, 0);
+}
+
+static void
+etci_realize (GnomeCanvasItem *item)
+{
+ ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
+ GdkWindow *window;
+ GdkColor c;
+
+ if (GNOME_CANVAS_ITEM_CLASS (etci_parent_class)-> realize)
+ (*GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->realize)(item);
+
+ window = GTK_WIDGET (item->canvas)->window;
+
+ etci->gc = gdk_gc_new (window);
+ gnome_canvas_get_color (item->canvas, "black", &c);
+ gdk_gc_set_foreground (etci->gc, &c);
+
+ etci->normal_cursor = gdk_cursor_new (GDK_ARROW);
+}
+
+static void
+etci_unrealize (GnomeCanvasItem *item)
+{
+ ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
+
+ gdk_gc_unref (etci->gc);
+ etci->gc = NULL;
+
+ gdk_cursor_destroy (etci->change_cursor);
+ etci->change_cursor = NULL;
+
+ gdk_cursor_destroy (etci->normal_cursor);
+ etci->normal_cursor = NULL;
+
+ if (GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->unrealize)
+ (*GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->unrealize)(item);
+}
+
+static void
+etci_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height)
+{
+ ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
+ GnomeCanvas *canvas = item->canvas;
+ GdkGC *gc;
+ const int cols = e_table_column_count (etci->etc);
+ int x2 = x1 + width;
+ int col, total;
+
+ total = 0;
+ for (col = 0; col < cols; col++){
+ ETableCol *col = e_table_column_get_column (etci->etc, col);
+ const int col_width = col->width;
+
+ if (x1 > total + col_width)
+ continue;
+
+ if (x2 < total)
+ return;
+
+ gc = canvas->style->bg_gc [GTK_STATE_ACTIVE];
+ gdk_draw_rectangle (drawble, gc, TRUE,
+ gtk_draw_shadow (canvas->style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ x, y, width, height
+ }
+}
+
+static double
+etci_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
+ GnomeCanvasItem **actual_item)
+{
+ *actual_item = *item;
+ return 0.0;
+}
+
+static void
+etci_event (GnomeCanvasItem *item, GdkEvent *e)
+{
+ switch (e->type){
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+etci_class_init (GtkObjectClass *object_class)
+{
+ GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
+
+ object_class->destroy = etci_destroy;
+ object_class->set_arg = etci_set_arg;
+
+ item_class->update = etci_update;
+ item_class->realize = etci_realize;
+ item_class->unrealize = etci_unrealize;
+ item_class->draw = etci_draw;
+ item_class->point = etci_point;
+ item_class->event = etci_event;
+
+ gtk_object_add_arg_type ("ETableColumnItem::ETableColumn", GTK_TYPE_POINTER,
+ GTK_ARG_WRITABLE, ARG_TABLE_COLUMN);
+}
+
+static void
+etci_init (GnomeCanvasItem *item)
+{
+ item->x1 = 0;
+ item->y1 = 0;
+ item->x2 = 0;
+ item->y2 = 0;
+}
+
+GtkType
+e_table_column_view_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableColumnItem",
+ sizeof (ETableColumnItem),
+ sizeof (ETableColumnItemClass),
+ (GtkClassInitFunc) etci_class_init,
+ (GtkObjectInitFunc) etci_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
+ }
+
+ return type;
+}
+
+
+
diff --git a/widgets/table/e-table-column-item.h b/widgets/table/e-table-column-item.h
new file mode 100644
index 0000000000..fd38681a73
--- /dev/null
+++ b/widgets/table/e-table-column-item.h
@@ -0,0 +1,20 @@
+#ifndef _E_TABLE_COLUMN_VIEW_H
+#defein _E_TABLE_COLUMN_VIEW_H
+
+#include "e-table-column.h"
+
+typedef struct {
+ GnomeCanvasItem parent;
+ ETableColumn *etc;
+
+ GdkGC *gc;
+ GdkCursor *change_cursor, *normal_cursor;
+} ETableColumnView;
+
+typedef struct {
+ GnomeCanvasItemClass parent_class;
+} ETableColumnViewClass;
+
+GtkType e_table_column_item_get_type (void);
+
+#endif /* _E_TABLE_COLUMN_VIEW_H */
diff --git a/widgets/table/e-table-column-model.h b/widgets/table/e-table-column-model.h
new file mode 100644
index 0000000000..043dd783ca
--- /dev/null
+++ b/widgets/table/e-table-column-model.h
@@ -0,0 +1,5 @@
+
+class ETableColumnModel {
+ virtual void add_column (ETableCol *et) = 0;
+ virtual ETableCol *get_column (int column);
+ virtual
diff --git a/widgets/table/e-table-column.c b/widgets/table/e-table-column.c
new file mode 100644
index 0000000000..851ebc4532
--- /dev/null
+++ b/widgets/table/e-table-column.c
@@ -0,0 +1,293 @@
+/*
+ * e-table-column.c: TableColumn implementation
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 International GNOME Support
+ */
+#include <config.h>
+#include "e-table-column.h"
+
+enum {
+ STRUCTURE_CHANGE,
+ DIMENSION_CHANGE,
+ LAST_SIGNAL
+};
+
+static guint etc_signals [LAST_SIGNAL] = { 0, };
+
+static GtkObjectClass *e_table_column_parent_class;
+
+static void
+e_table_column_destroy (GtkObject *object)
+{
+ ETableColumn *etc = E_TABLE_COLUMN (object);
+ const int cols = etc->col_count;
+
+ /*
+ * Destroy listeners
+ */
+ for (l = etc->listeners; l; l = l->next)
+ g_free (l->data);
+ g_slist_free (etc->listeners);
+ etc->listeners = NULL;
+
+ /*
+ * Destroy columns
+ */
+ for (i = 0; i < cols; i++)
+ e_table_column_remove (etc, i);
+
+ if (e_table_column_parent_class->destroy)
+ e_table_column_parent_class->destroy (object);
+}
+
+static void
+e_table_column_class_init (GtkObjectClass *object_class)
+{
+ object_class->destroy = e_table_column_destroy;
+
+ e_table_column_parent_class = (gtk_type_class (gtk_object_get_type ()));
+
+ etc_signals [STRUCTURE_CHANGE] =
+ gtk_signal_new ("structure_change",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableColumn, structure_change),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+ etc_signals [DIMENSION_CHANGE] =
+ gtk_signal_new ("dimension_change",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableColumn, dimension_change),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, etc_signals, LAST_SIGNAL);
+}
+
+GtkType
+e_table_column_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableColumn",
+ sizeof (ETableColumn),
+ sizeof (ETableColumnClass),
+ (GtkClassInitFunc) e_table_column_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (gtk_object_get_type (), &info);
+ }
+
+ return type;
+}
+
+static void
+etc_do_insert (ETableColumn *etc, int pos, ETableCol *val)
+{
+ memcpy (&etc->columns [pos+1], &etc->columns [pos],
+ sizeof (ETableCol *) * (etc->col_count - pos));
+ etc->columns [pos] = val;
+}
+
+void
+e_table_column_add_column (ETableColumn *etc, ETableCol *tc, int pos)
+{
+ ETableCol **new_ptr;
+
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (tc != NULL);
+ g_return_if_fail (pos >= 0 && pos < etc->col_count);
+
+ if (pos == -1)
+ pos = etc->col_count;
+ etc->columns = g_realloc (etc->columns, sizeof (ETableCol *) * (etc->col_count + 1));
+ etc_do_insert (etc, pos, tc);
+ etc->col_count++;
+
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
+}
+
+ETableCol *
+e_table_column_get_column (ETableColumn *etc, int column)
+{
+ g_return_val_if_fail (etc != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), NULL);
+
+ if (column < 0)
+ return NULL;
+
+ if (column >= etc->col_count)
+ return NULL;
+
+ return etc->columns [column];
+}
+
+int
+e_table_column_count (ETableColumn *etc)
+{
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ return etc->col_count;
+}
+
+int
+e_table_column_index (ETableColumn *etc, const char *identifier)
+{
+ int i;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+ g_return_val_if_fail (identifier != NULL, 0);
+
+ for (i = 0; i < etc->col_count; i++){
+ ETableCol *tc = etc->columns [i];
+
+ if (strcmp (i->id, identifier) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+int
+e_table_column_get_index_at (ETableColumn *etc, int x_offset)
+{
+ int i, total;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+ g_return_val_if_fail (identifier != NULL, 0);
+
+ total = 0;
+ for (i = 0; i < etc->col_count; i++){
+ total += etc->columns [i]->width;
+
+ if (x_offset < total)
+ return i;
+ }
+
+ return -1;
+}
+
+ETableCol **
+e_table_column_get_columns (ETableColumn *etc)
+{
+ ETableCol **ret;
+ int i;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ ret = g_new (ETableCol *, etc->col_count + 1);
+ memcpy (ret, etc->columns, sizeof (ETableCol *) * etc->col_count);
+ ret [etc->col_count] = NULL;
+
+ return ret;
+}
+
+gboolean
+e_table_column_selection_ok (ETableColumn *etc)
+{
+ g_return_val_if_fail (etc != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), FALSE);
+
+ return etc->selectable;
+}
+
+int
+ve_table_column_get_selected (ETableColumn *etc)
+{
+ int i;
+ int selected = 0;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ for (i = 0; i < etc->col_count; i++){
+ if (etc->columns [i]->selected)
+ selected++;
+ }
+
+ return selected;
+}
+
+int
+e_table_column_total_width (ETableColumn *etc)
+{
+ int total;
+
+ g_return_val_if_fail (etc != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
+
+ total = 0;
+ for (i = 0; i < etc->col_count; i++)
+ total += etc->columns [i].width;
+
+ return total;
+}
+
+static void
+etc_do_remove (ETableColumn *etc, int idx)
+{
+ memcpy (&etc->columns [idx], &etc->columns [idx+1],
+ sizeof (ETableCol *) * etc->col_count - idx);
+ etc->col_count--;
+}
+
+void
+e_table_column_move (ETableColumn *etc, int source_index, int target_index)
+{
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (source_index >= 0);
+ g_return_if_fail (target_index >= 0);
+ g_return_if_fail (source_index < etc->col_count);
+ g_return_if_fail (target_index < etc->col_count);
+
+ old = etc->columns [source_index];
+ etc_do_remove (etc, source_index);
+ etc_do_insert (etc, target_index, old);
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
+}
+
+void
+e_table_column_remove (ETableColumn *etc, int idx)
+{
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (idx >= 0);
+ g_return_if_fail (idx < etc->col_count);
+
+ etc_do_remove (etc, idx);
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
+}
+
+void
+e_table_column_set_selection (ETableColumn *etc, gboolean allow_selection);
+{
+}
+
+void
+e_table_column_set_size (ETableColumn *etc, int idx, int size)
+{
+ g_return_if_fail (etc != NULL);
+ g_return_if_fail (E_IS_TABLE_COLUMN (etc));
+ g_return_if_fail (idx >= 0);
+ g_return_if_fail (idx < etc->col_count);
+ g_return_if_fail (size > 0);
+
+ etc->columns [idx]->width = size;
+ gtk_signal_emit (GTK_OBJECT (etc), etc_signals [SIZE_CHANGE], idx);
+}
diff --git a/widgets/table/e-table-group.c b/widgets/table/e-table-group.c
new file mode 100644
index 0000000000..194bc6b235
--- /dev/null
+++ b/widgets/table/e-table-group.c
@@ -0,0 +1,98 @@
+/*
+ * E-Table-Group.c: Implements the grouping objects for elements on a table
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org()
+ *
+ * Copyright 1999, International GNOME Support.
+ */
+
+#include <config.h>
+#include "e-table-group.h"
+
+void
+e_table_group_destroy (ETableGroup *etg)
+{
+ g_return_val_if_fail (etg != NULL);
+
+ g_free (etg->title);
+
+ if (etg->is_leaf == 0){
+ GSList *l;
+
+ for (l = etg->u.children; l; l = l->next){
+ ETableGroup *child = l->data;
+
+ e_table_group_destroy (child);
+ }
+ g_slist_free (etg->u.children);
+ etg->u.children = NULL;
+ }
+ g_free (etg);
+}
+
+ETableGroup *
+e_table_group_new_leaf (const char *title, ETableModel *table)
+{
+ ETableGroup *etg;
+
+ g_return_val_if_fail (title != NULL, NULL);
+ g_return_val_if_fail (table != NULL, NULL);
+
+ etg = g_new (ETableGroup, 1);
+
+ etg->expanded = 0;
+ etg->is_leaf = 1;
+ etg->u.table = table;
+ etg->title = g_strdup (title);
+
+ return eg;
+}
+
+ETableGroup *
+e_table_group_new_leaf (const char *title)
+{
+ ETableGroup *etg;
+
+ g_return_val_if_fail (title != NULL, NULL);
+
+ etg = g_new (ETableGroup, 1);
+
+ etg->expanded = 0;
+ etg->is_leaf = 0;
+ etg->u.children = NULL;
+ etg->title = g_strdup (title);
+
+ return eg;
+}
+
+void
+e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
+{
+ g_return_val_if_fail (etg != NULL);
+ g_return_val_if_fail (child != NULL);
+ g_return_val_if_fail (etg->is_leaf != 0);
+
+ etg->u.children = g_slist_append (etg->u.children, child);
+}
+
+int
+e_table_group_size (ETableGroup *etg)
+{
+ g_return_val_if_fail (etg != NULL);
+
+ if (etg->is_leaf)
+ return e_table_model_height (etg->u.table);
+ else {
+ GSList *l;
+ int size = 0;
+
+ for (l = etg->u.children; l; l = l->next){
+ ETableGroup *child = l->data;
+
+ size += e_table_group_size (child);
+ }
+ return size;
+ }
+}
+
diff --git a/widgets/table/e-table-group.h b/widgets/table/e-table-group.h
new file mode 100644
index 0000000000..ab79d317e9
--- /dev/null
+++ b/widgets/table/e-table-group.h
@@ -0,0 +1,23 @@
+#ifndef _E_TABLE_TREE_H_
+#define _E_TABLE_TREE_H_
+
+typedef struct {
+ char *title;
+
+ union {
+ ETableModel *table;
+ GSList *children;
+ } u;
+
+ guint expanded :1;
+ guint is_leaf :1;
+} ETableGroup;
+
+ETableGroup *e_table_group_new (const char *title, ETableModel *table);
+ETableGroup *e_table_group_new_leaf (const char *title);
+void e_table_group_destroy (ETableGroup *etg);
+
+int e_table_group_size (ETableGroup *egroup);
+void e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
+
+#endif /* _E_TABLE_TREE_H_ */
diff --git a/widgets/table/e-table-model.c b/widgets/table/e-table-model.c
new file mode 100644
index 0000000000..23782e52c9
--- /dev/null
+++ b/widgets/table/e-table-model.c
@@ -0,0 +1,152 @@
+/*
+ * e-table-model.c: a Table Model
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 International GNOME Support.
+ */
+#include <config.h>
+#include "e-table-model.h"
+
+#define ETM_CLASS(e) ((ETableModelClass *)((GtkObject *)e)->klass)
+
+static GtkObjectClass *e_table_model_parent_class;
+
+int
+e_table_model_column_count (ETableModel *etable)
+{
+ return ETM_CLASS (etable)->column_count (etable);
+}
+
+const char *
+e_table_model_column_name (ETableModel *etable, int col)
+{
+ return ETM_CLASS (etable)->column_name (etable, col);
+}
+
+int
+e_table_model_row_count (ETableModel *etable)
+{
+ return ETM_CLASS (etable)->row_count (etable);
+}
+
+void *
+e_table_model_value_at (ETableModel *etable, int col, int row)
+{
+ return ETM_CLASS (etable)->value_at (etable, col, row);
+}
+
+void
+e_table_model_set_value_at (ETableModel *etable, int col, int row, void *data)
+{
+ return ETM_CLASS (etable)->set_value_at (etable, col, row, data);
+}
+
+gboolean
+e_table_model_is_cell_editable (ETableModel *etable, int col, int row)
+{
+ return ETM_CLASS (etable)->is_cell_editable (etable, col, row);
+}
+
+int
+e_table_model_row_height (ETableModel *etable, int row)
+{
+ return ETM_CLASS (etable)->row_height (etable, row);
+}
+
+typedef struct {
+ ETableModelListenerFn listener;
+ void *data;
+} listener_t;
+
+void
+e_table_model_add_listener (ETableModel *etable, ETableModelListenerFn listener, void *data)
+{
+ listener_t *lis;
+
+ lis = g_new (listener_t, 1);
+ lis->listener_t = listener;
+ lis->data = data;
+
+ etable->listeners = g_list_prepend (etable->listeners, lis);
+}
+
+void
+e_table_model_remove_listener (ETableModel *etable, ETableModelListenerFn listener, void *data)
+{
+ GSList *l;
+
+ for (l = etable->listeners; l; l = l->next){
+ listener_t *lis = l->data;
+
+ if (lis->listener == listener && lis->data == data){
+ etable->listeners = g_list_remove (etable->listeners, lis);
+ g_free (lis);
+ return;
+ }
+ }
+}
+
+static void
+e_table_model_destroy (GtkObject *object)
+{
+ GSList *l;
+
+ ETableModel *etable = (ETableModel *) object;
+
+ for (l = etable->listeners; l; l = l->next)
+ g_free (l->data);
+ g_list_free (etable->listeners);
+
+ if (e_table_model_parent_class->destroy)
+ (*e_table_model_parent_class->destroy)(object);
+}
+
+static void
+e_table_model_class_init (GtkObjectClass *class)
+{
+ e_table_model_parent_class = gtk_type_class (gtk_object_get_type ());
+
+ class->destroy = e_table_model_destroy;
+}
+
+GtkType
+e_table_model_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableModel",
+ sizeof (ETableModel),
+ sizeof (ETableModelClass),
+ (GtkClassInitFunc) e_table_model_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (gtk_object_get_type (), &info);
+ }
+
+ return type;
+}
+
+int
+e_table_model_height (ETableModel *etable)
+{
+ int rows;
+ int size;
+ g_return_val_if_fail (etable != NULL);
+
+ rows = e_table_model_row_count (etable);
+ size = 0;
+
+ for (i = 0; i < rows; i++)
+ size += e_table_model_row_height (etable, i);
+
+ return size;
+}
+
diff --git a/widgets/table/e-table-simple.c b/widgets/table/e-table-simple.c
new file mode 100644
index 0000000000..b586712942
--- /dev/null
+++ b/widgets/table/e-table-simple.c
@@ -0,0 +1,120 @@
+/*
+ * e-table-model.c: a simple table model implementation that uses function
+ * pointers to simplify the creation of new, exotic and colorful tables in
+ * no time.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 International GNOME Support.
+ */
+
+#include <config.h>
+#include "e-table-simple.h"
+
+static int
+simple_column_count (ETableModel *etm)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->col_count (etm)
+}
+
+static const char *
+simple_column_name (ETableModel *etm, int col)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->col_name (etm, col);
+}
+
+static int
+simple_row_count (ETableModel *etm)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->row_count (etm);
+}
+
+static void
+simple_value_at (ETableModel *etm, int col, int row)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->value_at (etm, col, row);
+}
+
+static void
+simple_set_value_at (ETableModel *etm, int col, int row, void *data)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->set_value_at (etm, col, row, data);
+}
+
+static gboolean
+simple_is_cell_editable (ETableModel *etm, int col, int row)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->is_cell_editable (etm, col, row, data);
+}
+
+static void
+e_table_simple_class_init (GtkObjectClass *object_class)
+{
+ ETableSimpleClass *simple_class = (ETableSimpleClass *) object_class;
+
+ simple_class->column_count = simple_column_count;
+ simple_class->column_name = simple_column_name;
+ simple_class->row_count = simple_row_count;
+ simple_class->value_at = simple_value_at;
+ simple_class->set_value_at = simple_set_value_at;
+ simple_class->is_cell_editable = simple_is_cell_editable;
+}
+
+GtkType
+e_table_simple_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETableSimple",
+ sizeof (ETableSimple),
+ sizeof (ETableSimpleClass),
+ (GtkClassInitFunc) e_table_simple_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (e_table_model_get_type (), &info);
+ }
+
+ return type;
+}
+
+ETable *
+e_table_simple_new (ETableSimpleColumnCountFn col_count,
+ ETableSimpleColumnNameFn col_name,
+ ETableSimpleRowCountFn row_count,
+ ETableSimpleValueAtFn value_at,
+ ETableSimpleSetValueAtFn set_value_at,
+ ETableSimpleIsCellEditableFn is_cell_editable,
+ void *data)
+{
+ ETableSimple *et;
+
+ et = gtk_type_new (e_table_simple_get_type ());
+
+ et->col_count = col_count;
+ et->col_name = col_name;
+ et->row_count = row_count;
+ et->value_at = value_at;
+ et->set_value_at = set_value_at;
+ et->is_cell_editable = is_cell_editable;
+
+ return (ETable *) et;
+}
diff --git a/widgets/table/e-table-simple.h b/widgets/table/e-table-simple.h
new file mode 100644
index 0000000000..b5c549a440
--- /dev/null
+++ b/widgets/table/e-table-simple.h
@@ -0,0 +1,38 @@
+#ifndef _E_TABLE_SIMPLE_H_
+#define _E_TABLE_SIMPLE_H_
+
+#include "e-table-model.h"
+
+typedef int (*ETableSimpleColumnCountFn) (ETableModel *etm);
+typedef const char *(*ETableSimpleColumnNameFn) (ETableModel *etm, int col);
+typedef int (*ETableSimpleRowCountFn) (ETableModel *etm);
+typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row);
+typedef void (*ETableSimpleSetValueAtFn) (ETableModel *etm, int col, int row, void *data);
+typedef gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row);
+typedef int (*ETableSimpleRowHeightFn (ETableModel *etm, int row);
+
+typedef struct {
+ ETableModel parent;
+
+ ETableSimpleColumnCountFn col_count;
+ ETableSimpleColumnNameFn col_name;
+ ETableSimpleRowCountFn row_count;
+ ETableSimpleValueAtFn value_at;
+ ETableSimpleSetValueAtFn set_value_at;
+ ETableSimpleIsCellEditableFn is_cell_editable;
+ ETableSimpleRowHeightFn row_height;
+ void *data;
+} ETableSimple;
+
+GtkType e_table_simple_get_type (void);
+
+ETable *e_table_simple_new (ETableSimpleColumnCountFn col_count,
+ ETableSimpleColumnNameFn col_name,
+ ETableSimpleRowCountFn row_count,
+ ETableSimpleValueAtFn value_at,
+ ETableSimpleSetValueAtFn set_value_at,
+ ETableSimpleIsCellEditableFn is_cell_editable,
+ void *data);
+
+#endif /* _E_TABLE_SIMPLE_H_ */
+
diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c
new file mode 100644
index 0000000000..427f527185
--- /dev/null
+++ b/widgets/table/e-table.c
@@ -0,0 +1,36 @@
+/*
+ * E-table-view.c: A graphical view of a Table.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * Copyright 1999, International GNOME Support
+ */
+#include <config.h>
+#include <libgnomeui/gnome-canvas.h>
+#include "e-table.h"
+
+#define PARENT_OBJECT_TYPE gnome_canvas_get_type ()
+
+GtkType
+e_table_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type){
+ GtkTypeInfo info = {
+ "ETable",
+ sizeof (ETable),
+ sizeof (ETableClass),
+ (GtkClassInitFunc) e_table_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
+ }
+
+ return type;
+}