diff options
Diffstat (limited to 'widgets')
65 files changed, 2196 insertions, 212 deletions
diff --git a/widgets/ChangeLog b/widgets/ChangeLog index e4c9cc9ab8..b5062dfedf 100644 --- a/widgets/ChangeLog +++ b/widgets/ChangeLog @@ -1,3 +1,36 @@ +1999-12-12 Miguel de Icaza <miguel@helixcode.com> + + * e-table-subset.c (etss_proxy_model_row_changed): Added model + proxying. + + * e-cell.h: Drop ETableModel from the ECell; + (realize): Now takes an ETableModel + + * e-cell-checkbox.c: Adapted to new class + changes; + * e-cell-toggle.c: ditto + + * e-table-subset.c (etss_row_count): Fix this guy. + +1999-12-11 Miguel de Icaza <miguel@helixcode.com> + + * e-table-item.c (eti_unrealize_cell_views): Null the cell views. + (eti_header_structure_changed): Only unrealize/realize if we were + realized before. + + * e-table-header.c (e_table_header_add_column): Allow -1 as an + insert position + +1999-12-11 Miguel de Icaza <miguel@helixcode.com> + + * e-table.c: Massive fixage. + + * test-table.c: Updates to test the mega widget. + +1999-12-10 Miguel de Icaza <miguel@helixcode.com> + + * e-table.c: New file, implements the mega widget. + 1999-12-09 Miguel de Icaza <miguel@gnu.org> * e-table-header.c (e_table_header_col_diff): fix this routine. diff --git a/widgets/Makefile.am b/widgets/Makefile.am index 677af55041..e59c03a18d 100644 --- a/widgets/Makefile.am +++ b/widgets/Makefile.am @@ -17,6 +17,8 @@ libevolutionwidgets_a_SOURCES = \ e-cell-toggle.h \ e-cursors.c \ e-cursors.h \ + e-table.c \ + e-table.h \ e-table-col.c \ e-table-col.h \ e-table-group.c \ @@ -32,7 +34,9 @@ libevolutionwidgets_a_SOURCES = \ e-table-simple.c \ e-table-simple.h \ e-table-sorted.c \ - e-table-sorted.h + e-table-sorted.h \ + e-table-subset.c \ + e-table-subset.h noinst_PROGRAMS = \ table-test diff --git a/widgets/ROADMAP.e-table b/widgets/ROADMAP.e-table index 08340f433c..4edacced86 100644 --- a/widgets/ROADMAP.e-table +++ b/widgets/ROADMAP.e-table @@ -11,6 +11,13 @@ The objects are rendered by various view objects. In the current code base, we use we use GnomeCanvasItems to do the rendering. One for each table and one for the headers. +* The main widget + +e-table.c, e-table.h: + + Implements a full widget. Uses various components described + below. Handles column display as well as grouping/nesting + * The Models All of them are GtkObjects. @@ -78,6 +85,14 @@ e-cell-text.c, e-cell-text.h implements text display: supports justification and font setting. Will add color in the future most likely +e-cell-toggle.c, e-cell-toggle.h + + A derivative of e-cell as well that support N-toggle values + using images. + +e-cell-check.c, e-cell-check.h + + An e-cell-toggle with two states only (for checkboxes). * The Filters diff --git a/widgets/TODO b/widgets/TODO index 20d491b4fa..29dbd454e5 100644 --- a/widgets/TODO +++ b/widgets/TODO @@ -18,3 +18,7 @@ mouse grabbing for scrolling * Make sure we can boot and shutdown with no memory leaks. * Run Insure on the thing. + +* Propagation + + * Row changes should be reflected in the subsets. diff --git a/widgets/e-cell-checkbox.c b/widgets/e-cell-checkbox.c index 73620b9ce4..6e4b597abf 100644 --- a/widgets/e-cell-checkbox.c +++ b/widgets/e-cell-checkbox.c @@ -34,11 +34,11 @@ e_cell_checkbox_class_init (GtkObjectClass *object_class) E_MAKE_TYPE(e_cell_checkbox, "ECellCheckbox", ECellCheckbox, e_cell_checkbox_class_init, NULL, PARENT_TYPE); ECell * -e_cell_checkbox_new (ETableModel *etm) +e_cell_checkbox_new (void) { ECellCheckbox *eccb = gtk_type_new (e_cell_checkbox_get_type ()); - e_cell_toggle_construct (E_CELL_TOGGLE (eccb), etm, 2, 2, checks); + e_cell_toggle_construct (E_CELL_TOGGLE (eccb), 2, 2, checks); return (ECell *) eccb; } diff --git a/widgets/e-cell-checkbox.h b/widgets/e-cell-checkbox.h index 6afca6bde2..969e4a5edc 100644 --- a/widgets/e-cell-checkbox.h +++ b/widgets/e-cell-checkbox.h @@ -18,7 +18,7 @@ typedef struct { } ECellCheckboxClass; GtkType e_cell_checkbox_get_type (void); -ECell *e_cell_checkbox_new (ETableModel *model); +ECell *e_cell_checkbox_new (void); #endif /* _E_CELL_CHECKBOX_H_ */ diff --git a/widgets/e-cell-text.c b/widgets/e-cell-text.c index 828be6cc29..79fe432326 100644 --- a/widgets/e-cell-text.c +++ b/widgets/e-cell-text.c @@ -13,6 +13,7 @@ #include <gtk/gtksignal.h> #include <gdk/gdkkeysyms.h> #include <libgnomeui/gnome-canvas.h> +#include <stdio.h> #include "e-cell-text.h" #include "e-util.h" #include "e-table-item.h" @@ -62,7 +63,7 @@ ect_accept_edits (ECellTextView *text_view) const char *text = gtk_entry_get_text (text_view->edit->entry); CellEdit *edit = text_view->edit; - e_table_model_set_value_at (text_view->eti->table_model, edit->model_col, edit->row, text); + e_table_model_set_value_at (text_view->cell_view.table_model, edit->model_col, edit->row, text); } /* @@ -100,7 +101,7 @@ ect_cancel_edit (ECellTextView *text_view) * ECell::realize method */ static ECellView * -ect_realize (ECell *ecell, void *view) +ect_realize (ECell *ecell, ETableModel *table_model, void *view) { ECellText *ect = E_CELL_TEXT (ecell); ECellTextView *text_view = g_new0 (ECellTextView, 1); @@ -108,6 +109,8 @@ ect_realize (ECell *ecell, void *view) GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; text_view->cell_view.ecell = ecell; + text_view->cell_view.table_model = table_model; + text_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window); if (ect->font_name){ GdkFont *f; @@ -123,7 +126,7 @@ ect_realize (ECell *ecell, void *view) text_view->eti = eti; text_view->canvas = canvas; - + return (ECellView *)text_view; } @@ -156,7 +159,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, ECellTextView *text_view = (ECellTextView *) ecell_view; GtkWidget *w = GTK_WIDGET (text_view->canvas); GdkRectangle rect; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); + const char *str = e_table_model_value_at (ecell_view->table_model, model_col, row); GdkFont *font = text_view->font; const int height = font->ascent + font->descent; int xoff; @@ -389,7 +392,7 @@ static void * ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); + const char *str = e_table_model_value_at (ecell_view->table_model, model_col, row); CellEdit *edit; edit = g_new (CellEdit, 1); @@ -476,7 +479,6 @@ e_cell_text_new (ETableModel *etm, const char *fontname, GtkJustification justif ect->font_name = g_strdup (fontname); ect->justify = justify; - E_CELL (ect)->table_model = etm; return (ECell *) ect; } diff --git a/widgets/e-cell-toggle.c b/widgets/e-cell-toggle.c index ec6fa38a38..dbe5fe5cbd 100644 --- a/widgets/e-cell-toggle.c +++ b/widgets/e-cell-toggle.c @@ -38,17 +38,18 @@ etog_queue_redraw (ECellToggleView *text_view, int view_col, int view_row) * ECell::realize method */ static ECellView * -etog_realize (ECell *ecell, void *view) +etog_realize (ECell *ecell, ETableModel *table_model, void *view) { ECellToggleView *toggle_view = g_new0 (ECellToggleView, 1); ETableItem *eti = E_TABLE_ITEM (view); GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; toggle_view->cell_view.ecell = ecell; + toggle_view->cell_view.table_model = table_model; toggle_view->eti = eti; toggle_view->canvas = canvas; toggle_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window); - + return (ECellView *) toggle_view; } @@ -80,7 +81,7 @@ etog_draw (ECellView *ecell_view, GdkDrawable *drawable, ArtPixBuf *art; int x, y, width, height; const int value = GPOINTER_TO_INT ( - e_table_model_value_at (ecell_view->ecell->table_model, model_col, row)); + e_table_model_value_at (ecell_view->table_model, model_col, row)); if (value >= toggle->n_states){ g_warning ("Value from the table model is %d, the states we support are [0..%d)\n", @@ -172,7 +173,8 @@ etog_set_value (ECellToggleView *toggle_view, int model_col, int view_col, int r if (value >= toggle->n_states) value = 0; - e_table_model_set_value_at (ecell->table_model, model_col, row, GINT_TO_POINTER (value)); + e_table_model_set_value_at (toggle_view->cell_view.table_model, + model_col, row, GINT_TO_POINTER (value)); etog_queue_redraw (toggle_view, view_col, row); } @@ -183,7 +185,7 @@ static gint etog_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { ECellToggleView *toggle_view = (ECellToggleView *) ecell_view; - void *_value = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); + void *_value = e_table_model_value_at (ecell_view->table_model, model_col, row); const int value = GPOINTER_TO_INT (_value); switch (event->type){ @@ -248,13 +250,11 @@ e_cell_toggle_class_init (GtkObjectClass *object_class) E_MAKE_TYPE(e_cell_toggle, "ECellToggle", ECellToggle, e_cell_toggle_class_init, NULL, PARENT_TYPE); void -e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_states, GdkPixbuf **images) +e_cell_toggle_construct (ECellToggle *etog, int border, int n_states, GdkPixbuf **images) { int max_height = 0; int i; - E_CELL (etog)->table_model = etm; - etog->border = border; etog->n_states = n_states; @@ -272,11 +272,13 @@ e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_ } ECell * -e_cell_toggle_new (ETableModel *etm, int border, int n_states, GdkPixbuf **images) +e_cell_toggle_new (int border, int n_states, GdkPixbuf **images) { ECellToggle *etog = gtk_type_new (e_cell_toggle_get_type ()); - e_cell_toggle_construct (etog, etm, border, n_states, images); + e_cell_toggle_construct (etog, border, n_states, images); return (ECell *) etog; } + + diff --git a/widgets/e-cell-toggle.h b/widgets/e-cell-toggle.h index 2a5b6adc18..d5773b454a 100644 --- a/widgets/e-cell-toggle.h +++ b/widgets/e-cell-toggle.h @@ -26,11 +26,9 @@ typedef struct { } ECellToggleClass; GtkType e_cell_toggle_get_type (void); -ECell *e_cell_toggle_new (ETableModel *model, int border, - int n_states, - GdkPixbuf **images); -void e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, - int border, int n_states, GdkPixbuf **images); +ECell *e_cell_toggle_new (int border, int n_states, GdkPixbuf **images); +void e_cell_toggle_construct (ECellToggle *etog, int border, + int n_states, GdkPixbuf **images); #endif /* _E_CELL_TOGGLE_H_ */ diff --git a/widgets/e-cell.c b/widgets/e-cell.c index a4a03655dc..4495bbb1a7 100644 --- a/widgets/e-cell.c +++ b/widgets/e-cell.c @@ -13,7 +13,7 @@ #define PARENT_TYPE gtk_object_get_type() static ECellView * -ec_realize (ECell *e_cell, void *view) +ec_realize (ECell *e_cell, ETableModel *table_model, void *view) { return NULL; } @@ -110,10 +110,10 @@ e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_co } ECellView * -e_cell_realize (ECell *ecell, void *view) +e_cell_realize (ECell *ecell, ETableModel *table_model, void *view) { return E_CELL_CLASS (GTK_OBJECT (ecell)->klass)->realize ( - ecell, view); + ecell, table_model, view); } void diff --git a/widgets/e-cell.h b/widgets/e-cell.h index f72f97e8dd..23173a586c 100644 --- a/widgets/e-cell.h +++ b/widgets/e-cell.h @@ -15,11 +15,12 @@ typedef struct _ECellView ECellView; struct _ECell { GtkObject object; - ETableModel *table_model; }; struct _ECellView { ECell *ecell; + ETableModel *table_model; + gint focus_x1, focus_y1, focus_x2, focus_y2; gint focus_col, focus_row; }; @@ -29,7 +30,7 @@ struct _ECellView { typedef struct { GtkObjectClass parent_class; - ECellView *(*realize) (ECell *ecell, void *view); + ECellView *(*realize) (ECell *ecell, ETableModel *table_model, void *view); void (*unrealize) (ECellView *e_cell_view); void (*draw) (ECellView *ecell_view, GdkDrawable *drawable, int model_col, int view_col, int row, @@ -46,7 +47,7 @@ typedef struct { GtkType e_cell_get_type (void); void e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row); -ECellView *e_cell_realize (ECell *ecell, void *view); +ECellView *e_cell_realize (ECell *ecell, ETableModel *table_model, void *view); void e_cell_unrealize (ECellView *ecell_view); void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr, int model_col, int view_col, int row, gboolean selected, diff --git a/widgets/e-table-header-item.c b/widgets/e-table-header-item.c index 0b5be9b84a..7cea9ae7a0 100644 --- a/widgets/e-table-header-item.c +++ b/widgets/e-table-header-item.c @@ -334,8 +334,6 @@ ethi_drag_motion (GtkObject *canvas, GdkDragContext *context, static void ethi_drag_end (GtkWidget *canvas, GdkDragContext *context, ETableHeaderItem *ethi) { - printf ("Ending\n"); - ethi_remove_drop_marker (ethi); ethi_remove_destroy_marker (ethi); ethi->drag_col = -1; diff --git a/widgets/e-table-header.c b/widgets/e-table-header.c index 375fd34c5d..32078d9a78 100644 --- a/widgets/e-table-header.c +++ b/widgets/e-table-header.c @@ -126,7 +126,7 @@ e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos) g_return_if_fail (E_IS_TABLE_HEADER (eth)); g_return_if_fail (tc != NULL); g_return_if_fail (E_IS_TABLE_COL (tc)); - g_return_if_fail (pos >= 0 && pos <= eth->col_count); + g_return_if_fail (pos >= -1 && pos <= eth->col_count); if (pos == -1) pos = eth->col_count; diff --git a/widgets/e-table-item.c b/widgets/e-table-item.c index bdeda14a7b..d0a0ad8cba 100644 --- a/widgets/e-table-item.c +++ b/widgets/e-table-item.c @@ -73,7 +73,7 @@ eti_realize_cell_views (ETableItem *eti) for (i = 0; i < eti->n_cells; i++){ ETableCol *col = e_table_header_get_column (eti->header, i); - eti->cell_views [i] = e_cell_realize (col->ecell, eti); + eti->cell_views [i] = e_cell_realize (col->ecell, eti->table_model, eti); } } @@ -91,6 +91,7 @@ eti_unrealize_cell_views (ETableItem *eti) eti->cell_views [i] = NULL; } g_free (eti->cell_views); + eti->cell_views = NULL; eti->n_cells = 0; } @@ -368,8 +369,12 @@ eti_header_structure_changed (ETableHeader *eth, ETableItem *eti) eti->cols = e_table_header_count (eti->header); eti->width = e_table_header_total_width (eti->header); - eti_unrealize_cell_views (eti); - eti_realize_cell_views (eti); + + if (eti->cell_views){ + eti_unrealize_cell_views (eti); + eti_realize_cell_views (eti); + } + eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); eti_request_redraw (eti); diff --git a/widgets/e-table-subset.c b/widgets/e-table-subset.c index 41763d309b..88f5c18c85 100644 --- a/widgets/e-table-subset.c +++ b/widgets/e-table-subset.c @@ -7,6 +7,8 @@ * (C) 1999 Helix Code, Inc. */ #include <config.h> +#include <stdlib.h> +#include <gtk/gtksignal.h> #include "e-util.h" #include "e-table-subset.h" @@ -36,20 +38,12 @@ etss_column_count (ETableModel *etm) return e_table_model_column_count (etss->source); } -static const char * -etss_column_name (ETableModel *etm, int col) -{ - ETableSubset *etss = (ETableSubset *)etm; - - return e_table_model_column_name (etss->source, col); -} - static int etss_row_count (ETableModel *etm) { ETableSubset *etss = (ETableSubset *)etm; - return e_table_model_row_count (etss->source); + return etss->n_map; } static void * @@ -61,7 +55,7 @@ etss_value_at (ETableModel *etm, int col, int row) } static void -etss_set_value_at (ETableModel *etm, int col, int row, void *val) +etss_set_value_at (ETableModel *etm, int col, int row, const void *val) { ETableSubset *etss = (ETableSubset *)etm; @@ -76,14 +70,6 @@ etss_is_cell_editable (ETableModel *etm, int col, int row) return e_table_model_is_cell_editable (etss->source, col, etss->map_table [row]); } -static int -etss_row_height (ETableModel *etm, int row) -{ - ETableSubset *etss = (ETableSubset *)etm; - - return e_table_model_row_height (etss->source, etss->map_table [row]); -} - static void etss_class_init (GtkObjectClass *klass) { @@ -94,25 +80,58 @@ etss_class_init (GtkObjectClass *klass) klass->destroy = etss_destroy; table_class->column_count = etss_column_count; - table_class->column_name = etss_column_name; table_class->row_count = etss_row_count; table_class->value_at = etss_value_at; table_class->set_value_at = etss_set_value_at; table_class->is_cell_editable = etss_is_cell_editable; - table_class->row_height = etss_row_height; - } E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, PARENT_TYPE); +static void +etss_proxy_model_changed (ETableModel *etm, ETableSubset *etss) +{ + e_table_model_changed (E_TABLE_MODEL (etss)); +} + +static void +etss_proxy_model_row_changed (ETableModel *etm, int row, ETableSubset *etss) +{ + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_row_changed (E_TABLE_MODEL (etss), i); + return; + } + } +} + +static void +etss_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSubset *etss) +{ + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_cell_changed (E_TABLE_MODEL (etss), col, i); + return; + } + } +} + ETableModel * e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) { unsigned int *buffer; int i; - buffer = (unsigned int *) malloc (sizeof (unsigned int *) * nvals); - if (buffer = NULL) + buffer = (unsigned int *) malloc (sizeof (unsigned int) * nvals); + if (buffer == NULL) return NULL; etss->map_table = buffer; etss->n_map = nvals; @@ -123,6 +142,14 @@ e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) for (i = 0; i < nvals; i++) etss->map_table [i] = i; + gtk_signal_connect (GTK_OBJECT (source), "model_changed", + GTK_SIGNAL_FUNC (etss_proxy_model_changed), etss); + gtk_signal_connect (GTK_OBJECT (source), "model_row_changed", + GTK_SIGNAL_FUNC (etss_proxy_model_row_changed), etss); + gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed", + GTK_SIGNAL_FUNC (etss_proxy_model_cell_changed), etss); + + return E_TABLE_MODEL (etss); } ETableModel * @@ -147,5 +174,5 @@ e_table_subset_get_toplevel (ETableSubset *table) if (E_IS_TABLE_SUBSET (table->source)) return e_table_subset_get_toplevel (E_TABLE_SUBSET (table->source)); else - return table->subset; + return table->source; } diff --git a/widgets/e-table-subset.h b/widgets/e-table-subset.h index 66d11e9658..314f28aea6 100644 --- a/widgets/e-table-subset.h +++ b/widgets/e-table-subset.h @@ -26,6 +26,7 @@ GtkType e_table_subset_get_type (void); ETableModel *e_table_subset_new (ETableModel *etm, int n_vals); ETableModel *e_table_subset_construct (ETableSubset *ets, ETableModel *source, int nvals); -ETableModel *e_table_subset_get_toplevel (ETableModel *table_model); +ETableModel *e_table_subset_get_toplevel (ETableSubset *table_model); #endif /* _E_TABLE_SUBSET_H_ */ + diff --git a/widgets/e-table.c b/widgets/e-table.c index 3b13e87d6b..f9a41a38fc 100644 --- a/widgets/e-table.c +++ b/widgets/e-table.c @@ -7,16 +7,491 @@ * Copyright 1999, Helix Code, Inc */ #include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <alloca.h> +#include <stdio.h> #include <libgnomeui/gnome-canvas.h> +#include <gtk/gtksignal.h> #include "e-table.h" #include "e-util.h" +#include "e-table-header-item.h" +#include "e-table-subset.h" +#include "e-table-item.h" -#define PARENT_OBJECT_TYPE gnome_canvas_get_type () +#define COLUMN_HEADER_HEIGHT 16 +#define TITLE_HEIGHT 16 +#define GROUP_INDENT 10 -E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, NULL, PARENT_TYPE); +#define PARENT_TYPE gtk_table_get_type () -ETable * -e_table_new (ETableHeader *eth, ETableModel *etm) +static GtkObjectClass *e_table_parent_class; + +typedef struct { + ETableModel *table; + GnomeCanvasItem *table_item; + GnomeCanvasItem *rect; +} Leaf; + +typedef struct { +} Node; + + +static void +et_destroy (GtkObject *object) +{ + ETable *et = E_TABLE (object); + + gtk_object_unref (GTK_OBJECT (et->model)); + gtk_object_unref (GTK_OBJECT (et->full_header)); + gtk_object_unref (GTK_OBJECT (et->header)); + + g_free (et->group_spec); + + (*e_table_parent_class->destroy)(object); +} + +static void +e_table_init (GtkObject *object) +{ + ETable *e_table = E_TABLE (object); + + e_table->draw_grid = 1; + e_table->draw_focus = 1; + e_table->spreadsheet = 1; +} + +static ETableHeader * +e_table_make_header (ETable *e_table, ETableHeader *full_header, const char *cols) +{ + ETableHeader *nh; + char *copy = alloca (strlen (cols) + 1); + char *p, *state; + const int max_cols = e_table_header_count (full_header); + + nh = e_table_header_new (); + strcpy (copy, cols); + while ((p = strtok_r (copy, ",", &state)) != NULL){ + int col = atoi (p); + + copy = NULL; + if (col >= max_cols) + continue; + + e_table_header_add_column (nh, e_table_header_get_column (full_header, col), -1); + } + + return nh; +} + +static void +e_table_setup_header (ETable *e_table) +{ + e_table->header_canvas = GNOME_CANVAS (gnome_canvas_new ()); + + gtk_widget_show (GTK_WIDGET (e_table->header_canvas)); + + e_table->header_item = gnome_canvas_item_new ( + gnome_canvas_root (e_table->header_canvas), + e_table_header_item_get_type (), + "ETableHeader", e_table->header, + "x", 0, + "y", 0, + NULL); + + gtk_widget_set_usize (GTK_WIDGET (e_table->header_canvas), -1, COLUMN_HEADER_HEIGHT); + g_warning ("Aqui"); + e_table->header_canvas = 0; + + gtk_table_attach ( + GTK_TABLE (e_table), GTK_WIDGET (e_table->header_canvas), + 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0); + +} + +static Leaf * +e_table_create_leaf (ETable *e_table, int x_off, int y_off, ETableModel *etm) +{ + Leaf *leaf; + int height; + + leaf = g_new (Leaf, 1); + leaf->table = etm; + + leaf->table_item = gnome_canvas_item_new ( + gnome_canvas_root (e_table->table_canvas), + e_table_item_get_type (), + "ETableHeader", e_table->header, + "ETableModel", etm, + "x", x_off + GROUP_INDENT, + "y", y_off + TITLE_HEIGHT, + "drawgrid", e_table->draw_grid, + "drawfocus", e_table->draw_focus, + "spreadsheet", e_table->spreadsheet, + NULL); + + height = E_TABLE_ITEM (leaf->table_item)->height; + + leaf->rect = gnome_canvas_item_new ( + gnome_canvas_root (e_table->table_canvas), + gnome_canvas_rect_get_type (), + "x1", (double) x_off, + "y1", (double) y_off, + "x2", (double) x_off + e_table->gen_header_width + GROUP_INDENT, + "y2", (double) y_off + TITLE_HEIGHT + height, + "fill_color", "gray", + "outline_color", "gray20", + NULL); + gnome_canvas_item_lower (leaf->rect, 1); + + return leaf; +} + +typedef struct { + void *value; + GArray *array; +} group_key_t; + +static GArray * +e_table_create_groups (ETableModel *etm, int key_col, GCompareFunc comp) +{ + GArray *groups; + const int rows = e_table_model_row_count (etm); + int row, i; + + groups = g_array_new (FALSE, FALSE, sizeof (group_key_t)); + + for (row = 0; row < rows; row++){ + void *val = e_table_model_value_at (etm, key_col, row); + const int n_groups = groups->len; + + /* + * Should replace this with a bsearch later + */ + for (i = 0; i < n_groups; i++){ + group_key_t *g = &g_array_index (groups, group_key_t, i); + + if ((*comp) (g->value, val)){ + g_array_append_val (g->array, row); + break; + } + } + if (i != n_groups) + continue; + + /* + * We need to create a new group + */ + { + group_key_t gk; + + gk.value = val; + gk.array = g_array_new (FALSE, FALSE, sizeof (int)); + + g_array_append_val (gk.array, row); + g_array_append_val (groups, gk); + } + } + + return groups; +} + +static void +e_table_destroy_groups (GArray *groups) +{ + const int n = groups->len; + int i; + + for (i = 0; i < n; i++){ + group_key_t *g = &g_array_index (groups, group_key_t, i); + + g_array_free (g->array, TRUE); + } + g_array_free (groups, TRUE); +} + +static ETableModel ** +e_table_make_subtables (ETableModel *model, GArray *groups) +{ + const int n_groups = groups->len; + ETableModel **tables; + int i; + + tables = g_new (ETableModel *, n_groups+1); + + for (i = 0; i < n_groups; i++){ + group_key_t *g = &g_array_index (groups, group_key_t, i); + const int sub_size = g->array->len; + ETableSubset *ss; + int j; + + printf ("Creating subset of %d elements\n", sub_size); + tables [i] = e_table_subset_new (model, sub_size); + ss = E_TABLE_SUBSET (tables [i]); + + for (j = 0; j < sub_size; j++) + ss->map_table [j] = g_array_index (g->array, int, j); + } + tables [i] = NULL; + + return (ETableModel **) tables; +} + +static int +leaf_height (Leaf *leaf) +{ + return E_TABLE_ITEM (leaf->table_item)->height + TITLE_HEIGHT; +} + +static int +e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, + GnomeCanvasGroup *root, int x_off, int y_off, + int *groups_list) +{ + GArray *groups; + ETableModel **tables; + int key_col; + int height, i; + GCompareFunc comp; + + if (groups_list) + key_col = *groups_list; + else + key_col = -1; + + if (key_col == -1){ + Leaf *leaf; + + printf ("Leaf->with %d rows\n", e_table_model_row_count (model)); + leaf = e_table_create_leaf (e_table, x_off, y_off, model); + + { + static int warn_shown; + + if (!warn_shown){ + g_warning ("Leak"); + warn_shown = 1; + } + } + return leaf_height (leaf); + } + + /* + * Create groups + */ + comp = e_table_header_get_column (header, key_col)->compare; + groups = e_table_create_groups (model, key_col, comp); + tables = e_table_make_subtables (e_table->model, groups); + e_table_destroy_groups (groups); + + height = 0; + for (i = 0; tables [i] != NULL; i++){ + printf ("Creating->%d with %d rows\n", i, e_table_model_row_count (tables [i])); + height += e_table_create_nodes ( + e_table, tables [i], header, root, + x_off + 20, + y_off + height, &groups_list [1]); + } + + return height; +} + +static int * +group_spec_to_desc (const char *group_spec) { + int a_size = 10; + int *elements; + char *p, *copy, *follow; + int n_elements = 0; + + if (group_spec == NULL) + return NULL; + + elements = g_new (int, a_size); + copy = alloca (strlen (group_spec) + 1); + strcpy (copy, group_spec); + + while ((p = strtok_r (copy, ",", &follow)) != NULL){ + elements [n_elements] = atoi (p); + ++n_elements; + if (n_elements+1 == a_size){ + int *new_e; + + n_elements += 10; + new_e = g_renew (int, elements, n_elements); + if (new_e == NULL){ + g_free (elements); + return NULL; + } + elements = new_e; + } + copy = NULL; + } + + /* Tag end */ + elements [n_elements] = -1; + + return elements; +} + +/* + * The ETableCanvas object is just used to enable us to + * hook up to the realize/unrealize phases of the canvas + * initialization (as laying out the subtables requires us to + * know the actual size of the subtables we are inserting + */ + +#define E_TABLE_CANVAS_PARENT_TYPE gnome_canvas_get_type () + +typedef struct { + GnomeCanvas base; + + ETable *e_table; +} ETableCanvas; + +typedef struct { + GnomeCanvasClass base_class; +} ETableCanvasClass; + +static GnomeCanvasClass *e_table_canvas_parent_class; + +static void +e_table_canvas_realize (GtkWidget *widget) +{ + ETableCanvas *e_table_canvas = (ETableCanvas *) widget; + ETable *e_table = e_table_canvas->e_table; + int *groups; + int height; + + GTK_WIDGET_CLASS (e_table_canvas_parent_class)->realize (widget); + + groups = group_spec_to_desc (e_table->group_spec); + + e_table->root = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (e_table->table_canvas->root), + gnome_canvas_group_get_type (), + "x", 0.0, + "y", 0.0, + NULL); + + e_table->gen_header_width = e_table_header_total_width (e_table->header); + + height = e_table_create_nodes ( + e_table, e_table->model, + e_table->header, GNOME_CANVAS_GROUP (e_table->root), 0, 0, groups); + + { + static int warn_shown; + + if (!warn_shown){ + g_warning ("Precompute the width, and update on model changes"); + warn_shown = 1; + } + } + + gnome_canvas_set_scroll_region ( + GNOME_CANVAS (e_table_canvas), + 0, 0, + e_table_header_total_width (e_table->header) + 200, + height); + + if (groups) + g_free (groups); +} + +static void +e_table_canvas_unrealize (GtkWidget *widget) +{ + ETableCanvas *e_table_canvas = (ETableCanvas *) widget; + ETable *e_table = e_table_canvas->e_table; + + gtk_object_destroy (GTK_OBJECT (e_table->root)); + e_table->root = NULL; + + GTK_WIDGET_CLASS (e_table_canvas_parent_class)->unrealize (widget); +} + +static void +e_table_canvas_class_init (GtkObjectClass *object_class) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass *) object_class; + + widget_class->realize = e_table_canvas_realize; + widget_class->unrealize = e_table_canvas_unrealize; + + e_table_canvas_parent_class = gtk_type_class (E_TABLE_CANVAS_PARENT_TYPE); +} + +GtkType e_table_canvas_get_type (void); + +E_MAKE_TYPE (e_table_canvas, "ETableCanvas", ETableCanvas, e_table_canvas_class_init, + NULL, E_TABLE_CANVAS_PARENT_TYPE); + +static GnomeCanvas * +e_table_canvas_new (ETable *e_table) +{ + ETableCanvas *e_table_canvas; + + e_table_canvas = gtk_type_new (e_table_canvas_get_type ()); + e_table_canvas->e_table = e_table; + + return GNOME_CANVAS (e_table_canvas); +} + +static void +e_table_setup_table (ETable *e_table) +{ + e_table->table_canvas = e_table_canvas_new (e_table); + + gtk_widget_show (GTK_WIDGET (e_table->table_canvas)); + gtk_table_attach ( + GTK_TABLE (e_table), GTK_WIDGET (e_table->table_canvas), + 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); +} + +void +e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, + const char *cols_spec, const char *group_spec) +{ + GTK_TABLE (e_table)->homogeneous = FALSE; + + gtk_table_resize (GTK_TABLE (e_table), 1, 2); + + e_table->full_header = full_header; + gtk_object_ref (GTK_OBJECT (full_header)); + + e_table->model = etm; + gtk_object_ref (GTK_OBJECT (etm)); + + e_table->header = e_table_make_header (e_table, full_header, cols_spec); + + e_table_setup_header (e_table); + e_table_setup_table (e_table); + + e_table->group_spec = g_strdup (group_spec); + } +GtkWidget * +e_table_new (ETableHeader *full_header, ETableModel *etm, const char *cols_spec, const char *group_spec) +{ + ETable *e_table; + + e_table = gtk_type_new (e_table_get_type ()); + + e_table_construct (e_table, full_header, etm, cols_spec, group_spec); + + return (GtkWidget *) e_table; +} + +static void +e_table_class_init (GtkObjectClass *object_class) +{ + e_table_parent_class = gtk_type_class (PARENT_TYPE); + + object_class->destroy = et_destroy; +} + +E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, e_table_init, PARENT_TYPE); + diff --git a/widgets/e-table.h b/widgets/e-table.h index 0847ddde6c..eb089781b9 100644 --- a/widgets/e-table.h +++ b/widgets/e-table.h @@ -1,6 +1,53 @@ #ifndef _E_TABLE_H_ #define _E_TABLE_H_ -GtkType e_table_get_type (void); -ETable * +#include <libgnomeui/gnome-canvas.h> +#include <gtk/gtktable.h> +#include "e-table-model.h" +#include "e-table-header.h" + +BEGIN_GNOME_DECLS + +#define E_TABLE_TYPE (e_table_get_type ()) +#define E_TABLE(o) (GTK_CHECK_CAST ((o), E_TABLE_TYPE, ETable)) +#define E_TABLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_TYPE, ETableClass)) +#define E_IS_TABLE(o) (GTK_CHECK_TYPE ((o), E_TABLE_TYPE)) +#define E_IS_TABLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_TYPE)) + +typedef struct { + GtkTable parent; + + ETableModel *model; + + ETableHeader *full_header, *header; + + GnomeCanvas *header_canvas, *table_canvas; + + GnomeCanvasItem *header_item, *root; + + guint draw_grid:1; + guint draw_focus:1; + guint spreadsheet:1; + + char *group_spec; + + /* + * Used during table generation + */ + int gen_header_width; +} ETable; + +typedef struct { + GtkTableClass parent_class; +} ETableClass; + +GtkType e_table_get_type (void); +void e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, + const char *cols_spec, const char *group_spec); +GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm, + const char *cols_spec, const char *group_spec); + + +END_GNOME_DECLS + #endif /* _E_TABLE_H_ */ diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog index e4c9cc9ab8..b5062dfedf 100644 --- a/widgets/e-table/ChangeLog +++ b/widgets/e-table/ChangeLog @@ -1,3 +1,36 @@ +1999-12-12 Miguel de Icaza <miguel@helixcode.com> + + * e-table-subset.c (etss_proxy_model_row_changed): Added model + proxying. + + * e-cell.h: Drop ETableModel from the ECell; + (realize): Now takes an ETableModel + + * e-cell-checkbox.c: Adapted to new class + changes; + * e-cell-toggle.c: ditto + + * e-table-subset.c (etss_row_count): Fix this guy. + +1999-12-11 Miguel de Icaza <miguel@helixcode.com> + + * e-table-item.c (eti_unrealize_cell_views): Null the cell views. + (eti_header_structure_changed): Only unrealize/realize if we were + realized before. + + * e-table-header.c (e_table_header_add_column): Allow -1 as an + insert position + +1999-12-11 Miguel de Icaza <miguel@helixcode.com> + + * e-table.c: Massive fixage. + + * test-table.c: Updates to test the mega widget. + +1999-12-10 Miguel de Icaza <miguel@helixcode.com> + + * e-table.c: New file, implements the mega widget. + 1999-12-09 Miguel de Icaza <miguel@gnu.org> * e-table-header.c (e_table_header_col_diff): fix this routine. diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am index 677af55041..e59c03a18d 100644 --- a/widgets/e-table/Makefile.am +++ b/widgets/e-table/Makefile.am @@ -17,6 +17,8 @@ libevolutionwidgets_a_SOURCES = \ e-cell-toggle.h \ e-cursors.c \ e-cursors.h \ + e-table.c \ + e-table.h \ e-table-col.c \ e-table-col.h \ e-table-group.c \ @@ -32,7 +34,9 @@ libevolutionwidgets_a_SOURCES = \ e-table-simple.c \ e-table-simple.h \ e-table-sorted.c \ - e-table-sorted.h + e-table-sorted.h \ + e-table-subset.c \ + e-table-subset.h noinst_PROGRAMS = \ table-test diff --git a/widgets/e-table/ROADMAP.e-table b/widgets/e-table/ROADMAP.e-table index 08340f433c..4edacced86 100644 --- a/widgets/e-table/ROADMAP.e-table +++ b/widgets/e-table/ROADMAP.e-table @@ -11,6 +11,13 @@ The objects are rendered by various view objects. In the current code base, we use we use GnomeCanvasItems to do the rendering. One for each table and one for the headers. +* The main widget + +e-table.c, e-table.h: + + Implements a full widget. Uses various components described + below. Handles column display as well as grouping/nesting + * The Models All of them are GtkObjects. @@ -78,6 +85,14 @@ e-cell-text.c, e-cell-text.h implements text display: supports justification and font setting. Will add color in the future most likely +e-cell-toggle.c, e-cell-toggle.h + + A derivative of e-cell as well that support N-toggle values + using images. + +e-cell-check.c, e-cell-check.h + + An e-cell-toggle with two states only (for checkboxes). * The Filters diff --git a/widgets/e-table/TODO b/widgets/e-table/TODO index 20d491b4fa..29dbd454e5 100644 --- a/widgets/e-table/TODO +++ b/widgets/e-table/TODO @@ -18,3 +18,7 @@ mouse grabbing for scrolling * Make sure we can boot and shutdown with no memory leaks. * Run Insure on the thing. + +* Propagation + + * Row changes should be reflected in the subsets. diff --git a/widgets/e-table/e-cell-checkbox.c b/widgets/e-table/e-cell-checkbox.c index 73620b9ce4..6e4b597abf 100644 --- a/widgets/e-table/e-cell-checkbox.c +++ b/widgets/e-table/e-cell-checkbox.c @@ -34,11 +34,11 @@ e_cell_checkbox_class_init (GtkObjectClass *object_class) E_MAKE_TYPE(e_cell_checkbox, "ECellCheckbox", ECellCheckbox, e_cell_checkbox_class_init, NULL, PARENT_TYPE); ECell * -e_cell_checkbox_new (ETableModel *etm) +e_cell_checkbox_new (void) { ECellCheckbox *eccb = gtk_type_new (e_cell_checkbox_get_type ()); - e_cell_toggle_construct (E_CELL_TOGGLE (eccb), etm, 2, 2, checks); + e_cell_toggle_construct (E_CELL_TOGGLE (eccb), 2, 2, checks); return (ECell *) eccb; } diff --git a/widgets/e-table/e-cell-checkbox.h b/widgets/e-table/e-cell-checkbox.h index 6afca6bde2..969e4a5edc 100644 --- a/widgets/e-table/e-cell-checkbox.h +++ b/widgets/e-table/e-cell-checkbox.h @@ -18,7 +18,7 @@ typedef struct { } ECellCheckboxClass; GtkType e_cell_checkbox_get_type (void); -ECell *e_cell_checkbox_new (ETableModel *model); +ECell *e_cell_checkbox_new (void); #endif /* _E_CELL_CHECKBOX_H_ */ diff --git a/widgets/e-table/e-cell-text.c b/widgets/e-table/e-cell-text.c index 828be6cc29..79fe432326 100644 --- a/widgets/e-table/e-cell-text.c +++ b/widgets/e-table/e-cell-text.c @@ -13,6 +13,7 @@ #include <gtk/gtksignal.h> #include <gdk/gdkkeysyms.h> #include <libgnomeui/gnome-canvas.h> +#include <stdio.h> #include "e-cell-text.h" #include "e-util.h" #include "e-table-item.h" @@ -62,7 +63,7 @@ ect_accept_edits (ECellTextView *text_view) const char *text = gtk_entry_get_text (text_view->edit->entry); CellEdit *edit = text_view->edit; - e_table_model_set_value_at (text_view->eti->table_model, edit->model_col, edit->row, text); + e_table_model_set_value_at (text_view->cell_view.table_model, edit->model_col, edit->row, text); } /* @@ -100,7 +101,7 @@ ect_cancel_edit (ECellTextView *text_view) * ECell::realize method */ static ECellView * -ect_realize (ECell *ecell, void *view) +ect_realize (ECell *ecell, ETableModel *table_model, void *view) { ECellText *ect = E_CELL_TEXT (ecell); ECellTextView *text_view = g_new0 (ECellTextView, 1); @@ -108,6 +109,8 @@ ect_realize (ECell *ecell, void *view) GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; text_view->cell_view.ecell = ecell; + text_view->cell_view.table_model = table_model; + text_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window); if (ect->font_name){ GdkFont *f; @@ -123,7 +126,7 @@ ect_realize (ECell *ecell, void *view) text_view->eti = eti; text_view->canvas = canvas; - + return (ECellView *)text_view; } @@ -156,7 +159,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, ECellTextView *text_view = (ECellTextView *) ecell_view; GtkWidget *w = GTK_WIDGET (text_view->canvas); GdkRectangle rect; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); + const char *str = e_table_model_value_at (ecell_view->table_model, model_col, row); GdkFont *font = text_view->font; const int height = font->ascent + font->descent; int xoff; @@ -389,7 +392,7 @@ static void * ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); + const char *str = e_table_model_value_at (ecell_view->table_model, model_col, row); CellEdit *edit; edit = g_new (CellEdit, 1); @@ -476,7 +479,6 @@ e_cell_text_new (ETableModel *etm, const char *fontname, GtkJustification justif ect->font_name = g_strdup (fontname); ect->justify = justify; - E_CELL (ect)->table_model = etm; return (ECell *) ect; } diff --git a/widgets/e-table/e-cell-toggle.c b/widgets/e-table/e-cell-toggle.c index ec6fa38a38..dbe5fe5cbd 100644 --- a/widgets/e-table/e-cell-toggle.c +++ b/widgets/e-table/e-cell-toggle.c @@ -38,17 +38,18 @@ etog_queue_redraw (ECellToggleView *text_view, int view_col, int view_row) * ECell::realize method */ static ECellView * -etog_realize (ECell *ecell, void *view) +etog_realize (ECell *ecell, ETableModel *table_model, void *view) { ECellToggleView *toggle_view = g_new0 (ECellToggleView, 1); ETableItem *eti = E_TABLE_ITEM (view); GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; toggle_view->cell_view.ecell = ecell; + toggle_view->cell_view.table_model = table_model; toggle_view->eti = eti; toggle_view->canvas = canvas; toggle_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window); - + return (ECellView *) toggle_view; } @@ -80,7 +81,7 @@ etog_draw (ECellView *ecell_view, GdkDrawable *drawable, ArtPixBuf *art; int x, y, width, height; const int value = GPOINTER_TO_INT ( - e_table_model_value_at (ecell_view->ecell->table_model, model_col, row)); + e_table_model_value_at (ecell_view->table_model, model_col, row)); if (value >= toggle->n_states){ g_warning ("Value from the table model is %d, the states we support are [0..%d)\n", @@ -172,7 +173,8 @@ etog_set_value (ECellToggleView *toggle_view, int model_col, int view_col, int r if (value >= toggle->n_states) value = 0; - e_table_model_set_value_at (ecell->table_model, model_col, row, GINT_TO_POINTER (value)); + e_table_model_set_value_at (toggle_view->cell_view.table_model, + model_col, row, GINT_TO_POINTER (value)); etog_queue_redraw (toggle_view, view_col, row); } @@ -183,7 +185,7 @@ static gint etog_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { ECellToggleView *toggle_view = (ECellToggleView *) ecell_view; - void *_value = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); + void *_value = e_table_model_value_at (ecell_view->table_model, model_col, row); const int value = GPOINTER_TO_INT (_value); switch (event->type){ @@ -248,13 +250,11 @@ e_cell_toggle_class_init (GtkObjectClass *object_class) E_MAKE_TYPE(e_cell_toggle, "ECellToggle", ECellToggle, e_cell_toggle_class_init, NULL, PARENT_TYPE); void -e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_states, GdkPixbuf **images) +e_cell_toggle_construct (ECellToggle *etog, int border, int n_states, GdkPixbuf **images) { int max_height = 0; int i; - E_CELL (etog)->table_model = etm; - etog->border = border; etog->n_states = n_states; @@ -272,11 +272,13 @@ e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_ } ECell * -e_cell_toggle_new (ETableModel *etm, int border, int n_states, GdkPixbuf **images) +e_cell_toggle_new (int border, int n_states, GdkPixbuf **images) { ECellToggle *etog = gtk_type_new (e_cell_toggle_get_type ()); - e_cell_toggle_construct (etog, etm, border, n_states, images); + e_cell_toggle_construct (etog, border, n_states, images); return (ECell *) etog; } + + diff --git a/widgets/e-table/e-cell-toggle.h b/widgets/e-table/e-cell-toggle.h index 2a5b6adc18..d5773b454a 100644 --- a/widgets/e-table/e-cell-toggle.h +++ b/widgets/e-table/e-cell-toggle.h @@ -26,11 +26,9 @@ typedef struct { } ECellToggleClass; GtkType e_cell_toggle_get_type (void); -ECell *e_cell_toggle_new (ETableModel *model, int border, - int n_states, - GdkPixbuf **images); -void e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, - int border, int n_states, GdkPixbuf **images); +ECell *e_cell_toggle_new (int border, int n_states, GdkPixbuf **images); +void e_cell_toggle_construct (ECellToggle *etog, int border, + int n_states, GdkPixbuf **images); #endif /* _E_CELL_TOGGLE_H_ */ diff --git a/widgets/e-table/e-cell.c b/widgets/e-table/e-cell.c index a4a03655dc..4495bbb1a7 100644 --- a/widgets/e-table/e-cell.c +++ b/widgets/e-table/e-cell.c @@ -13,7 +13,7 @@ #define PARENT_TYPE gtk_object_get_type() static ECellView * -ec_realize (ECell *e_cell, void *view) +ec_realize (ECell *e_cell, ETableModel *table_model, void *view) { return NULL; } @@ -110,10 +110,10 @@ e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_co } ECellView * -e_cell_realize (ECell *ecell, void *view) +e_cell_realize (ECell *ecell, ETableModel *table_model, void *view) { return E_CELL_CLASS (GTK_OBJECT (ecell)->klass)->realize ( - ecell, view); + ecell, table_model, view); } void diff --git a/widgets/e-table/e-cell.h b/widgets/e-table/e-cell.h index f72f97e8dd..23173a586c 100644 --- a/widgets/e-table/e-cell.h +++ b/widgets/e-table/e-cell.h @@ -15,11 +15,12 @@ typedef struct _ECellView ECellView; struct _ECell { GtkObject object; - ETableModel *table_model; }; struct _ECellView { ECell *ecell; + ETableModel *table_model; + gint focus_x1, focus_y1, focus_x2, focus_y2; gint focus_col, focus_row; }; @@ -29,7 +30,7 @@ struct _ECellView { typedef struct { GtkObjectClass parent_class; - ECellView *(*realize) (ECell *ecell, void *view); + ECellView *(*realize) (ECell *ecell, ETableModel *table_model, void *view); void (*unrealize) (ECellView *e_cell_view); void (*draw) (ECellView *ecell_view, GdkDrawable *drawable, int model_col, int view_col, int row, @@ -46,7 +47,7 @@ typedef struct { GtkType e_cell_get_type (void); void e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row); -ECellView *e_cell_realize (ECell *ecell, void *view); +ECellView *e_cell_realize (ECell *ecell, ETableModel *table_model, void *view); void e_cell_unrealize (ECellView *ecell_view); void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr, int model_col, int view_col, int row, gboolean selected, diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c index 0b5be9b84a..7cea9ae7a0 100644 --- a/widgets/e-table/e-table-header-item.c +++ b/widgets/e-table/e-table-header-item.c @@ -334,8 +334,6 @@ ethi_drag_motion (GtkObject *canvas, GdkDragContext *context, static void ethi_drag_end (GtkWidget *canvas, GdkDragContext *context, ETableHeaderItem *ethi) { - printf ("Ending\n"); - ethi_remove_drop_marker (ethi); ethi_remove_destroy_marker (ethi); ethi->drag_col = -1; diff --git a/widgets/e-table/e-table-header.c b/widgets/e-table/e-table-header.c index 375fd34c5d..32078d9a78 100644 --- a/widgets/e-table/e-table-header.c +++ b/widgets/e-table/e-table-header.c @@ -126,7 +126,7 @@ e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos) g_return_if_fail (E_IS_TABLE_HEADER (eth)); g_return_if_fail (tc != NULL); g_return_if_fail (E_IS_TABLE_COL (tc)); - g_return_if_fail (pos >= 0 && pos <= eth->col_count); + g_return_if_fail (pos >= -1 && pos <= eth->col_count); if (pos == -1) pos = eth->col_count; diff --git a/widgets/e-table/e-table-item.c b/widgets/e-table/e-table-item.c index bdeda14a7b..d0a0ad8cba 100644 --- a/widgets/e-table/e-table-item.c +++ b/widgets/e-table/e-table-item.c @@ -73,7 +73,7 @@ eti_realize_cell_views (ETableItem *eti) for (i = 0; i < eti->n_cells; i++){ ETableCol *col = e_table_header_get_column (eti->header, i); - eti->cell_views [i] = e_cell_realize (col->ecell, eti); + eti->cell_views [i] = e_cell_realize (col->ecell, eti->table_model, eti); } } @@ -91,6 +91,7 @@ eti_unrealize_cell_views (ETableItem *eti) eti->cell_views [i] = NULL; } g_free (eti->cell_views); + eti->cell_views = NULL; eti->n_cells = 0; } @@ -368,8 +369,12 @@ eti_header_structure_changed (ETableHeader *eth, ETableItem *eti) eti->cols = e_table_header_count (eti->header); eti->width = e_table_header_total_width (eti->header); - eti_unrealize_cell_views (eti); - eti_realize_cell_views (eti); + + if (eti->cell_views){ + eti_unrealize_cell_views (eti); + eti_realize_cell_views (eti); + } + eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); eti_request_redraw (eti); diff --git a/widgets/e-table/e-table-subset.c b/widgets/e-table/e-table-subset.c index 41763d309b..88f5c18c85 100644 --- a/widgets/e-table/e-table-subset.c +++ b/widgets/e-table/e-table-subset.c @@ -7,6 +7,8 @@ * (C) 1999 Helix Code, Inc. */ #include <config.h> +#include <stdlib.h> +#include <gtk/gtksignal.h> #include "e-util.h" #include "e-table-subset.h" @@ -36,20 +38,12 @@ etss_column_count (ETableModel *etm) return e_table_model_column_count (etss->source); } -static const char * -etss_column_name (ETableModel *etm, int col) -{ - ETableSubset *etss = (ETableSubset *)etm; - - return e_table_model_column_name (etss->source, col); -} - static int etss_row_count (ETableModel *etm) { ETableSubset *etss = (ETableSubset *)etm; - return e_table_model_row_count (etss->source); + return etss->n_map; } static void * @@ -61,7 +55,7 @@ etss_value_at (ETableModel *etm, int col, int row) } static void -etss_set_value_at (ETableModel *etm, int col, int row, void *val) +etss_set_value_at (ETableModel *etm, int col, int row, const void *val) { ETableSubset *etss = (ETableSubset *)etm; @@ -76,14 +70,6 @@ etss_is_cell_editable (ETableModel *etm, int col, int row) return e_table_model_is_cell_editable (etss->source, col, etss->map_table [row]); } -static int -etss_row_height (ETableModel *etm, int row) -{ - ETableSubset *etss = (ETableSubset *)etm; - - return e_table_model_row_height (etss->source, etss->map_table [row]); -} - static void etss_class_init (GtkObjectClass *klass) { @@ -94,25 +80,58 @@ etss_class_init (GtkObjectClass *klass) klass->destroy = etss_destroy; table_class->column_count = etss_column_count; - table_class->column_name = etss_column_name; table_class->row_count = etss_row_count; table_class->value_at = etss_value_at; table_class->set_value_at = etss_set_value_at; table_class->is_cell_editable = etss_is_cell_editable; - table_class->row_height = etss_row_height; - } E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, PARENT_TYPE); +static void +etss_proxy_model_changed (ETableModel *etm, ETableSubset *etss) +{ + e_table_model_changed (E_TABLE_MODEL (etss)); +} + +static void +etss_proxy_model_row_changed (ETableModel *etm, int row, ETableSubset *etss) +{ + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_row_changed (E_TABLE_MODEL (etss), i); + return; + } + } +} + +static void +etss_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSubset *etss) +{ + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_cell_changed (E_TABLE_MODEL (etss), col, i); + return; + } + } +} + ETableModel * e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) { unsigned int *buffer; int i; - buffer = (unsigned int *) malloc (sizeof (unsigned int *) * nvals); - if (buffer = NULL) + buffer = (unsigned int *) malloc (sizeof (unsigned int) * nvals); + if (buffer == NULL) return NULL; etss->map_table = buffer; etss->n_map = nvals; @@ -123,6 +142,14 @@ e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) for (i = 0; i < nvals; i++) etss->map_table [i] = i; + gtk_signal_connect (GTK_OBJECT (source), "model_changed", + GTK_SIGNAL_FUNC (etss_proxy_model_changed), etss); + gtk_signal_connect (GTK_OBJECT (source), "model_row_changed", + GTK_SIGNAL_FUNC (etss_proxy_model_row_changed), etss); + gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed", + GTK_SIGNAL_FUNC (etss_proxy_model_cell_changed), etss); + + return E_TABLE_MODEL (etss); } ETableModel * @@ -147,5 +174,5 @@ e_table_subset_get_toplevel (ETableSubset *table) if (E_IS_TABLE_SUBSET (table->source)) return e_table_subset_get_toplevel (E_TABLE_SUBSET (table->source)); else - return table->subset; + return table->source; } diff --git a/widgets/e-table/e-table-subset.h b/widgets/e-table/e-table-subset.h index 66d11e9658..314f28aea6 100644 --- a/widgets/e-table/e-table-subset.h +++ b/widgets/e-table/e-table-subset.h @@ -26,6 +26,7 @@ GtkType e_table_subset_get_type (void); ETableModel *e_table_subset_new (ETableModel *etm, int n_vals); ETableModel *e_table_subset_construct (ETableSubset *ets, ETableModel *source, int nvals); -ETableModel *e_table_subset_get_toplevel (ETableModel *table_model); +ETableModel *e_table_subset_get_toplevel (ETableSubset *table_model); #endif /* _E_TABLE_SUBSET_H_ */ + diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c index 3b13e87d6b..f9a41a38fc 100644 --- a/widgets/e-table/e-table.c +++ b/widgets/e-table/e-table.c @@ -7,16 +7,491 @@ * Copyright 1999, Helix Code, Inc */ #include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <alloca.h> +#include <stdio.h> #include <libgnomeui/gnome-canvas.h> +#include <gtk/gtksignal.h> #include "e-table.h" #include "e-util.h" +#include "e-table-header-item.h" +#include "e-table-subset.h" +#include "e-table-item.h" -#define PARENT_OBJECT_TYPE gnome_canvas_get_type () +#define COLUMN_HEADER_HEIGHT 16 +#define TITLE_HEIGHT 16 +#define GROUP_INDENT 10 -E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, NULL, PARENT_TYPE); +#define PARENT_TYPE gtk_table_get_type () -ETable * -e_table_new (ETableHeader *eth, ETableModel *etm) +static GtkObjectClass *e_table_parent_class; + +typedef struct { + ETableModel *table; + GnomeCanvasItem *table_item; + GnomeCanvasItem *rect; +} Leaf; + +typedef struct { +} Node; + + +static void +et_destroy (GtkObject *object) +{ + ETable *et = E_TABLE (object); + + gtk_object_unref (GTK_OBJECT (et->model)); + gtk_object_unref (GTK_OBJECT (et->full_header)); + gtk_object_unref (GTK_OBJECT (et->header)); + + g_free (et->group_spec); + + (*e_table_parent_class->destroy)(object); +} + +static void +e_table_init (GtkObject *object) +{ + ETable *e_table = E_TABLE (object); + + e_table->draw_grid = 1; + e_table->draw_focus = 1; + e_table->spreadsheet = 1; +} + +static ETableHeader * +e_table_make_header (ETable *e_table, ETableHeader *full_header, const char *cols) +{ + ETableHeader *nh; + char *copy = alloca (strlen (cols) + 1); + char *p, *state; + const int max_cols = e_table_header_count (full_header); + + nh = e_table_header_new (); + strcpy (copy, cols); + while ((p = strtok_r (copy, ",", &state)) != NULL){ + int col = atoi (p); + + copy = NULL; + if (col >= max_cols) + continue; + + e_table_header_add_column (nh, e_table_header_get_column (full_header, col), -1); + } + + return nh; +} + +static void +e_table_setup_header (ETable *e_table) +{ + e_table->header_canvas = GNOME_CANVAS (gnome_canvas_new ()); + + gtk_widget_show (GTK_WIDGET (e_table->header_canvas)); + + e_table->header_item = gnome_canvas_item_new ( + gnome_canvas_root (e_table->header_canvas), + e_table_header_item_get_type (), + "ETableHeader", e_table->header, + "x", 0, + "y", 0, + NULL); + + gtk_widget_set_usize (GTK_WIDGET (e_table->header_canvas), -1, COLUMN_HEADER_HEIGHT); + g_warning ("Aqui"); + e_table->header_canvas = 0; + + gtk_table_attach ( + GTK_TABLE (e_table), GTK_WIDGET (e_table->header_canvas), + 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0); + +} + +static Leaf * +e_table_create_leaf (ETable *e_table, int x_off, int y_off, ETableModel *etm) +{ + Leaf *leaf; + int height; + + leaf = g_new (Leaf, 1); + leaf->table = etm; + + leaf->table_item = gnome_canvas_item_new ( + gnome_canvas_root (e_table->table_canvas), + e_table_item_get_type (), + "ETableHeader", e_table->header, + "ETableModel", etm, + "x", x_off + GROUP_INDENT, + "y", y_off + TITLE_HEIGHT, + "drawgrid", e_table->draw_grid, + "drawfocus", e_table->draw_focus, + "spreadsheet", e_table->spreadsheet, + NULL); + + height = E_TABLE_ITEM (leaf->table_item)->height; + + leaf->rect = gnome_canvas_item_new ( + gnome_canvas_root (e_table->table_canvas), + gnome_canvas_rect_get_type (), + "x1", (double) x_off, + "y1", (double) y_off, + "x2", (double) x_off + e_table->gen_header_width + GROUP_INDENT, + "y2", (double) y_off + TITLE_HEIGHT + height, + "fill_color", "gray", + "outline_color", "gray20", + NULL); + gnome_canvas_item_lower (leaf->rect, 1); + + return leaf; +} + +typedef struct { + void *value; + GArray *array; +} group_key_t; + +static GArray * +e_table_create_groups (ETableModel *etm, int key_col, GCompareFunc comp) +{ + GArray *groups; + const int rows = e_table_model_row_count (etm); + int row, i; + + groups = g_array_new (FALSE, FALSE, sizeof (group_key_t)); + + for (row = 0; row < rows; row++){ + void *val = e_table_model_value_at (etm, key_col, row); + const int n_groups = groups->len; + + /* + * Should replace this with a bsearch later + */ + for (i = 0; i < n_groups; i++){ + group_key_t *g = &g_array_index (groups, group_key_t, i); + + if ((*comp) (g->value, val)){ + g_array_append_val (g->array, row); + break; + } + } + if (i != n_groups) + continue; + + /* + * We need to create a new group + */ + { + group_key_t gk; + + gk.value = val; + gk.array = g_array_new (FALSE, FALSE, sizeof (int)); + + g_array_append_val (gk.array, row); + g_array_append_val (groups, gk); + } + } + + return groups; +} + +static void +e_table_destroy_groups (GArray *groups) +{ + const int n = groups->len; + int i; + + for (i = 0; i < n; i++){ + group_key_t *g = &g_array_index (groups, group_key_t, i); + + g_array_free (g->array, TRUE); + } + g_array_free (groups, TRUE); +} + +static ETableModel ** +e_table_make_subtables (ETableModel *model, GArray *groups) +{ + const int n_groups = groups->len; + ETableModel **tables; + int i; + + tables = g_new (ETableModel *, n_groups+1); + + for (i = 0; i < n_groups; i++){ + group_key_t *g = &g_array_index (groups, group_key_t, i); + const int sub_size = g->array->len; + ETableSubset *ss; + int j; + + printf ("Creating subset of %d elements\n", sub_size); + tables [i] = e_table_subset_new (model, sub_size); + ss = E_TABLE_SUBSET (tables [i]); + + for (j = 0; j < sub_size; j++) + ss->map_table [j] = g_array_index (g->array, int, j); + } + tables [i] = NULL; + + return (ETableModel **) tables; +} + +static int +leaf_height (Leaf *leaf) +{ + return E_TABLE_ITEM (leaf->table_item)->height + TITLE_HEIGHT; +} + +static int +e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, + GnomeCanvasGroup *root, int x_off, int y_off, + int *groups_list) +{ + GArray *groups; + ETableModel **tables; + int key_col; + int height, i; + GCompareFunc comp; + + if (groups_list) + key_col = *groups_list; + else + key_col = -1; + + if (key_col == -1){ + Leaf *leaf; + + printf ("Leaf->with %d rows\n", e_table_model_row_count (model)); + leaf = e_table_create_leaf (e_table, x_off, y_off, model); + + { + static int warn_shown; + + if (!warn_shown){ + g_warning ("Leak"); + warn_shown = 1; + } + } + return leaf_height (leaf); + } + + /* + * Create groups + */ + comp = e_table_header_get_column (header, key_col)->compare; + groups = e_table_create_groups (model, key_col, comp); + tables = e_table_make_subtables (e_table->model, groups); + e_table_destroy_groups (groups); + + height = 0; + for (i = 0; tables [i] != NULL; i++){ + printf ("Creating->%d with %d rows\n", i, e_table_model_row_count (tables [i])); + height += e_table_create_nodes ( + e_table, tables [i], header, root, + x_off + 20, + y_off + height, &groups_list [1]); + } + + return height; +} + +static int * +group_spec_to_desc (const char *group_spec) { + int a_size = 10; + int *elements; + char *p, *copy, *follow; + int n_elements = 0; + + if (group_spec == NULL) + return NULL; + + elements = g_new (int, a_size); + copy = alloca (strlen (group_spec) + 1); + strcpy (copy, group_spec); + + while ((p = strtok_r (copy, ",", &follow)) != NULL){ + elements [n_elements] = atoi (p); + ++n_elements; + if (n_elements+1 == a_size){ + int *new_e; + + n_elements += 10; + new_e = g_renew (int, elements, n_elements); + if (new_e == NULL){ + g_free (elements); + return NULL; + } + elements = new_e; + } + copy = NULL; + } + + /* Tag end */ + elements [n_elements] = -1; + + return elements; +} + +/* + * The ETableCanvas object is just used to enable us to + * hook up to the realize/unrealize phases of the canvas + * initialization (as laying out the subtables requires us to + * know the actual size of the subtables we are inserting + */ + +#define E_TABLE_CANVAS_PARENT_TYPE gnome_canvas_get_type () + +typedef struct { + GnomeCanvas base; + + ETable *e_table; +} ETableCanvas; + +typedef struct { + GnomeCanvasClass base_class; +} ETableCanvasClass; + +static GnomeCanvasClass *e_table_canvas_parent_class; + +static void +e_table_canvas_realize (GtkWidget *widget) +{ + ETableCanvas *e_table_canvas = (ETableCanvas *) widget; + ETable *e_table = e_table_canvas->e_table; + int *groups; + int height; + + GTK_WIDGET_CLASS (e_table_canvas_parent_class)->realize (widget); + + groups = group_spec_to_desc (e_table->group_spec); + + e_table->root = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (e_table->table_canvas->root), + gnome_canvas_group_get_type (), + "x", 0.0, + "y", 0.0, + NULL); + + e_table->gen_header_width = e_table_header_total_width (e_table->header); + + height = e_table_create_nodes ( + e_table, e_table->model, + e_table->header, GNOME_CANVAS_GROUP (e_table->root), 0, 0, groups); + + { + static int warn_shown; + + if (!warn_shown){ + g_warning ("Precompute the width, and update on model changes"); + warn_shown = 1; + } + } + + gnome_canvas_set_scroll_region ( + GNOME_CANVAS (e_table_canvas), + 0, 0, + e_table_header_total_width (e_table->header) + 200, + height); + + if (groups) + g_free (groups); +} + +static void +e_table_canvas_unrealize (GtkWidget *widget) +{ + ETableCanvas *e_table_canvas = (ETableCanvas *) widget; + ETable *e_table = e_table_canvas->e_table; + + gtk_object_destroy (GTK_OBJECT (e_table->root)); + e_table->root = NULL; + + GTK_WIDGET_CLASS (e_table_canvas_parent_class)->unrealize (widget); +} + +static void +e_table_canvas_class_init (GtkObjectClass *object_class) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass *) object_class; + + widget_class->realize = e_table_canvas_realize; + widget_class->unrealize = e_table_canvas_unrealize; + + e_table_canvas_parent_class = gtk_type_class (E_TABLE_CANVAS_PARENT_TYPE); +} + +GtkType e_table_canvas_get_type (void); + +E_MAKE_TYPE (e_table_canvas, "ETableCanvas", ETableCanvas, e_table_canvas_class_init, + NULL, E_TABLE_CANVAS_PARENT_TYPE); + +static GnomeCanvas * +e_table_canvas_new (ETable *e_table) +{ + ETableCanvas *e_table_canvas; + + e_table_canvas = gtk_type_new (e_table_canvas_get_type ()); + e_table_canvas->e_table = e_table; + + return GNOME_CANVAS (e_table_canvas); +} + +static void +e_table_setup_table (ETable *e_table) +{ + e_table->table_canvas = e_table_canvas_new (e_table); + + gtk_widget_show (GTK_WIDGET (e_table->table_canvas)); + gtk_table_attach ( + GTK_TABLE (e_table), GTK_WIDGET (e_table->table_canvas), + 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); +} + +void +e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, + const char *cols_spec, const char *group_spec) +{ + GTK_TABLE (e_table)->homogeneous = FALSE; + + gtk_table_resize (GTK_TABLE (e_table), 1, 2); + + e_table->full_header = full_header; + gtk_object_ref (GTK_OBJECT (full_header)); + + e_table->model = etm; + gtk_object_ref (GTK_OBJECT (etm)); + + e_table->header = e_table_make_header (e_table, full_header, cols_spec); + + e_table_setup_header (e_table); + e_table_setup_table (e_table); + + e_table->group_spec = g_strdup (group_spec); + } +GtkWidget * +e_table_new (ETableHeader *full_header, ETableModel *etm, const char *cols_spec, const char *group_spec) +{ + ETable *e_table; + + e_table = gtk_type_new (e_table_get_type ()); + + e_table_construct (e_table, full_header, etm, cols_spec, group_spec); + + return (GtkWidget *) e_table; +} + +static void +e_table_class_init (GtkObjectClass *object_class) +{ + e_table_parent_class = gtk_type_class (PARENT_TYPE); + + object_class->destroy = et_destroy; +} + +E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, e_table_init, PARENT_TYPE); + diff --git a/widgets/e-table/e-table.h b/widgets/e-table/e-table.h index 0847ddde6c..eb089781b9 100644 --- a/widgets/e-table/e-table.h +++ b/widgets/e-table/e-table.h @@ -1,6 +1,53 @@ #ifndef _E_TABLE_H_ #define _E_TABLE_H_ -GtkType e_table_get_type (void); -ETable * +#include <libgnomeui/gnome-canvas.h> +#include <gtk/gtktable.h> +#include "e-table-model.h" +#include "e-table-header.h" + +BEGIN_GNOME_DECLS + +#define E_TABLE_TYPE (e_table_get_type ()) +#define E_TABLE(o) (GTK_CHECK_CAST ((o), E_TABLE_TYPE, ETable)) +#define E_TABLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_TYPE, ETableClass)) +#define E_IS_TABLE(o) (GTK_CHECK_TYPE ((o), E_TABLE_TYPE)) +#define E_IS_TABLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_TYPE)) + +typedef struct { + GtkTable parent; + + ETableModel *model; + + ETableHeader *full_header, *header; + + GnomeCanvas *header_canvas, *table_canvas; + + GnomeCanvasItem *header_item, *root; + + guint draw_grid:1; + guint draw_focus:1; + guint spreadsheet:1; + + char *group_spec; + + /* + * Used during table generation + */ + int gen_header_width; +} ETable; + +typedef struct { + GtkTableClass parent_class; +} ETableClass; + +GtkType e_table_get_type (void); +void e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, + const char *cols_spec, const char *group_spec); +GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm, + const char *cols_spec, const char *group_spec); + + +END_GNOME_DECLS + #endif /* _E_TABLE_H_ */ diff --git a/widgets/e-table/sample.table b/widgets/e-table/sample.table index 2cb09d7f1f..45c8ff0691 100644 --- a/widgets/e-table/sample.table +++ b/widgets/e-table/sample.table @@ -5,4 +5,7 @@ c1.c c2.c a.c tit-1 DorkB c1.d c2.d a.d tit-2 ADork c1.e c2.e a.e tit-1 DorkC c1.f c2.f a.f tit-2 UDork +c1.g c2.g a.g tit-3 Dork--- +j k k tit-1 DorkA + diff --git a/widgets/e-table/table-test.c b/widgets/e-table/table-test.c index e60dd893fe..9de673ede4 100644 --- a/widgets/e-table/table-test.c +++ b/widgets/e-table/table-test.c @@ -10,6 +10,7 @@ #include <fcntl.h> #include <gnome.h> #include "e-cursors.h" +#include "table-test.h" int main (int argc, char *argv []) @@ -33,6 +34,8 @@ main (int argc, char *argv []) table_browser_test (); multi_cols_test (); check_test (); + e_table_test (); + gtk_main (); e_cursors_shutdown (); diff --git a/widgets/e-table/test-check.c b/widgets/e-table/test-check.c index 9968426327..9e003ce9a1 100644 --- a/widgets/e-table/test-check.c +++ b/widgets/e-table/test-check.c @@ -16,6 +16,8 @@ #include "e-cell-text.h" #include "e-cell-checkbox.h" +#include "table-test.h" + #define LINES 4 static struct { @@ -105,7 +107,7 @@ check_test (void) cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT); - cell_image_check = e_cell_checkbox_new (e_table_model); + cell_image_check = e_cell_checkbox_new (); col_0 = e_table_col_new (0, "", 18, 18, cell_image_check, g_int_equal, TRUE); e_table_header_add_column (e_table_header, col_0, 0); diff --git a/widgets/e-table/test-cols.c b/widgets/e-table/test-cols.c index 4406c6b3b9..b7979c2f3d 100644 --- a/widgets/e-table/test-cols.c +++ b/widgets/e-table/test-cols.c @@ -16,6 +16,8 @@ #include "e-cell-text.h" #include "e-cell-toggle.h" +#include "table-test.h" + #define LINES 4 static struct { @@ -90,7 +92,6 @@ multi_cols_test (void) ETableHeader *e_table_header, *e_table_header_multiple; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_toggle; - int i; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); @@ -114,7 +115,7 @@ multi_cols_test (void) images [1] = gdk_pixbuf_new_from_file ("image2.png"); images [2] = gdk_pixbuf_new_from_file ("image3.png"); - cell_image_toggle = e_cell_toggle_new (e_table_model, 0, 3, images); + cell_image_toggle = e_cell_toggle_new (0, 3, images); for (i = 0; i < 3; i++) gdk_pixbuf_unref (images [i]); diff --git a/widgets/e-table/test-table.c b/widgets/e-table/test-table.c index 04c40959af..83a130d72a 100644 --- a/widgets/e-table/test-table.c +++ b/widgets/e-table/test-table.c @@ -14,6 +14,9 @@ #include "e-table-item.h" #include "e-cursors.h" #include "e-cell-text.h" +#include "e-table.h" + +#include "table-test.h" char buffer [1024]; char **column_labels; @@ -97,6 +100,16 @@ load_data () { int i; + { + static int loaded; + + if (loaded) + return; + + loaded = TRUE; + } + + parse_headers (); while (fgets (buffer, sizeof (buffer)-1, stdin) != NULL){ @@ -231,3 +244,49 @@ table_browser_test (void) NULL); } +static void +do_e_table_demo (const char *col_spec, const char *group_spec) +{ + GtkWidget *e_table, *window; + ETableModel *e_table_model; + ECell *cell_left_just; + ETableHeader *full_header; + int i; + + /* + * Data model + */ + e_table_model = e_table_simple_new ( + col_count, row_count, value_at, + set_value_at, is_cell_editable, NULL); + + full_header = e_table_header_new (); + cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT); + + for (i = 0; i < cols; i++){ + ETableCol *ecol = e_table_col_new ( + i, column_labels [i], + 80, 20, cell_left_just, + g_str_equal, TRUE); + + e_table_header_add_column (full_header, ecol, i); + } + + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + e_table = e_table_new (full_header, e_table_model, col_spec, group_spec); + + gtk_container_add (GTK_CONTAINER (window), e_table); + + gtk_widget_show (e_table); + gtk_widget_show (window); +} + +void +e_table_test (void) +{ + load_data (); + do_e_table_demo ("0,1,2,3,4", NULL); + do_e_table_demo ("0,1,2,3,4", "3"); + do_e_table_demo ("0,1,2,3,4", "3,4"); +} diff --git a/widgets/sample.table b/widgets/sample.table index 2cb09d7f1f..45c8ff0691 100644 --- a/widgets/sample.table +++ b/widgets/sample.table @@ -5,4 +5,7 @@ c1.c c2.c a.c tit-1 DorkB c1.d c2.d a.d tit-2 ADork c1.e c2.e a.e tit-1 DorkC c1.f c2.f a.f tit-2 UDork +c1.g c2.g a.g tit-3 Dork--- +j k k tit-1 DorkA + diff --git a/widgets/table-test.c b/widgets/table-test.c index e60dd893fe..9de673ede4 100644 --- a/widgets/table-test.c +++ b/widgets/table-test.c @@ -10,6 +10,7 @@ #include <fcntl.h> #include <gnome.h> #include "e-cursors.h" +#include "table-test.h" int main (int argc, char *argv []) @@ -33,6 +34,8 @@ main (int argc, char *argv []) table_browser_test (); multi_cols_test (); check_test (); + e_table_test (); + gtk_main (); e_cursors_shutdown (); diff --git a/widgets/table/e-cell-checkbox.c b/widgets/table/e-cell-checkbox.c index 73620b9ce4..6e4b597abf 100644 --- a/widgets/table/e-cell-checkbox.c +++ b/widgets/table/e-cell-checkbox.c @@ -34,11 +34,11 @@ e_cell_checkbox_class_init (GtkObjectClass *object_class) E_MAKE_TYPE(e_cell_checkbox, "ECellCheckbox", ECellCheckbox, e_cell_checkbox_class_init, NULL, PARENT_TYPE); ECell * -e_cell_checkbox_new (ETableModel *etm) +e_cell_checkbox_new (void) { ECellCheckbox *eccb = gtk_type_new (e_cell_checkbox_get_type ()); - e_cell_toggle_construct (E_CELL_TOGGLE (eccb), etm, 2, 2, checks); + e_cell_toggle_construct (E_CELL_TOGGLE (eccb), 2, 2, checks); return (ECell *) eccb; } diff --git a/widgets/table/e-cell-checkbox.h b/widgets/table/e-cell-checkbox.h index 6afca6bde2..969e4a5edc 100644 --- a/widgets/table/e-cell-checkbox.h +++ b/widgets/table/e-cell-checkbox.h @@ -18,7 +18,7 @@ typedef struct { } ECellCheckboxClass; GtkType e_cell_checkbox_get_type (void); -ECell *e_cell_checkbox_new (ETableModel *model); +ECell *e_cell_checkbox_new (void); #endif /* _E_CELL_CHECKBOX_H_ */ diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c index 828be6cc29..79fe432326 100644 --- a/widgets/table/e-cell-text.c +++ b/widgets/table/e-cell-text.c @@ -13,6 +13,7 @@ #include <gtk/gtksignal.h> #include <gdk/gdkkeysyms.h> #include <libgnomeui/gnome-canvas.h> +#include <stdio.h> #include "e-cell-text.h" #include "e-util.h" #include "e-table-item.h" @@ -62,7 +63,7 @@ ect_accept_edits (ECellTextView *text_view) const char *text = gtk_entry_get_text (text_view->edit->entry); CellEdit *edit = text_view->edit; - e_table_model_set_value_at (text_view->eti->table_model, edit->model_col, edit->row, text); + e_table_model_set_value_at (text_view->cell_view.table_model, edit->model_col, edit->row, text); } /* @@ -100,7 +101,7 @@ ect_cancel_edit (ECellTextView *text_view) * ECell::realize method */ static ECellView * -ect_realize (ECell *ecell, void *view) +ect_realize (ECell *ecell, ETableModel *table_model, void *view) { ECellText *ect = E_CELL_TEXT (ecell); ECellTextView *text_view = g_new0 (ECellTextView, 1); @@ -108,6 +109,8 @@ ect_realize (ECell *ecell, void *view) GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; text_view->cell_view.ecell = ecell; + text_view->cell_view.table_model = table_model; + text_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window); if (ect->font_name){ GdkFont *f; @@ -123,7 +126,7 @@ ect_realize (ECell *ecell, void *view) text_view->eti = eti; text_view->canvas = canvas; - + return (ECellView *)text_view; } @@ -156,7 +159,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, ECellTextView *text_view = (ECellTextView *) ecell_view; GtkWidget *w = GTK_WIDGET (text_view->canvas); GdkRectangle rect; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); + const char *str = e_table_model_value_at (ecell_view->table_model, model_col, row); GdkFont *font = text_view->font; const int height = font->ascent + font->descent; int xoff; @@ -389,7 +392,7 @@ static void * ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); + const char *str = e_table_model_value_at (ecell_view->table_model, model_col, row); CellEdit *edit; edit = g_new (CellEdit, 1); @@ -476,7 +479,6 @@ e_cell_text_new (ETableModel *etm, const char *fontname, GtkJustification justif ect->font_name = g_strdup (fontname); ect->justify = justify; - E_CELL (ect)->table_model = etm; return (ECell *) ect; } diff --git a/widgets/table/e-cell-toggle.c b/widgets/table/e-cell-toggle.c index ec6fa38a38..dbe5fe5cbd 100644 --- a/widgets/table/e-cell-toggle.c +++ b/widgets/table/e-cell-toggle.c @@ -38,17 +38,18 @@ etog_queue_redraw (ECellToggleView *text_view, int view_col, int view_row) * ECell::realize method */ static ECellView * -etog_realize (ECell *ecell, void *view) +etog_realize (ECell *ecell, ETableModel *table_model, void *view) { ECellToggleView *toggle_view = g_new0 (ECellToggleView, 1); ETableItem *eti = E_TABLE_ITEM (view); GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; toggle_view->cell_view.ecell = ecell; + toggle_view->cell_view.table_model = table_model; toggle_view->eti = eti; toggle_view->canvas = canvas; toggle_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window); - + return (ECellView *) toggle_view; } @@ -80,7 +81,7 @@ etog_draw (ECellView *ecell_view, GdkDrawable *drawable, ArtPixBuf *art; int x, y, width, height; const int value = GPOINTER_TO_INT ( - e_table_model_value_at (ecell_view->ecell->table_model, model_col, row)); + e_table_model_value_at (ecell_view->table_model, model_col, row)); if (value >= toggle->n_states){ g_warning ("Value from the table model is %d, the states we support are [0..%d)\n", @@ -172,7 +173,8 @@ etog_set_value (ECellToggleView *toggle_view, int model_col, int view_col, int r if (value >= toggle->n_states) value = 0; - e_table_model_set_value_at (ecell->table_model, model_col, row, GINT_TO_POINTER (value)); + e_table_model_set_value_at (toggle_view->cell_view.table_model, + model_col, row, GINT_TO_POINTER (value)); etog_queue_redraw (toggle_view, view_col, row); } @@ -183,7 +185,7 @@ static gint etog_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { ECellToggleView *toggle_view = (ECellToggleView *) ecell_view; - void *_value = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); + void *_value = e_table_model_value_at (ecell_view->table_model, model_col, row); const int value = GPOINTER_TO_INT (_value); switch (event->type){ @@ -248,13 +250,11 @@ e_cell_toggle_class_init (GtkObjectClass *object_class) E_MAKE_TYPE(e_cell_toggle, "ECellToggle", ECellToggle, e_cell_toggle_class_init, NULL, PARENT_TYPE); void -e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_states, GdkPixbuf **images) +e_cell_toggle_construct (ECellToggle *etog, int border, int n_states, GdkPixbuf **images) { int max_height = 0; int i; - E_CELL (etog)->table_model = etm; - etog->border = border; etog->n_states = n_states; @@ -272,11 +272,13 @@ e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_ } ECell * -e_cell_toggle_new (ETableModel *etm, int border, int n_states, GdkPixbuf **images) +e_cell_toggle_new (int border, int n_states, GdkPixbuf **images) { ECellToggle *etog = gtk_type_new (e_cell_toggle_get_type ()); - e_cell_toggle_construct (etog, etm, border, n_states, images); + e_cell_toggle_construct (etog, border, n_states, images); return (ECell *) etog; } + + diff --git a/widgets/table/e-cell-toggle.h b/widgets/table/e-cell-toggle.h index 2a5b6adc18..d5773b454a 100644 --- a/widgets/table/e-cell-toggle.h +++ b/widgets/table/e-cell-toggle.h @@ -26,11 +26,9 @@ typedef struct { } ECellToggleClass; GtkType e_cell_toggle_get_type (void); -ECell *e_cell_toggle_new (ETableModel *model, int border, - int n_states, - GdkPixbuf **images); -void e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, - int border, int n_states, GdkPixbuf **images); +ECell *e_cell_toggle_new (int border, int n_states, GdkPixbuf **images); +void e_cell_toggle_construct (ECellToggle *etog, int border, + int n_states, GdkPixbuf **images); #endif /* _E_CELL_TOGGLE_H_ */ diff --git a/widgets/table/e-cell.c b/widgets/table/e-cell.c index a4a03655dc..4495bbb1a7 100644 --- a/widgets/table/e-cell.c +++ b/widgets/table/e-cell.c @@ -13,7 +13,7 @@ #define PARENT_TYPE gtk_object_get_type() static ECellView * -ec_realize (ECell *e_cell, void *view) +ec_realize (ECell *e_cell, ETableModel *table_model, void *view) { return NULL; } @@ -110,10 +110,10 @@ e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_co } ECellView * -e_cell_realize (ECell *ecell, void *view) +e_cell_realize (ECell *ecell, ETableModel *table_model, void *view) { return E_CELL_CLASS (GTK_OBJECT (ecell)->klass)->realize ( - ecell, view); + ecell, table_model, view); } void diff --git a/widgets/table/e-cell.h b/widgets/table/e-cell.h index f72f97e8dd..23173a586c 100644 --- a/widgets/table/e-cell.h +++ b/widgets/table/e-cell.h @@ -15,11 +15,12 @@ typedef struct _ECellView ECellView; struct _ECell { GtkObject object; - ETableModel *table_model; }; struct _ECellView { ECell *ecell; + ETableModel *table_model; + gint focus_x1, focus_y1, focus_x2, focus_y2; gint focus_col, focus_row; }; @@ -29,7 +30,7 @@ struct _ECellView { typedef struct { GtkObjectClass parent_class; - ECellView *(*realize) (ECell *ecell, void *view); + ECellView *(*realize) (ECell *ecell, ETableModel *table_model, void *view); void (*unrealize) (ECellView *e_cell_view); void (*draw) (ECellView *ecell_view, GdkDrawable *drawable, int model_col, int view_col, int row, @@ -46,7 +47,7 @@ typedef struct { GtkType e_cell_get_type (void); void e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row); -ECellView *e_cell_realize (ECell *ecell, void *view); +ECellView *e_cell_realize (ECell *ecell, ETableModel *table_model, void *view); void e_cell_unrealize (ECellView *ecell_view); void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr, int model_col, int view_col, int row, gboolean selected, diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c index 0b5be9b84a..7cea9ae7a0 100644 --- a/widgets/table/e-table-header-item.c +++ b/widgets/table/e-table-header-item.c @@ -334,8 +334,6 @@ ethi_drag_motion (GtkObject *canvas, GdkDragContext *context, static void ethi_drag_end (GtkWidget *canvas, GdkDragContext *context, ETableHeaderItem *ethi) { - printf ("Ending\n"); - ethi_remove_drop_marker (ethi); ethi_remove_destroy_marker (ethi); ethi->drag_col = -1; diff --git a/widgets/table/e-table-header.c b/widgets/table/e-table-header.c index 375fd34c5d..32078d9a78 100644 --- a/widgets/table/e-table-header.c +++ b/widgets/table/e-table-header.c @@ -126,7 +126,7 @@ e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos) g_return_if_fail (E_IS_TABLE_HEADER (eth)); g_return_if_fail (tc != NULL); g_return_if_fail (E_IS_TABLE_COL (tc)); - g_return_if_fail (pos >= 0 && pos <= eth->col_count); + g_return_if_fail (pos >= -1 && pos <= eth->col_count); if (pos == -1) pos = eth->col_count; diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c index bdeda14a7b..d0a0ad8cba 100644 --- a/widgets/table/e-table-item.c +++ b/widgets/table/e-table-item.c @@ -73,7 +73,7 @@ eti_realize_cell_views (ETableItem *eti) for (i = 0; i < eti->n_cells; i++){ ETableCol *col = e_table_header_get_column (eti->header, i); - eti->cell_views [i] = e_cell_realize (col->ecell, eti); + eti->cell_views [i] = e_cell_realize (col->ecell, eti->table_model, eti); } } @@ -91,6 +91,7 @@ eti_unrealize_cell_views (ETableItem *eti) eti->cell_views [i] = NULL; } g_free (eti->cell_views); + eti->cell_views = NULL; eti->n_cells = 0; } @@ -368,8 +369,12 @@ eti_header_structure_changed (ETableHeader *eth, ETableItem *eti) eti->cols = e_table_header_count (eti->header); eti->width = e_table_header_total_width (eti->header); - eti_unrealize_cell_views (eti); - eti_realize_cell_views (eti); + + if (eti->cell_views){ + eti_unrealize_cell_views (eti); + eti_realize_cell_views (eti); + } + eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); eti_request_redraw (eti); diff --git a/widgets/table/e-table-subset.c b/widgets/table/e-table-subset.c index 41763d309b..88f5c18c85 100644 --- a/widgets/table/e-table-subset.c +++ b/widgets/table/e-table-subset.c @@ -7,6 +7,8 @@ * (C) 1999 Helix Code, Inc. */ #include <config.h> +#include <stdlib.h> +#include <gtk/gtksignal.h> #include "e-util.h" #include "e-table-subset.h" @@ -36,20 +38,12 @@ etss_column_count (ETableModel *etm) return e_table_model_column_count (etss->source); } -static const char * -etss_column_name (ETableModel *etm, int col) -{ - ETableSubset *etss = (ETableSubset *)etm; - - return e_table_model_column_name (etss->source, col); -} - static int etss_row_count (ETableModel *etm) { ETableSubset *etss = (ETableSubset *)etm; - return e_table_model_row_count (etss->source); + return etss->n_map; } static void * @@ -61,7 +55,7 @@ etss_value_at (ETableModel *etm, int col, int row) } static void -etss_set_value_at (ETableModel *etm, int col, int row, void *val) +etss_set_value_at (ETableModel *etm, int col, int row, const void *val) { ETableSubset *etss = (ETableSubset *)etm; @@ -76,14 +70,6 @@ etss_is_cell_editable (ETableModel *etm, int col, int row) return e_table_model_is_cell_editable (etss->source, col, etss->map_table [row]); } -static int -etss_row_height (ETableModel *etm, int row) -{ - ETableSubset *etss = (ETableSubset *)etm; - - return e_table_model_row_height (etss->source, etss->map_table [row]); -} - static void etss_class_init (GtkObjectClass *klass) { @@ -94,25 +80,58 @@ etss_class_init (GtkObjectClass *klass) klass->destroy = etss_destroy; table_class->column_count = etss_column_count; - table_class->column_name = etss_column_name; table_class->row_count = etss_row_count; table_class->value_at = etss_value_at; table_class->set_value_at = etss_set_value_at; table_class->is_cell_editable = etss_is_cell_editable; - table_class->row_height = etss_row_height; - } E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, PARENT_TYPE); +static void +etss_proxy_model_changed (ETableModel *etm, ETableSubset *etss) +{ + e_table_model_changed (E_TABLE_MODEL (etss)); +} + +static void +etss_proxy_model_row_changed (ETableModel *etm, int row, ETableSubset *etss) +{ + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_row_changed (E_TABLE_MODEL (etss), i); + return; + } + } +} + +static void +etss_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSubset *etss) +{ + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_cell_changed (E_TABLE_MODEL (etss), col, i); + return; + } + } +} + ETableModel * e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) { unsigned int *buffer; int i; - buffer = (unsigned int *) malloc (sizeof (unsigned int *) * nvals); - if (buffer = NULL) + buffer = (unsigned int *) malloc (sizeof (unsigned int) * nvals); + if (buffer == NULL) return NULL; etss->map_table = buffer; etss->n_map = nvals; @@ -123,6 +142,14 @@ e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) for (i = 0; i < nvals; i++) etss->map_table [i] = i; + gtk_signal_connect (GTK_OBJECT (source), "model_changed", + GTK_SIGNAL_FUNC (etss_proxy_model_changed), etss); + gtk_signal_connect (GTK_OBJECT (source), "model_row_changed", + GTK_SIGNAL_FUNC (etss_proxy_model_row_changed), etss); + gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed", + GTK_SIGNAL_FUNC (etss_proxy_model_cell_changed), etss); + + return E_TABLE_MODEL (etss); } ETableModel * @@ -147,5 +174,5 @@ e_table_subset_get_toplevel (ETableSubset *table) if (E_IS_TABLE_SUBSET (table->source)) return e_table_subset_get_toplevel (E_TABLE_SUBSET (table->source)); else - return table->subset; + return table->source; } diff --git a/widgets/table/e-table-subset.h b/widgets/table/e-table-subset.h index 66d11e9658..314f28aea6 100644 --- a/widgets/table/e-table-subset.h +++ b/widgets/table/e-table-subset.h @@ -26,6 +26,7 @@ GtkType e_table_subset_get_type (void); ETableModel *e_table_subset_new (ETableModel *etm, int n_vals); ETableModel *e_table_subset_construct (ETableSubset *ets, ETableModel *source, int nvals); -ETableModel *e_table_subset_get_toplevel (ETableModel *table_model); +ETableModel *e_table_subset_get_toplevel (ETableSubset *table_model); #endif /* _E_TABLE_SUBSET_H_ */ + diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index 3b13e87d6b..f9a41a38fc 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -7,16 +7,491 @@ * Copyright 1999, Helix Code, Inc */ #include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <alloca.h> +#include <stdio.h> #include <libgnomeui/gnome-canvas.h> +#include <gtk/gtksignal.h> #include "e-table.h" #include "e-util.h" +#include "e-table-header-item.h" +#include "e-table-subset.h" +#include "e-table-item.h" -#define PARENT_OBJECT_TYPE gnome_canvas_get_type () +#define COLUMN_HEADER_HEIGHT 16 +#define TITLE_HEIGHT 16 +#define GROUP_INDENT 10 -E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, NULL, PARENT_TYPE); +#define PARENT_TYPE gtk_table_get_type () -ETable * -e_table_new (ETableHeader *eth, ETableModel *etm) +static GtkObjectClass *e_table_parent_class; + +typedef struct { + ETableModel *table; + GnomeCanvasItem *table_item; + GnomeCanvasItem *rect; +} Leaf; + +typedef struct { +} Node; + + +static void +et_destroy (GtkObject *object) +{ + ETable *et = E_TABLE (object); + + gtk_object_unref (GTK_OBJECT (et->model)); + gtk_object_unref (GTK_OBJECT (et->full_header)); + gtk_object_unref (GTK_OBJECT (et->header)); + + g_free (et->group_spec); + + (*e_table_parent_class->destroy)(object); +} + +static void +e_table_init (GtkObject *object) +{ + ETable *e_table = E_TABLE (object); + + e_table->draw_grid = 1; + e_table->draw_focus = 1; + e_table->spreadsheet = 1; +} + +static ETableHeader * +e_table_make_header (ETable *e_table, ETableHeader *full_header, const char *cols) +{ + ETableHeader *nh; + char *copy = alloca (strlen (cols) + 1); + char *p, *state; + const int max_cols = e_table_header_count (full_header); + + nh = e_table_header_new (); + strcpy (copy, cols); + while ((p = strtok_r (copy, ",", &state)) != NULL){ + int col = atoi (p); + + copy = NULL; + if (col >= max_cols) + continue; + + e_table_header_add_column (nh, e_table_header_get_column (full_header, col), -1); + } + + return nh; +} + +static void +e_table_setup_header (ETable *e_table) +{ + e_table->header_canvas = GNOME_CANVAS (gnome_canvas_new ()); + + gtk_widget_show (GTK_WIDGET (e_table->header_canvas)); + + e_table->header_item = gnome_canvas_item_new ( + gnome_canvas_root (e_table->header_canvas), + e_table_header_item_get_type (), + "ETableHeader", e_table->header, + "x", 0, + "y", 0, + NULL); + + gtk_widget_set_usize (GTK_WIDGET (e_table->header_canvas), -1, COLUMN_HEADER_HEIGHT); + g_warning ("Aqui"); + e_table->header_canvas = 0; + + gtk_table_attach ( + GTK_TABLE (e_table), GTK_WIDGET (e_table->header_canvas), + 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0); + +} + +static Leaf * +e_table_create_leaf (ETable *e_table, int x_off, int y_off, ETableModel *etm) +{ + Leaf *leaf; + int height; + + leaf = g_new (Leaf, 1); + leaf->table = etm; + + leaf->table_item = gnome_canvas_item_new ( + gnome_canvas_root (e_table->table_canvas), + e_table_item_get_type (), + "ETableHeader", e_table->header, + "ETableModel", etm, + "x", x_off + GROUP_INDENT, + "y", y_off + TITLE_HEIGHT, + "drawgrid", e_table->draw_grid, + "drawfocus", e_table->draw_focus, + "spreadsheet", e_table->spreadsheet, + NULL); + + height = E_TABLE_ITEM (leaf->table_item)->height; + + leaf->rect = gnome_canvas_item_new ( + gnome_canvas_root (e_table->table_canvas), + gnome_canvas_rect_get_type (), + "x1", (double) x_off, + "y1", (double) y_off, + "x2", (double) x_off + e_table->gen_header_width + GROUP_INDENT, + "y2", (double) y_off + TITLE_HEIGHT + height, + "fill_color", "gray", + "outline_color", "gray20", + NULL); + gnome_canvas_item_lower (leaf->rect, 1); + + return leaf; +} + +typedef struct { + void *value; + GArray *array; +} group_key_t; + +static GArray * +e_table_create_groups (ETableModel *etm, int key_col, GCompareFunc comp) +{ + GArray *groups; + const int rows = e_table_model_row_count (etm); + int row, i; + + groups = g_array_new (FALSE, FALSE, sizeof (group_key_t)); + + for (row = 0; row < rows; row++){ + void *val = e_table_model_value_at (etm, key_col, row); + const int n_groups = groups->len; + + /* + * Should replace this with a bsearch later + */ + for (i = 0; i < n_groups; i++){ + group_key_t *g = &g_array_index (groups, group_key_t, i); + + if ((*comp) (g->value, val)){ + g_array_append_val (g->array, row); + break; + } + } + if (i != n_groups) + continue; + + /* + * We need to create a new group + */ + { + group_key_t gk; + + gk.value = val; + gk.array = g_array_new (FALSE, FALSE, sizeof (int)); + + g_array_append_val (gk.array, row); + g_array_append_val (groups, gk); + } + } + + return groups; +} + +static void +e_table_destroy_groups (GArray *groups) +{ + const int n = groups->len; + int i; + + for (i = 0; i < n; i++){ + group_key_t *g = &g_array_index (groups, group_key_t, i); + + g_array_free (g->array, TRUE); + } + g_array_free (groups, TRUE); +} + +static ETableModel ** +e_table_make_subtables (ETableModel *model, GArray *groups) +{ + const int n_groups = groups->len; + ETableModel **tables; + int i; + + tables = g_new (ETableModel *, n_groups+1); + + for (i = 0; i < n_groups; i++){ + group_key_t *g = &g_array_index (groups, group_key_t, i); + const int sub_size = g->array->len; + ETableSubset *ss; + int j; + + printf ("Creating subset of %d elements\n", sub_size); + tables [i] = e_table_subset_new (model, sub_size); + ss = E_TABLE_SUBSET (tables [i]); + + for (j = 0; j < sub_size; j++) + ss->map_table [j] = g_array_index (g->array, int, j); + } + tables [i] = NULL; + + return (ETableModel **) tables; +} + +static int +leaf_height (Leaf *leaf) +{ + return E_TABLE_ITEM (leaf->table_item)->height + TITLE_HEIGHT; +} + +static int +e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, + GnomeCanvasGroup *root, int x_off, int y_off, + int *groups_list) +{ + GArray *groups; + ETableModel **tables; + int key_col; + int height, i; + GCompareFunc comp; + + if (groups_list) + key_col = *groups_list; + else + key_col = -1; + + if (key_col == -1){ + Leaf *leaf; + + printf ("Leaf->with %d rows\n", e_table_model_row_count (model)); + leaf = e_table_create_leaf (e_table, x_off, y_off, model); + + { + static int warn_shown; + + if (!warn_shown){ + g_warning ("Leak"); + warn_shown = 1; + } + } + return leaf_height (leaf); + } + + /* + * Create groups + */ + comp = e_table_header_get_column (header, key_col)->compare; + groups = e_table_create_groups (model, key_col, comp); + tables = e_table_make_subtables (e_table->model, groups); + e_table_destroy_groups (groups); + + height = 0; + for (i = 0; tables [i] != NULL; i++){ + printf ("Creating->%d with %d rows\n", i, e_table_model_row_count (tables [i])); + height += e_table_create_nodes ( + e_table, tables [i], header, root, + x_off + 20, + y_off + height, &groups_list [1]); + } + + return height; +} + +static int * +group_spec_to_desc (const char *group_spec) { + int a_size = 10; + int *elements; + char *p, *copy, *follow; + int n_elements = 0; + + if (group_spec == NULL) + return NULL; + + elements = g_new (int, a_size); + copy = alloca (strlen (group_spec) + 1); + strcpy (copy, group_spec); + + while ((p = strtok_r (copy, ",", &follow)) != NULL){ + elements [n_elements] = atoi (p); + ++n_elements; + if (n_elements+1 == a_size){ + int *new_e; + + n_elements += 10; + new_e = g_renew (int, elements, n_elements); + if (new_e == NULL){ + g_free (elements); + return NULL; + } + elements = new_e; + } + copy = NULL; + } + + /* Tag end */ + elements [n_elements] = -1; + + return elements; +} + +/* + * The ETableCanvas object is just used to enable us to + * hook up to the realize/unrealize phases of the canvas + * initialization (as laying out the subtables requires us to + * know the actual size of the subtables we are inserting + */ + +#define E_TABLE_CANVAS_PARENT_TYPE gnome_canvas_get_type () + +typedef struct { + GnomeCanvas base; + + ETable *e_table; +} ETableCanvas; + +typedef struct { + GnomeCanvasClass base_class; +} ETableCanvasClass; + +static GnomeCanvasClass *e_table_canvas_parent_class; + +static void +e_table_canvas_realize (GtkWidget *widget) +{ + ETableCanvas *e_table_canvas = (ETableCanvas *) widget; + ETable *e_table = e_table_canvas->e_table; + int *groups; + int height; + + GTK_WIDGET_CLASS (e_table_canvas_parent_class)->realize (widget); + + groups = group_spec_to_desc (e_table->group_spec); + + e_table->root = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (e_table->table_canvas->root), + gnome_canvas_group_get_type (), + "x", 0.0, + "y", 0.0, + NULL); + + e_table->gen_header_width = e_table_header_total_width (e_table->header); + + height = e_table_create_nodes ( + e_table, e_table->model, + e_table->header, GNOME_CANVAS_GROUP (e_table->root), 0, 0, groups); + + { + static int warn_shown; + + if (!warn_shown){ + g_warning ("Precompute the width, and update on model changes"); + warn_shown = 1; + } + } + + gnome_canvas_set_scroll_region ( + GNOME_CANVAS (e_table_canvas), + 0, 0, + e_table_header_total_width (e_table->header) + 200, + height); + + if (groups) + g_free (groups); +} + +static void +e_table_canvas_unrealize (GtkWidget *widget) +{ + ETableCanvas *e_table_canvas = (ETableCanvas *) widget; + ETable *e_table = e_table_canvas->e_table; + + gtk_object_destroy (GTK_OBJECT (e_table->root)); + e_table->root = NULL; + + GTK_WIDGET_CLASS (e_table_canvas_parent_class)->unrealize (widget); +} + +static void +e_table_canvas_class_init (GtkObjectClass *object_class) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass *) object_class; + + widget_class->realize = e_table_canvas_realize; + widget_class->unrealize = e_table_canvas_unrealize; + + e_table_canvas_parent_class = gtk_type_class (E_TABLE_CANVAS_PARENT_TYPE); +} + +GtkType e_table_canvas_get_type (void); + +E_MAKE_TYPE (e_table_canvas, "ETableCanvas", ETableCanvas, e_table_canvas_class_init, + NULL, E_TABLE_CANVAS_PARENT_TYPE); + +static GnomeCanvas * +e_table_canvas_new (ETable *e_table) +{ + ETableCanvas *e_table_canvas; + + e_table_canvas = gtk_type_new (e_table_canvas_get_type ()); + e_table_canvas->e_table = e_table; + + return GNOME_CANVAS (e_table_canvas); +} + +static void +e_table_setup_table (ETable *e_table) +{ + e_table->table_canvas = e_table_canvas_new (e_table); + + gtk_widget_show (GTK_WIDGET (e_table->table_canvas)); + gtk_table_attach ( + GTK_TABLE (e_table), GTK_WIDGET (e_table->table_canvas), + 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); +} + +void +e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, + const char *cols_spec, const char *group_spec) +{ + GTK_TABLE (e_table)->homogeneous = FALSE; + + gtk_table_resize (GTK_TABLE (e_table), 1, 2); + + e_table->full_header = full_header; + gtk_object_ref (GTK_OBJECT (full_header)); + + e_table->model = etm; + gtk_object_ref (GTK_OBJECT (etm)); + + e_table->header = e_table_make_header (e_table, full_header, cols_spec); + + e_table_setup_header (e_table); + e_table_setup_table (e_table); + + e_table->group_spec = g_strdup (group_spec); + } +GtkWidget * +e_table_new (ETableHeader *full_header, ETableModel *etm, const char *cols_spec, const char *group_spec) +{ + ETable *e_table; + + e_table = gtk_type_new (e_table_get_type ()); + + e_table_construct (e_table, full_header, etm, cols_spec, group_spec); + + return (GtkWidget *) e_table; +} + +static void +e_table_class_init (GtkObjectClass *object_class) +{ + e_table_parent_class = gtk_type_class (PARENT_TYPE); + + object_class->destroy = et_destroy; +} + +E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, e_table_init, PARENT_TYPE); + diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h index 0847ddde6c..eb089781b9 100644 --- a/widgets/table/e-table.h +++ b/widgets/table/e-table.h @@ -1,6 +1,53 @@ #ifndef _E_TABLE_H_ #define _E_TABLE_H_ -GtkType e_table_get_type (void); -ETable * +#include <libgnomeui/gnome-canvas.h> +#include <gtk/gtktable.h> +#include "e-table-model.h" +#include "e-table-header.h" + +BEGIN_GNOME_DECLS + +#define E_TABLE_TYPE (e_table_get_type ()) +#define E_TABLE(o) (GTK_CHECK_CAST ((o), E_TABLE_TYPE, ETable)) +#define E_TABLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_TYPE, ETableClass)) +#define E_IS_TABLE(o) (GTK_CHECK_TYPE ((o), E_TABLE_TYPE)) +#define E_IS_TABLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_TYPE)) + +typedef struct { + GtkTable parent; + + ETableModel *model; + + ETableHeader *full_header, *header; + + GnomeCanvas *header_canvas, *table_canvas; + + GnomeCanvasItem *header_item, *root; + + guint draw_grid:1; + guint draw_focus:1; + guint spreadsheet:1; + + char *group_spec; + + /* + * Used during table generation + */ + int gen_header_width; +} ETable; + +typedef struct { + GtkTableClass parent_class; +} ETableClass; + +GtkType e_table_get_type (void); +void e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, + const char *cols_spec, const char *group_spec); +GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm, + const char *cols_spec, const char *group_spec); + + +END_GNOME_DECLS + #endif /* _E_TABLE_H_ */ diff --git a/widgets/table/sample.table b/widgets/table/sample.table index 2cb09d7f1f..45c8ff0691 100644 --- a/widgets/table/sample.table +++ b/widgets/table/sample.table @@ -5,4 +5,7 @@ c1.c c2.c a.c tit-1 DorkB c1.d c2.d a.d tit-2 ADork c1.e c2.e a.e tit-1 DorkC c1.f c2.f a.f tit-2 UDork +c1.g c2.g a.g tit-3 Dork--- +j k k tit-1 DorkA + diff --git a/widgets/table/table-test.c b/widgets/table/table-test.c index e60dd893fe..9de673ede4 100644 --- a/widgets/table/table-test.c +++ b/widgets/table/table-test.c @@ -10,6 +10,7 @@ #include <fcntl.h> #include <gnome.h> #include "e-cursors.h" +#include "table-test.h" int main (int argc, char *argv []) @@ -33,6 +34,8 @@ main (int argc, char *argv []) table_browser_test (); multi_cols_test (); check_test (); + e_table_test (); + gtk_main (); e_cursors_shutdown (); diff --git a/widgets/table/test-check.c b/widgets/table/test-check.c index 9968426327..9e003ce9a1 100644 --- a/widgets/table/test-check.c +++ b/widgets/table/test-check.c @@ -16,6 +16,8 @@ #include "e-cell-text.h" #include "e-cell-checkbox.h" +#include "table-test.h" + #define LINES 4 static struct { @@ -105,7 +107,7 @@ check_test (void) cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT); - cell_image_check = e_cell_checkbox_new (e_table_model); + cell_image_check = e_cell_checkbox_new (); col_0 = e_table_col_new (0, "", 18, 18, cell_image_check, g_int_equal, TRUE); e_table_header_add_column (e_table_header, col_0, 0); diff --git a/widgets/table/test-cols.c b/widgets/table/test-cols.c index 4406c6b3b9..b7979c2f3d 100644 --- a/widgets/table/test-cols.c +++ b/widgets/table/test-cols.c @@ -16,6 +16,8 @@ #include "e-cell-text.h" #include "e-cell-toggle.h" +#include "table-test.h" + #define LINES 4 static struct { @@ -90,7 +92,6 @@ multi_cols_test (void) ETableHeader *e_table_header, *e_table_header_multiple; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_toggle; - int i; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); @@ -114,7 +115,7 @@ multi_cols_test (void) images [1] = gdk_pixbuf_new_from_file ("image2.png"); images [2] = gdk_pixbuf_new_from_file ("image3.png"); - cell_image_toggle = e_cell_toggle_new (e_table_model, 0, 3, images); + cell_image_toggle = e_cell_toggle_new (0, 3, images); for (i = 0; i < 3; i++) gdk_pixbuf_unref (images [i]); diff --git a/widgets/table/test-table.c b/widgets/table/test-table.c index 04c40959af..83a130d72a 100644 --- a/widgets/table/test-table.c +++ b/widgets/table/test-table.c @@ -14,6 +14,9 @@ #include "e-table-item.h" #include "e-cursors.h" #include "e-cell-text.h" +#include "e-table.h" + +#include "table-test.h" char buffer [1024]; char **column_labels; @@ -97,6 +100,16 @@ load_data () { int i; + { + static int loaded; + + if (loaded) + return; + + loaded = TRUE; + } + + parse_headers (); while (fgets (buffer, sizeof (buffer)-1, stdin) != NULL){ @@ -231,3 +244,49 @@ table_browser_test (void) NULL); } +static void +do_e_table_demo (const char *col_spec, const char *group_spec) +{ + GtkWidget *e_table, *window; + ETableModel *e_table_model; + ECell *cell_left_just; + ETableHeader *full_header; + int i; + + /* + * Data model + */ + e_table_model = e_table_simple_new ( + col_count, row_count, value_at, + set_value_at, is_cell_editable, NULL); + + full_header = e_table_header_new (); + cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT); + + for (i = 0; i < cols; i++){ + ETableCol *ecol = e_table_col_new ( + i, column_labels [i], + 80, 20, cell_left_just, + g_str_equal, TRUE); + + e_table_header_add_column (full_header, ecol, i); + } + + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + e_table = e_table_new (full_header, e_table_model, col_spec, group_spec); + + gtk_container_add (GTK_CONTAINER (window), e_table); + + gtk_widget_show (e_table); + gtk_widget_show (window); +} + +void +e_table_test (void) +{ + load_data (); + do_e_table_demo ("0,1,2,3,4", NULL); + do_e_table_demo ("0,1,2,3,4", "3"); + do_e_table_demo ("0,1,2,3,4", "3,4"); +} diff --git a/widgets/test-check.c b/widgets/test-check.c index 9968426327..9e003ce9a1 100644 --- a/widgets/test-check.c +++ b/widgets/test-check.c @@ -16,6 +16,8 @@ #include "e-cell-text.h" #include "e-cell-checkbox.h" +#include "table-test.h" + #define LINES 4 static struct { @@ -105,7 +107,7 @@ check_test (void) cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT); - cell_image_check = e_cell_checkbox_new (e_table_model); + cell_image_check = e_cell_checkbox_new (); col_0 = e_table_col_new (0, "", 18, 18, cell_image_check, g_int_equal, TRUE); e_table_header_add_column (e_table_header, col_0, 0); diff --git a/widgets/test-cols.c b/widgets/test-cols.c index 4406c6b3b9..b7979c2f3d 100644 --- a/widgets/test-cols.c +++ b/widgets/test-cols.c @@ -16,6 +16,8 @@ #include "e-cell-text.h" #include "e-cell-toggle.h" +#include "table-test.h" + #define LINES 4 static struct { @@ -90,7 +92,6 @@ multi_cols_test (void) ETableHeader *e_table_header, *e_table_header_multiple; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_toggle; - int i; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); @@ -114,7 +115,7 @@ multi_cols_test (void) images [1] = gdk_pixbuf_new_from_file ("image2.png"); images [2] = gdk_pixbuf_new_from_file ("image3.png"); - cell_image_toggle = e_cell_toggle_new (e_table_model, 0, 3, images); + cell_image_toggle = e_cell_toggle_new (0, 3, images); for (i = 0; i < 3; i++) gdk_pixbuf_unref (images [i]); diff --git a/widgets/test-table.c b/widgets/test-table.c index 04c40959af..83a130d72a 100644 --- a/widgets/test-table.c +++ b/widgets/test-table.c @@ -14,6 +14,9 @@ #include "e-table-item.h" #include "e-cursors.h" #include "e-cell-text.h" +#include "e-table.h" + +#include "table-test.h" char buffer [1024]; char **column_labels; @@ -97,6 +100,16 @@ load_data () { int i; + { + static int loaded; + + if (loaded) + return; + + loaded = TRUE; + } + + parse_headers (); while (fgets (buffer, sizeof (buffer)-1, stdin) != NULL){ @@ -231,3 +244,49 @@ table_browser_test (void) NULL); } +static void +do_e_table_demo (const char *col_spec, const char *group_spec) +{ + GtkWidget *e_table, *window; + ETableModel *e_table_model; + ECell *cell_left_just; + ETableHeader *full_header; + int i; + + /* + * Data model + */ + e_table_model = e_table_simple_new ( + col_count, row_count, value_at, + set_value_at, is_cell_editable, NULL); + + full_header = e_table_header_new (); + cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT); + + for (i = 0; i < cols; i++){ + ETableCol *ecol = e_table_col_new ( + i, column_labels [i], + 80, 20, cell_left_just, + g_str_equal, TRUE); + + e_table_header_add_column (full_header, ecol, i); + } + + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + e_table = e_table_new (full_header, e_table_model, col_spec, group_spec); + + gtk_container_add (GTK_CONTAINER (window), e_table); + + gtk_widget_show (e_table); + gtk_widget_show (window); +} + +void +e_table_test (void) +{ + load_data (); + do_e_table_demo ("0,1,2,3,4", NULL); + do_e_table_demo ("0,1,2,3,4", "3"); + do_e_table_demo ("0,1,2,3,4", "3,4"); +} |