From 385ccbd512c4c43305dee900f86d0f51f94b1200 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Thu, 25 Nov 1999 08:02:13 +0000 Subject: Realize cells. 1999-11-25 Miguel de Icaza * e-table-header-item.c (ethi_realize): Realize cells. * e-table-item.c (eti_header_dim_changed): redraw before and after. * e-table-header-item.c (ethi_event): Add continuous resizing. 1999-11-24 Miguel de Icaza * e-table-subset.h, e-table-subset.c: New files, used to implement subset tables. * e-table-sorted.h, e-table-sorted.c: Now they derive from e-table-subset. * e-cell.c, e-cell.h: realize method now return per view instance data. svn path=/trunk/; revision=1434 --- widgets/ChangeLog | 19 +++++ widgets/Makefile.am | 2 - widgets/ROADMAP.e-table | 19 +++-- widgets/e-cell-text.c | 139 +++++++++++++++++++++++++++++++--- widgets/e-cell-text.h | 9 ++- widgets/e-cell.c | 71 +++++++++++++++-- widgets/e-cell.h | 38 ++++++++-- widgets/e-table-col.c | 7 +- widgets/e-table-col.h | 17 ++--- widgets/e-table-header-item.c | 39 ++++++++-- widgets/e-table-header-item.h | 5 ++ widgets/e-table-item.c | 80 ++++++++++++++++--- widgets/e-table-item.h | 7 +- widgets/e-table-model.c | 35 +++++++++ widgets/e-table-model.h | 9 ++- widgets/e-table-simple.c | 4 +- widgets/e-table-sorted.c | 137 +++++++++------------------------ widgets/e-table-sorted.h | 19 ++--- widgets/e-table-subset.c | 114 ++++++++++++++++++++++------ widgets/e-table-subset.h | 12 +-- widgets/e-table.c | 26 ++----- widgets/e-table/ChangeLog | 19 +++++ widgets/e-table/Makefile.am | 2 - widgets/e-table/ROADMAP.e-table | 19 +++-- widgets/e-table/e-cell-text.c | 139 +++++++++++++++++++++++++++++++--- widgets/e-table/e-cell-text.h | 9 ++- widgets/e-table/e-cell.c | 71 +++++++++++++++-- widgets/e-table/e-cell.h | 38 ++++++++-- widgets/e-table/e-table-col.c | 7 +- widgets/e-table/e-table-col.h | 17 ++--- widgets/e-table/e-table-header-item.c | 39 ++++++++-- widgets/e-table/e-table-header-item.h | 5 ++ widgets/e-table/e-table-item.c | 80 ++++++++++++++++--- widgets/e-table/e-table-item.h | 7 +- widgets/e-table/e-table-model.c | 35 +++++++++ widgets/e-table/e-table-model.h | 9 ++- widgets/e-table/e-table-simple.c | 4 +- widgets/e-table/e-table-sorted.c | 137 +++++++++------------------------ widgets/e-table/e-table-sorted.h | 19 ++--- widgets/e-table/e-table-subset.c | 114 ++++++++++++++++++++++------ widgets/e-table/e-table-subset.h | 12 +-- widgets/e-table/e-table.c | 26 ++----- widgets/e-table/table-test.c | 8 +- widgets/table-test.c | 8 +- widgets/table/e-cell-text.c | 139 +++++++++++++++++++++++++++++++--- widgets/table/e-cell-text.h | 9 ++- widgets/table/e-cell.c | 71 +++++++++++++++-- widgets/table/e-cell.h | 38 ++++++++-- widgets/table/e-table-col.c | 7 +- widgets/table/e-table-col.h | 17 ++--- widgets/table/e-table-header-item.c | 39 ++++++++-- widgets/table/e-table-header-item.h | 5 ++ widgets/table/e-table-item.c | 80 ++++++++++++++++--- widgets/table/e-table-item.h | 7 +- widgets/table/e-table-model.c | 35 +++++++++ widgets/table/e-table-model.h | 9 ++- widgets/table/e-table-simple.c | 4 +- widgets/table/e-table-sorted.c | 137 +++++++++------------------------ widgets/table/e-table-sorted.h | 19 ++--- widgets/table/e-table-subset.c | 114 ++++++++++++++++++++++------ widgets/table/e-table-subset.h | 12 +-- widgets/table/e-table.c | 26 ++----- widgets/table/table-test.c | 8 +- 63 files changed, 1713 insertions(+), 695 deletions(-) diff --git a/widgets/ChangeLog b/widgets/ChangeLog index 188b1ff00c..973eb5d189 100644 --- a/widgets/ChangeLog +++ b/widgets/ChangeLog @@ -1,3 +1,22 @@ +1999-11-25 Miguel de Icaza + + * e-table-header-item.c (ethi_realize): Realize cells. + + * e-table-item.c (eti_header_dim_changed): redraw before and after. + + * e-table-header-item.c (ethi_event): Add continuous resizing. + +1999-11-24 Miguel de Icaza + + * e-table-subset.h, e-table-subset.c: New files, used to implement + subset tables. + + * e-table-sorted.h, e-table-sorted.c: Now they derive from + e-table-subset. + + * e-cell.c, e-cell.h: realize method now return per view instance + data. + 1999-11-20 Miguel de Icaza * e-table-item.c (eti_draw): WOOOOHOOOOOoO! It took me quite a diff --git a/widgets/Makefile.am b/widgets/Makefile.am index ac2858025c..d9748531d5 100644 --- a/widgets/Makefile.am +++ b/widgets/Makefile.am @@ -25,8 +25,6 @@ libevolutionwidgets_a_SOURCES = \ e-table-item.h \ e-table-model.c \ e-table-model.h \ - e-table-render.c \ - e-table-render.h \ e-table-simple.c \ e-table-simple.h \ e-table-sorted.c \ diff --git a/widgets/ROADMAP.e-table b/widgets/ROADMAP.e-table index 88afe506c3..65f19dabe1 100644 --- a/widgets/ROADMAP.e-table +++ b/widgets/ROADMAP.e-table @@ -29,14 +29,6 @@ e-table-simple.h, e-table-simple.c: routines (you provide the callbacks). For lazy people, like me. -e-table-header.h, e-table-header.c: - - These implement the ETableHeader model. They describe what - columns are shown in the screen and in which order. - - These emit signals: column-size-changed and structure-changed - (if a column is added/removed) - e-cell.c, e-cell.h: These are actually miss-named. Objects of type e-cell know @@ -60,6 +52,17 @@ e-table-col.h, e-table-col.c: * The Views +e-table-header.h, e-table-header.c: + + These implement the ETableHeaderItem canvas item. This item is + used both to control the columns displayed as well as displaying them. + + They describe what columns are shown in the screen and in + which order. + + These emit signals: column-size-changed and structure-changed + (if a column is added/removed) + e-table-item.c, e-table-item.h This is a canvas item that renders the contents of a diff --git a/widgets/e-cell-text.c b/widgets/e-cell-text.c index c30e42cfd3..1b3f524a2e 100644 --- a/widgets/e-cell-text.c +++ b/widgets/e-cell-text.c @@ -7,42 +7,157 @@ * (C) 1999 Helix Code, Inc */ #include +#include #include "e-cell-text.h" #include "e-util.h" -#define PARENT_TYPE gtk_object_get_type() +#define PARENT_TYPE e_cell_get_type() + +typedef struct { + ECellView cell_view; + GdkGC *gc; + GdkFont *font; + GnomeCanvas *canvas; +} ECellTextView; + +static ECellClass *parent_class; + +static ECellView * +ect_realize (ECell *ecell, GnomeCanvas *canvas) +{ + ECellText *ect = E_CELL_TEXT (ecell); + ECellTextView *ectv = g_new (ECellTextView, 1); + + ectv->cell_view.ecell = ecell; + ectv->gc = gdk_gc_new (GTK_WIDGET (canvas)->window); + ectv->font = gdk_fontset_load (ect->font_name ? ect->font_name : "fixed"); + ectv->canvas = canvas; + + return (ECellView *)ectv; +} static void -ec_realize (ECell *e_cell, GnomeCanvas *canvas) +ect_unrealize (ECellView *ecv) { + ECellTextView *ectv = (ECellTextView *) ecv; + + gdk_gc_unref (ectv->gc); + ectv->gc = NULL; + + gdk_font_unref (ectv->font); + ectv->font = NULL; + + g_free (ectv); } static void -ec_unrealize (ECell *e_cell) +ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2) { + ECellText *ect = E_CELL_TEXT (ecell_view->ecell); + GdkRectangle rect; + const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + int selected = e_table_model_get_selected_row (ecell_view->ecell->table_model) == row; + int xoff, w; + + rect.x = x1; + rect.y = y1; + rect.width = x2 - x1; + rect.height = y2 - y1; + + gdk_gc_set_clip_rectangle (ect->gc, &rect); + + switch (ect->justify){ + case GTK_JUSTIFY_LEFT: + xoff = 1; + break; + + case GTK_JUSTIFY_RIGHT: + w = 1 + gdk_text_width (ect->font, str, strlen (str)); + xoff = (x2 - x1) - w; + break; + + case GTK_JUSTIFY_CENTER: + xoff = ((x2 - x1) - gdk_text_width (ect->font, str, strlen (str))) / 2; + break; + default: + g_warning ("Can not handle GTK_JUSTIFY_FILL"); + break; + } + + /* Draw now */ + { + GtkWidget *w = GTK_WIDGET (ect->canvas); + GdkColor *background; + int idx; + + if (selected) + idx = GTK_STATE_SELECTED; + else + idx = GTK_STATE_NORMAL; + + gdk_gc_set_foreground (ect->gc, &w->style->bg [idx]); + gdk_draw_rectangle (drawable, ect->gc, TRUE, rect.x, rect.y, rect.width, rect.height); + gdk_gc_set_foreground (ect->gc, &w->style->fg [idx]); + gdk_draw_string (drawable, ect->font, ect->gc, x1 + xoff, y2 + ect->font->descent, str); + } } static void -ec_draw (ECell *ecell, int x1, int y1, int x2, int y2) +e_cell_text_start_editing (ECellText *ect, int col, int row) { + printf ("Starting to edit %d %d\n", col, row); } static gint -ec_event (ECell *ecell, GdkEvent *event) +ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) { + ECell *ecell = ecell_view->ecell; + ECellText *ect = E_CELL_TEXT (ecell); + + switch (event->type){ + case GDK_BUTTON_PRESS: + if (e_table_model_get_selected_row (ecell->table_model) == row) + e_cell_text_start_editing (ect, col, row); + else + e_table_model_select_row (ecell->table_model, row); + return TRUE; + } } static void -e_cell_class_init (GtkObjectClass *object_class) +ect_destroy (GtkObject *object) { - ECellClass *ecc = (ECellClass *) object_class; + ECellText *ect = E_CELL_TEXT (object); + + g_free (ect->font_name); - ecc->realize = ec_realize; - ecc->unrealize = ec_unrealize; - ecc->draw = ec_draw; - ecc->event = ec_event; + GTK_OBJECT_CLASS (parent_class)->destroy (object); } -E_MAKE_TYPE(e_cell, "ECell", ECell, e_cell_class_init, NULL, PARENT_TYPE); +static void +e_cell_text_class_init (GtkObjectClass *object_class) +{ + ECellClass *ecc = (ECellClass *) object_class; + object_class->destroy = ect_destroy; + ecc->realize = ect_realize; + ecc->unrealize = ect_unrealize; + ecc->draw = ect_draw; + ecc->event = ect_event; + + parent_class = gtk_type_class (PARENT_TYPE); +} + +E_MAKE_TYPE(e_cell_text, "ECellText", ECellText, e_cell_text_class_init, NULL, PARENT_TYPE); + +ECell * +e_cell_text_new (const char *fontname, GtkJustification justify) +{ + ECellText *ect = gtk_type_new (e_cell_text_get_type ()); + + ect->font_name = g_strdup (fontname); + ect->justify = justify; + + return (ECell *) ect; +} diff --git a/widgets/e-cell-text.h b/widgets/e-cell-text.h index 19d913a678..24def9f0f8 100644 --- a/widgets/e-cell-text.h +++ b/widgets/e-cell-text.h @@ -12,6 +12,13 @@ typedef struct { ECell parent; + + GdkGC *gc; + GdkFont *font; + GtkJustification justify; + + char *font_name; + GnomeCanvas *canvas; } ECellText; typedef struct { @@ -19,6 +26,6 @@ typedef struct { } ECellTextClass; GtkType e_cell_text_get_type (void); -ECell *e_cell_text_new (void); +ECell *e_cell_text_new (const char *fontname, GtkJustification justify); #endif /* _E_CELL_TEXT_H_ */ diff --git a/widgets/e-cell.c b/widgets/e-cell.c index e5ceb0fe8a..bff0fb88f2 100644 --- a/widgets/e-cell.c +++ b/widgets/e-cell.c @@ -12,24 +12,49 @@ #define PARENT_TYPE gtk_object_get_type() -static void +static ECellView * ec_realize (ECell *e_cell, GnomeCanvas *canvas) { + return NULL; } static void -ec_unrealize (ECell *e_cell) +ec_unrealize (ECellView *e_cell) { } static void -ec_draw (ECell *ecell, int x1, int y1, int x2, int y2) +ec_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2) { + g_warning ("e-cell-draw invoked\n"); } static gint -ec_event (ECell *ecell, GdkEvent *event) +ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row) { + g_warning ("e-cell-event invoked\n"); +} + +static void +ec_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2) +{ + ecell_view->focus_col = col; + ecell_view->focus_row = row; + ecell_view->focus_x1 = x1; + ecell_view->focus_y1 = y1; + ecell_view->focus_x2 = x2; + ecell_view->focus_y2 = y2; +} + +static void +ec_unfocus (ECellView *ecell_view) +{ + ecell_view->focus_col = -1; + ecell_view->focus_row = -1; + ecell_view->focus_x1 = -1; + ecell_view->focus_y1 = -1; + ecell_view->focus_x2 = -1; + ecell_view->focus_y2 = -1; } static void @@ -41,8 +66,44 @@ e_cell_class_init (GtkObjectClass *object_class) ecc->unrealize = ec_unrealize; ecc->draw = ec_draw; ecc->event = ec_event; + ecc->focus = ec_focus; + ecc->unfocus = ec_unfocus; +} + +static void +e_cell_init (GtkObject *object) +{ + ECell *e_cell = E_CELL (object); } -E_MAKE_TYPE(e_cell, "ECell", ECell, e_cell_class_init, NULL, PARENT_TYPE); +E_MAKE_TYPE(e_cell, "ECell", ECell, e_cell_class_init, e_cell_init, PARENT_TYPE); +void +e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +{ + E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->event ( + ecell_view, event, col, row); +} + +ECellView * +e_cell_realize (ECell *ecell, GnomeCanvas *canvas) +{ + return E_CELL_CLASS (GTK_OBJECT (ecell)->klass)->realize ( + ecell, canvas); +} + +void +e_cell_unrealize (ECellView *ecell_view) +{ + E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->unrealize (ecell_view); +} + +void +e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable, + int col, int row, int x1, int y1, int x2, int y2) +{ + E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->draw ( + ecell_view, drawable, col, row, x1, y1, x2, y2); +} + diff --git a/widgets/e-cell.h b/widgets/e-cell.h index 8395d3e290..0cafe0fff4 100644 --- a/widgets/e-cell.h +++ b/widgets/e-cell.h @@ -2,6 +2,7 @@ #define _E_CELL_H_ #include +#include "e-table-model.h" #define E_CELL_TYPE (e_cell_get_type ()) #define E_CELL(o) (GTK_CHECK_CAST ((o), E_CELL_TYPE, ECell)) @@ -9,19 +10,42 @@ #define E_IS_CELL(o) (GTK_CHECK_TYPE ((o), E_CELL_TYPE)) #define E_IS_CELL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_TYPE)) -typedef struct { +typedef struct _ECell ECell; +typedef struct _ECellView ECellView; + +struct _ECell { GtkObject object; -} ECell; + + ETableModel *table_model; +}; + +struct _ECellView { + ECell *ecell; + gint focus_x1, focus_y1, focus_x2, focus_y2; + gint focus_col, focus_row; +}; + +#define E_CELL_IS_FOCUSED(ecell_view) (ecell_view->focus_x1 != -1) typedef struct { GtkObjectClass parent_class; - void (*realize) (ECell *, GnomeCanvas *canvas); - void (*unrealize) (ECell *); - void (*draw) (ECell *ecell, int x1, int y1, int x2, int y2); - gint (*event) (ECell *ecell, GdkEvent *event); + ECellView *(*realize) (ECell *, GnomeCanvas *canvas); + void (*unrealize) (ECellView *); + void (*draw) (ECellView *ecell_view, GdkDrawable *drawable, + int col, int row, int x1, int y1, int x2, int y2); + gint (*event) (ECellView *ecell_view, GdkEvent *event, int col, int row); + void (*focus) (ECellView *ecell, int col, int row, int x1, int y1, int x2, int y2); + void (*unfocus) (ECellView *ecell); } ECellClass; -GtkType e_cell_get_type (void); +GtkType e_cell_get_type (void); +void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row); +ECellView *e_cell_realize (ECell *ecell, GnomeCanvas *canvas); +void e_cell_unrealize (ECellView *ecell); +void e_cell_draw (ECellView *ecell, GdkDrawable *dr, + int col, int row, int x1, int y1, int x2, int y2); +void e_cell_focus (ECellView *ecell, int col, int row, int x1, int y1, int x2, int y2); +void e_cell_unfocus (ECellView *ecell); #endif /* _E_CELL_H_ */ diff --git a/widgets/e-table-col.c b/widgets/e-table-col.c index c75bc6b195..4c61cddd0f 100644 --- a/widgets/e-table-col.c +++ b/widgets/e-table-col.c @@ -13,8 +13,7 @@ ETableCol * e_table_col_new (const char *id, int width, int min_width, - ETableColRenderFn render, void *render_data, - GCompareFunc compare, gboolean resizable) + ECell *ecell, GCompareFunc compare, gboolean resizable) { ETableCol *etc; @@ -22,7 +21,6 @@ e_table_col_new (const char *id, int width, int min_width, g_return_if_fail (width >= 0); g_return_if_fail (min_width >= 0); g_return_if_fail (width >= min_width); - g_return_if_fail (render != NULL); g_return_if_fail (compare != NULL); etc = g_new (ETableCol, 1); @@ -30,8 +28,7 @@ e_table_col_new (const char *id, int width, int min_width, etc->id = g_strdup (id); etc->width = width; etc->min_width = min_width; - etc->render = render; - etc->render_data = render_data; + etc->ecell = ecell; etc->compare = compare; etc->selected = 0; diff --git a/widgets/e-table-col.h b/widgets/e-table-col.h index 215df07797..950bf23352 100644 --- a/widgets/e-table-col.h +++ b/widgets/e-table-col.h @@ -2,13 +2,7 @@ #define _E_TABLE_COL_H_ typedef struct _ETableCol ETableCol; - -/* - * Rendering function for the column header - */ -typedef struct ERenderContext ERenderContext; - -typedef void (*ETableColRenderFn)(ERenderContext *ctxt); +typedef struct _ECell ECell; /* * Information about a single column @@ -18,16 +12,17 @@ struct _ETableCol { short width; short min_width; short x; - ETableColRenderFn render; GCompareFunc compare; - void *render_data; unsigned int selected:1; unsigned int resizeable:1; + + ECell *ecell; }; ETableCol *e_table_col_new (const char *id, int width, int min_width, - ETableColRenderFn render, void *render_data, - GCompareFunc compare, gboolean resizable); + ECell *ecell, GCompareFunc compare, + gboolean resizable); #endif /* _E_TABLE_COL_H_ */ + diff --git a/widgets/e-table-header-item.c b/widgets/e-table-header-item.c index dab5d3d71d..ab59d9a01c 100644 --- a/widgets/e-table-header-item.c +++ b/widgets/e-table-header-item.c @@ -157,6 +157,7 @@ ethi_realize (GnomeCanvasItem *item) ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); GdkWindow *window; GdkColor c; + int i; if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)-> realize) (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->realize)(item); @@ -171,13 +172,27 @@ ethi_realize (GnomeCanvasItem *item) if (!ethi->font) ethi_font_load (ethi, "fixed"); + + /* + * Now realize the various ECells + */ + ethi->n_cells = e_table_header_count (ethi->eth); + ethi->cell_views = g_new (ECellView *, ethi->n_cells); + + for (i = 0; i < ethi->n_cells; i++){ + ETableCol *col = e_table_header_get_column (ethi->eth, i); + + ethi->cell_views [i] = e_cell_realize (col->ecell, item->canvas); + } + } static void ethi_unrealize (GnomeCanvasItem *item) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); - + int i; + gdk_gc_unref (ethi->gc); ethi->gc = NULL; @@ -187,6 +202,14 @@ ethi_unrealize (GnomeCanvasItem *item) gdk_cursor_destroy (ethi->normal_cursor); ethi->normal_cursor = NULL; + for (i = 0; i < ethi->n_cells; i++){ + ETableCol *col = e_table_header_get_column (ethi->eth, i); + + e_cell_unrealize (col->ecell, ethi->cell_views [i]); + ethi->cell_views = NULL; + } + g_free (ethi->cell_views); + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize) (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item); } @@ -244,8 +267,10 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int wid total = 0; x = -x1; +#if 0 printf ("My coords are: %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2); +#endif for (col = 0; col < cols; col++){ ETableCol *ecol = e_table_header_get_column (ethi->eth, col); @@ -353,11 +378,6 @@ ethi_end_resize (ETableHeaderItem *ethi, int new_size) { e_table_header_set_size (ethi->eth, ethi->resize_col, new_size); - if (ethi->resize_guide){ -#warning Fix this - /* gtk_object_destroy (ethi->resize_guide);*/ - ethi->resize_guide = NULL; - } ethi->resize_col = -1; ethi_request_redraw (ethi); } @@ -394,9 +414,12 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (x - ethi->resize_start_pos <= 0) break; - + + ethi_request_redraw (ethi); + ethi->resize_width = x - ethi->resize_start_pos; - + e_table_header_set_size (ethi->eth, ethi->resize_col, ethi->resize_width); + ethi_request_redraw (ethi); } else set_cursor (ethi, x); diff --git a/widgets/e-table-header-item.h b/widgets/e-table-header-item.h index d6b7d64a9f..10b84e1897 100644 --- a/widgets/e-table-header-item.h +++ b/widgets/e-table-header-item.h @@ -10,6 +10,8 @@ #define E_IS_TABLE_HEADER_ITEM(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_ITEM_TYPE)) #define E_IS_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_ITEM_TYPE)) +typedef struct _ECellView ECellView; + typedef struct { GnomeCanvasItem parent; ETableHeader *eth; @@ -28,6 +30,9 @@ typedef struct { int resize_start_pos; GtkObject *resize_guide; + ECellView **cell_views; + int n_cells; + /* * Ids */ diff --git a/widgets/e-table-item.c b/widgets/e-table-item.c index 1e53180804..5bf1e24fd0 100644 --- a/widgets/e-table-item.c +++ b/widgets/e-table-item.c @@ -44,9 +44,11 @@ eti_remove_table_model (ETableItem *eti) return; gtk_signal_disconnect (eti->table_model_change_id); + gtk_signal_disconnect (eti->table_model_selection_id); gtk_object_unref (GTK_OBJECT (eti->table_model)); eti->table_model_change_id = 0; + eti->table_model_selection_id = 0; eti->table_model = NULL; } @@ -73,6 +75,23 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti) eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); } +static void +eti_request_redraw (ETableItem *eti) +{ + GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; + + gnome_canvas_request_redraw (canvas, eti->x1, eti->y1, + eti->x1 + eti->width + 1, + eti->y1 + eti->height + 1); +} + +static void +eti_table_model_row_selection (ETableModel *table_model, ETableItem *eti) +{ + /* FIXME: we should optimize this to only redraw the selection change */ + eti_request_redraw (eti); +} + static void eti_add_table_model (ETableItem *eti, ETableModel *table_model) { @@ -83,31 +102,30 @@ eti_add_table_model (ETableItem *eti, ETableModel *table_model) eti->table_model_change_id = gtk_signal_connect ( GTK_OBJECT (table_model), "model_changed", GTK_SIGNAL_FUNC (eti_table_model_changed), eti); -} - -static void -eti_request_redraw (ETableItem *eti) -{ - GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; - - gnome_canvas_request_redraw (canvas, eti->x1, eti->y1, eti->x1 + eti->width, eti->y1 + eti->height); + eti->table_model_selection_id = gtk_signal_connect ( + GTK_OBJECT (table_model), "row_selection", + GTK_SIGNAL_FUNC (eti_table_model_row_selection), eti); } static void eti_header_dim_changed (ETableHeader *eth, int col, ETableItem *eti) { - eti->width = e_table_header_total_width (eti->header); + eti_request_redraw (eti); + eti->width = e_table_header_total_width (eti->header); eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); + eti_request_redraw (eti); } static void eti_header_structure_changed (ETableHeader *eth, ETableItem *eti) { - eti->width = e_table_header_total_width (eti->header); + eti_request_redraw (eti); + eti->width = e_table_header_total_width (eti->header); eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); + eti_request_redraw (eti); } @@ -181,6 +199,9 @@ static void eti_init (GnomeCanvasItem *item) { ETableItem *eti = E_TABLE_ITEM (item); + + eti->focused_col = -1; + eti->focused_row = -1; } static void @@ -199,6 +220,7 @@ eti_realize (GnomeCanvasItem *item) gdk_gc_ref (canvas_widget->style->white_gc); eti->grid_gc = gdk_gc_new (window); gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->fg [GTK_STATE_NORMAL]); + } static void @@ -277,7 +299,10 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, if (first_col == -1) return; +#if 0 printf ("Cols %d %d\n", first_col, last_col); +#endif + /* * Draw individual lines */ @@ -318,6 +343,25 @@ eti_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, static int eti_event (GnomeCanvasItem *item, GdkEvent *e) { + ETableItem *eti = E_TABLE_ITEM (item); + ETableCol *etc; + + switch (e->type){ + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_2BUTTON_PRESS: + + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: + if (eti->focused_col == -1) + return FALSE; + + etc = e_table_header_get_column (eti->header, eti->focused_col); + + e_cell_event (etc->ecell, e, eti->focused_col, eti->focused_row); + break; + + } return FALSE; } @@ -371,3 +415,19 @@ e_table_item_get_type (void) return type; } +void +e_table_item_focus (ETableItem *eti, int col, int row) +{ + if (eti->focused_col != -1) + e_table_item_unfocus (eti); + + eti->focused_col = col; + eti->focused_row = row; +} + +void +e_table_item_unfocus (ETableItem *eti) +{ + eti->focused_col = -1; + eti->focused_row = -1; +} diff --git a/widgets/e-table-item.h b/widgets/e-table-item.h index 7e548cf49d..fefa221227 100644 --- a/widgets/e-table-item.h +++ b/widgets/e-table-item.h @@ -27,11 +27,14 @@ typedef struct { int header_dim_change_id; int header_structure_change_id; int table_model_change_id; - + int table_model_selection_id; + GdkGC *fill_gc; GdkGC *grid_gc; unsigned int draw_grid:1; + + int focused_col, focused_row; } ETableItem; typedef struct { @@ -39,5 +42,7 @@ typedef struct { } ETableItemClass; GtkType e_table_item_get_type (void); +void e_table_item_focus (ETableItem *eti, int col, int row); +void e_table_item_unfocus (ETableItem *eti); #endif /* _E_TABLE_ITEM_H_ */ diff --git a/widgets/e-table-model.c b/widgets/e-table-model.c index de7bc67c51..1176b33ec7 100644 --- a/widgets/e-table-model.c +++ b/widgets/e-table-model.c @@ -16,6 +16,7 @@ static GtkObjectClass *e_table_model_parent_class; enum { MODEL_CHANGED, + ROW_SELECTION, LAST_SIGNAL }; @@ -88,6 +89,14 @@ e_table_model_class_init (GtkObjectClass *object_class) GTK_SIGNAL_OFFSET (ETableModelClass, model_changed), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); + + etm_signals [ROW_SELECTION] = + gtk_signal_new ("row_selection", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableModelClass, row_selection), + gtk_marshal_NONE__INT_INT, + GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); gtk_object_class_add_signals (object_class, etm_signals, LAST_SIGNAL); } @@ -158,3 +167,29 @@ e_table_model_max_col_width (ETableModel *etm, int col) return max; } #endif + +void +e_table_model_select_row (ETableModel *etm, int row) +{ + gtk_signal_emit (GTK_OBJECT (etm), etm_signals [ROW_SELECTION], row, 1); + etm->row_selected = row; +} + +void +e_table_model_unselect_row (ETableModel *etm, int row) +{ + if (etm->row_selected != -1){ + gtk_signal_emit ( + GTK_OBJECT (etm), etm_signals [ROW_SELECTION], + etm->row_selected, 0); + } + + etm->row_selected = -1; +} + +gint +e_table_model_get_selected_row (ETableModel *etm) +{ + return etm->row_selected; +} + diff --git a/widgets/e-table-model.h b/widgets/e-table-model.h index d12a465c0b..2d439a0065 100644 --- a/widgets/e-table-model.h +++ b/widgets/e-table-model.h @@ -11,6 +11,9 @@ typedef struct { GtkObject base; + + /* Temporary. I swear */ + int row_selected; } ETableModel; typedef struct { @@ -30,7 +33,8 @@ typedef struct { /* * Signals */ - void (*model_changed) (ETableModel *etm, int row); + void (*model_changed) (ETableModel *etm); + void (*row_selection) (ETableModel *etc, int row); } ETableModelClass; GtkType e_table_model_get_type (void); @@ -44,6 +48,9 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col, void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data); gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row); +void e_table_model_select_row (ETableModel *e_table_model, int row); +gint e_table_model_get_selected_row (ETableModel *e_table_model); + /* * Routines for emitting signals on the e_table */ diff --git a/widgets/e-table-simple.c b/widgets/e-table-simple.c index 32f7145bc6..b23cda1220 100644 --- a/widgets/e-table-simple.c +++ b/widgets/e-table-simple.c @@ -12,6 +12,8 @@ #include #include "e-table-simple.h" +#define PARENT_TYPE e_table_model_get_type() + static int simple_column_count (ETableModel *etm) { @@ -99,7 +101,7 @@ e_table_simple_get_type (void) (GtkClassInitFunc) NULL }; - type = gtk_type_unique (e_table_model_get_type (), &info); + type = gtk_type_unique (PARENT_TYPE, &info); } return type; diff --git a/widgets/e-table-sorted.c b/widgets/e-table-sorted.c index 2d53c79e5d..be19de2efb 100644 --- a/widgets/e-table-sorted.c +++ b/widgets/e-table-sorted.c @@ -11,93 +11,16 @@ #include "e-util.h" #include "e-table-sorted.h" -#define PARENT_TYPE E_TABLE_MODEL_TYPE +#define PARENT_TYPE E_TABLE_SUBSET_TYPE static ETableModelClass *ets_parent_class; -static void -ets_destroy (GtkObject *object) -{ - ETableSorted *ets = E_TABLE_SORTED (object); - - gtk_object_unref (GTK_OBJECT (ets->source)); - gtk_object_unref (GTK_OBJECT (ets->header)); - free (ets->map_table); - - GTK_OBJECT_CLASS (ets_parent_class)->destroy (object); -} - -static int -ets_column_count (ETableModel *etm) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_column_count (ets->source); -} - -static const char * -ets_column_name (ETableModel *etm, int col) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_column_name (ets->source, col); -} - -static int -ets_row_count (ETableModel *etm) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_row_count (ets->source); -} - -static void * -ets_value_at (ETableModel *etm, int col, int row) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_value_at (ets->source, col, ets->map_table [row]); -} - -static void -ets_set_value_at (ETableModel *etm, int col, int row, void *val) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_set_value_at (ets->source, col, ets->map_table [row], val); -} - -static gboolean -ets_is_cell_editable (ETableModel *etm, int col, int row) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_is_cell_editable (ets->source, col, ets->map_table [row]); -} - -static int -ets_row_height (ETableModel *etm, int row) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_row_height (ets->source, ets->map_table [row]); -} - static void ets_class_init (GtkObjectClass *klass) { ETableModelClass *table_class = (ETableModelClass *) klass; ets_parent_class = gtk_type_class (PARENT_TYPE); - klass->destroy = ets_destroy; - - table_class->column_count = ets_column_count; - table_class->column_name = ets_column_name; - table_class->row_count = ets_row_count; - table_class->value_at = ets_value_at; - table_class->set_value_at = ets_set_value_at; - table_class->is_cell_editable = ets_is_cell_editable; - table_class->row_height = ets_row_height; } E_MAKE_TYPE(e_table_sorted, "ETableSorted", ETableSorted, ets_class_init, NULL, PARENT_TYPE); @@ -108,49 +31,63 @@ static int my_sort (const void *a, const void *b) { GCompareFunc comp; + ETableModel *source = E_TABLE_SUBSET (sort_ets)->source; const int *ia = (const int *) a; const int *ib = (const int *) b; void *va, *vb; - va = e_table_model_value_at (sort_ets->source, sort_ets->sort_idx, *ia); - vb = e_table_model_value_at (sort_ets->source, sort_ets->sort_idx, *ib); + va = e_table_model_value_at (source, sort_ets->sort_col, *ia); + vb = e_table_model_value_at (source, sort_ets->sort_col, *ib); - comp = sort_ets->sort_col->compare; + return (*sort_ets->compare) (va, vb); +} - return (*comp) (va, vb); +static void +do_sort (ETableSorted *ets) +{ + ETableSubset *etss = E_TABLE_SUBSET (ets); + g_assert (sort_ets == NULL); + + sort_ets = ets; + qsort (etss->map_table, etss->n_map, sizeof (unsigned int), my_sort); + sort_ets = NULL; } ETableModel * -e_table_sorted_new (ETableModel *source, ETableHeader *header, short sort_field) +e_table_sorted_new (ETableModel *source, int col, GCompareFunc compare) { ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE); + ETableSubset *etss = E_TABLE_SUBSET (ets); const int nvals = e_table_model_row_count (source); unsigned int *buffer; int i; - buffer = malloc (sizeof (unsigned int *) * nvals); - if (buffer = NULL) + if (e_table_subset_construct (etss, source, nvals) == NULL){ + gtk_object_destroy (GTK_OBJECT (ets)); return NULL; - ets->map_table = buffer; - ets->n_map = nvals; - ets->source = source; - ets->header = header; - ets->sort_col = e_table_header_get_column (header, sort_field); - ets->sort_idx = sort_field; - gtk_object_ref (GTK_OBJECT (source)); - gtk_object_ref (GTK_OBJECT (header)); + } + + ets->compare = compare; + ets->sort_col = col; /* Init */ for (i = 0; i < nvals; i++) - ets->map_table [i] = i; + etss->map_table [i] = i; - /* Sort */ - g_assert (sort_ets == NULL); - sort_ets = ets; - qsort (ets->map_table, nvals, sizeof (unsigned int), my_sort); - sort_ets = NULL; + do_sort (ets); return (ETableModel *) ets; } - +void +e_table_sorted_resort (ETableSorted *ets, int col, GCompareFunc compare) +{ + if (col == -1 || compare == NULL) + do_sort (ets); + else { + ets->sort_col = col; + ets->compare = compare; + do_sort (ets); + } +} + diff --git a/widgets/e-table-sorted.h b/widgets/e-table-sorted.h index 65578b7b83..2ec52df2e7 100644 --- a/widgets/e-table-sorted.h +++ b/widgets/e-table-sorted.h @@ -3,7 +3,7 @@ #include #include "e-table-model.h" -#include "e-table-header.h" +#include "e-table-subset.h" #define E_TABLE_SORTED_TYPE (e_table_sorted_get_type ()) #define E_TABLE_SORTED(o) (GTK_CHECK_CAST ((o), E_TABLE_SORTED_TYPE, ETableSorted)) @@ -12,23 +12,18 @@ #define E_IS_TABLE_SORTED_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SORTED_TYPE)) typedef struct { - ETableModel base; + ETableSubset base; - ETableModel *source; - ETableHeader *header; - ETableCol *sort_col; - short sort_idx; - - int n_map; - unsigned int *map_table; + short sort_col; + GCompareFunc compare; } ETableSorted; typedef struct { - ETableModelClass parent_class; + ETableSubset parent_class; } ETableSortedClass; GtkType e_table_sorted_get_type (void); -ETableModel *e_table_sorted_new (ETableModel *etm, ETableHeader *header, - short sort_field); +ETableModel *e_table_sorted_new (ETableModel *etm, int col, GCompareFunc compare); +void e_table_sorted_resort (ETableSorted *ets, int col, GCompareFunc compare); #endif /* _E_TABLE_SORTED_H_ */ diff --git a/widgets/e-table-subset.c b/widgets/e-table-subset.c index 0b9621ac84..afa1b862b4 100644 --- a/widgets/e-table-subset.c +++ b/widgets/e-table-subset.c @@ -19,52 +19,122 @@ etss_destroy (GtkObject *object) { ETableSubset *etss = E_TABLE_SUBSET (object); - gtk_object_unref (GTK_OBJECT (etss->source)); - free (ets->subset_table); + if (etss->source) + gtk_object_unref (GTK_OBJECT (etss->source)); - GTK_OBJECT_CLASS (ets_parent_class)->destroy (object); + if (etss->map_table) + free (etss->map_table); + + GTK_OBJECT_CLASS (etss_parent_class)->destroy (object); +} + +static int +etss_column_count (ETableModel *etm) +{ + ETableSubset *etss = (ETableSubset *)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); +} + +static void * +etss_value_at (ETableModel *etm, int col, int row) +{ + ETableSubset *etss = (ETableSubset *)etm; + + return e_table_model_value_at (etss->source, col, etss->map_table [row]); +} + +static void +etss_set_value_at (ETableModel *etm, int col, int row, void *val) +{ + ETableSubset *etss = (ETableSubset *)etm; + + return e_table_model_set_value_at (etss->source, col, etss->map_table [row], val); +} + +static gboolean +etss_is_cell_editable (ETableModel *etm, int col, int row) +{ + ETableSubset *etss = (ETableSubset *)etm; + + 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) { + ETableModelClass *table_class = (ETableModelClass *) klass; + etss_parent_class = gtk_type_class (PARENT_TYPE); 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); ETableModel * -e_table_subset_new (ETableModel *source, ETableHeader *header, short sort_field) +e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) { - ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE); - const int nvals = e_table_model_row_count (source); unsigned int *buffer; int i; - buffer = malloc (sizeof (unsigned int *) * nvals); + buffer = (unsigned int *) malloc (sizeof (unsigned int *) * nvals); if (buffer = NULL) return NULL; - ets->map_table = buffer; - ets->n_map = nvals; - ets->source = source; - ets->header = header; - ets->sort_col = e_table_header_get_column (header, sort_field); - ets->sort_idx = sort_field; + etss->map_table = buffer; + etss->n_map = nvals; + etss->source = source; gtk_object_ref (GTK_OBJECT (source)); - gtk_object_ref (GTK_OBJECT (header)); /* Init */ for (i = 0; i < nvals; i++) - ets->map_table [i] = i; + etss->map_table [i] = i; - /* Sort */ - g_assert (sort_ets == NULL); - sort_ets = ets; - qsort (ets->map_table, nvals, sizeof (unsigned int), my_sort); - sort_ets = NULL; - - return (ETableModel *) ets; +} + +ETableModel * +e_table_subset_new (ETableModel *source, const int nvals) +{ + ETableSubset *etss = gtk_type_new (E_TABLE_SUBSET_TYPE); + + if (e_table_subset_construct (etss, source, nvals) == NULL){ + gtk_object_destroy (GTK_OBJECT (etss)); + return NULL; + } + + return (ETableModel *) etss; } diff --git a/widgets/e-table-subset.h b/widgets/e-table-subset.h index a87d6d0df8..5576c55f1d 100644 --- a/widgets/e-table-subset.h +++ b/widgets/e-table-subset.h @@ -3,7 +3,6 @@ #include #include "e-table-model.h" -#include "e-table-header.h" #define E_TABLE_SUBSET_TYPE (e_table_subset_get_type ()) #define E_TABLE_SUBSET(o) (GTK_CHECK_CAST ((o), E_TABLE_SUBSET_TYPE, ETableSubset)) @@ -15,15 +14,16 @@ typedef struct { ETableModel base; ETableModel *source; - int subset_count; - int *subset_table; + int n_map; + int *map_table; } ETableSubset; typedef struct { ETableModelClass parent_class; } ETableSubsetClass; -GtkType e_table_subset_get_type (void); -ETableModel *e_table_subset_new (ETableModel *etm, - int n_vals, int *ptrs); +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); + #endif /* _E_TABLE_SUBSET_H_ */ diff --git a/widgets/e-table.c b/widgets/e-table.c index 795c737b36..3b13e87d6b 100644 --- a/widgets/e-table.c +++ b/widgets/e-table.c @@ -9,28 +9,14 @@ #include #include #include "e-table.h" +#include "e-util.h" #define PARENT_OBJECT_TYPE gnome_canvas_get_type () -GtkType -e_table_get_type (void) -{ - static GtkType type = 0; - - if (!type){ - GtkTypeInfo info = { - "ETable", - sizeof (ETable), - sizeof (ETableClass), - (GtkClassInitFunc) e_table_class_init, - (GtkObjectInitFunc) NULL, - NULL, /* reserved 1 */ - NULL, /* reserved 2 */ - (GtkClassInitFunc) NULL - }; - - type = gtk_type_unique (PARENT_OBJECT_TYPE, &info); - } +E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, NULL, PARENT_TYPE); - return type; +ETable * +e_table_new (ETableHeader *eth, ETableModel *etm) +{ } + diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog index 188b1ff00c..973eb5d189 100644 --- a/widgets/e-table/ChangeLog +++ b/widgets/e-table/ChangeLog @@ -1,3 +1,22 @@ +1999-11-25 Miguel de Icaza + + * e-table-header-item.c (ethi_realize): Realize cells. + + * e-table-item.c (eti_header_dim_changed): redraw before and after. + + * e-table-header-item.c (ethi_event): Add continuous resizing. + +1999-11-24 Miguel de Icaza + + * e-table-subset.h, e-table-subset.c: New files, used to implement + subset tables. + + * e-table-sorted.h, e-table-sorted.c: Now they derive from + e-table-subset. + + * e-cell.c, e-cell.h: realize method now return per view instance + data. + 1999-11-20 Miguel de Icaza * e-table-item.c (eti_draw): WOOOOHOOOOOoO! It took me quite a diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am index ac2858025c..d9748531d5 100644 --- a/widgets/e-table/Makefile.am +++ b/widgets/e-table/Makefile.am @@ -25,8 +25,6 @@ libevolutionwidgets_a_SOURCES = \ e-table-item.h \ e-table-model.c \ e-table-model.h \ - e-table-render.c \ - e-table-render.h \ e-table-simple.c \ e-table-simple.h \ e-table-sorted.c \ diff --git a/widgets/e-table/ROADMAP.e-table b/widgets/e-table/ROADMAP.e-table index 88afe506c3..65f19dabe1 100644 --- a/widgets/e-table/ROADMAP.e-table +++ b/widgets/e-table/ROADMAP.e-table @@ -29,14 +29,6 @@ e-table-simple.h, e-table-simple.c: routines (you provide the callbacks). For lazy people, like me. -e-table-header.h, e-table-header.c: - - These implement the ETableHeader model. They describe what - columns are shown in the screen and in which order. - - These emit signals: column-size-changed and structure-changed - (if a column is added/removed) - e-cell.c, e-cell.h: These are actually miss-named. Objects of type e-cell know @@ -60,6 +52,17 @@ e-table-col.h, e-table-col.c: * The Views +e-table-header.h, e-table-header.c: + + These implement the ETableHeaderItem canvas item. This item is + used both to control the columns displayed as well as displaying them. + + They describe what columns are shown in the screen and in + which order. + + These emit signals: column-size-changed and structure-changed + (if a column is added/removed) + e-table-item.c, e-table-item.h This is a canvas item that renders the contents of a diff --git a/widgets/e-table/e-cell-text.c b/widgets/e-table/e-cell-text.c index c30e42cfd3..1b3f524a2e 100644 --- a/widgets/e-table/e-cell-text.c +++ b/widgets/e-table/e-cell-text.c @@ -7,42 +7,157 @@ * (C) 1999 Helix Code, Inc */ #include +#include #include "e-cell-text.h" #include "e-util.h" -#define PARENT_TYPE gtk_object_get_type() +#define PARENT_TYPE e_cell_get_type() + +typedef struct { + ECellView cell_view; + GdkGC *gc; + GdkFont *font; + GnomeCanvas *canvas; +} ECellTextView; + +static ECellClass *parent_class; + +static ECellView * +ect_realize (ECell *ecell, GnomeCanvas *canvas) +{ + ECellText *ect = E_CELL_TEXT (ecell); + ECellTextView *ectv = g_new (ECellTextView, 1); + + ectv->cell_view.ecell = ecell; + ectv->gc = gdk_gc_new (GTK_WIDGET (canvas)->window); + ectv->font = gdk_fontset_load (ect->font_name ? ect->font_name : "fixed"); + ectv->canvas = canvas; + + return (ECellView *)ectv; +} static void -ec_realize (ECell *e_cell, GnomeCanvas *canvas) +ect_unrealize (ECellView *ecv) { + ECellTextView *ectv = (ECellTextView *) ecv; + + gdk_gc_unref (ectv->gc); + ectv->gc = NULL; + + gdk_font_unref (ectv->font); + ectv->font = NULL; + + g_free (ectv); } static void -ec_unrealize (ECell *e_cell) +ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2) { + ECellText *ect = E_CELL_TEXT (ecell_view->ecell); + GdkRectangle rect; + const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + int selected = e_table_model_get_selected_row (ecell_view->ecell->table_model) == row; + int xoff, w; + + rect.x = x1; + rect.y = y1; + rect.width = x2 - x1; + rect.height = y2 - y1; + + gdk_gc_set_clip_rectangle (ect->gc, &rect); + + switch (ect->justify){ + case GTK_JUSTIFY_LEFT: + xoff = 1; + break; + + case GTK_JUSTIFY_RIGHT: + w = 1 + gdk_text_width (ect->font, str, strlen (str)); + xoff = (x2 - x1) - w; + break; + + case GTK_JUSTIFY_CENTER: + xoff = ((x2 - x1) - gdk_text_width (ect->font, str, strlen (str))) / 2; + break; + default: + g_warning ("Can not handle GTK_JUSTIFY_FILL"); + break; + } + + /* Draw now */ + { + GtkWidget *w = GTK_WIDGET (ect->canvas); + GdkColor *background; + int idx; + + if (selected) + idx = GTK_STATE_SELECTED; + else + idx = GTK_STATE_NORMAL; + + gdk_gc_set_foreground (ect->gc, &w->style->bg [idx]); + gdk_draw_rectangle (drawable, ect->gc, TRUE, rect.x, rect.y, rect.width, rect.height); + gdk_gc_set_foreground (ect->gc, &w->style->fg [idx]); + gdk_draw_string (drawable, ect->font, ect->gc, x1 + xoff, y2 + ect->font->descent, str); + } } static void -ec_draw (ECell *ecell, int x1, int y1, int x2, int y2) +e_cell_text_start_editing (ECellText *ect, int col, int row) { + printf ("Starting to edit %d %d\n", col, row); } static gint -ec_event (ECell *ecell, GdkEvent *event) +ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) { + ECell *ecell = ecell_view->ecell; + ECellText *ect = E_CELL_TEXT (ecell); + + switch (event->type){ + case GDK_BUTTON_PRESS: + if (e_table_model_get_selected_row (ecell->table_model) == row) + e_cell_text_start_editing (ect, col, row); + else + e_table_model_select_row (ecell->table_model, row); + return TRUE; + } } static void -e_cell_class_init (GtkObjectClass *object_class) +ect_destroy (GtkObject *object) { - ECellClass *ecc = (ECellClass *) object_class; + ECellText *ect = E_CELL_TEXT (object); + + g_free (ect->font_name); - ecc->realize = ec_realize; - ecc->unrealize = ec_unrealize; - ecc->draw = ec_draw; - ecc->event = ec_event; + GTK_OBJECT_CLASS (parent_class)->destroy (object); } -E_MAKE_TYPE(e_cell, "ECell", ECell, e_cell_class_init, NULL, PARENT_TYPE); +static void +e_cell_text_class_init (GtkObjectClass *object_class) +{ + ECellClass *ecc = (ECellClass *) object_class; + object_class->destroy = ect_destroy; + ecc->realize = ect_realize; + ecc->unrealize = ect_unrealize; + ecc->draw = ect_draw; + ecc->event = ect_event; + + parent_class = gtk_type_class (PARENT_TYPE); +} + +E_MAKE_TYPE(e_cell_text, "ECellText", ECellText, e_cell_text_class_init, NULL, PARENT_TYPE); + +ECell * +e_cell_text_new (const char *fontname, GtkJustification justify) +{ + ECellText *ect = gtk_type_new (e_cell_text_get_type ()); + + ect->font_name = g_strdup (fontname); + ect->justify = justify; + + return (ECell *) ect; +} diff --git a/widgets/e-table/e-cell-text.h b/widgets/e-table/e-cell-text.h index 19d913a678..24def9f0f8 100644 --- a/widgets/e-table/e-cell-text.h +++ b/widgets/e-table/e-cell-text.h @@ -12,6 +12,13 @@ typedef struct { ECell parent; + + GdkGC *gc; + GdkFont *font; + GtkJustification justify; + + char *font_name; + GnomeCanvas *canvas; } ECellText; typedef struct { @@ -19,6 +26,6 @@ typedef struct { } ECellTextClass; GtkType e_cell_text_get_type (void); -ECell *e_cell_text_new (void); +ECell *e_cell_text_new (const char *fontname, GtkJustification justify); #endif /* _E_CELL_TEXT_H_ */ diff --git a/widgets/e-table/e-cell.c b/widgets/e-table/e-cell.c index e5ceb0fe8a..bff0fb88f2 100644 --- a/widgets/e-table/e-cell.c +++ b/widgets/e-table/e-cell.c @@ -12,24 +12,49 @@ #define PARENT_TYPE gtk_object_get_type() -static void +static ECellView * ec_realize (ECell *e_cell, GnomeCanvas *canvas) { + return NULL; } static void -ec_unrealize (ECell *e_cell) +ec_unrealize (ECellView *e_cell) { } static void -ec_draw (ECell *ecell, int x1, int y1, int x2, int y2) +ec_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2) { + g_warning ("e-cell-draw invoked\n"); } static gint -ec_event (ECell *ecell, GdkEvent *event) +ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row) { + g_warning ("e-cell-event invoked\n"); +} + +static void +ec_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2) +{ + ecell_view->focus_col = col; + ecell_view->focus_row = row; + ecell_view->focus_x1 = x1; + ecell_view->focus_y1 = y1; + ecell_view->focus_x2 = x2; + ecell_view->focus_y2 = y2; +} + +static void +ec_unfocus (ECellView *ecell_view) +{ + ecell_view->focus_col = -1; + ecell_view->focus_row = -1; + ecell_view->focus_x1 = -1; + ecell_view->focus_y1 = -1; + ecell_view->focus_x2 = -1; + ecell_view->focus_y2 = -1; } static void @@ -41,8 +66,44 @@ e_cell_class_init (GtkObjectClass *object_class) ecc->unrealize = ec_unrealize; ecc->draw = ec_draw; ecc->event = ec_event; + ecc->focus = ec_focus; + ecc->unfocus = ec_unfocus; +} + +static void +e_cell_init (GtkObject *object) +{ + ECell *e_cell = E_CELL (object); } -E_MAKE_TYPE(e_cell, "ECell", ECell, e_cell_class_init, NULL, PARENT_TYPE); +E_MAKE_TYPE(e_cell, "ECell", ECell, e_cell_class_init, e_cell_init, PARENT_TYPE); +void +e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +{ + E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->event ( + ecell_view, event, col, row); +} + +ECellView * +e_cell_realize (ECell *ecell, GnomeCanvas *canvas) +{ + return E_CELL_CLASS (GTK_OBJECT (ecell)->klass)->realize ( + ecell, canvas); +} + +void +e_cell_unrealize (ECellView *ecell_view) +{ + E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->unrealize (ecell_view); +} + +void +e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable, + int col, int row, int x1, int y1, int x2, int y2) +{ + E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->draw ( + ecell_view, drawable, col, row, x1, y1, x2, y2); +} + diff --git a/widgets/e-table/e-cell.h b/widgets/e-table/e-cell.h index 8395d3e290..0cafe0fff4 100644 --- a/widgets/e-table/e-cell.h +++ b/widgets/e-table/e-cell.h @@ -2,6 +2,7 @@ #define _E_CELL_H_ #include +#include "e-table-model.h" #define E_CELL_TYPE (e_cell_get_type ()) #define E_CELL(o) (GTK_CHECK_CAST ((o), E_CELL_TYPE, ECell)) @@ -9,19 +10,42 @@ #define E_IS_CELL(o) (GTK_CHECK_TYPE ((o), E_CELL_TYPE)) #define E_IS_CELL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_TYPE)) -typedef struct { +typedef struct _ECell ECell; +typedef struct _ECellView ECellView; + +struct _ECell { GtkObject object; -} ECell; + + ETableModel *table_model; +}; + +struct _ECellView { + ECell *ecell; + gint focus_x1, focus_y1, focus_x2, focus_y2; + gint focus_col, focus_row; +}; + +#define E_CELL_IS_FOCUSED(ecell_view) (ecell_view->focus_x1 != -1) typedef struct { GtkObjectClass parent_class; - void (*realize) (ECell *, GnomeCanvas *canvas); - void (*unrealize) (ECell *); - void (*draw) (ECell *ecell, int x1, int y1, int x2, int y2); - gint (*event) (ECell *ecell, GdkEvent *event); + ECellView *(*realize) (ECell *, GnomeCanvas *canvas); + void (*unrealize) (ECellView *); + void (*draw) (ECellView *ecell_view, GdkDrawable *drawable, + int col, int row, int x1, int y1, int x2, int y2); + gint (*event) (ECellView *ecell_view, GdkEvent *event, int col, int row); + void (*focus) (ECellView *ecell, int col, int row, int x1, int y1, int x2, int y2); + void (*unfocus) (ECellView *ecell); } ECellClass; -GtkType e_cell_get_type (void); +GtkType e_cell_get_type (void); +void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row); +ECellView *e_cell_realize (ECell *ecell, GnomeCanvas *canvas); +void e_cell_unrealize (ECellView *ecell); +void e_cell_draw (ECellView *ecell, GdkDrawable *dr, + int col, int row, int x1, int y1, int x2, int y2); +void e_cell_focus (ECellView *ecell, int col, int row, int x1, int y1, int x2, int y2); +void e_cell_unfocus (ECellView *ecell); #endif /* _E_CELL_H_ */ diff --git a/widgets/e-table/e-table-col.c b/widgets/e-table/e-table-col.c index c75bc6b195..4c61cddd0f 100644 --- a/widgets/e-table/e-table-col.c +++ b/widgets/e-table/e-table-col.c @@ -13,8 +13,7 @@ ETableCol * e_table_col_new (const char *id, int width, int min_width, - ETableColRenderFn render, void *render_data, - GCompareFunc compare, gboolean resizable) + ECell *ecell, GCompareFunc compare, gboolean resizable) { ETableCol *etc; @@ -22,7 +21,6 @@ e_table_col_new (const char *id, int width, int min_width, g_return_if_fail (width >= 0); g_return_if_fail (min_width >= 0); g_return_if_fail (width >= min_width); - g_return_if_fail (render != NULL); g_return_if_fail (compare != NULL); etc = g_new (ETableCol, 1); @@ -30,8 +28,7 @@ e_table_col_new (const char *id, int width, int min_width, etc->id = g_strdup (id); etc->width = width; etc->min_width = min_width; - etc->render = render; - etc->render_data = render_data; + etc->ecell = ecell; etc->compare = compare; etc->selected = 0; diff --git a/widgets/e-table/e-table-col.h b/widgets/e-table/e-table-col.h index 215df07797..950bf23352 100644 --- a/widgets/e-table/e-table-col.h +++ b/widgets/e-table/e-table-col.h @@ -2,13 +2,7 @@ #define _E_TABLE_COL_H_ typedef struct _ETableCol ETableCol; - -/* - * Rendering function for the column header - */ -typedef struct ERenderContext ERenderContext; - -typedef void (*ETableColRenderFn)(ERenderContext *ctxt); +typedef struct _ECell ECell; /* * Information about a single column @@ -18,16 +12,17 @@ struct _ETableCol { short width; short min_width; short x; - ETableColRenderFn render; GCompareFunc compare; - void *render_data; unsigned int selected:1; unsigned int resizeable:1; + + ECell *ecell; }; ETableCol *e_table_col_new (const char *id, int width, int min_width, - ETableColRenderFn render, void *render_data, - GCompareFunc compare, gboolean resizable); + ECell *ecell, GCompareFunc compare, + gboolean resizable); #endif /* _E_TABLE_COL_H_ */ + diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c index dab5d3d71d..ab59d9a01c 100644 --- a/widgets/e-table/e-table-header-item.c +++ b/widgets/e-table/e-table-header-item.c @@ -157,6 +157,7 @@ ethi_realize (GnomeCanvasItem *item) ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); GdkWindow *window; GdkColor c; + int i; if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)-> realize) (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->realize)(item); @@ -171,13 +172,27 @@ ethi_realize (GnomeCanvasItem *item) if (!ethi->font) ethi_font_load (ethi, "fixed"); + + /* + * Now realize the various ECells + */ + ethi->n_cells = e_table_header_count (ethi->eth); + ethi->cell_views = g_new (ECellView *, ethi->n_cells); + + for (i = 0; i < ethi->n_cells; i++){ + ETableCol *col = e_table_header_get_column (ethi->eth, i); + + ethi->cell_views [i] = e_cell_realize (col->ecell, item->canvas); + } + } static void ethi_unrealize (GnomeCanvasItem *item) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); - + int i; + gdk_gc_unref (ethi->gc); ethi->gc = NULL; @@ -187,6 +202,14 @@ ethi_unrealize (GnomeCanvasItem *item) gdk_cursor_destroy (ethi->normal_cursor); ethi->normal_cursor = NULL; + for (i = 0; i < ethi->n_cells; i++){ + ETableCol *col = e_table_header_get_column (ethi->eth, i); + + e_cell_unrealize (col->ecell, ethi->cell_views [i]); + ethi->cell_views = NULL; + } + g_free (ethi->cell_views); + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize) (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item); } @@ -244,8 +267,10 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int wid total = 0; x = -x1; +#if 0 printf ("My coords are: %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2); +#endif for (col = 0; col < cols; col++){ ETableCol *ecol = e_table_header_get_column (ethi->eth, col); @@ -353,11 +378,6 @@ ethi_end_resize (ETableHeaderItem *ethi, int new_size) { e_table_header_set_size (ethi->eth, ethi->resize_col, new_size); - if (ethi->resize_guide){ -#warning Fix this - /* gtk_object_destroy (ethi->resize_guide);*/ - ethi->resize_guide = NULL; - } ethi->resize_col = -1; ethi_request_redraw (ethi); } @@ -394,9 +414,12 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (x - ethi->resize_start_pos <= 0) break; - + + ethi_request_redraw (ethi); + ethi->resize_width = x - ethi->resize_start_pos; - + e_table_header_set_size (ethi->eth, ethi->resize_col, ethi->resize_width); + ethi_request_redraw (ethi); } else set_cursor (ethi, x); diff --git a/widgets/e-table/e-table-header-item.h b/widgets/e-table/e-table-header-item.h index d6b7d64a9f..10b84e1897 100644 --- a/widgets/e-table/e-table-header-item.h +++ b/widgets/e-table/e-table-header-item.h @@ -10,6 +10,8 @@ #define E_IS_TABLE_HEADER_ITEM(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_ITEM_TYPE)) #define E_IS_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_ITEM_TYPE)) +typedef struct _ECellView ECellView; + typedef struct { GnomeCanvasItem parent; ETableHeader *eth; @@ -28,6 +30,9 @@ typedef struct { int resize_start_pos; GtkObject *resize_guide; + ECellView **cell_views; + int n_cells; + /* * Ids */ diff --git a/widgets/e-table/e-table-item.c b/widgets/e-table/e-table-item.c index 1e53180804..5bf1e24fd0 100644 --- a/widgets/e-table/e-table-item.c +++ b/widgets/e-table/e-table-item.c @@ -44,9 +44,11 @@ eti_remove_table_model (ETableItem *eti) return; gtk_signal_disconnect (eti->table_model_change_id); + gtk_signal_disconnect (eti->table_model_selection_id); gtk_object_unref (GTK_OBJECT (eti->table_model)); eti->table_model_change_id = 0; + eti->table_model_selection_id = 0; eti->table_model = NULL; } @@ -73,6 +75,23 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti) eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); } +static void +eti_request_redraw (ETableItem *eti) +{ + GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; + + gnome_canvas_request_redraw (canvas, eti->x1, eti->y1, + eti->x1 + eti->width + 1, + eti->y1 + eti->height + 1); +} + +static void +eti_table_model_row_selection (ETableModel *table_model, ETableItem *eti) +{ + /* FIXME: we should optimize this to only redraw the selection change */ + eti_request_redraw (eti); +} + static void eti_add_table_model (ETableItem *eti, ETableModel *table_model) { @@ -83,31 +102,30 @@ eti_add_table_model (ETableItem *eti, ETableModel *table_model) eti->table_model_change_id = gtk_signal_connect ( GTK_OBJECT (table_model), "model_changed", GTK_SIGNAL_FUNC (eti_table_model_changed), eti); -} - -static void -eti_request_redraw (ETableItem *eti) -{ - GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; - - gnome_canvas_request_redraw (canvas, eti->x1, eti->y1, eti->x1 + eti->width, eti->y1 + eti->height); + eti->table_model_selection_id = gtk_signal_connect ( + GTK_OBJECT (table_model), "row_selection", + GTK_SIGNAL_FUNC (eti_table_model_row_selection), eti); } static void eti_header_dim_changed (ETableHeader *eth, int col, ETableItem *eti) { - eti->width = e_table_header_total_width (eti->header); + eti_request_redraw (eti); + eti->width = e_table_header_total_width (eti->header); eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); + eti_request_redraw (eti); } static void eti_header_structure_changed (ETableHeader *eth, ETableItem *eti) { - eti->width = e_table_header_total_width (eti->header); + eti_request_redraw (eti); + eti->width = e_table_header_total_width (eti->header); eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); + eti_request_redraw (eti); } @@ -181,6 +199,9 @@ static void eti_init (GnomeCanvasItem *item) { ETableItem *eti = E_TABLE_ITEM (item); + + eti->focused_col = -1; + eti->focused_row = -1; } static void @@ -199,6 +220,7 @@ eti_realize (GnomeCanvasItem *item) gdk_gc_ref (canvas_widget->style->white_gc); eti->grid_gc = gdk_gc_new (window); gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->fg [GTK_STATE_NORMAL]); + } static void @@ -277,7 +299,10 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, if (first_col == -1) return; +#if 0 printf ("Cols %d %d\n", first_col, last_col); +#endif + /* * Draw individual lines */ @@ -318,6 +343,25 @@ eti_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, static int eti_event (GnomeCanvasItem *item, GdkEvent *e) { + ETableItem *eti = E_TABLE_ITEM (item); + ETableCol *etc; + + switch (e->type){ + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_2BUTTON_PRESS: + + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: + if (eti->focused_col == -1) + return FALSE; + + etc = e_table_header_get_column (eti->header, eti->focused_col); + + e_cell_event (etc->ecell, e, eti->focused_col, eti->focused_row); + break; + + } return FALSE; } @@ -371,3 +415,19 @@ e_table_item_get_type (void) return type; } +void +e_table_item_focus (ETableItem *eti, int col, int row) +{ + if (eti->focused_col != -1) + e_table_item_unfocus (eti); + + eti->focused_col = col; + eti->focused_row = row; +} + +void +e_table_item_unfocus (ETableItem *eti) +{ + eti->focused_col = -1; + eti->focused_row = -1; +} diff --git a/widgets/e-table/e-table-item.h b/widgets/e-table/e-table-item.h index 7e548cf49d..fefa221227 100644 --- a/widgets/e-table/e-table-item.h +++ b/widgets/e-table/e-table-item.h @@ -27,11 +27,14 @@ typedef struct { int header_dim_change_id; int header_structure_change_id; int table_model_change_id; - + int table_model_selection_id; + GdkGC *fill_gc; GdkGC *grid_gc; unsigned int draw_grid:1; + + int focused_col, focused_row; } ETableItem; typedef struct { @@ -39,5 +42,7 @@ typedef struct { } ETableItemClass; GtkType e_table_item_get_type (void); +void e_table_item_focus (ETableItem *eti, int col, int row); +void e_table_item_unfocus (ETableItem *eti); #endif /* _E_TABLE_ITEM_H_ */ diff --git a/widgets/e-table/e-table-model.c b/widgets/e-table/e-table-model.c index de7bc67c51..1176b33ec7 100644 --- a/widgets/e-table/e-table-model.c +++ b/widgets/e-table/e-table-model.c @@ -16,6 +16,7 @@ static GtkObjectClass *e_table_model_parent_class; enum { MODEL_CHANGED, + ROW_SELECTION, LAST_SIGNAL }; @@ -88,6 +89,14 @@ e_table_model_class_init (GtkObjectClass *object_class) GTK_SIGNAL_OFFSET (ETableModelClass, model_changed), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); + + etm_signals [ROW_SELECTION] = + gtk_signal_new ("row_selection", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableModelClass, row_selection), + gtk_marshal_NONE__INT_INT, + GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); gtk_object_class_add_signals (object_class, etm_signals, LAST_SIGNAL); } @@ -158,3 +167,29 @@ e_table_model_max_col_width (ETableModel *etm, int col) return max; } #endif + +void +e_table_model_select_row (ETableModel *etm, int row) +{ + gtk_signal_emit (GTK_OBJECT (etm), etm_signals [ROW_SELECTION], row, 1); + etm->row_selected = row; +} + +void +e_table_model_unselect_row (ETableModel *etm, int row) +{ + if (etm->row_selected != -1){ + gtk_signal_emit ( + GTK_OBJECT (etm), etm_signals [ROW_SELECTION], + etm->row_selected, 0); + } + + etm->row_selected = -1; +} + +gint +e_table_model_get_selected_row (ETableModel *etm) +{ + return etm->row_selected; +} + diff --git a/widgets/e-table/e-table-model.h b/widgets/e-table/e-table-model.h index d12a465c0b..2d439a0065 100644 --- a/widgets/e-table/e-table-model.h +++ b/widgets/e-table/e-table-model.h @@ -11,6 +11,9 @@ typedef struct { GtkObject base; + + /* Temporary. I swear */ + int row_selected; } ETableModel; typedef struct { @@ -30,7 +33,8 @@ typedef struct { /* * Signals */ - void (*model_changed) (ETableModel *etm, int row); + void (*model_changed) (ETableModel *etm); + void (*row_selection) (ETableModel *etc, int row); } ETableModelClass; GtkType e_table_model_get_type (void); @@ -44,6 +48,9 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col, void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data); gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row); +void e_table_model_select_row (ETableModel *e_table_model, int row); +gint e_table_model_get_selected_row (ETableModel *e_table_model); + /* * Routines for emitting signals on the e_table */ diff --git a/widgets/e-table/e-table-simple.c b/widgets/e-table/e-table-simple.c index 32f7145bc6..b23cda1220 100644 --- a/widgets/e-table/e-table-simple.c +++ b/widgets/e-table/e-table-simple.c @@ -12,6 +12,8 @@ #include #include "e-table-simple.h" +#define PARENT_TYPE e_table_model_get_type() + static int simple_column_count (ETableModel *etm) { @@ -99,7 +101,7 @@ e_table_simple_get_type (void) (GtkClassInitFunc) NULL }; - type = gtk_type_unique (e_table_model_get_type (), &info); + type = gtk_type_unique (PARENT_TYPE, &info); } return type; diff --git a/widgets/e-table/e-table-sorted.c b/widgets/e-table/e-table-sorted.c index 2d53c79e5d..be19de2efb 100644 --- a/widgets/e-table/e-table-sorted.c +++ b/widgets/e-table/e-table-sorted.c @@ -11,93 +11,16 @@ #include "e-util.h" #include "e-table-sorted.h" -#define PARENT_TYPE E_TABLE_MODEL_TYPE +#define PARENT_TYPE E_TABLE_SUBSET_TYPE static ETableModelClass *ets_parent_class; -static void -ets_destroy (GtkObject *object) -{ - ETableSorted *ets = E_TABLE_SORTED (object); - - gtk_object_unref (GTK_OBJECT (ets->source)); - gtk_object_unref (GTK_OBJECT (ets->header)); - free (ets->map_table); - - GTK_OBJECT_CLASS (ets_parent_class)->destroy (object); -} - -static int -ets_column_count (ETableModel *etm) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_column_count (ets->source); -} - -static const char * -ets_column_name (ETableModel *etm, int col) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_column_name (ets->source, col); -} - -static int -ets_row_count (ETableModel *etm) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_row_count (ets->source); -} - -static void * -ets_value_at (ETableModel *etm, int col, int row) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_value_at (ets->source, col, ets->map_table [row]); -} - -static void -ets_set_value_at (ETableModel *etm, int col, int row, void *val) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_set_value_at (ets->source, col, ets->map_table [row], val); -} - -static gboolean -ets_is_cell_editable (ETableModel *etm, int col, int row) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_is_cell_editable (ets->source, col, ets->map_table [row]); -} - -static int -ets_row_height (ETableModel *etm, int row) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_row_height (ets->source, ets->map_table [row]); -} - static void ets_class_init (GtkObjectClass *klass) { ETableModelClass *table_class = (ETableModelClass *) klass; ets_parent_class = gtk_type_class (PARENT_TYPE); - klass->destroy = ets_destroy; - - table_class->column_count = ets_column_count; - table_class->column_name = ets_column_name; - table_class->row_count = ets_row_count; - table_class->value_at = ets_value_at; - table_class->set_value_at = ets_set_value_at; - table_class->is_cell_editable = ets_is_cell_editable; - table_class->row_height = ets_row_height; } E_MAKE_TYPE(e_table_sorted, "ETableSorted", ETableSorted, ets_class_init, NULL, PARENT_TYPE); @@ -108,49 +31,63 @@ static int my_sort (const void *a, const void *b) { GCompareFunc comp; + ETableModel *source = E_TABLE_SUBSET (sort_ets)->source; const int *ia = (const int *) a; const int *ib = (const int *) b; void *va, *vb; - va = e_table_model_value_at (sort_ets->source, sort_ets->sort_idx, *ia); - vb = e_table_model_value_at (sort_ets->source, sort_ets->sort_idx, *ib); + va = e_table_model_value_at (source, sort_ets->sort_col, *ia); + vb = e_table_model_value_at (source, sort_ets->sort_col, *ib); - comp = sort_ets->sort_col->compare; + return (*sort_ets->compare) (va, vb); +} - return (*comp) (va, vb); +static void +do_sort (ETableSorted *ets) +{ + ETableSubset *etss = E_TABLE_SUBSET (ets); + g_assert (sort_ets == NULL); + + sort_ets = ets; + qsort (etss->map_table, etss->n_map, sizeof (unsigned int), my_sort); + sort_ets = NULL; } ETableModel * -e_table_sorted_new (ETableModel *source, ETableHeader *header, short sort_field) +e_table_sorted_new (ETableModel *source, int col, GCompareFunc compare) { ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE); + ETableSubset *etss = E_TABLE_SUBSET (ets); const int nvals = e_table_model_row_count (source); unsigned int *buffer; int i; - buffer = malloc (sizeof (unsigned int *) * nvals); - if (buffer = NULL) + if (e_table_subset_construct (etss, source, nvals) == NULL){ + gtk_object_destroy (GTK_OBJECT (ets)); return NULL; - ets->map_table = buffer; - ets->n_map = nvals; - ets->source = source; - ets->header = header; - ets->sort_col = e_table_header_get_column (header, sort_field); - ets->sort_idx = sort_field; - gtk_object_ref (GTK_OBJECT (source)); - gtk_object_ref (GTK_OBJECT (header)); + } + + ets->compare = compare; + ets->sort_col = col; /* Init */ for (i = 0; i < nvals; i++) - ets->map_table [i] = i; + etss->map_table [i] = i; - /* Sort */ - g_assert (sort_ets == NULL); - sort_ets = ets; - qsort (ets->map_table, nvals, sizeof (unsigned int), my_sort); - sort_ets = NULL; + do_sort (ets); return (ETableModel *) ets; } - +void +e_table_sorted_resort (ETableSorted *ets, int col, GCompareFunc compare) +{ + if (col == -1 || compare == NULL) + do_sort (ets); + else { + ets->sort_col = col; + ets->compare = compare; + do_sort (ets); + } +} + diff --git a/widgets/e-table/e-table-sorted.h b/widgets/e-table/e-table-sorted.h index 65578b7b83..2ec52df2e7 100644 --- a/widgets/e-table/e-table-sorted.h +++ b/widgets/e-table/e-table-sorted.h @@ -3,7 +3,7 @@ #include #include "e-table-model.h" -#include "e-table-header.h" +#include "e-table-subset.h" #define E_TABLE_SORTED_TYPE (e_table_sorted_get_type ()) #define E_TABLE_SORTED(o) (GTK_CHECK_CAST ((o), E_TABLE_SORTED_TYPE, ETableSorted)) @@ -12,23 +12,18 @@ #define E_IS_TABLE_SORTED_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SORTED_TYPE)) typedef struct { - ETableModel base; + ETableSubset base; - ETableModel *source; - ETableHeader *header; - ETableCol *sort_col; - short sort_idx; - - int n_map; - unsigned int *map_table; + short sort_col; + GCompareFunc compare; } ETableSorted; typedef struct { - ETableModelClass parent_class; + ETableSubset parent_class; } ETableSortedClass; GtkType e_table_sorted_get_type (void); -ETableModel *e_table_sorted_new (ETableModel *etm, ETableHeader *header, - short sort_field); +ETableModel *e_table_sorted_new (ETableModel *etm, int col, GCompareFunc compare); +void e_table_sorted_resort (ETableSorted *ets, int col, GCompareFunc compare); #endif /* _E_TABLE_SORTED_H_ */ diff --git a/widgets/e-table/e-table-subset.c b/widgets/e-table/e-table-subset.c index 0b9621ac84..afa1b862b4 100644 --- a/widgets/e-table/e-table-subset.c +++ b/widgets/e-table/e-table-subset.c @@ -19,52 +19,122 @@ etss_destroy (GtkObject *object) { ETableSubset *etss = E_TABLE_SUBSET (object); - gtk_object_unref (GTK_OBJECT (etss->source)); - free (ets->subset_table); + if (etss->source) + gtk_object_unref (GTK_OBJECT (etss->source)); - GTK_OBJECT_CLASS (ets_parent_class)->destroy (object); + if (etss->map_table) + free (etss->map_table); + + GTK_OBJECT_CLASS (etss_parent_class)->destroy (object); +} + +static int +etss_column_count (ETableModel *etm) +{ + ETableSubset *etss = (ETableSubset *)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); +} + +static void * +etss_value_at (ETableModel *etm, int col, int row) +{ + ETableSubset *etss = (ETableSubset *)etm; + + return e_table_model_value_at (etss->source, col, etss->map_table [row]); +} + +static void +etss_set_value_at (ETableModel *etm, int col, int row, void *val) +{ + ETableSubset *etss = (ETableSubset *)etm; + + return e_table_model_set_value_at (etss->source, col, etss->map_table [row], val); +} + +static gboolean +etss_is_cell_editable (ETableModel *etm, int col, int row) +{ + ETableSubset *etss = (ETableSubset *)etm; + + 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) { + ETableModelClass *table_class = (ETableModelClass *) klass; + etss_parent_class = gtk_type_class (PARENT_TYPE); 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); ETableModel * -e_table_subset_new (ETableModel *source, ETableHeader *header, short sort_field) +e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) { - ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE); - const int nvals = e_table_model_row_count (source); unsigned int *buffer; int i; - buffer = malloc (sizeof (unsigned int *) * nvals); + buffer = (unsigned int *) malloc (sizeof (unsigned int *) * nvals); if (buffer = NULL) return NULL; - ets->map_table = buffer; - ets->n_map = nvals; - ets->source = source; - ets->header = header; - ets->sort_col = e_table_header_get_column (header, sort_field); - ets->sort_idx = sort_field; + etss->map_table = buffer; + etss->n_map = nvals; + etss->source = source; gtk_object_ref (GTK_OBJECT (source)); - gtk_object_ref (GTK_OBJECT (header)); /* Init */ for (i = 0; i < nvals; i++) - ets->map_table [i] = i; + etss->map_table [i] = i; - /* Sort */ - g_assert (sort_ets == NULL); - sort_ets = ets; - qsort (ets->map_table, nvals, sizeof (unsigned int), my_sort); - sort_ets = NULL; - - return (ETableModel *) ets; +} + +ETableModel * +e_table_subset_new (ETableModel *source, const int nvals) +{ + ETableSubset *etss = gtk_type_new (E_TABLE_SUBSET_TYPE); + + if (e_table_subset_construct (etss, source, nvals) == NULL){ + gtk_object_destroy (GTK_OBJECT (etss)); + return NULL; + } + + return (ETableModel *) etss; } diff --git a/widgets/e-table/e-table-subset.h b/widgets/e-table/e-table-subset.h index a87d6d0df8..5576c55f1d 100644 --- a/widgets/e-table/e-table-subset.h +++ b/widgets/e-table/e-table-subset.h @@ -3,7 +3,6 @@ #include #include "e-table-model.h" -#include "e-table-header.h" #define E_TABLE_SUBSET_TYPE (e_table_subset_get_type ()) #define E_TABLE_SUBSET(o) (GTK_CHECK_CAST ((o), E_TABLE_SUBSET_TYPE, ETableSubset)) @@ -15,15 +14,16 @@ typedef struct { ETableModel base; ETableModel *source; - int subset_count; - int *subset_table; + int n_map; + int *map_table; } ETableSubset; typedef struct { ETableModelClass parent_class; } ETableSubsetClass; -GtkType e_table_subset_get_type (void); -ETableModel *e_table_subset_new (ETableModel *etm, - int n_vals, int *ptrs); +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); + #endif /* _E_TABLE_SUBSET_H_ */ diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c index 795c737b36..3b13e87d6b 100644 --- a/widgets/e-table/e-table.c +++ b/widgets/e-table/e-table.c @@ -9,28 +9,14 @@ #include #include #include "e-table.h" +#include "e-util.h" #define PARENT_OBJECT_TYPE gnome_canvas_get_type () -GtkType -e_table_get_type (void) -{ - static GtkType type = 0; - - if (!type){ - GtkTypeInfo info = { - "ETable", - sizeof (ETable), - sizeof (ETableClass), - (GtkClassInitFunc) e_table_class_init, - (GtkObjectInitFunc) NULL, - NULL, /* reserved 1 */ - NULL, /* reserved 2 */ - (GtkClassInitFunc) NULL - }; - - type = gtk_type_unique (PARENT_OBJECT_TYPE, &info); - } +E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, NULL, PARENT_TYPE); - return type; +ETable * +e_table_new (ETableHeader *eth, ETableModel *etm) +{ } + diff --git a/widgets/e-table/table-test.c b/widgets/e-table/table-test.c index 54392a73bc..e646b44655 100644 --- a/widgets/e-table/table-test.c +++ b/widgets/e-table/table-test.c @@ -11,7 +11,6 @@ #include "e-table-simple.h" #include "e-table-header.h" #include "e-table-header-item.h" -#include "e-table-render.h" #include "e-table-item.h" char buffer [1024]; @@ -185,6 +184,7 @@ main (int argc, char *argv []) GtkWidget *canvas, *window; ETableModel *e_table_model; ETableHeader *e_table_header; + ECell *cell_left_just; int i; gnome_init ("TableTest", "TableTest", argc, argv); @@ -203,10 +203,12 @@ main (int argc, char *argv []) * Header */ e_table_header = e_table_header_new (); + cell_left_just = e_cell_text_new ("fixed", GTK_JUSTIFY_LEFT); + for (i = 0; i < cols; i++){ ETableCol *ecol = e_table_col_new ( - column_labels [i], 80, 20, e_table_render_string, - NULL, g_str_equal, TRUE); + column_labels [i], 80, 20, cell_left_just, + g_str_equal, TRUE); e_table_header_add_column (e_table_header, ecol, i); } diff --git a/widgets/table-test.c b/widgets/table-test.c index 54392a73bc..e646b44655 100644 --- a/widgets/table-test.c +++ b/widgets/table-test.c @@ -11,7 +11,6 @@ #include "e-table-simple.h" #include "e-table-header.h" #include "e-table-header-item.h" -#include "e-table-render.h" #include "e-table-item.h" char buffer [1024]; @@ -185,6 +184,7 @@ main (int argc, char *argv []) GtkWidget *canvas, *window; ETableModel *e_table_model; ETableHeader *e_table_header; + ECell *cell_left_just; int i; gnome_init ("TableTest", "TableTest", argc, argv); @@ -203,10 +203,12 @@ main (int argc, char *argv []) * Header */ e_table_header = e_table_header_new (); + cell_left_just = e_cell_text_new ("fixed", GTK_JUSTIFY_LEFT); + for (i = 0; i < cols; i++){ ETableCol *ecol = e_table_col_new ( - column_labels [i], 80, 20, e_table_render_string, - NULL, g_str_equal, TRUE); + column_labels [i], 80, 20, cell_left_just, + g_str_equal, TRUE); e_table_header_add_column (e_table_header, ecol, i); } diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c index c30e42cfd3..1b3f524a2e 100644 --- a/widgets/table/e-cell-text.c +++ b/widgets/table/e-cell-text.c @@ -7,42 +7,157 @@ * (C) 1999 Helix Code, Inc */ #include +#include #include "e-cell-text.h" #include "e-util.h" -#define PARENT_TYPE gtk_object_get_type() +#define PARENT_TYPE e_cell_get_type() + +typedef struct { + ECellView cell_view; + GdkGC *gc; + GdkFont *font; + GnomeCanvas *canvas; +} ECellTextView; + +static ECellClass *parent_class; + +static ECellView * +ect_realize (ECell *ecell, GnomeCanvas *canvas) +{ + ECellText *ect = E_CELL_TEXT (ecell); + ECellTextView *ectv = g_new (ECellTextView, 1); + + ectv->cell_view.ecell = ecell; + ectv->gc = gdk_gc_new (GTK_WIDGET (canvas)->window); + ectv->font = gdk_fontset_load (ect->font_name ? ect->font_name : "fixed"); + ectv->canvas = canvas; + + return (ECellView *)ectv; +} static void -ec_realize (ECell *e_cell, GnomeCanvas *canvas) +ect_unrealize (ECellView *ecv) { + ECellTextView *ectv = (ECellTextView *) ecv; + + gdk_gc_unref (ectv->gc); + ectv->gc = NULL; + + gdk_font_unref (ectv->font); + ectv->font = NULL; + + g_free (ectv); } static void -ec_unrealize (ECell *e_cell) +ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2) { + ECellText *ect = E_CELL_TEXT (ecell_view->ecell); + GdkRectangle rect; + const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + int selected = e_table_model_get_selected_row (ecell_view->ecell->table_model) == row; + int xoff, w; + + rect.x = x1; + rect.y = y1; + rect.width = x2 - x1; + rect.height = y2 - y1; + + gdk_gc_set_clip_rectangle (ect->gc, &rect); + + switch (ect->justify){ + case GTK_JUSTIFY_LEFT: + xoff = 1; + break; + + case GTK_JUSTIFY_RIGHT: + w = 1 + gdk_text_width (ect->font, str, strlen (str)); + xoff = (x2 - x1) - w; + break; + + case GTK_JUSTIFY_CENTER: + xoff = ((x2 - x1) - gdk_text_width (ect->font, str, strlen (str))) / 2; + break; + default: + g_warning ("Can not handle GTK_JUSTIFY_FILL"); + break; + } + + /* Draw now */ + { + GtkWidget *w = GTK_WIDGET (ect->canvas); + GdkColor *background; + int idx; + + if (selected) + idx = GTK_STATE_SELECTED; + else + idx = GTK_STATE_NORMAL; + + gdk_gc_set_foreground (ect->gc, &w->style->bg [idx]); + gdk_draw_rectangle (drawable, ect->gc, TRUE, rect.x, rect.y, rect.width, rect.height); + gdk_gc_set_foreground (ect->gc, &w->style->fg [idx]); + gdk_draw_string (drawable, ect->font, ect->gc, x1 + xoff, y2 + ect->font->descent, str); + } } static void -ec_draw (ECell *ecell, int x1, int y1, int x2, int y2) +e_cell_text_start_editing (ECellText *ect, int col, int row) { + printf ("Starting to edit %d %d\n", col, row); } static gint -ec_event (ECell *ecell, GdkEvent *event) +ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) { + ECell *ecell = ecell_view->ecell; + ECellText *ect = E_CELL_TEXT (ecell); + + switch (event->type){ + case GDK_BUTTON_PRESS: + if (e_table_model_get_selected_row (ecell->table_model) == row) + e_cell_text_start_editing (ect, col, row); + else + e_table_model_select_row (ecell->table_model, row); + return TRUE; + } } static void -e_cell_class_init (GtkObjectClass *object_class) +ect_destroy (GtkObject *object) { - ECellClass *ecc = (ECellClass *) object_class; + ECellText *ect = E_CELL_TEXT (object); + + g_free (ect->font_name); - ecc->realize = ec_realize; - ecc->unrealize = ec_unrealize; - ecc->draw = ec_draw; - ecc->event = ec_event; + GTK_OBJECT_CLASS (parent_class)->destroy (object); } -E_MAKE_TYPE(e_cell, "ECell", ECell, e_cell_class_init, NULL, PARENT_TYPE); +static void +e_cell_text_class_init (GtkObjectClass *object_class) +{ + ECellClass *ecc = (ECellClass *) object_class; + object_class->destroy = ect_destroy; + ecc->realize = ect_realize; + ecc->unrealize = ect_unrealize; + ecc->draw = ect_draw; + ecc->event = ect_event; + + parent_class = gtk_type_class (PARENT_TYPE); +} + +E_MAKE_TYPE(e_cell_text, "ECellText", ECellText, e_cell_text_class_init, NULL, PARENT_TYPE); + +ECell * +e_cell_text_new (const char *fontname, GtkJustification justify) +{ + ECellText *ect = gtk_type_new (e_cell_text_get_type ()); + + ect->font_name = g_strdup (fontname); + ect->justify = justify; + + return (ECell *) ect; +} diff --git a/widgets/table/e-cell-text.h b/widgets/table/e-cell-text.h index 19d913a678..24def9f0f8 100644 --- a/widgets/table/e-cell-text.h +++ b/widgets/table/e-cell-text.h @@ -12,6 +12,13 @@ typedef struct { ECell parent; + + GdkGC *gc; + GdkFont *font; + GtkJustification justify; + + char *font_name; + GnomeCanvas *canvas; } ECellText; typedef struct { @@ -19,6 +26,6 @@ typedef struct { } ECellTextClass; GtkType e_cell_text_get_type (void); -ECell *e_cell_text_new (void); +ECell *e_cell_text_new (const char *fontname, GtkJustification justify); #endif /* _E_CELL_TEXT_H_ */ diff --git a/widgets/table/e-cell.c b/widgets/table/e-cell.c index e5ceb0fe8a..bff0fb88f2 100644 --- a/widgets/table/e-cell.c +++ b/widgets/table/e-cell.c @@ -12,24 +12,49 @@ #define PARENT_TYPE gtk_object_get_type() -static void +static ECellView * ec_realize (ECell *e_cell, GnomeCanvas *canvas) { + return NULL; } static void -ec_unrealize (ECell *e_cell) +ec_unrealize (ECellView *e_cell) { } static void -ec_draw (ECell *ecell, int x1, int y1, int x2, int y2) +ec_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2) { + g_warning ("e-cell-draw invoked\n"); } static gint -ec_event (ECell *ecell, GdkEvent *event) +ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row) { + g_warning ("e-cell-event invoked\n"); +} + +static void +ec_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2) +{ + ecell_view->focus_col = col; + ecell_view->focus_row = row; + ecell_view->focus_x1 = x1; + ecell_view->focus_y1 = y1; + ecell_view->focus_x2 = x2; + ecell_view->focus_y2 = y2; +} + +static void +ec_unfocus (ECellView *ecell_view) +{ + ecell_view->focus_col = -1; + ecell_view->focus_row = -1; + ecell_view->focus_x1 = -1; + ecell_view->focus_y1 = -1; + ecell_view->focus_x2 = -1; + ecell_view->focus_y2 = -1; } static void @@ -41,8 +66,44 @@ e_cell_class_init (GtkObjectClass *object_class) ecc->unrealize = ec_unrealize; ecc->draw = ec_draw; ecc->event = ec_event; + ecc->focus = ec_focus; + ecc->unfocus = ec_unfocus; +} + +static void +e_cell_init (GtkObject *object) +{ + ECell *e_cell = E_CELL (object); } -E_MAKE_TYPE(e_cell, "ECell", ECell, e_cell_class_init, NULL, PARENT_TYPE); +E_MAKE_TYPE(e_cell, "ECell", ECell, e_cell_class_init, e_cell_init, PARENT_TYPE); +void +e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +{ + E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->event ( + ecell_view, event, col, row); +} + +ECellView * +e_cell_realize (ECell *ecell, GnomeCanvas *canvas) +{ + return E_CELL_CLASS (GTK_OBJECT (ecell)->klass)->realize ( + ecell, canvas); +} + +void +e_cell_unrealize (ECellView *ecell_view) +{ + E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->unrealize (ecell_view); +} + +void +e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable, + int col, int row, int x1, int y1, int x2, int y2) +{ + E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->draw ( + ecell_view, drawable, col, row, x1, y1, x2, y2); +} + diff --git a/widgets/table/e-cell.h b/widgets/table/e-cell.h index 8395d3e290..0cafe0fff4 100644 --- a/widgets/table/e-cell.h +++ b/widgets/table/e-cell.h @@ -2,6 +2,7 @@ #define _E_CELL_H_ #include +#include "e-table-model.h" #define E_CELL_TYPE (e_cell_get_type ()) #define E_CELL(o) (GTK_CHECK_CAST ((o), E_CELL_TYPE, ECell)) @@ -9,19 +10,42 @@ #define E_IS_CELL(o) (GTK_CHECK_TYPE ((o), E_CELL_TYPE)) #define E_IS_CELL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_TYPE)) -typedef struct { +typedef struct _ECell ECell; +typedef struct _ECellView ECellView; + +struct _ECell { GtkObject object; -} ECell; + + ETableModel *table_model; +}; + +struct _ECellView { + ECell *ecell; + gint focus_x1, focus_y1, focus_x2, focus_y2; + gint focus_col, focus_row; +}; + +#define E_CELL_IS_FOCUSED(ecell_view) (ecell_view->focus_x1 != -1) typedef struct { GtkObjectClass parent_class; - void (*realize) (ECell *, GnomeCanvas *canvas); - void (*unrealize) (ECell *); - void (*draw) (ECell *ecell, int x1, int y1, int x2, int y2); - gint (*event) (ECell *ecell, GdkEvent *event); + ECellView *(*realize) (ECell *, GnomeCanvas *canvas); + void (*unrealize) (ECellView *); + void (*draw) (ECellView *ecell_view, GdkDrawable *drawable, + int col, int row, int x1, int y1, int x2, int y2); + gint (*event) (ECellView *ecell_view, GdkEvent *event, int col, int row); + void (*focus) (ECellView *ecell, int col, int row, int x1, int y1, int x2, int y2); + void (*unfocus) (ECellView *ecell); } ECellClass; -GtkType e_cell_get_type (void); +GtkType e_cell_get_type (void); +void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row); +ECellView *e_cell_realize (ECell *ecell, GnomeCanvas *canvas); +void e_cell_unrealize (ECellView *ecell); +void e_cell_draw (ECellView *ecell, GdkDrawable *dr, + int col, int row, int x1, int y1, int x2, int y2); +void e_cell_focus (ECellView *ecell, int col, int row, int x1, int y1, int x2, int y2); +void e_cell_unfocus (ECellView *ecell); #endif /* _E_CELL_H_ */ diff --git a/widgets/table/e-table-col.c b/widgets/table/e-table-col.c index c75bc6b195..4c61cddd0f 100644 --- a/widgets/table/e-table-col.c +++ b/widgets/table/e-table-col.c @@ -13,8 +13,7 @@ ETableCol * e_table_col_new (const char *id, int width, int min_width, - ETableColRenderFn render, void *render_data, - GCompareFunc compare, gboolean resizable) + ECell *ecell, GCompareFunc compare, gboolean resizable) { ETableCol *etc; @@ -22,7 +21,6 @@ e_table_col_new (const char *id, int width, int min_width, g_return_if_fail (width >= 0); g_return_if_fail (min_width >= 0); g_return_if_fail (width >= min_width); - g_return_if_fail (render != NULL); g_return_if_fail (compare != NULL); etc = g_new (ETableCol, 1); @@ -30,8 +28,7 @@ e_table_col_new (const char *id, int width, int min_width, etc->id = g_strdup (id); etc->width = width; etc->min_width = min_width; - etc->render = render; - etc->render_data = render_data; + etc->ecell = ecell; etc->compare = compare; etc->selected = 0; diff --git a/widgets/table/e-table-col.h b/widgets/table/e-table-col.h index 215df07797..950bf23352 100644 --- a/widgets/table/e-table-col.h +++ b/widgets/table/e-table-col.h @@ -2,13 +2,7 @@ #define _E_TABLE_COL_H_ typedef struct _ETableCol ETableCol; - -/* - * Rendering function for the column header - */ -typedef struct ERenderContext ERenderContext; - -typedef void (*ETableColRenderFn)(ERenderContext *ctxt); +typedef struct _ECell ECell; /* * Information about a single column @@ -18,16 +12,17 @@ struct _ETableCol { short width; short min_width; short x; - ETableColRenderFn render; GCompareFunc compare; - void *render_data; unsigned int selected:1; unsigned int resizeable:1; + + ECell *ecell; }; ETableCol *e_table_col_new (const char *id, int width, int min_width, - ETableColRenderFn render, void *render_data, - GCompareFunc compare, gboolean resizable); + ECell *ecell, GCompareFunc compare, + gboolean resizable); #endif /* _E_TABLE_COL_H_ */ + diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c index dab5d3d71d..ab59d9a01c 100644 --- a/widgets/table/e-table-header-item.c +++ b/widgets/table/e-table-header-item.c @@ -157,6 +157,7 @@ ethi_realize (GnomeCanvasItem *item) ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); GdkWindow *window; GdkColor c; + int i; if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)-> realize) (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->realize)(item); @@ -171,13 +172,27 @@ ethi_realize (GnomeCanvasItem *item) if (!ethi->font) ethi_font_load (ethi, "fixed"); + + /* + * Now realize the various ECells + */ + ethi->n_cells = e_table_header_count (ethi->eth); + ethi->cell_views = g_new (ECellView *, ethi->n_cells); + + for (i = 0; i < ethi->n_cells; i++){ + ETableCol *col = e_table_header_get_column (ethi->eth, i); + + ethi->cell_views [i] = e_cell_realize (col->ecell, item->canvas); + } + } static void ethi_unrealize (GnomeCanvasItem *item) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); - + int i; + gdk_gc_unref (ethi->gc); ethi->gc = NULL; @@ -187,6 +202,14 @@ ethi_unrealize (GnomeCanvasItem *item) gdk_cursor_destroy (ethi->normal_cursor); ethi->normal_cursor = NULL; + for (i = 0; i < ethi->n_cells; i++){ + ETableCol *col = e_table_header_get_column (ethi->eth, i); + + e_cell_unrealize (col->ecell, ethi->cell_views [i]); + ethi->cell_views = NULL; + } + g_free (ethi->cell_views); + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize) (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item); } @@ -244,8 +267,10 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int wid total = 0; x = -x1; +#if 0 printf ("My coords are: %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2); +#endif for (col = 0; col < cols; col++){ ETableCol *ecol = e_table_header_get_column (ethi->eth, col); @@ -353,11 +378,6 @@ ethi_end_resize (ETableHeaderItem *ethi, int new_size) { e_table_header_set_size (ethi->eth, ethi->resize_col, new_size); - if (ethi->resize_guide){ -#warning Fix this - /* gtk_object_destroy (ethi->resize_guide);*/ - ethi->resize_guide = NULL; - } ethi->resize_col = -1; ethi_request_redraw (ethi); } @@ -394,9 +414,12 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (x - ethi->resize_start_pos <= 0) break; - + + ethi_request_redraw (ethi); + ethi->resize_width = x - ethi->resize_start_pos; - + e_table_header_set_size (ethi->eth, ethi->resize_col, ethi->resize_width); + ethi_request_redraw (ethi); } else set_cursor (ethi, x); diff --git a/widgets/table/e-table-header-item.h b/widgets/table/e-table-header-item.h index d6b7d64a9f..10b84e1897 100644 --- a/widgets/table/e-table-header-item.h +++ b/widgets/table/e-table-header-item.h @@ -10,6 +10,8 @@ #define E_IS_TABLE_HEADER_ITEM(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_ITEM_TYPE)) #define E_IS_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_ITEM_TYPE)) +typedef struct _ECellView ECellView; + typedef struct { GnomeCanvasItem parent; ETableHeader *eth; @@ -28,6 +30,9 @@ typedef struct { int resize_start_pos; GtkObject *resize_guide; + ECellView **cell_views; + int n_cells; + /* * Ids */ diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c index 1e53180804..5bf1e24fd0 100644 --- a/widgets/table/e-table-item.c +++ b/widgets/table/e-table-item.c @@ -44,9 +44,11 @@ eti_remove_table_model (ETableItem *eti) return; gtk_signal_disconnect (eti->table_model_change_id); + gtk_signal_disconnect (eti->table_model_selection_id); gtk_object_unref (GTK_OBJECT (eti->table_model)); eti->table_model_change_id = 0; + eti->table_model_selection_id = 0; eti->table_model = NULL; } @@ -73,6 +75,23 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti) eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); } +static void +eti_request_redraw (ETableItem *eti) +{ + GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; + + gnome_canvas_request_redraw (canvas, eti->x1, eti->y1, + eti->x1 + eti->width + 1, + eti->y1 + eti->height + 1); +} + +static void +eti_table_model_row_selection (ETableModel *table_model, ETableItem *eti) +{ + /* FIXME: we should optimize this to only redraw the selection change */ + eti_request_redraw (eti); +} + static void eti_add_table_model (ETableItem *eti, ETableModel *table_model) { @@ -83,31 +102,30 @@ eti_add_table_model (ETableItem *eti, ETableModel *table_model) eti->table_model_change_id = gtk_signal_connect ( GTK_OBJECT (table_model), "model_changed", GTK_SIGNAL_FUNC (eti_table_model_changed), eti); -} - -static void -eti_request_redraw (ETableItem *eti) -{ - GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; - - gnome_canvas_request_redraw (canvas, eti->x1, eti->y1, eti->x1 + eti->width, eti->y1 + eti->height); + eti->table_model_selection_id = gtk_signal_connect ( + GTK_OBJECT (table_model), "row_selection", + GTK_SIGNAL_FUNC (eti_table_model_row_selection), eti); } static void eti_header_dim_changed (ETableHeader *eth, int col, ETableItem *eti) { - eti->width = e_table_header_total_width (eti->header); + eti_request_redraw (eti); + eti->width = e_table_header_total_width (eti->header); eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); + eti_request_redraw (eti); } static void eti_header_structure_changed (ETableHeader *eth, ETableItem *eti) { - eti->width = e_table_header_total_width (eti->header); + eti_request_redraw (eti); + eti->width = e_table_header_total_width (eti->header); eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); + eti_request_redraw (eti); } @@ -181,6 +199,9 @@ static void eti_init (GnomeCanvasItem *item) { ETableItem *eti = E_TABLE_ITEM (item); + + eti->focused_col = -1; + eti->focused_row = -1; } static void @@ -199,6 +220,7 @@ eti_realize (GnomeCanvasItem *item) gdk_gc_ref (canvas_widget->style->white_gc); eti->grid_gc = gdk_gc_new (window); gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->fg [GTK_STATE_NORMAL]); + } static void @@ -277,7 +299,10 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, if (first_col == -1) return; +#if 0 printf ("Cols %d %d\n", first_col, last_col); +#endif + /* * Draw individual lines */ @@ -318,6 +343,25 @@ eti_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, static int eti_event (GnomeCanvasItem *item, GdkEvent *e) { + ETableItem *eti = E_TABLE_ITEM (item); + ETableCol *etc; + + switch (e->type){ + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_2BUTTON_PRESS: + + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: + if (eti->focused_col == -1) + return FALSE; + + etc = e_table_header_get_column (eti->header, eti->focused_col); + + e_cell_event (etc->ecell, e, eti->focused_col, eti->focused_row); + break; + + } return FALSE; } @@ -371,3 +415,19 @@ e_table_item_get_type (void) return type; } +void +e_table_item_focus (ETableItem *eti, int col, int row) +{ + if (eti->focused_col != -1) + e_table_item_unfocus (eti); + + eti->focused_col = col; + eti->focused_row = row; +} + +void +e_table_item_unfocus (ETableItem *eti) +{ + eti->focused_col = -1; + eti->focused_row = -1; +} diff --git a/widgets/table/e-table-item.h b/widgets/table/e-table-item.h index 7e548cf49d..fefa221227 100644 --- a/widgets/table/e-table-item.h +++ b/widgets/table/e-table-item.h @@ -27,11 +27,14 @@ typedef struct { int header_dim_change_id; int header_structure_change_id; int table_model_change_id; - + int table_model_selection_id; + GdkGC *fill_gc; GdkGC *grid_gc; unsigned int draw_grid:1; + + int focused_col, focused_row; } ETableItem; typedef struct { @@ -39,5 +42,7 @@ typedef struct { } ETableItemClass; GtkType e_table_item_get_type (void); +void e_table_item_focus (ETableItem *eti, int col, int row); +void e_table_item_unfocus (ETableItem *eti); #endif /* _E_TABLE_ITEM_H_ */ diff --git a/widgets/table/e-table-model.c b/widgets/table/e-table-model.c index de7bc67c51..1176b33ec7 100644 --- a/widgets/table/e-table-model.c +++ b/widgets/table/e-table-model.c @@ -16,6 +16,7 @@ static GtkObjectClass *e_table_model_parent_class; enum { MODEL_CHANGED, + ROW_SELECTION, LAST_SIGNAL }; @@ -88,6 +89,14 @@ e_table_model_class_init (GtkObjectClass *object_class) GTK_SIGNAL_OFFSET (ETableModelClass, model_changed), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); + + etm_signals [ROW_SELECTION] = + gtk_signal_new ("row_selection", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableModelClass, row_selection), + gtk_marshal_NONE__INT_INT, + GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); gtk_object_class_add_signals (object_class, etm_signals, LAST_SIGNAL); } @@ -158,3 +167,29 @@ e_table_model_max_col_width (ETableModel *etm, int col) return max; } #endif + +void +e_table_model_select_row (ETableModel *etm, int row) +{ + gtk_signal_emit (GTK_OBJECT (etm), etm_signals [ROW_SELECTION], row, 1); + etm->row_selected = row; +} + +void +e_table_model_unselect_row (ETableModel *etm, int row) +{ + if (etm->row_selected != -1){ + gtk_signal_emit ( + GTK_OBJECT (etm), etm_signals [ROW_SELECTION], + etm->row_selected, 0); + } + + etm->row_selected = -1; +} + +gint +e_table_model_get_selected_row (ETableModel *etm) +{ + return etm->row_selected; +} + diff --git a/widgets/table/e-table-model.h b/widgets/table/e-table-model.h index d12a465c0b..2d439a0065 100644 --- a/widgets/table/e-table-model.h +++ b/widgets/table/e-table-model.h @@ -11,6 +11,9 @@ typedef struct { GtkObject base; + + /* Temporary. I swear */ + int row_selected; } ETableModel; typedef struct { @@ -30,7 +33,8 @@ typedef struct { /* * Signals */ - void (*model_changed) (ETableModel *etm, int row); + void (*model_changed) (ETableModel *etm); + void (*row_selection) (ETableModel *etc, int row); } ETableModelClass; GtkType e_table_model_get_type (void); @@ -44,6 +48,9 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col, void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data); gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row); +void e_table_model_select_row (ETableModel *e_table_model, int row); +gint e_table_model_get_selected_row (ETableModel *e_table_model); + /* * Routines for emitting signals on the e_table */ diff --git a/widgets/table/e-table-simple.c b/widgets/table/e-table-simple.c index 32f7145bc6..b23cda1220 100644 --- a/widgets/table/e-table-simple.c +++ b/widgets/table/e-table-simple.c @@ -12,6 +12,8 @@ #include #include "e-table-simple.h" +#define PARENT_TYPE e_table_model_get_type() + static int simple_column_count (ETableModel *etm) { @@ -99,7 +101,7 @@ e_table_simple_get_type (void) (GtkClassInitFunc) NULL }; - type = gtk_type_unique (e_table_model_get_type (), &info); + type = gtk_type_unique (PARENT_TYPE, &info); } return type; diff --git a/widgets/table/e-table-sorted.c b/widgets/table/e-table-sorted.c index 2d53c79e5d..be19de2efb 100644 --- a/widgets/table/e-table-sorted.c +++ b/widgets/table/e-table-sorted.c @@ -11,93 +11,16 @@ #include "e-util.h" #include "e-table-sorted.h" -#define PARENT_TYPE E_TABLE_MODEL_TYPE +#define PARENT_TYPE E_TABLE_SUBSET_TYPE static ETableModelClass *ets_parent_class; -static void -ets_destroy (GtkObject *object) -{ - ETableSorted *ets = E_TABLE_SORTED (object); - - gtk_object_unref (GTK_OBJECT (ets->source)); - gtk_object_unref (GTK_OBJECT (ets->header)); - free (ets->map_table); - - GTK_OBJECT_CLASS (ets_parent_class)->destroy (object); -} - -static int -ets_column_count (ETableModel *etm) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_column_count (ets->source); -} - -static const char * -ets_column_name (ETableModel *etm, int col) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_column_name (ets->source, col); -} - -static int -ets_row_count (ETableModel *etm) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_row_count (ets->source); -} - -static void * -ets_value_at (ETableModel *etm, int col, int row) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_value_at (ets->source, col, ets->map_table [row]); -} - -static void -ets_set_value_at (ETableModel *etm, int col, int row, void *val) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_set_value_at (ets->source, col, ets->map_table [row], val); -} - -static gboolean -ets_is_cell_editable (ETableModel *etm, int col, int row) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_is_cell_editable (ets->source, col, ets->map_table [row]); -} - -static int -ets_row_height (ETableModel *etm, int row) -{ - ETableSorted *ets = (ETableSorted *)etm; - - return e_table_model_row_height (ets->source, ets->map_table [row]); -} - static void ets_class_init (GtkObjectClass *klass) { ETableModelClass *table_class = (ETableModelClass *) klass; ets_parent_class = gtk_type_class (PARENT_TYPE); - klass->destroy = ets_destroy; - - table_class->column_count = ets_column_count; - table_class->column_name = ets_column_name; - table_class->row_count = ets_row_count; - table_class->value_at = ets_value_at; - table_class->set_value_at = ets_set_value_at; - table_class->is_cell_editable = ets_is_cell_editable; - table_class->row_height = ets_row_height; } E_MAKE_TYPE(e_table_sorted, "ETableSorted", ETableSorted, ets_class_init, NULL, PARENT_TYPE); @@ -108,49 +31,63 @@ static int my_sort (const void *a, const void *b) { GCompareFunc comp; + ETableModel *source = E_TABLE_SUBSET (sort_ets)->source; const int *ia = (const int *) a; const int *ib = (const int *) b; void *va, *vb; - va = e_table_model_value_at (sort_ets->source, sort_ets->sort_idx, *ia); - vb = e_table_model_value_at (sort_ets->source, sort_ets->sort_idx, *ib); + va = e_table_model_value_at (source, sort_ets->sort_col, *ia); + vb = e_table_model_value_at (source, sort_ets->sort_col, *ib); - comp = sort_ets->sort_col->compare; + return (*sort_ets->compare) (va, vb); +} - return (*comp) (va, vb); +static void +do_sort (ETableSorted *ets) +{ + ETableSubset *etss = E_TABLE_SUBSET (ets); + g_assert (sort_ets == NULL); + + sort_ets = ets; + qsort (etss->map_table, etss->n_map, sizeof (unsigned int), my_sort); + sort_ets = NULL; } ETableModel * -e_table_sorted_new (ETableModel *source, ETableHeader *header, short sort_field) +e_table_sorted_new (ETableModel *source, int col, GCompareFunc compare) { ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE); + ETableSubset *etss = E_TABLE_SUBSET (ets); const int nvals = e_table_model_row_count (source); unsigned int *buffer; int i; - buffer = malloc (sizeof (unsigned int *) * nvals); - if (buffer = NULL) + if (e_table_subset_construct (etss, source, nvals) == NULL){ + gtk_object_destroy (GTK_OBJECT (ets)); return NULL; - ets->map_table = buffer; - ets->n_map = nvals; - ets->source = source; - ets->header = header; - ets->sort_col = e_table_header_get_column (header, sort_field); - ets->sort_idx = sort_field; - gtk_object_ref (GTK_OBJECT (source)); - gtk_object_ref (GTK_OBJECT (header)); + } + + ets->compare = compare; + ets->sort_col = col; /* Init */ for (i = 0; i < nvals; i++) - ets->map_table [i] = i; + etss->map_table [i] = i; - /* Sort */ - g_assert (sort_ets == NULL); - sort_ets = ets; - qsort (ets->map_table, nvals, sizeof (unsigned int), my_sort); - sort_ets = NULL; + do_sort (ets); return (ETableModel *) ets; } - +void +e_table_sorted_resort (ETableSorted *ets, int col, GCompareFunc compare) +{ + if (col == -1 || compare == NULL) + do_sort (ets); + else { + ets->sort_col = col; + ets->compare = compare; + do_sort (ets); + } +} + diff --git a/widgets/table/e-table-sorted.h b/widgets/table/e-table-sorted.h index 65578b7b83..2ec52df2e7 100644 --- a/widgets/table/e-table-sorted.h +++ b/widgets/table/e-table-sorted.h @@ -3,7 +3,7 @@ #include #include "e-table-model.h" -#include "e-table-header.h" +#include "e-table-subset.h" #define E_TABLE_SORTED_TYPE (e_table_sorted_get_type ()) #define E_TABLE_SORTED(o) (GTK_CHECK_CAST ((o), E_TABLE_SORTED_TYPE, ETableSorted)) @@ -12,23 +12,18 @@ #define E_IS_TABLE_SORTED_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SORTED_TYPE)) typedef struct { - ETableModel base; + ETableSubset base; - ETableModel *source; - ETableHeader *header; - ETableCol *sort_col; - short sort_idx; - - int n_map; - unsigned int *map_table; + short sort_col; + GCompareFunc compare; } ETableSorted; typedef struct { - ETableModelClass parent_class; + ETableSubset parent_class; } ETableSortedClass; GtkType e_table_sorted_get_type (void); -ETableModel *e_table_sorted_new (ETableModel *etm, ETableHeader *header, - short sort_field); +ETableModel *e_table_sorted_new (ETableModel *etm, int col, GCompareFunc compare); +void e_table_sorted_resort (ETableSorted *ets, int col, GCompareFunc compare); #endif /* _E_TABLE_SORTED_H_ */ diff --git a/widgets/table/e-table-subset.c b/widgets/table/e-table-subset.c index 0b9621ac84..afa1b862b4 100644 --- a/widgets/table/e-table-subset.c +++ b/widgets/table/e-table-subset.c @@ -19,52 +19,122 @@ etss_destroy (GtkObject *object) { ETableSubset *etss = E_TABLE_SUBSET (object); - gtk_object_unref (GTK_OBJECT (etss->source)); - free (ets->subset_table); + if (etss->source) + gtk_object_unref (GTK_OBJECT (etss->source)); - GTK_OBJECT_CLASS (ets_parent_class)->destroy (object); + if (etss->map_table) + free (etss->map_table); + + GTK_OBJECT_CLASS (etss_parent_class)->destroy (object); +} + +static int +etss_column_count (ETableModel *etm) +{ + ETableSubset *etss = (ETableSubset *)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); +} + +static void * +etss_value_at (ETableModel *etm, int col, int row) +{ + ETableSubset *etss = (ETableSubset *)etm; + + return e_table_model_value_at (etss->source, col, etss->map_table [row]); +} + +static void +etss_set_value_at (ETableModel *etm, int col, int row, void *val) +{ + ETableSubset *etss = (ETableSubset *)etm; + + return e_table_model_set_value_at (etss->source, col, etss->map_table [row], val); +} + +static gboolean +etss_is_cell_editable (ETableModel *etm, int col, int row) +{ + ETableSubset *etss = (ETableSubset *)etm; + + 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) { + ETableModelClass *table_class = (ETableModelClass *) klass; + etss_parent_class = gtk_type_class (PARENT_TYPE); 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); ETableModel * -e_table_subset_new (ETableModel *source, ETableHeader *header, short sort_field) +e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) { - ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE); - const int nvals = e_table_model_row_count (source); unsigned int *buffer; int i; - buffer = malloc (sizeof (unsigned int *) * nvals); + buffer = (unsigned int *) malloc (sizeof (unsigned int *) * nvals); if (buffer = NULL) return NULL; - ets->map_table = buffer; - ets->n_map = nvals; - ets->source = source; - ets->header = header; - ets->sort_col = e_table_header_get_column (header, sort_field); - ets->sort_idx = sort_field; + etss->map_table = buffer; + etss->n_map = nvals; + etss->source = source; gtk_object_ref (GTK_OBJECT (source)); - gtk_object_ref (GTK_OBJECT (header)); /* Init */ for (i = 0; i < nvals; i++) - ets->map_table [i] = i; + etss->map_table [i] = i; - /* Sort */ - g_assert (sort_ets == NULL); - sort_ets = ets; - qsort (ets->map_table, nvals, sizeof (unsigned int), my_sort); - sort_ets = NULL; - - return (ETableModel *) ets; +} + +ETableModel * +e_table_subset_new (ETableModel *source, const int nvals) +{ + ETableSubset *etss = gtk_type_new (E_TABLE_SUBSET_TYPE); + + if (e_table_subset_construct (etss, source, nvals) == NULL){ + gtk_object_destroy (GTK_OBJECT (etss)); + return NULL; + } + + return (ETableModel *) etss; } diff --git a/widgets/table/e-table-subset.h b/widgets/table/e-table-subset.h index a87d6d0df8..5576c55f1d 100644 --- a/widgets/table/e-table-subset.h +++ b/widgets/table/e-table-subset.h @@ -3,7 +3,6 @@ #include #include "e-table-model.h" -#include "e-table-header.h" #define E_TABLE_SUBSET_TYPE (e_table_subset_get_type ()) #define E_TABLE_SUBSET(o) (GTK_CHECK_CAST ((o), E_TABLE_SUBSET_TYPE, ETableSubset)) @@ -15,15 +14,16 @@ typedef struct { ETableModel base; ETableModel *source; - int subset_count; - int *subset_table; + int n_map; + int *map_table; } ETableSubset; typedef struct { ETableModelClass parent_class; } ETableSubsetClass; -GtkType e_table_subset_get_type (void); -ETableModel *e_table_subset_new (ETableModel *etm, - int n_vals, int *ptrs); +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); + #endif /* _E_TABLE_SUBSET_H_ */ diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index 795c737b36..3b13e87d6b 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -9,28 +9,14 @@ #include #include #include "e-table.h" +#include "e-util.h" #define PARENT_OBJECT_TYPE gnome_canvas_get_type () -GtkType -e_table_get_type (void) -{ - static GtkType type = 0; - - if (!type){ - GtkTypeInfo info = { - "ETable", - sizeof (ETable), - sizeof (ETableClass), - (GtkClassInitFunc) e_table_class_init, - (GtkObjectInitFunc) NULL, - NULL, /* reserved 1 */ - NULL, /* reserved 2 */ - (GtkClassInitFunc) NULL - }; - - type = gtk_type_unique (PARENT_OBJECT_TYPE, &info); - } +E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, NULL, PARENT_TYPE); - return type; +ETable * +e_table_new (ETableHeader *eth, ETableModel *etm) +{ } + diff --git a/widgets/table/table-test.c b/widgets/table/table-test.c index 54392a73bc..e646b44655 100644 --- a/widgets/table/table-test.c +++ b/widgets/table/table-test.c @@ -11,7 +11,6 @@ #include "e-table-simple.h" #include "e-table-header.h" #include "e-table-header-item.h" -#include "e-table-render.h" #include "e-table-item.h" char buffer [1024]; @@ -185,6 +184,7 @@ main (int argc, char *argv []) GtkWidget *canvas, *window; ETableModel *e_table_model; ETableHeader *e_table_header; + ECell *cell_left_just; int i; gnome_init ("TableTest", "TableTest", argc, argv); @@ -203,10 +203,12 @@ main (int argc, char *argv []) * Header */ e_table_header = e_table_header_new (); + cell_left_just = e_cell_text_new ("fixed", GTK_JUSTIFY_LEFT); + for (i = 0; i < cols; i++){ ETableCol *ecol = e_table_col_new ( - column_labels [i], 80, 20, e_table_render_string, - NULL, g_str_equal, TRUE); + column_labels [i], 80, 20, cell_left_just, + g_str_equal, TRUE); e_table_header_add_column (e_table_header, ecol, i); } -- cgit