diff options
Diffstat (limited to 'widgets/table')
-rw-r--r-- | widgets/table/e-cell-checkbox.c | 4 | ||||
-rw-r--r-- | widgets/table/e-cell-checkbox.h | 2 | ||||
-rw-r--r-- | widgets/table/e-cell-text.c | 14 | ||||
-rw-r--r-- | widgets/table/e-cell-toggle.c | 22 | ||||
-rw-r--r-- | widgets/table/e-cell-toggle.h | 8 | ||||
-rw-r--r-- | widgets/table/e-cell.c | 6 | ||||
-rw-r--r-- | widgets/table/e-cell.h | 7 | ||||
-rw-r--r-- | widgets/table/e-table-header-item.c | 2 | ||||
-rw-r--r-- | widgets/table/e-table-header.c | 2 | ||||
-rw-r--r-- | widgets/table/e-table-item.c | 11 | ||||
-rw-r--r-- | widgets/table/e-table-subset.c | 75 | ||||
-rw-r--r-- | widgets/table/e-table-subset.h | 3 | ||||
-rw-r--r-- | widgets/table/e-table.c | 483 | ||||
-rw-r--r-- | widgets/table/e-table.h | 51 | ||||
-rw-r--r-- | widgets/table/sample.table | 3 | ||||
-rw-r--r-- | widgets/table/table-test.c | 3 | ||||
-rw-r--r-- | widgets/table/test-check.c | 4 | ||||
-rw-r--r-- | widgets/table/test-cols.c | 5 | ||||
-rw-r--r-- | widgets/table/test-table.c | 59 |
19 files changed, 694 insertions, 70 deletions
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"); +} |