diff options
35 files changed, 2161 insertions, 239 deletions
diff --git a/widgets/Makefile.am b/widgets/Makefile.am index a9614cf1d7..1a410e298e 100644 --- a/widgets/Makefile.am +++ b/widgets/Makefile.am @@ -13,10 +13,10 @@ INCLUDES = \ CPPFLAGS = \ -DE_GUIDIR=\"$(guidir)\" -noinst_LTLIBRARIES = \ - libevolutionwidgets.la +noinst_LIBRARIES = \ + libevolutionwidgets.a -libevolutionwidgets_la_SOURCES = \ +libevolutionwidgets_a_SOURCES = \ e-msg-composer-address-dialog.c \ e-msg-composer-address-dialog.h \ e-msg-composer-address-entry.c \ @@ -28,5 +28,15 @@ libevolutionwidgets_la_SOURCES = \ e-msg-composer-hdrs.c \ e-msg-composer-hdrs.h \ e-msg-composer.c \ - e-msg-composer.h + e-msg-composer.h \ + e-table-group.c \ + e-table-group.h \ + e-table-header.c \ + e-table-header.h \ + e-table-header-item.c \ + e-table-header-item.h \ + e-table-model.c \ + e-table-model.h \ + e-table-simple.c \ + e-table-simple.h diff --git a/widgets/e-table-group.c b/widgets/e-table-group.c index 194bc6b235..07a3fb60f2 100644 --- a/widgets/e-table-group.c +++ b/widgets/e-table-group.c @@ -13,7 +13,7 @@ void e_table_group_destroy (ETableGroup *etg) { - g_return_val_if_fail (etg != NULL); + g_return_if_fail (etg != NULL); g_free (etg->title); @@ -46,11 +46,11 @@ e_table_group_new_leaf (const char *title, ETableModel *table) etg->u.table = table; etg->title = g_strdup (title); - return eg; + return etg; } ETableGroup * -e_table_group_new_leaf (const char *title) +e_table_group_new (const char *title) { ETableGroup *etg; @@ -63,15 +63,15 @@ e_table_group_new_leaf (const char *title) etg->u.children = NULL; etg->title = g_strdup (title); - return eg; + return etg; } 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); + g_return_if_fail (etg != NULL); + g_return_if_fail (child != NULL); + g_return_if_fail (etg->is_leaf != 0); etg->u.children = g_slist_append (etg->u.children, child); } @@ -79,7 +79,7 @@ e_table_group_append_child (ETableGroup *etg, ETableGroup *child) int e_table_group_size (ETableGroup *etg) { - g_return_val_if_fail (etg != NULL); + g_return_if_fail (etg != NULL); if (etg->is_leaf) return e_table_model_height (etg->u.table); diff --git a/widgets/e-table-group.h b/widgets/e-table-group.h index ab79d317e9..d673aebd11 100644 --- a/widgets/e-table-group.h +++ b/widgets/e-table-group.h @@ -1,6 +1,8 @@ #ifndef _E_TABLE_TREE_H_ #define _E_TABLE_TREE_H_ +#include "e-table-model.h" + typedef struct { char *title; @@ -13,11 +15,11 @@ typedef struct { guint is_leaf :1; } ETableGroup; -ETableGroup *e_table_group_new (const char *title, ETableModel *table); -ETableGroup *e_table_group_new_leaf (const char *title); +ETableGroup *e_table_group_new (const char *title); +ETableGroup *e_table_group_new_leaf (const char *title, ETableModel *table); void e_table_group_destroy (ETableGroup *etg); int e_table_group_size (ETableGroup *egroup); -void e_table_group_append_child (ETableGroup *etg, ETableGroup *child) +void e_table_group_append_child (ETableGroup *etg, ETableGroup *child); #endif /* _E_TABLE_TREE_H_ */ diff --git a/widgets/e-table-header-item.c b/widgets/e-table-header-item.c new file mode 100644 index 0000000000..796a2e493b --- /dev/null +++ b/widgets/e-table-header-item.c @@ -0,0 +1,233 @@ +/* + * 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-header.h" +#include "e-table-header-item.h" + +#define ETHI_HEIGHT 14 + +#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type () + +static GnomeCanvasItemClass *ethi_parent_class; + +enum { + ARG_0, + ARG_TABLE_HEADER +}; + +static void +ethi_destroy (GtkObject *object) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (object); + + gtk_object_unref (GTK_OBJECT (ethi)); + + if (GTK_OBJECT_CLASS (ethi_parent_class)->destroy) + (*GTK_OBJECT_CLASS (ethi_parent_class)->destroy) (object); +} + +static void +ethi_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->update) + (*GNOME_CANVAS_ITEM_CLASS (ethi_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 +ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + ETableHeaderItem *ethi; + int v; + + item = GNOME_CANVAS_ITEM (o); + ethi = E_TABLE_HEADER_ITEM (o); + + switch (arg_id){ + case ARG_TABLE_HEADER: + ethi->eth = GTK_VALUE_POINTER (*arg); + break; + } + ethi_update (item, NULL, NULL, 0); +} + +static void +ethi_realize (GnomeCanvasItem *item) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); + GdkWindow *window; + GdkColor c; + + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)-> realize) + (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->realize)(item); + + window = GTK_WIDGET (item->canvas)->window; + + ethi->gc = gdk_gc_new (window); + gnome_canvas_get_color (item->canvas, "black", &c); + gdk_gc_set_foreground (ethi->gc, &c); + + ethi->normal_cursor = gdk_cursor_new (GDK_ARROW); +} + +static void +ethi_unrealize (GnomeCanvasItem *item) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); + + gdk_gc_unref (ethi->gc); + ethi->gc = NULL; + + gdk_cursor_destroy (ethi->change_cursor); + ethi->change_cursor = NULL; + + gdk_cursor_destroy (ethi->normal_cursor); + ethi->normal_cursor = NULL; + + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize) + (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item); +} + +static void +ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); + GnomeCanvas *canvas = item->canvas; + GdkGC *gc; + const int cols = e_table_header_count (ethi->eth); + int x2 = x1 + width; + int col, total; + int x; + + total = 0; + x = 0; + for (col = 0; col < cols; col++){ + ETableCol *ecol = e_table_header_get_column (ethi->eth, col); + const int col_width = ecol->width; + + if (x1 > total + col_width){ + x += col_width; + continue; + } + + if (x2 < total) + return; + + gc = GTK_WIDGET (canvas)->style->bg_gc [GTK_STATE_ACTIVE]; + + gdk_draw_rectangle ( + drawable, gc, TRUE, + x + 1, -y1 + 1, col_width - 2, ETHI_HEIGHT - 2); + + gtk_draw_shadow ( + GTK_WIDGET (canvas)->style, drawable, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + x , -y1, col_width, ETHI_HEIGHT); + + if (ecol->render != NULL) + (*ecol->render)(ecol, item, drawable, x1, y1, width, height, ecol->render_data); + else { + GdkRectangle clip; + GdkFont *font = GTK_WIDGET (canvas)->style->font; + + clip.x = x + 2; + clip.y = -y1 + 2; + clip.width = col_width - 4; + clip.height = ETHI_HEIGHT - 4; + gdk_gc_set_clip_rectangle (gc, &clip); + + /* + * FIXME: should be obvious + */ + gdk_draw_text (drawable, font, gc, x, -y1 + 10, "TEST", 4); + + gdk_gc_set_clip_rectangle (gc, NULL); + } + } +} + +static double +ethi_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, + GnomeCanvasItem **actual_item) +{ + *actual_item = item; + return 0.0; +} + +static int +ethi_event (GnomeCanvasItem *item, GdkEvent *e) +{ + switch (e->type){ + default: + return FALSE; + } + return TRUE; +} + +static void +ethi_class_init (GtkObjectClass *object_class) +{ + GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + + ethi_parent_class = gtk_type_class (gnome_canvas_item_get_type ()); + + object_class->destroy = ethi_destroy; + object_class->set_arg = ethi_set_arg; + + item_class->update = ethi_update; + item_class->realize = ethi_realize; + item_class->unrealize = ethi_unrealize; + item_class->draw = ethi_draw; + item_class->point = ethi_point; + item_class->event = ethi_event; + + gtk_object_add_arg_type ("ETableHeaderItem::ETableColumn", GTK_TYPE_POINTER, + GTK_ARG_WRITABLE, ARG_TABLE_HEADER); +} + +static void +ethi_init (GnomeCanvasItem *item) +{ + item->x1 = 0; + item->y1 = 0; + item->x2 = 0; + item->y2 = 0; +} + +GtkType +e_table_header_view_get_type (void) +{ + static GtkType type = 0; + + if (!type){ + GtkTypeInfo info = { + "ETableHeaderItem", + sizeof (ETableHeaderItem), + sizeof (ETableHeaderItemClass), + (GtkClassInitFunc) ethi_class_init, + (GtkObjectInitFunc) ethi_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-header-item.h b/widgets/e-table-header-item.h new file mode 100644 index 0000000000..9a66b56782 --- /dev/null +++ b/widgets/e-table-header-item.h @@ -0,0 +1,27 @@ +#ifndef _E_TABLE_HEADER_ITEM_H_ +#define _E_TABLE_HEADER_ITEM_H_ + +#include <libgnomeui/gnome-canvas.h> +#include "e-table-header.h" + +#define E_TABLE_HEADER_ITEM_TYPE (e_table_header_item_get_type ()) +#define E_TABLE_HEADER_ITEM(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItem)) +#define E_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItemClass)) +#define E_IS_TABLE_HEADER_ITEM(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_ITEM_TYPE)) +#define E_IS_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_ITEM_TYPE)) + +typedef struct { + GnomeCanvasItem parent; + ETableHeader *eth; + + GdkGC *gc; + GdkCursor *change_cursor, *normal_cursor; +} ETableHeaderItem; + +typedef struct { + GnomeCanvasItemClass parent_class; +} ETableHeaderItemClass; + +GtkType e_table_header_item_get_type (void); + +#endif /* _E_TABLE_HEADER_ITEM_H_ */ diff --git a/widgets/e-table-header.c b/widgets/e-table-header.c new file mode 100644 index 0000000000..fb493c32a0 --- /dev/null +++ b/widgets/e-table-header.c @@ -0,0 +1,299 @@ +/* + * E-table-col-head.c: TableColHead implementation + * + * Author: + * Miguel de Icaza (miguel@gnu.org) + * + * (C) 1999 International GNOME Support + */ +#include <config.h> +#include <gtk/gtkobject.h> +#include <gtk/gtksignal.h> +#include "e-table-header.h" + +enum { + STRUCTURE_CHANGE, + DIMENSION_CHANGE, + LAST_SIGNAL +}; + +static guint eth_signals [LAST_SIGNAL] = { 0, }; + +static GtkObjectClass *e_table_header_parent_class; + +static void +e_table_header_destroy (GtkObject *object) +{ + ETableHeader *eth = E_TABLE_HEADER (object); + const int cols = eth->col_count; + int i; + + /* + * Destroy columns + */ + for (i = 0; i < cols; i++) + e_table_header_remove (eth, i); + + if (e_table_header_parent_class->destroy) + e_table_header_parent_class->destroy (object); +} + +static void +e_table_header_class_init (GtkObjectClass *object_class) +{ + object_class->destroy = e_table_header_destroy; + + e_table_header_parent_class = (gtk_type_class (gtk_object_get_type ())); + + eth_signals [STRUCTURE_CHANGE] = + gtk_signal_new ("structure_change", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableHeaderClass, structure_change), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + eth_signals [DIMENSION_CHANGE] = + gtk_signal_new ("dimension_change", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableHeaderClass, dimension_change), + gtk_marshal_NONE__INT, + GTK_TYPE_NONE, 1, GTK_TYPE_INT); + + gtk_object_class_add_signals (object_class, eth_signals, LAST_SIGNAL); +} + +GtkType +e_table_header_get_type (void) +{ + static GtkType type = 0; + + if (!type){ + GtkTypeInfo info = { + "ETableHeader", + sizeof (ETableHeader), + sizeof (ETableHeaderClass), + (GtkClassInitFunc) e_table_header_class_init, + (GtkObjectInitFunc) NULL, + NULL, /* reserved 1 */ + NULL, /* reserved 2 */ + (GtkClassInitFunc) NULL + }; + + type = gtk_type_unique (gtk_object_get_type (), &info); + } + + return type; +} + +ETableHeader * +e_table_header_new (void) +{ + ETableHeader *eth; + + eth = gtk_type_new (e_table_header_get_type ()); + + return eth; +} + +static void +eth_do_insert (ETableHeader *eth, int pos, ETableCol *val) +{ + memcpy (ð->columns [pos+1], ð->columns [pos], + sizeof (ETableCol *) * (eth->col_count - pos)); + eth->columns [pos] = val; +} + +void +e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos) +{ + ETableCol **new_ptr; + + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (tc != NULL); + g_return_if_fail (pos >= 0 && pos < eth->col_count); + + if (pos == -1) + pos = eth->col_count; + eth->columns = g_realloc (eth->columns, sizeof (ETableCol *) * (eth->col_count + 1)); + eth_do_insert (eth, pos, tc); + eth->col_count++; + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +ETableCol * +e_table_header_get_column (ETableHeader *eth, int column) +{ + g_return_val_if_fail (eth != NULL, NULL); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), NULL); + + if (column < 0) + return NULL; + + if (column >= eth->col_count) + return NULL; + + return eth->columns [column]; +} + +int +e_table_header_count (ETableHeader *eth) +{ + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + return eth->col_count; +} + +int +e_table_header_index (ETableHeader *eth, const char *identifier) +{ + int i; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + g_return_val_if_fail (identifier != NULL, 0); + + for (i = 0; i < eth->col_count; i++){ + ETableCol *tc = eth->columns [i]; + + if (strcmp (tc->id, identifier) == 0) + return i; + } + + return -1; +} + +int +e_table_header_get_index_at (ETableHeader *eth, int x_offset) +{ + int i, total; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + total = 0; + for (i = 0; i < eth->col_count; i++){ + total += eth->columns [i]->width; + + if (x_offset < total) + return i; + } + + return -1; +} + +ETableCol ** +e_table_header_get_columns (ETableHeader *eth) +{ + ETableCol **ret; + int i; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + ret = g_new (ETableCol *, eth->col_count + 1); + memcpy (ret, eth->columns, sizeof (ETableCol *) * eth->col_count); + ret [eth->col_count] = NULL; + + return ret; +} + +gboolean +e_table_header_selection_ok (ETableHeader *eth) +{ + g_return_val_if_fail (eth != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), FALSE); + + return eth->selectable; +} + +int +ve_table_header_get_selected (ETableHeader *eth) +{ + int i; + int selected = 0; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + for (i = 0; i < eth->col_count; i++){ + if (eth->columns [i]->selected) + selected++; + } + + return selected; +} + +int +e_table_header_total_width (ETableHeader *eth) +{ + int total, i; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + total = 0; + for (i = 0; i < eth->col_count; i++) + total += eth->columns [i]->width; + + return total; +} + +static void +eth_do_remove (ETableHeader *eth, int idx) +{ + memcpy (ð->columns [idx], ð->columns [idx+1], + sizeof (ETableCol *) * eth->col_count - idx); + eth->col_count--; +} + +void +e_table_header_move (ETableHeader *eth, int source_index, int target_index) +{ + ETableCol *old; + + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (source_index >= 0); + g_return_if_fail (target_index >= 0); + g_return_if_fail (source_index < eth->col_count); + g_return_if_fail (target_index < eth->col_count); + + old = eth->columns [source_index]; + eth_do_remove (eth, source_index); + eth_do_insert (eth, target_index, old); + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +void +e_table_header_remove (ETableHeader *eth, int idx) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (idx >= 0); + g_return_if_fail (idx < eth->col_count); + + eth_do_remove (eth, idx); + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +void +e_table_header_set_selection (ETableHeader *eth, gboolean allow_selection) +{ +} + +void +e_table_header_set_size (ETableHeader *eth, int idx, int size) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (idx >= 0); + g_return_if_fail (idx < eth->col_count); + g_return_if_fail (size > 0); + + eth->columns [idx]->width = size; + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE], idx); +} diff --git a/widgets/e-table-header.h b/widgets/e-table-header.h new file mode 100644 index 0000000000..d8e04ea8fd --- /dev/null +++ b/widgets/e-table-header.h @@ -0,0 +1,81 @@ +#ifndef _E_TABLE_COLUMN_H_ +#define _E_TABLE_COLUMN_H_ + +#include <gtk/gtkobject.h> +#include <gdk/gdk.h> +#include "e-table-col.h" + +typedef struct _ETableHeader ETableHeader; +typedef struct _ETableCol ETableCol; + +/* + * Rendering function for the column header + */ +typedef void (*ETableColRenderFn)( + ETableCol *etc, void *gnome_canvas_item, void *drawable, + int x, int y, int w, int h, void *data); + +/* + * Information about a single column + */ +struct _ETableCol { + const char *id; + int width; + ETableColRenderFn render; + void *render_data; + unsigned int selected:1; + int resizeable:1; + int min_size; +}; + +#define E_TABLE_HEADER_TYPE (e_table_header_get_type ()) +#define E_TABLE_HEADER(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_TYPE, ETableHeader)) +#define E_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_HEADER_TYPE, ETableHeaderClass)) +#define E_IS_TABLE_HEADER(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_TYPE)) +#define E_IS_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_TYPE)) + +/* + * A Columnar header. + */ +struct _ETableHeader { + GtkObject base; + + int col_count; + ETableCol **columns; + gboolean selectable; +}; + +typedef struct { + GtkObjectClass parent_class; + + void (*structure_change) (ETableHeader *etc); + void (*dimension_change) (ETableHeader *etc, int col); +} ETableHeaderClass; + +GtkType e_table_header_get_type (void); +ETableHeader *e_table_header_new (void); + +void e_table_header_add_column (ETableHeader *etc, + ETableCol *tc, int pos); +ETableCol * e_table_header_get_column (ETableHeader *etc, + int column); +int e_table_header_count (ETableHeader *etc); +int e_table_header_index (ETableHeader *etc, + const char *identifier); +int e_table_header_get_index_at (ETableHeader *etc, + int x_offset); +ETableCol **e_table_header_get_columns (ETableHeader *etc); +gboolean e_table_header_selection_ok (ETableHeader *etc); +int e_table_header_get_selected (ETableHeader *etc); +int e_table_header_total_width (ETableHeader *etc); +void e_table_header_move (ETableHeader *etc, + int source_index, + int target_index); +void e_table_header_remove (ETableHeader *etc, int idx); +void e_table_header_set_size (ETableHeader *etc, int idx, int size); +void e_table_header_set_selection (ETableHeader *etc, + gboolean allow_selection); + +GList *e_table_header_get_selected_indexes(ETableHeader *etc); + +#endif /* _E_TABLE_HEADER_H_ */ diff --git a/widgets/e-table-model.c b/widgets/e-table-model.c index 23782e52c9..868664cf08 100644 --- a/widgets/e-table-model.c +++ b/widgets/e-table-model.c @@ -40,7 +40,7 @@ e_table_model_value_at (ETableModel *etable, int col, int 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); + return ETM_CLASS (etable)->set_value_at (etable, col, row); } gboolean @@ -55,39 +55,6 @@ 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) { @@ -95,10 +62,6 @@ e_table_model_destroy (GtkObject *object) 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); } @@ -137,9 +100,9 @@ e_table_model_get_type (void) int e_table_model_height (ETableModel *etable) { - int rows; - int size; - g_return_val_if_fail (etable != NULL); + int rows, size, i; + + g_return_val_if_fail (etable != NULL, 0); rows = e_table_model_row_count (etable); size = 0; diff --git a/widgets/e-table-simple.c b/widgets/e-table-simple.c index b586712942..e52a9498f8 100644 --- a/widgets/e-table-simple.c +++ b/widgets/e-table-simple.c @@ -17,7 +17,7 @@ simple_column_count (ETableModel *etm) { ETableSimple *simple = (ETableSimple *)etm; - return simple->col_count (etm) + return simple->col_count (etm, simple->data); } static const char * @@ -25,7 +25,7 @@ simple_column_name (ETableModel *etm, int col) { ETableSimple *simple = (ETableSimple *)etm; - return simple->col_name (etm, col); + return simple->col_name (etm, col, simple->data); } static int @@ -33,23 +33,23 @@ simple_row_count (ETableModel *etm) { ETableSimple *simple = (ETableSimple *)etm; - return simple->row_count (etm); + return simple->row_count (etm, simple->data); } -static void +static void * simple_value_at (ETableModel *etm, int col, int row) { ETableSimple *simple = (ETableSimple *)etm; - return simple->value_at (etm, col, row); + return simple->value_at (etm, col, row, simple->data); } static void -simple_set_value_at (ETableModel *etm, int col, int row, void *data) +simple_set_value_at (ETableModel *etm, int col, int row) { ETableSimple *simple = (ETableSimple *)etm; - return simple->set_value_at (etm, col, row, data); + simple->set_value_at (etm, col, row, simple->data); } static gboolean @@ -57,20 +57,20 @@ simple_is_cell_editable (ETableModel *etm, int col, int row) { ETableSimple *simple = (ETableSimple *)etm; - return simple->is_cell_editable (etm, col, row, data); + return simple->is_cell_editable (etm, col, row, simple->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; + ETableModelClass *model_class = (ETableModelClass *) object_class; + + model_class->column_count = simple_column_count; + model_class->column_name = simple_column_name; + model_class->row_count = simple_row_count; + model_class->value_at = simple_value_at; + model_class->set_value_at = simple_set_value_at; + model_class->is_cell_editable = simple_is_cell_editable; } GtkType @@ -96,7 +96,7 @@ e_table_simple_get_type (void) return type; } -ETable * +ETableModel * e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleColumnNameFn col_name, ETableSimpleRowCountFn row_count, @@ -116,5 +116,5 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count, et->set_value_at = set_value_at; et->is_cell_editable = is_cell_editable; - return (ETable *) et; + return (ETableModel *) et; } diff --git a/widgets/e-table-simple.h b/widgets/e-table-simple.h index b5c549a440..fc69ce19d0 100644 --- a/widgets/e-table-simple.h +++ b/widgets/e-table-simple.h @@ -3,13 +3,13 @@ #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 int (*ETableSimpleColumnCountFn) (ETableModel *etm, void *data); +typedef const char *(*ETableSimpleColumnNameFn) (ETableModel *etm, int col, void *data); +typedef int (*ETableSimpleRowCountFn) (ETableModel *etm, void *data); +typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row, void *data); 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 gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row, void *data); +typedef int (*ETableSimpleRowHeightFn) (ETableModel *etm, int row, void *data); typedef struct { ETableModel parent; @@ -24,9 +24,13 @@ typedef struct { void *data; } ETableSimple; +typedef struct { + ETableModel parent_class; +} ETableSimpleClass; + GtkType e_table_simple_get_type (void); -ETable *e_table_simple_new (ETableSimpleColumnCountFn col_count, +ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleColumnNameFn col_name, ETableSimpleRowCountFn row_count, ETableSimpleValueAtFn value_at, diff --git a/widgets/e-table-tree.h b/widgets/e-table-tree.h new file mode 100644 index 0000000000..e7e125a6af --- /dev/null +++ b/widgets/e-table-tree.h @@ -0,0 +1,19 @@ +#ifndef _E_TABLE_TREE_H_ +#define _E_TABLE_TREE_H_ + +typedef struct { + char *title; + + union { + ETableModel *table; + GList *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); + +#endif /* _E_TABLE_TREE_H_ */ diff --git a/widgets/e-table.h b/widgets/e-table.h new file mode 100644 index 0000000000..0847ddde6c --- /dev/null +++ b/widgets/e-table.h @@ -0,0 +1,6 @@ +#ifndef _E_TABLE_H_ +#define _E_TABLE_H_ + +GtkType e_table_get_type (void); +ETable * +#endif /* _E_TABLE_H_ */ diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am index a9614cf1d7..1a410e298e 100644 --- a/widgets/e-table/Makefile.am +++ b/widgets/e-table/Makefile.am @@ -13,10 +13,10 @@ INCLUDES = \ CPPFLAGS = \ -DE_GUIDIR=\"$(guidir)\" -noinst_LTLIBRARIES = \ - libevolutionwidgets.la +noinst_LIBRARIES = \ + libevolutionwidgets.a -libevolutionwidgets_la_SOURCES = \ +libevolutionwidgets_a_SOURCES = \ e-msg-composer-address-dialog.c \ e-msg-composer-address-dialog.h \ e-msg-composer-address-entry.c \ @@ -28,5 +28,15 @@ libevolutionwidgets_la_SOURCES = \ e-msg-composer-hdrs.c \ e-msg-composer-hdrs.h \ e-msg-composer.c \ - e-msg-composer.h + e-msg-composer.h \ + e-table-group.c \ + e-table-group.h \ + e-table-header.c \ + e-table-header.h \ + e-table-header-item.c \ + e-table-header-item.h \ + e-table-model.c \ + e-table-model.h \ + e-table-simple.c \ + e-table-simple.h diff --git a/widgets/e-table/e-table-group.c b/widgets/e-table/e-table-group.c index 194bc6b235..07a3fb60f2 100644 --- a/widgets/e-table/e-table-group.c +++ b/widgets/e-table/e-table-group.c @@ -13,7 +13,7 @@ void e_table_group_destroy (ETableGroup *etg) { - g_return_val_if_fail (etg != NULL); + g_return_if_fail (etg != NULL); g_free (etg->title); @@ -46,11 +46,11 @@ e_table_group_new_leaf (const char *title, ETableModel *table) etg->u.table = table; etg->title = g_strdup (title); - return eg; + return etg; } ETableGroup * -e_table_group_new_leaf (const char *title) +e_table_group_new (const char *title) { ETableGroup *etg; @@ -63,15 +63,15 @@ e_table_group_new_leaf (const char *title) etg->u.children = NULL; etg->title = g_strdup (title); - return eg; + return etg; } 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); + g_return_if_fail (etg != NULL); + g_return_if_fail (child != NULL); + g_return_if_fail (etg->is_leaf != 0); etg->u.children = g_slist_append (etg->u.children, child); } @@ -79,7 +79,7 @@ e_table_group_append_child (ETableGroup *etg, ETableGroup *child) int e_table_group_size (ETableGroup *etg) { - g_return_val_if_fail (etg != NULL); + g_return_if_fail (etg != NULL); if (etg->is_leaf) return e_table_model_height (etg->u.table); diff --git a/widgets/e-table/e-table-group.h b/widgets/e-table/e-table-group.h index ab79d317e9..d673aebd11 100644 --- a/widgets/e-table/e-table-group.h +++ b/widgets/e-table/e-table-group.h @@ -1,6 +1,8 @@ #ifndef _E_TABLE_TREE_H_ #define _E_TABLE_TREE_H_ +#include "e-table-model.h" + typedef struct { char *title; @@ -13,11 +15,11 @@ typedef struct { guint is_leaf :1; } ETableGroup; -ETableGroup *e_table_group_new (const char *title, ETableModel *table); -ETableGroup *e_table_group_new_leaf (const char *title); +ETableGroup *e_table_group_new (const char *title); +ETableGroup *e_table_group_new_leaf (const char *title, ETableModel *table); void e_table_group_destroy (ETableGroup *etg); int e_table_group_size (ETableGroup *egroup); -void e_table_group_append_child (ETableGroup *etg, ETableGroup *child) +void e_table_group_append_child (ETableGroup *etg, ETableGroup *child); #endif /* _E_TABLE_TREE_H_ */ diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c new file mode 100644 index 0000000000..796a2e493b --- /dev/null +++ b/widgets/e-table/e-table-header-item.c @@ -0,0 +1,233 @@ +/* + * 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-header.h" +#include "e-table-header-item.h" + +#define ETHI_HEIGHT 14 + +#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type () + +static GnomeCanvasItemClass *ethi_parent_class; + +enum { + ARG_0, + ARG_TABLE_HEADER +}; + +static void +ethi_destroy (GtkObject *object) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (object); + + gtk_object_unref (GTK_OBJECT (ethi)); + + if (GTK_OBJECT_CLASS (ethi_parent_class)->destroy) + (*GTK_OBJECT_CLASS (ethi_parent_class)->destroy) (object); +} + +static void +ethi_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->update) + (*GNOME_CANVAS_ITEM_CLASS (ethi_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 +ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + ETableHeaderItem *ethi; + int v; + + item = GNOME_CANVAS_ITEM (o); + ethi = E_TABLE_HEADER_ITEM (o); + + switch (arg_id){ + case ARG_TABLE_HEADER: + ethi->eth = GTK_VALUE_POINTER (*arg); + break; + } + ethi_update (item, NULL, NULL, 0); +} + +static void +ethi_realize (GnomeCanvasItem *item) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); + GdkWindow *window; + GdkColor c; + + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)-> realize) + (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->realize)(item); + + window = GTK_WIDGET (item->canvas)->window; + + ethi->gc = gdk_gc_new (window); + gnome_canvas_get_color (item->canvas, "black", &c); + gdk_gc_set_foreground (ethi->gc, &c); + + ethi->normal_cursor = gdk_cursor_new (GDK_ARROW); +} + +static void +ethi_unrealize (GnomeCanvasItem *item) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); + + gdk_gc_unref (ethi->gc); + ethi->gc = NULL; + + gdk_cursor_destroy (ethi->change_cursor); + ethi->change_cursor = NULL; + + gdk_cursor_destroy (ethi->normal_cursor); + ethi->normal_cursor = NULL; + + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize) + (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item); +} + +static void +ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); + GnomeCanvas *canvas = item->canvas; + GdkGC *gc; + const int cols = e_table_header_count (ethi->eth); + int x2 = x1 + width; + int col, total; + int x; + + total = 0; + x = 0; + for (col = 0; col < cols; col++){ + ETableCol *ecol = e_table_header_get_column (ethi->eth, col); + const int col_width = ecol->width; + + if (x1 > total + col_width){ + x += col_width; + continue; + } + + if (x2 < total) + return; + + gc = GTK_WIDGET (canvas)->style->bg_gc [GTK_STATE_ACTIVE]; + + gdk_draw_rectangle ( + drawable, gc, TRUE, + x + 1, -y1 + 1, col_width - 2, ETHI_HEIGHT - 2); + + gtk_draw_shadow ( + GTK_WIDGET (canvas)->style, drawable, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + x , -y1, col_width, ETHI_HEIGHT); + + if (ecol->render != NULL) + (*ecol->render)(ecol, item, drawable, x1, y1, width, height, ecol->render_data); + else { + GdkRectangle clip; + GdkFont *font = GTK_WIDGET (canvas)->style->font; + + clip.x = x + 2; + clip.y = -y1 + 2; + clip.width = col_width - 4; + clip.height = ETHI_HEIGHT - 4; + gdk_gc_set_clip_rectangle (gc, &clip); + + /* + * FIXME: should be obvious + */ + gdk_draw_text (drawable, font, gc, x, -y1 + 10, "TEST", 4); + + gdk_gc_set_clip_rectangle (gc, NULL); + } + } +} + +static double +ethi_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, + GnomeCanvasItem **actual_item) +{ + *actual_item = item; + return 0.0; +} + +static int +ethi_event (GnomeCanvasItem *item, GdkEvent *e) +{ + switch (e->type){ + default: + return FALSE; + } + return TRUE; +} + +static void +ethi_class_init (GtkObjectClass *object_class) +{ + GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + + ethi_parent_class = gtk_type_class (gnome_canvas_item_get_type ()); + + object_class->destroy = ethi_destroy; + object_class->set_arg = ethi_set_arg; + + item_class->update = ethi_update; + item_class->realize = ethi_realize; + item_class->unrealize = ethi_unrealize; + item_class->draw = ethi_draw; + item_class->point = ethi_point; + item_class->event = ethi_event; + + gtk_object_add_arg_type ("ETableHeaderItem::ETableColumn", GTK_TYPE_POINTER, + GTK_ARG_WRITABLE, ARG_TABLE_HEADER); +} + +static void +ethi_init (GnomeCanvasItem *item) +{ + item->x1 = 0; + item->y1 = 0; + item->x2 = 0; + item->y2 = 0; +} + +GtkType +e_table_header_view_get_type (void) +{ + static GtkType type = 0; + + if (!type){ + GtkTypeInfo info = { + "ETableHeaderItem", + sizeof (ETableHeaderItem), + sizeof (ETableHeaderItemClass), + (GtkClassInitFunc) ethi_class_init, + (GtkObjectInitFunc) ethi_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-header-item.h b/widgets/e-table/e-table-header-item.h new file mode 100644 index 0000000000..9a66b56782 --- /dev/null +++ b/widgets/e-table/e-table-header-item.h @@ -0,0 +1,27 @@ +#ifndef _E_TABLE_HEADER_ITEM_H_ +#define _E_TABLE_HEADER_ITEM_H_ + +#include <libgnomeui/gnome-canvas.h> +#include "e-table-header.h" + +#define E_TABLE_HEADER_ITEM_TYPE (e_table_header_item_get_type ()) +#define E_TABLE_HEADER_ITEM(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItem)) +#define E_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItemClass)) +#define E_IS_TABLE_HEADER_ITEM(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_ITEM_TYPE)) +#define E_IS_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_ITEM_TYPE)) + +typedef struct { + GnomeCanvasItem parent; + ETableHeader *eth; + + GdkGC *gc; + GdkCursor *change_cursor, *normal_cursor; +} ETableHeaderItem; + +typedef struct { + GnomeCanvasItemClass parent_class; +} ETableHeaderItemClass; + +GtkType e_table_header_item_get_type (void); + +#endif /* _E_TABLE_HEADER_ITEM_H_ */ diff --git a/widgets/e-table/e-table-header.c b/widgets/e-table/e-table-header.c new file mode 100644 index 0000000000..fb493c32a0 --- /dev/null +++ b/widgets/e-table/e-table-header.c @@ -0,0 +1,299 @@ +/* + * E-table-col-head.c: TableColHead implementation + * + * Author: + * Miguel de Icaza (miguel@gnu.org) + * + * (C) 1999 International GNOME Support + */ +#include <config.h> +#include <gtk/gtkobject.h> +#include <gtk/gtksignal.h> +#include "e-table-header.h" + +enum { + STRUCTURE_CHANGE, + DIMENSION_CHANGE, + LAST_SIGNAL +}; + +static guint eth_signals [LAST_SIGNAL] = { 0, }; + +static GtkObjectClass *e_table_header_parent_class; + +static void +e_table_header_destroy (GtkObject *object) +{ + ETableHeader *eth = E_TABLE_HEADER (object); + const int cols = eth->col_count; + int i; + + /* + * Destroy columns + */ + for (i = 0; i < cols; i++) + e_table_header_remove (eth, i); + + if (e_table_header_parent_class->destroy) + e_table_header_parent_class->destroy (object); +} + +static void +e_table_header_class_init (GtkObjectClass *object_class) +{ + object_class->destroy = e_table_header_destroy; + + e_table_header_parent_class = (gtk_type_class (gtk_object_get_type ())); + + eth_signals [STRUCTURE_CHANGE] = + gtk_signal_new ("structure_change", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableHeaderClass, structure_change), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + eth_signals [DIMENSION_CHANGE] = + gtk_signal_new ("dimension_change", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableHeaderClass, dimension_change), + gtk_marshal_NONE__INT, + GTK_TYPE_NONE, 1, GTK_TYPE_INT); + + gtk_object_class_add_signals (object_class, eth_signals, LAST_SIGNAL); +} + +GtkType +e_table_header_get_type (void) +{ + static GtkType type = 0; + + if (!type){ + GtkTypeInfo info = { + "ETableHeader", + sizeof (ETableHeader), + sizeof (ETableHeaderClass), + (GtkClassInitFunc) e_table_header_class_init, + (GtkObjectInitFunc) NULL, + NULL, /* reserved 1 */ + NULL, /* reserved 2 */ + (GtkClassInitFunc) NULL + }; + + type = gtk_type_unique (gtk_object_get_type (), &info); + } + + return type; +} + +ETableHeader * +e_table_header_new (void) +{ + ETableHeader *eth; + + eth = gtk_type_new (e_table_header_get_type ()); + + return eth; +} + +static void +eth_do_insert (ETableHeader *eth, int pos, ETableCol *val) +{ + memcpy (ð->columns [pos+1], ð->columns [pos], + sizeof (ETableCol *) * (eth->col_count - pos)); + eth->columns [pos] = val; +} + +void +e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos) +{ + ETableCol **new_ptr; + + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (tc != NULL); + g_return_if_fail (pos >= 0 && pos < eth->col_count); + + if (pos == -1) + pos = eth->col_count; + eth->columns = g_realloc (eth->columns, sizeof (ETableCol *) * (eth->col_count + 1)); + eth_do_insert (eth, pos, tc); + eth->col_count++; + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +ETableCol * +e_table_header_get_column (ETableHeader *eth, int column) +{ + g_return_val_if_fail (eth != NULL, NULL); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), NULL); + + if (column < 0) + return NULL; + + if (column >= eth->col_count) + return NULL; + + return eth->columns [column]; +} + +int +e_table_header_count (ETableHeader *eth) +{ + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + return eth->col_count; +} + +int +e_table_header_index (ETableHeader *eth, const char *identifier) +{ + int i; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + g_return_val_if_fail (identifier != NULL, 0); + + for (i = 0; i < eth->col_count; i++){ + ETableCol *tc = eth->columns [i]; + + if (strcmp (tc->id, identifier) == 0) + return i; + } + + return -1; +} + +int +e_table_header_get_index_at (ETableHeader *eth, int x_offset) +{ + int i, total; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + total = 0; + for (i = 0; i < eth->col_count; i++){ + total += eth->columns [i]->width; + + if (x_offset < total) + return i; + } + + return -1; +} + +ETableCol ** +e_table_header_get_columns (ETableHeader *eth) +{ + ETableCol **ret; + int i; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + ret = g_new (ETableCol *, eth->col_count + 1); + memcpy (ret, eth->columns, sizeof (ETableCol *) * eth->col_count); + ret [eth->col_count] = NULL; + + return ret; +} + +gboolean +e_table_header_selection_ok (ETableHeader *eth) +{ + g_return_val_if_fail (eth != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), FALSE); + + return eth->selectable; +} + +int +ve_table_header_get_selected (ETableHeader *eth) +{ + int i; + int selected = 0; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + for (i = 0; i < eth->col_count; i++){ + if (eth->columns [i]->selected) + selected++; + } + + return selected; +} + +int +e_table_header_total_width (ETableHeader *eth) +{ + int total, i; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + total = 0; + for (i = 0; i < eth->col_count; i++) + total += eth->columns [i]->width; + + return total; +} + +static void +eth_do_remove (ETableHeader *eth, int idx) +{ + memcpy (ð->columns [idx], ð->columns [idx+1], + sizeof (ETableCol *) * eth->col_count - idx); + eth->col_count--; +} + +void +e_table_header_move (ETableHeader *eth, int source_index, int target_index) +{ + ETableCol *old; + + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (source_index >= 0); + g_return_if_fail (target_index >= 0); + g_return_if_fail (source_index < eth->col_count); + g_return_if_fail (target_index < eth->col_count); + + old = eth->columns [source_index]; + eth_do_remove (eth, source_index); + eth_do_insert (eth, target_index, old); + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +void +e_table_header_remove (ETableHeader *eth, int idx) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (idx >= 0); + g_return_if_fail (idx < eth->col_count); + + eth_do_remove (eth, idx); + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +void +e_table_header_set_selection (ETableHeader *eth, gboolean allow_selection) +{ +} + +void +e_table_header_set_size (ETableHeader *eth, int idx, int size) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (idx >= 0); + g_return_if_fail (idx < eth->col_count); + g_return_if_fail (size > 0); + + eth->columns [idx]->width = size; + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE], idx); +} diff --git a/widgets/e-table/e-table-header.h b/widgets/e-table/e-table-header.h new file mode 100644 index 0000000000..d8e04ea8fd --- /dev/null +++ b/widgets/e-table/e-table-header.h @@ -0,0 +1,81 @@ +#ifndef _E_TABLE_COLUMN_H_ +#define _E_TABLE_COLUMN_H_ + +#include <gtk/gtkobject.h> +#include <gdk/gdk.h> +#include "e-table-col.h" + +typedef struct _ETableHeader ETableHeader; +typedef struct _ETableCol ETableCol; + +/* + * Rendering function for the column header + */ +typedef void (*ETableColRenderFn)( + ETableCol *etc, void *gnome_canvas_item, void *drawable, + int x, int y, int w, int h, void *data); + +/* + * Information about a single column + */ +struct _ETableCol { + const char *id; + int width; + ETableColRenderFn render; + void *render_data; + unsigned int selected:1; + int resizeable:1; + int min_size; +}; + +#define E_TABLE_HEADER_TYPE (e_table_header_get_type ()) +#define E_TABLE_HEADER(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_TYPE, ETableHeader)) +#define E_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_HEADER_TYPE, ETableHeaderClass)) +#define E_IS_TABLE_HEADER(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_TYPE)) +#define E_IS_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_TYPE)) + +/* + * A Columnar header. + */ +struct _ETableHeader { + GtkObject base; + + int col_count; + ETableCol **columns; + gboolean selectable; +}; + +typedef struct { + GtkObjectClass parent_class; + + void (*structure_change) (ETableHeader *etc); + void (*dimension_change) (ETableHeader *etc, int col); +} ETableHeaderClass; + +GtkType e_table_header_get_type (void); +ETableHeader *e_table_header_new (void); + +void e_table_header_add_column (ETableHeader *etc, + ETableCol *tc, int pos); +ETableCol * e_table_header_get_column (ETableHeader *etc, + int column); +int e_table_header_count (ETableHeader *etc); +int e_table_header_index (ETableHeader *etc, + const char *identifier); +int e_table_header_get_index_at (ETableHeader *etc, + int x_offset); +ETableCol **e_table_header_get_columns (ETableHeader *etc); +gboolean e_table_header_selection_ok (ETableHeader *etc); +int e_table_header_get_selected (ETableHeader *etc); +int e_table_header_total_width (ETableHeader *etc); +void e_table_header_move (ETableHeader *etc, + int source_index, + int target_index); +void e_table_header_remove (ETableHeader *etc, int idx); +void e_table_header_set_size (ETableHeader *etc, int idx, int size); +void e_table_header_set_selection (ETableHeader *etc, + gboolean allow_selection); + +GList *e_table_header_get_selected_indexes(ETableHeader *etc); + +#endif /* _E_TABLE_HEADER_H_ */ diff --git a/widgets/e-table/e-table-model.c b/widgets/e-table/e-table-model.c index 23782e52c9..868664cf08 100644 --- a/widgets/e-table/e-table-model.c +++ b/widgets/e-table/e-table-model.c @@ -40,7 +40,7 @@ e_table_model_value_at (ETableModel *etable, int col, int 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); + return ETM_CLASS (etable)->set_value_at (etable, col, row); } gboolean @@ -55,39 +55,6 @@ 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) { @@ -95,10 +62,6 @@ e_table_model_destroy (GtkObject *object) 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); } @@ -137,9 +100,9 @@ e_table_model_get_type (void) int e_table_model_height (ETableModel *etable) { - int rows; - int size; - g_return_val_if_fail (etable != NULL); + int rows, size, i; + + g_return_val_if_fail (etable != NULL, 0); rows = e_table_model_row_count (etable); size = 0; diff --git a/widgets/e-table/e-table-simple.c b/widgets/e-table/e-table-simple.c index b586712942..e52a9498f8 100644 --- a/widgets/e-table/e-table-simple.c +++ b/widgets/e-table/e-table-simple.c @@ -17,7 +17,7 @@ simple_column_count (ETableModel *etm) { ETableSimple *simple = (ETableSimple *)etm; - return simple->col_count (etm) + return simple->col_count (etm, simple->data); } static const char * @@ -25,7 +25,7 @@ simple_column_name (ETableModel *etm, int col) { ETableSimple *simple = (ETableSimple *)etm; - return simple->col_name (etm, col); + return simple->col_name (etm, col, simple->data); } static int @@ -33,23 +33,23 @@ simple_row_count (ETableModel *etm) { ETableSimple *simple = (ETableSimple *)etm; - return simple->row_count (etm); + return simple->row_count (etm, simple->data); } -static void +static void * simple_value_at (ETableModel *etm, int col, int row) { ETableSimple *simple = (ETableSimple *)etm; - return simple->value_at (etm, col, row); + return simple->value_at (etm, col, row, simple->data); } static void -simple_set_value_at (ETableModel *etm, int col, int row, void *data) +simple_set_value_at (ETableModel *etm, int col, int row) { ETableSimple *simple = (ETableSimple *)etm; - return simple->set_value_at (etm, col, row, data); + simple->set_value_at (etm, col, row, simple->data); } static gboolean @@ -57,20 +57,20 @@ simple_is_cell_editable (ETableModel *etm, int col, int row) { ETableSimple *simple = (ETableSimple *)etm; - return simple->is_cell_editable (etm, col, row, data); + return simple->is_cell_editable (etm, col, row, simple->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; + ETableModelClass *model_class = (ETableModelClass *) object_class; + + model_class->column_count = simple_column_count; + model_class->column_name = simple_column_name; + model_class->row_count = simple_row_count; + model_class->value_at = simple_value_at; + model_class->set_value_at = simple_set_value_at; + model_class->is_cell_editable = simple_is_cell_editable; } GtkType @@ -96,7 +96,7 @@ e_table_simple_get_type (void) return type; } -ETable * +ETableModel * e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleColumnNameFn col_name, ETableSimpleRowCountFn row_count, @@ -116,5 +116,5 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count, et->set_value_at = set_value_at; et->is_cell_editable = is_cell_editable; - return (ETable *) et; + return (ETableModel *) et; } diff --git a/widgets/e-table/e-table-simple.h b/widgets/e-table/e-table-simple.h index b5c549a440..fc69ce19d0 100644 --- a/widgets/e-table/e-table-simple.h +++ b/widgets/e-table/e-table-simple.h @@ -3,13 +3,13 @@ #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 int (*ETableSimpleColumnCountFn) (ETableModel *etm, void *data); +typedef const char *(*ETableSimpleColumnNameFn) (ETableModel *etm, int col, void *data); +typedef int (*ETableSimpleRowCountFn) (ETableModel *etm, void *data); +typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row, void *data); 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 gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row, void *data); +typedef int (*ETableSimpleRowHeightFn) (ETableModel *etm, int row, void *data); typedef struct { ETableModel parent; @@ -24,9 +24,13 @@ typedef struct { void *data; } ETableSimple; +typedef struct { + ETableModel parent_class; +} ETableSimpleClass; + GtkType e_table_simple_get_type (void); -ETable *e_table_simple_new (ETableSimpleColumnCountFn col_count, +ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleColumnNameFn col_name, ETableSimpleRowCountFn row_count, ETableSimpleValueAtFn value_at, diff --git a/widgets/e-table/e-table-tree.h b/widgets/e-table/e-table-tree.h new file mode 100644 index 0000000000..e7e125a6af --- /dev/null +++ b/widgets/e-table/e-table-tree.h @@ -0,0 +1,19 @@ +#ifndef _E_TABLE_TREE_H_ +#define _E_TABLE_TREE_H_ + +typedef struct { + char *title; + + union { + ETableModel *table; + GList *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); + +#endif /* _E_TABLE_TREE_H_ */ diff --git a/widgets/e-table/e-table.h b/widgets/e-table/e-table.h new file mode 100644 index 0000000000..0847ddde6c --- /dev/null +++ b/widgets/e-table/e-table.h @@ -0,0 +1,6 @@ +#ifndef _E_TABLE_H_ +#define _E_TABLE_H_ + +GtkType e_table_get_type (void); +ETable * +#endif /* _E_TABLE_H_ */ diff --git a/widgets/table/e-table-group.c b/widgets/table/e-table-group.c index 194bc6b235..07a3fb60f2 100644 --- a/widgets/table/e-table-group.c +++ b/widgets/table/e-table-group.c @@ -13,7 +13,7 @@ void e_table_group_destroy (ETableGroup *etg) { - g_return_val_if_fail (etg != NULL); + g_return_if_fail (etg != NULL); g_free (etg->title); @@ -46,11 +46,11 @@ e_table_group_new_leaf (const char *title, ETableModel *table) etg->u.table = table; etg->title = g_strdup (title); - return eg; + return etg; } ETableGroup * -e_table_group_new_leaf (const char *title) +e_table_group_new (const char *title) { ETableGroup *etg; @@ -63,15 +63,15 @@ e_table_group_new_leaf (const char *title) etg->u.children = NULL; etg->title = g_strdup (title); - return eg; + return etg; } 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); + g_return_if_fail (etg != NULL); + g_return_if_fail (child != NULL); + g_return_if_fail (etg->is_leaf != 0); etg->u.children = g_slist_append (etg->u.children, child); } @@ -79,7 +79,7 @@ e_table_group_append_child (ETableGroup *etg, ETableGroup *child) int e_table_group_size (ETableGroup *etg) { - g_return_val_if_fail (etg != NULL); + g_return_if_fail (etg != NULL); if (etg->is_leaf) return e_table_model_height (etg->u.table); diff --git a/widgets/table/e-table-group.h b/widgets/table/e-table-group.h index ab79d317e9..d673aebd11 100644 --- a/widgets/table/e-table-group.h +++ b/widgets/table/e-table-group.h @@ -1,6 +1,8 @@ #ifndef _E_TABLE_TREE_H_ #define _E_TABLE_TREE_H_ +#include "e-table-model.h" + typedef struct { char *title; @@ -13,11 +15,11 @@ typedef struct { guint is_leaf :1; } ETableGroup; -ETableGroup *e_table_group_new (const char *title, ETableModel *table); -ETableGroup *e_table_group_new_leaf (const char *title); +ETableGroup *e_table_group_new (const char *title); +ETableGroup *e_table_group_new_leaf (const char *title, ETableModel *table); void e_table_group_destroy (ETableGroup *etg); int e_table_group_size (ETableGroup *egroup); -void e_table_group_append_child (ETableGroup *etg, ETableGroup *child) +void e_table_group_append_child (ETableGroup *etg, ETableGroup *child); #endif /* _E_TABLE_TREE_H_ */ diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c new file mode 100644 index 0000000000..796a2e493b --- /dev/null +++ b/widgets/table/e-table-header-item.c @@ -0,0 +1,233 @@ +/* + * 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-header.h" +#include "e-table-header-item.h" + +#define ETHI_HEIGHT 14 + +#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type () + +static GnomeCanvasItemClass *ethi_parent_class; + +enum { + ARG_0, + ARG_TABLE_HEADER +}; + +static void +ethi_destroy (GtkObject *object) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (object); + + gtk_object_unref (GTK_OBJECT (ethi)); + + if (GTK_OBJECT_CLASS (ethi_parent_class)->destroy) + (*GTK_OBJECT_CLASS (ethi_parent_class)->destroy) (object); +} + +static void +ethi_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->update) + (*GNOME_CANVAS_ITEM_CLASS (ethi_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 +ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + ETableHeaderItem *ethi; + int v; + + item = GNOME_CANVAS_ITEM (o); + ethi = E_TABLE_HEADER_ITEM (o); + + switch (arg_id){ + case ARG_TABLE_HEADER: + ethi->eth = GTK_VALUE_POINTER (*arg); + break; + } + ethi_update (item, NULL, NULL, 0); +} + +static void +ethi_realize (GnomeCanvasItem *item) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); + GdkWindow *window; + GdkColor c; + + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)-> realize) + (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->realize)(item); + + window = GTK_WIDGET (item->canvas)->window; + + ethi->gc = gdk_gc_new (window); + gnome_canvas_get_color (item->canvas, "black", &c); + gdk_gc_set_foreground (ethi->gc, &c); + + ethi->normal_cursor = gdk_cursor_new (GDK_ARROW); +} + +static void +ethi_unrealize (GnomeCanvasItem *item) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); + + gdk_gc_unref (ethi->gc); + ethi->gc = NULL; + + gdk_cursor_destroy (ethi->change_cursor); + ethi->change_cursor = NULL; + + gdk_cursor_destroy (ethi->normal_cursor); + ethi->normal_cursor = NULL; + + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize) + (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item); +} + +static void +ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height) +{ + ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); + GnomeCanvas *canvas = item->canvas; + GdkGC *gc; + const int cols = e_table_header_count (ethi->eth); + int x2 = x1 + width; + int col, total; + int x; + + total = 0; + x = 0; + for (col = 0; col < cols; col++){ + ETableCol *ecol = e_table_header_get_column (ethi->eth, col); + const int col_width = ecol->width; + + if (x1 > total + col_width){ + x += col_width; + continue; + } + + if (x2 < total) + return; + + gc = GTK_WIDGET (canvas)->style->bg_gc [GTK_STATE_ACTIVE]; + + gdk_draw_rectangle ( + drawable, gc, TRUE, + x + 1, -y1 + 1, col_width - 2, ETHI_HEIGHT - 2); + + gtk_draw_shadow ( + GTK_WIDGET (canvas)->style, drawable, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + x , -y1, col_width, ETHI_HEIGHT); + + if (ecol->render != NULL) + (*ecol->render)(ecol, item, drawable, x1, y1, width, height, ecol->render_data); + else { + GdkRectangle clip; + GdkFont *font = GTK_WIDGET (canvas)->style->font; + + clip.x = x + 2; + clip.y = -y1 + 2; + clip.width = col_width - 4; + clip.height = ETHI_HEIGHT - 4; + gdk_gc_set_clip_rectangle (gc, &clip); + + /* + * FIXME: should be obvious + */ + gdk_draw_text (drawable, font, gc, x, -y1 + 10, "TEST", 4); + + gdk_gc_set_clip_rectangle (gc, NULL); + } + } +} + +static double +ethi_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, + GnomeCanvasItem **actual_item) +{ + *actual_item = item; + return 0.0; +} + +static int +ethi_event (GnomeCanvasItem *item, GdkEvent *e) +{ + switch (e->type){ + default: + return FALSE; + } + return TRUE; +} + +static void +ethi_class_init (GtkObjectClass *object_class) +{ + GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + + ethi_parent_class = gtk_type_class (gnome_canvas_item_get_type ()); + + object_class->destroy = ethi_destroy; + object_class->set_arg = ethi_set_arg; + + item_class->update = ethi_update; + item_class->realize = ethi_realize; + item_class->unrealize = ethi_unrealize; + item_class->draw = ethi_draw; + item_class->point = ethi_point; + item_class->event = ethi_event; + + gtk_object_add_arg_type ("ETableHeaderItem::ETableColumn", GTK_TYPE_POINTER, + GTK_ARG_WRITABLE, ARG_TABLE_HEADER); +} + +static void +ethi_init (GnomeCanvasItem *item) +{ + item->x1 = 0; + item->y1 = 0; + item->x2 = 0; + item->y2 = 0; +} + +GtkType +e_table_header_view_get_type (void) +{ + static GtkType type = 0; + + if (!type){ + GtkTypeInfo info = { + "ETableHeaderItem", + sizeof (ETableHeaderItem), + sizeof (ETableHeaderItemClass), + (GtkClassInitFunc) ethi_class_init, + (GtkObjectInitFunc) ethi_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-header-item.h b/widgets/table/e-table-header-item.h new file mode 100644 index 0000000000..9a66b56782 --- /dev/null +++ b/widgets/table/e-table-header-item.h @@ -0,0 +1,27 @@ +#ifndef _E_TABLE_HEADER_ITEM_H_ +#define _E_TABLE_HEADER_ITEM_H_ + +#include <libgnomeui/gnome-canvas.h> +#include "e-table-header.h" + +#define E_TABLE_HEADER_ITEM_TYPE (e_table_header_item_get_type ()) +#define E_TABLE_HEADER_ITEM(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItem)) +#define E_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItemClass)) +#define E_IS_TABLE_HEADER_ITEM(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_ITEM_TYPE)) +#define E_IS_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_ITEM_TYPE)) + +typedef struct { + GnomeCanvasItem parent; + ETableHeader *eth; + + GdkGC *gc; + GdkCursor *change_cursor, *normal_cursor; +} ETableHeaderItem; + +typedef struct { + GnomeCanvasItemClass parent_class; +} ETableHeaderItemClass; + +GtkType e_table_header_item_get_type (void); + +#endif /* _E_TABLE_HEADER_ITEM_H_ */ diff --git a/widgets/table/e-table-header.c b/widgets/table/e-table-header.c new file mode 100644 index 0000000000..fb493c32a0 --- /dev/null +++ b/widgets/table/e-table-header.c @@ -0,0 +1,299 @@ +/* + * E-table-col-head.c: TableColHead implementation + * + * Author: + * Miguel de Icaza (miguel@gnu.org) + * + * (C) 1999 International GNOME Support + */ +#include <config.h> +#include <gtk/gtkobject.h> +#include <gtk/gtksignal.h> +#include "e-table-header.h" + +enum { + STRUCTURE_CHANGE, + DIMENSION_CHANGE, + LAST_SIGNAL +}; + +static guint eth_signals [LAST_SIGNAL] = { 0, }; + +static GtkObjectClass *e_table_header_parent_class; + +static void +e_table_header_destroy (GtkObject *object) +{ + ETableHeader *eth = E_TABLE_HEADER (object); + const int cols = eth->col_count; + int i; + + /* + * Destroy columns + */ + for (i = 0; i < cols; i++) + e_table_header_remove (eth, i); + + if (e_table_header_parent_class->destroy) + e_table_header_parent_class->destroy (object); +} + +static void +e_table_header_class_init (GtkObjectClass *object_class) +{ + object_class->destroy = e_table_header_destroy; + + e_table_header_parent_class = (gtk_type_class (gtk_object_get_type ())); + + eth_signals [STRUCTURE_CHANGE] = + gtk_signal_new ("structure_change", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableHeaderClass, structure_change), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + eth_signals [DIMENSION_CHANGE] = + gtk_signal_new ("dimension_change", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableHeaderClass, dimension_change), + gtk_marshal_NONE__INT, + GTK_TYPE_NONE, 1, GTK_TYPE_INT); + + gtk_object_class_add_signals (object_class, eth_signals, LAST_SIGNAL); +} + +GtkType +e_table_header_get_type (void) +{ + static GtkType type = 0; + + if (!type){ + GtkTypeInfo info = { + "ETableHeader", + sizeof (ETableHeader), + sizeof (ETableHeaderClass), + (GtkClassInitFunc) e_table_header_class_init, + (GtkObjectInitFunc) NULL, + NULL, /* reserved 1 */ + NULL, /* reserved 2 */ + (GtkClassInitFunc) NULL + }; + + type = gtk_type_unique (gtk_object_get_type (), &info); + } + + return type; +} + +ETableHeader * +e_table_header_new (void) +{ + ETableHeader *eth; + + eth = gtk_type_new (e_table_header_get_type ()); + + return eth; +} + +static void +eth_do_insert (ETableHeader *eth, int pos, ETableCol *val) +{ + memcpy (ð->columns [pos+1], ð->columns [pos], + sizeof (ETableCol *) * (eth->col_count - pos)); + eth->columns [pos] = val; +} + +void +e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos) +{ + ETableCol **new_ptr; + + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (tc != NULL); + g_return_if_fail (pos >= 0 && pos < eth->col_count); + + if (pos == -1) + pos = eth->col_count; + eth->columns = g_realloc (eth->columns, sizeof (ETableCol *) * (eth->col_count + 1)); + eth_do_insert (eth, pos, tc); + eth->col_count++; + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +ETableCol * +e_table_header_get_column (ETableHeader *eth, int column) +{ + g_return_val_if_fail (eth != NULL, NULL); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), NULL); + + if (column < 0) + return NULL; + + if (column >= eth->col_count) + return NULL; + + return eth->columns [column]; +} + +int +e_table_header_count (ETableHeader *eth) +{ + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + return eth->col_count; +} + +int +e_table_header_index (ETableHeader *eth, const char *identifier) +{ + int i; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + g_return_val_if_fail (identifier != NULL, 0); + + for (i = 0; i < eth->col_count; i++){ + ETableCol *tc = eth->columns [i]; + + if (strcmp (tc->id, identifier) == 0) + return i; + } + + return -1; +} + +int +e_table_header_get_index_at (ETableHeader *eth, int x_offset) +{ + int i, total; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + total = 0; + for (i = 0; i < eth->col_count; i++){ + total += eth->columns [i]->width; + + if (x_offset < total) + return i; + } + + return -1; +} + +ETableCol ** +e_table_header_get_columns (ETableHeader *eth) +{ + ETableCol **ret; + int i; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + ret = g_new (ETableCol *, eth->col_count + 1); + memcpy (ret, eth->columns, sizeof (ETableCol *) * eth->col_count); + ret [eth->col_count] = NULL; + + return ret; +} + +gboolean +e_table_header_selection_ok (ETableHeader *eth) +{ + g_return_val_if_fail (eth != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), FALSE); + + return eth->selectable; +} + +int +ve_table_header_get_selected (ETableHeader *eth) +{ + int i; + int selected = 0; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + for (i = 0; i < eth->col_count; i++){ + if (eth->columns [i]->selected) + selected++; + } + + return selected; +} + +int +e_table_header_total_width (ETableHeader *eth) +{ + int total, i; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_COLUMN (eth), 0); + + total = 0; + for (i = 0; i < eth->col_count; i++) + total += eth->columns [i]->width; + + return total; +} + +static void +eth_do_remove (ETableHeader *eth, int idx) +{ + memcpy (ð->columns [idx], ð->columns [idx+1], + sizeof (ETableCol *) * eth->col_count - idx); + eth->col_count--; +} + +void +e_table_header_move (ETableHeader *eth, int source_index, int target_index) +{ + ETableCol *old; + + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (source_index >= 0); + g_return_if_fail (target_index >= 0); + g_return_if_fail (source_index < eth->col_count); + g_return_if_fail (target_index < eth->col_count); + + old = eth->columns [source_index]; + eth_do_remove (eth, source_index); + eth_do_insert (eth, target_index, old); + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +void +e_table_header_remove (ETableHeader *eth, int idx) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (idx >= 0); + g_return_if_fail (idx < eth->col_count); + + eth_do_remove (eth, idx); + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +void +e_table_header_set_selection (ETableHeader *eth, gboolean allow_selection) +{ +} + +void +e_table_header_set_size (ETableHeader *eth, int idx, int size) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_COLUMN (eth)); + g_return_if_fail (idx >= 0); + g_return_if_fail (idx < eth->col_count); + g_return_if_fail (size > 0); + + eth->columns [idx]->width = size; + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE], idx); +} diff --git a/widgets/table/e-table-header.h b/widgets/table/e-table-header.h new file mode 100644 index 0000000000..d8e04ea8fd --- /dev/null +++ b/widgets/table/e-table-header.h @@ -0,0 +1,81 @@ +#ifndef _E_TABLE_COLUMN_H_ +#define _E_TABLE_COLUMN_H_ + +#include <gtk/gtkobject.h> +#include <gdk/gdk.h> +#include "e-table-col.h" + +typedef struct _ETableHeader ETableHeader; +typedef struct _ETableCol ETableCol; + +/* + * Rendering function for the column header + */ +typedef void (*ETableColRenderFn)( + ETableCol *etc, void *gnome_canvas_item, void *drawable, + int x, int y, int w, int h, void *data); + +/* + * Information about a single column + */ +struct _ETableCol { + const char *id; + int width; + ETableColRenderFn render; + void *render_data; + unsigned int selected:1; + int resizeable:1; + int min_size; +}; + +#define E_TABLE_HEADER_TYPE (e_table_header_get_type ()) +#define E_TABLE_HEADER(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_TYPE, ETableHeader)) +#define E_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_HEADER_TYPE, ETableHeaderClass)) +#define E_IS_TABLE_HEADER(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_TYPE)) +#define E_IS_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_TYPE)) + +/* + * A Columnar header. + */ +struct _ETableHeader { + GtkObject base; + + int col_count; + ETableCol **columns; + gboolean selectable; +}; + +typedef struct { + GtkObjectClass parent_class; + + void (*structure_change) (ETableHeader *etc); + void (*dimension_change) (ETableHeader *etc, int col); +} ETableHeaderClass; + +GtkType e_table_header_get_type (void); +ETableHeader *e_table_header_new (void); + +void e_table_header_add_column (ETableHeader *etc, + ETableCol *tc, int pos); +ETableCol * e_table_header_get_column (ETableHeader *etc, + int column); +int e_table_header_count (ETableHeader *etc); +int e_table_header_index (ETableHeader *etc, + const char *identifier); +int e_table_header_get_index_at (ETableHeader *etc, + int x_offset); +ETableCol **e_table_header_get_columns (ETableHeader *etc); +gboolean e_table_header_selection_ok (ETableHeader *etc); +int e_table_header_get_selected (ETableHeader *etc); +int e_table_header_total_width (ETableHeader *etc); +void e_table_header_move (ETableHeader *etc, + int source_index, + int target_index); +void e_table_header_remove (ETableHeader *etc, int idx); +void e_table_header_set_size (ETableHeader *etc, int idx, int size); +void e_table_header_set_selection (ETableHeader *etc, + gboolean allow_selection); + +GList *e_table_header_get_selected_indexes(ETableHeader *etc); + +#endif /* _E_TABLE_HEADER_H_ */ diff --git a/widgets/table/e-table-model.c b/widgets/table/e-table-model.c index 23782e52c9..868664cf08 100644 --- a/widgets/table/e-table-model.c +++ b/widgets/table/e-table-model.c @@ -40,7 +40,7 @@ e_table_model_value_at (ETableModel *etable, int col, int 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); + return ETM_CLASS (etable)->set_value_at (etable, col, row); } gboolean @@ -55,39 +55,6 @@ 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) { @@ -95,10 +62,6 @@ e_table_model_destroy (GtkObject *object) 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); } @@ -137,9 +100,9 @@ e_table_model_get_type (void) int e_table_model_height (ETableModel *etable) { - int rows; - int size; - g_return_val_if_fail (etable != NULL); + int rows, size, i; + + g_return_val_if_fail (etable != NULL, 0); rows = e_table_model_row_count (etable); size = 0; diff --git a/widgets/table/e-table-simple.c b/widgets/table/e-table-simple.c index b586712942..e52a9498f8 100644 --- a/widgets/table/e-table-simple.c +++ b/widgets/table/e-table-simple.c @@ -17,7 +17,7 @@ simple_column_count (ETableModel *etm) { ETableSimple *simple = (ETableSimple *)etm; - return simple->col_count (etm) + return simple->col_count (etm, simple->data); } static const char * @@ -25,7 +25,7 @@ simple_column_name (ETableModel *etm, int col) { ETableSimple *simple = (ETableSimple *)etm; - return simple->col_name (etm, col); + return simple->col_name (etm, col, simple->data); } static int @@ -33,23 +33,23 @@ simple_row_count (ETableModel *etm) { ETableSimple *simple = (ETableSimple *)etm; - return simple->row_count (etm); + return simple->row_count (etm, simple->data); } -static void +static void * simple_value_at (ETableModel *etm, int col, int row) { ETableSimple *simple = (ETableSimple *)etm; - return simple->value_at (etm, col, row); + return simple->value_at (etm, col, row, simple->data); } static void -simple_set_value_at (ETableModel *etm, int col, int row, void *data) +simple_set_value_at (ETableModel *etm, int col, int row) { ETableSimple *simple = (ETableSimple *)etm; - return simple->set_value_at (etm, col, row, data); + simple->set_value_at (etm, col, row, simple->data); } static gboolean @@ -57,20 +57,20 @@ simple_is_cell_editable (ETableModel *etm, int col, int row) { ETableSimple *simple = (ETableSimple *)etm; - return simple->is_cell_editable (etm, col, row, data); + return simple->is_cell_editable (etm, col, row, simple->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; + ETableModelClass *model_class = (ETableModelClass *) object_class; + + model_class->column_count = simple_column_count; + model_class->column_name = simple_column_name; + model_class->row_count = simple_row_count; + model_class->value_at = simple_value_at; + model_class->set_value_at = simple_set_value_at; + model_class->is_cell_editable = simple_is_cell_editable; } GtkType @@ -96,7 +96,7 @@ e_table_simple_get_type (void) return type; } -ETable * +ETableModel * e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleColumnNameFn col_name, ETableSimpleRowCountFn row_count, @@ -116,5 +116,5 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count, et->set_value_at = set_value_at; et->is_cell_editable = is_cell_editable; - return (ETable *) et; + return (ETableModel *) et; } diff --git a/widgets/table/e-table-simple.h b/widgets/table/e-table-simple.h index b5c549a440..fc69ce19d0 100644 --- a/widgets/table/e-table-simple.h +++ b/widgets/table/e-table-simple.h @@ -3,13 +3,13 @@ #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 int (*ETableSimpleColumnCountFn) (ETableModel *etm, void *data); +typedef const char *(*ETableSimpleColumnNameFn) (ETableModel *etm, int col, void *data); +typedef int (*ETableSimpleRowCountFn) (ETableModel *etm, void *data); +typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row, void *data); 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 gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row, void *data); +typedef int (*ETableSimpleRowHeightFn) (ETableModel *etm, int row, void *data); typedef struct { ETableModel parent; @@ -24,9 +24,13 @@ typedef struct { void *data; } ETableSimple; +typedef struct { + ETableModel parent_class; +} ETableSimpleClass; + GtkType e_table_simple_get_type (void); -ETable *e_table_simple_new (ETableSimpleColumnCountFn col_count, +ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleColumnNameFn col_name, ETableSimpleRowCountFn row_count, ETableSimpleValueAtFn value_at, diff --git a/widgets/table/e-table-tree.h b/widgets/table/e-table-tree.h new file mode 100644 index 0000000000..e7e125a6af --- /dev/null +++ b/widgets/table/e-table-tree.h @@ -0,0 +1,19 @@ +#ifndef _E_TABLE_TREE_H_ +#define _E_TABLE_TREE_H_ + +typedef struct { + char *title; + + union { + ETableModel *table; + GList *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); + +#endif /* _E_TABLE_TREE_H_ */ diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h new file mode 100644 index 0000000000..0847ddde6c --- /dev/null +++ b/widgets/table/e-table.h @@ -0,0 +1,6 @@ +#ifndef _E_TABLE_H_ +#define _E_TABLE_H_ + +GtkType e_table_get_type (void); +ETable * +#endif /* _E_TABLE_H_ */ |