diff options
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; +} |