From 48618eb6eb0d02a6bc74d19d0241ac6b0849d136 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Fri, 10 Dec 1999 07:36:51 +0000 Subject: fix this routine. 1999-12-09 Miguel de Icaza * e-table-header.c (e_table_header_col_diff): fix this routine. 1999-12-04 Miguel de Icaza * e-table-header-item.c (ethi_event): Started drag and drop support. * e-table-item.c (eti_table_model_changed): The columns are controled by the Header, not by the TableModel. * e-table-header-item.c (ethi_draw): Fixed redraw logic to support arbitrary header positioning. * e-cell.h: Revamped e-cell interface. We now provide the model column and the view column to all methods (so that the methods can talk to the view and to the model at the same time). * e-table-item.c: Update to new API * e-cell-test.c: Update to new API 1999-12-03 Miguel de Icaza * e-cell.c (e_cell_class_init): Provide emtpy methods for enter_edit, and leave_edit. * e-table-item.c: Killed draw cell. (eti_draw): Perform column mapping here. (e_table_item_leave_edit): ditto. (e_table_item_enter_edit): ditto. (eti_event): ditto. svn path=/trunk/; revision=1478 --- widgets/ChangeLog | 33 ++++ widgets/Makefile.am | 4 +- widgets/e-cell-text.c | 37 ++-- widgets/e-cell-toggle.c | 27 ++- widgets/e-cell.c | 44 +++-- widgets/e-cell.h | 27 +-- widgets/e-table-header-item.c | 316 +++++++++++++++++++++++++++++++--- widgets/e-table-header-item.h | 11 ++ widgets/e-table-header.c | 25 ++- widgets/e-table-header.h | 3 + widgets/e-table-item.c | 115 ++++++------- widgets/e-table-item.h | 2 + widgets/e-table-model.c | 11 +- widgets/e-table-model.h | 6 + widgets/e-table-sorted.c | 2 - widgets/e-table/ChangeLog | 33 ++++ widgets/e-table/Makefile.am | 4 +- widgets/e-table/e-cell-text.c | 37 ++-- widgets/e-table/e-cell-toggle.c | 27 ++- widgets/e-table/e-cell.c | 44 +++-- widgets/e-table/e-cell.h | 27 +-- widgets/e-table/e-table-header-item.c | 316 +++++++++++++++++++++++++++++++--- widgets/e-table/e-table-header-item.h | 11 ++ widgets/e-table/e-table-header.c | 25 ++- widgets/e-table/e-table-header.h | 3 + widgets/e-table/e-table-item.c | 115 ++++++------- widgets/e-table/e-table-item.h | 2 + widgets/e-table/e-table-model.c | 11 +- widgets/e-table/e-table-model.h | 6 + widgets/e-table/e-table-sorted.c | 2 - widgets/e-table/table-test.c | 2 +- widgets/e-table/test-check.c | 1 - widgets/e-table/test-cols.c | 37 +++- widgets/table-test.c | 2 +- widgets/table/e-cell-text.c | 37 ++-- widgets/table/e-cell-toggle.c | 27 ++- widgets/table/e-cell.c | 44 +++-- widgets/table/e-cell.h | 27 +-- widgets/table/e-table-header-item.c | 316 +++++++++++++++++++++++++++++++--- widgets/table/e-table-header-item.h | 11 ++ widgets/table/e-table-header.c | 25 ++- widgets/table/e-table-header.h | 3 + widgets/table/e-table-item.c | 115 ++++++------- widgets/table/e-table-item.h | 2 + widgets/table/e-table-model.c | 11 +- widgets/table/e-table-model.h | 6 + widgets/table/e-table-sorted.c | 2 - widgets/table/table-test.c | 2 +- widgets/table/test-check.c | 1 - widgets/table/test-cols.c | 37 +++- widgets/test-check.c | 1 - widgets/test-cols.c | 37 +++- 52 files changed, 1599 insertions(+), 473 deletions(-) (limited to 'widgets') diff --git a/widgets/ChangeLog b/widgets/ChangeLog index be5207f31b..e4c9cc9ab8 100644 --- a/widgets/ChangeLog +++ b/widgets/ChangeLog @@ -1,3 +1,36 @@ +1999-12-09 Miguel de Icaza + + * e-table-header.c (e_table_header_col_diff): fix this routine. + +1999-12-04 Miguel de Icaza + + * e-table-header-item.c (ethi_event): Started drag and drop + support. + + * e-table-item.c (eti_table_model_changed): The columns are + controled by the Header, not by the TableModel. + + * e-table-header-item.c (ethi_draw): Fixed redraw logic to support + arbitrary header positioning. + + * e-cell.h: Revamped e-cell interface. We now provide the model + column and the view column to all methods (so that the methods can + talk to the view and to the model at the same time). + + * e-table-item.c: Update to new API + * e-cell-test.c: Update to new API + +1999-12-03 Miguel de Icaza + + * e-cell.c (e_cell_class_init): Provide emtpy methods for + enter_edit, and leave_edit. + + * e-table-item.c: Killed draw cell. + (eti_draw): Perform column mapping here. + (e_table_item_leave_edit): ditto. + (e_table_item_enter_edit): ditto. + (eti_event): ditto. + 1999-12-02 Miguel de Icaza * e-table-header.c (e_table_header_index): fixed api. diff --git a/widgets/Makefile.am b/widgets/Makefile.am index 1b237dce70..677af55041 100644 --- a/widgets/Makefile.am +++ b/widgets/Makefile.am @@ -51,5 +51,7 @@ table_test_LDFLAGS = `gnome-config --libs gdk_pixbuf` EXTRA_DIST = \ sample.table \ + add-col.xpm \ check-empty.xpm \ - check-filled.xpm + check-filled.xpm \ + remove-col.xpm diff --git a/widgets/e-cell-text.c b/widgets/e-cell-text.c index d9d8a568db..828be6cc29 100644 --- a/widgets/e-cell-text.c +++ b/widgets/e-cell-text.c @@ -29,7 +29,7 @@ typedef struct { /* * Where the editing is taking place */ - int col, row; + int model_col, view_col, row; } CellEdit; typedef struct { @@ -48,9 +48,9 @@ typedef struct { static ECellClass *parent_class; static void -ect_queue_redraw (ECellTextView *text_view, int col, int row) +ect_queue_redraw (ECellTextView *text_view, int view_col, int view_row) { - e_table_item_redraw_range (text_view->eti, col, row, col, row); + e_table_item_redraw_range (text_view->eti, view_col, view_row, view_col, view_row); } /* @@ -62,7 +62,7 @@ ect_accept_edits (ECellTextView *text_view) const char *text = gtk_entry_get_text (text_view->edit->entry); CellEdit *edit = text_view->edit; - e_table_model_set_value_at (text_view->eti->table_model, edit->col, edit->row, text); + e_table_model_set_value_at (text_view->eti->table_model, edit->model_col, edit->row, text); } /* @@ -92,7 +92,7 @@ ect_stop_editing (ECellTextView *text_view) static void ect_cancel_edit (ECellTextView *text_view) { - ect_queue_redraw (text_view, text_view->edit->col, text_view->edit->row); + ect_queue_redraw (text_view, text_view->edit->view_col, text_view->edit->row); ect_stop_editing (text_view); } @@ -149,14 +149,14 @@ ect_unrealize (ECellView *ecv) */ static void ect_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { ECellText *ect = E_CELL_TEXT (ecell_view->ecell); ECellTextView *text_view = (ECellTextView *) ecell_view; GtkWidget *w = GTK_WIDGET (text_view->canvas); GdkRectangle rect; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); GdkFont *font = text_view->font; const int height = font->ascent + font->descent; int xoff; @@ -168,7 +168,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, if (text_view->edit){ CellEdit *edit = text_view->edit; - if ((edit->col == col) && (edit->row == row)) + if ((edit->view_col == view_col) && (edit->row == row)) edit_display = TRUE; } @@ -312,7 +312,7 @@ ect_edit_select_all (ECellTextView *text_view) * ECell::event method */ static gint -ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; @@ -327,7 +327,7 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) if (text_view->edit){ printf ("FIXME: Should handle click here\n"); } else - e_table_item_enter_edit (text_view->eti, col, row); + e_table_item_enter_edit (text_view->eti, view_col, row); break; case GDK_BUTTON_RELEASE: @@ -345,12 +345,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) } if (!text_view->edit){ - e_table_item_enter_edit (text_view->eti, col, row); + e_table_item_enter_edit (text_view->eti, view_col, row); ect_edit_select_all (text_view); } gtk_widget_event (GTK_WIDGET (text_view->edit->entry), event); - ect_queue_redraw (text_view, col, row); + ect_queue_redraw (text_view, view_col, row); break; case GDK_KEY_RELEASE: @@ -366,7 +366,7 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) * ECell::height method */ static int -ect_height (ECellView *ecell_view, int col, int row) +ect_height (ECellView *ecell_view, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; @@ -386,16 +386,17 @@ ect_entry_activate (GtkEntry *entry, ECellTextView *text_view) * ECellView::enter_edit method */ static void * -ect_enter_edit (ECellView *ecell_view, int col, int row) +ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); CellEdit *edit; edit = g_new (CellEdit, 1); text_view->edit = edit; - edit->col = col; + edit->model_col = model_col; + edit->view_col = view_col; edit->row = row; edit->entry = (GtkEntry *) gtk_entry_new (); @@ -412,7 +413,7 @@ ect_enter_edit (ECellView *ecell_view, int col, int row) gtk_widget_set_uposition (edit->entry_top, 20000, 20000); gtk_widget_show_all (edit->entry_top); - ect_queue_redraw (text_view, col, row); + ect_queue_redraw (text_view, view_col, row); return NULL; } @@ -421,7 +422,7 @@ ect_enter_edit (ECellView *ecell_view, int col, int row) * ECellView::leave_edit method */ static void -ect_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context) +ect_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context) { ECellTextView *text_view = (ECellTextView *) ecell_view; diff --git a/widgets/e-cell-toggle.c b/widgets/e-cell-toggle.c index 8e06d8d87d..ec6fa38a38 100644 --- a/widgets/e-cell-toggle.c +++ b/widgets/e-cell-toggle.c @@ -29,9 +29,9 @@ typedef struct { static ECellClass *parent_class; static void -etog_queue_redraw (ECellToggleView *text_view, int col, int row) +etog_queue_redraw (ECellToggleView *text_view, int view_col, int view_row) { - e_table_item_redraw_range (text_view->eti, col, row, col, row); + e_table_item_redraw_range (text_view->eti, view_col, view_row, view_col, view_row); } /* @@ -40,7 +40,6 @@ etog_queue_redraw (ECellToggleView *text_view, int col, int row) static ECellView * etog_realize (ECell *ecell, void *view) { - ECellToggle *eccb = E_CELL_TOGGLE (ecell); ECellToggleView *toggle_view = g_new0 (ECellToggleView, 1); ETableItem *eti = E_TABLE_ITEM (view); GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; @@ -72,7 +71,7 @@ etog_unrealize (ECellView *ecv) */ static void etog_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell); @@ -80,9 +79,8 @@ etog_draw (ECellView *ecell_view, GdkDrawable *drawable, GdkPixbuf *image; ArtPixBuf *art; int x, y, width, height; - gboolean free_image; const int value = GPOINTER_TO_INT ( - e_table_model_value_at (ecell_view->ecell->table_model, col, row)); + e_table_model_value_at (ecell_view->ecell->table_model, model_col, row)); if (value >= toggle->n_states){ g_warning ("Value from the table model is %d, the states we support are [0..%d)\n", @@ -166,7 +164,7 @@ etog_draw (ECellView *ecell_view, GdkDrawable *drawable, } static void -etog_set_value (ECellToggleView *toggle_view, int col, int row, int value) +etog_set_value (ECellToggleView *toggle_view, int model_col, int view_col, int row, int value) { ECell *ecell = toggle_view->cell_view.ecell; ECellToggle *toggle = E_CELL_TOGGLE (ecell); @@ -174,29 +172,28 @@ etog_set_value (ECellToggleView *toggle_view, int col, int row, int value) if (value >= toggle->n_states) value = 0; - e_table_model_set_value_at (ecell->table_model, col, row, GINT_TO_POINTER (value)); - etog_queue_redraw (toggle_view, col, row); + e_table_model_set_value_at (ecell->table_model, model_col, row, GINT_TO_POINTER (value)); + etog_queue_redraw (toggle_view, view_col, row); } /* * ECell::event method */ static gint -etog_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +etog_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { - ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell); ECellToggleView *toggle_view = (ECellToggleView *) ecell_view; - void *_value = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + void *_value = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); const int value = GPOINTER_TO_INT (_value); switch (event->type){ case GDK_BUTTON_RELEASE: - etog_set_value (toggle_view, col, row, value + 1); + etog_set_value (toggle_view, model_col, view_col, row, value + 1); return TRUE; case GDK_KEY_PRESS: if (event->key.keyval == GDK_space){ - etog_set_value (toggle_view, col, row, value + 1); + etog_set_value (toggle_view, model_col, view_col, row, value + 1); return TRUE; } return FALSE; @@ -211,7 +208,7 @@ etog_event (ECellView *ecell_view, GdkEvent *event, int col, int row) * ECell::height method */ static int -etog_height (ECellView *ecell_view, int col, int row) +etog_height (ECellView *ecell_view, int model_col, int view_col, int row) { ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell); diff --git a/widgets/e-cell.c b/widgets/e-cell.c index 2bc49f7a45..a4a03655dc 100644 --- a/widgets/e-cell.c +++ b/widgets/e-cell.c @@ -25,30 +25,30 @@ ec_unrealize (ECellView *e_cell) static void ec_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { g_error ("e-cell-draw invoked\n"); } static gint -ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +ec_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { g_error ("e-cell-event invoked\n"); return 0; } static gint -ec_height (ECellView *ecell_view, int col, int row) +ec_height (ECellView *ecell_view, int model_col, int view_col, int row) { g_error ("e-cell-event invoked\n"); return 0; } static void -ec_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2) +ec_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2) { - ecell_view->focus_col = col; + ecell_view->focus_col = view_col; ecell_view->focus_row = row; ecell_view->focus_x1 = x1; ecell_view->focus_y1 = y1; @@ -67,6 +67,17 @@ ec_unfocus (ECellView *ecell_view) ecell_view->focus_y2 = -1; } +static void * +ec_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) +{ + return NULL; +} + +static void +ec_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *context) +{ +} + static void e_cell_class_init (GtkObjectClass *object_class) { @@ -79,22 +90,23 @@ e_cell_class_init (GtkObjectClass *object_class) ecc->focus = ec_focus; ecc->unfocus = ec_unfocus; ecc->height = ec_height; + ecc->enter_edit = ec_enter_edit; + ecc->leave_edit = ec_leave_edit; } static void e_cell_init (GtkObject *object) { - ECell *e_cell = E_CELL (object); } 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_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->event ( - ecell_view, event, col, row); + ecell_view, event, model_col, view_col, row); } ECellView * @@ -112,29 +124,29 @@ e_cell_unrealize (ECellView *ecell_view) void e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, int x1, int y1, int x2, int y2) + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->draw ( - ecell_view, drawable, col, row, selected, x1, y1, x2, y2); + ecell_view, drawable, model_col, view_col, row, selected, x1, y1, x2, y2); } int -e_cell_height (ECellView *ecell_view, int col, int row) +e_cell_height (ECellView *ecell_view, int model_col, int view_col, int row) { return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->height ( - ecell_view, col, row); + ecell_view, model_col, view_col, row); } void * -e_cell_enter_edit (ECellView *ecell_view, int col, int row) +e_cell_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) { return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->enter_edit ( - ecell_view, col, row); + ecell_view, model_col, view_col, row); } void -e_cell_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context) +e_cell_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context) { E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->leave_edit ( - ecell_view, col, row, edit_context); + ecell_view, model_col, view_col, row, edit_context); } diff --git a/widgets/e-cell.h b/widgets/e-cell.h index b0f62d020c..f72f97e8dd 100644 --- a/widgets/e-cell.h +++ b/widgets/e-cell.h @@ -32,28 +32,31 @@ typedef struct { ECellView *(*realize) (ECell *ecell, void *view); void (*unrealize) (ECellView *e_cell_view); void (*draw) (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, int x1, int y1, int x2, int y2); - gint (*event) (ECellView *ecell_view, GdkEvent *event, int col, int row); - void (*focus) (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2); + int model_col, int view_col, int row, + gboolean selected, int x1, int y1, int x2, int y2); + gint (*event) (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row); + void (*focus) (ECellView *ecell_view, int model_col, int view_col, + int row, int x1, int y1, int x2, int y2); void (*unfocus) (ECellView *ecell_view); - int (*height) (ECellView *ecell_view, int col, int row); + int (*height) (ECellView *ecell_view, int model_col, int view_col, int row); - void *(*enter_edit)(ECellView *ecell_view, int col, int row); - void (*leave_edit)(ECellView *ecell_view, int col, int row, void *context); + void *(*enter_edit)(ECellView *ecell_view, int model_col, int view_col, int row); + void (*leave_edit)(ECellView *ecell_view, int model_col, int view_col, int row, void *context); } ECellClass; GtkType e_cell_get_type (void); -void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row); +void e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row); ECellView *e_cell_realize (ECell *ecell, void *view); void e_cell_unrealize (ECellView *ecell_view); void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, + int x1, int y1, int x2, int y2); +void e_cell_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2); -void e_cell_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2); void e_cell_unfocus (ECellView *ecell_view); -int e_cell_height (ECellView *ecell_view, int col, int row); +int e_cell_height (ECellView *ecell_view, int model_col, int view_col, int row); -void *e_cell_enter_edit(ECellView *ecell_view, int col, int row); -void e_cell_leave_edit(ECellView *ecell_view, int col, int row, void *edit_context); +void *e_cell_enter_edit(ECellView *ecell_view, int model_col, int view_col, int row); +void e_cell_leave_edit(ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context); #endif /* _E_CELL_H_ */ diff --git a/widgets/e-table-header-item.c b/widgets/e-table-header-item.c index 5368f10602..0b5be9b84a 100644 --- a/widgets/e-table-header-item.c +++ b/widgets/e-table-header-item.c @@ -8,10 +8,19 @@ */ #include #include +#include +#include +#include +#include +#include #include "e-table-header.h" #include "e-table-header-item.h" +#include "e-table-col-dnd.h" #include "e-cursors.h" +#include "add-col.xpm" +#include "remove-col.xpm" + /* Padding above and below of the string in the header display */ #define PADDING 4 @@ -22,8 +31,17 @@ #define PARENT_OBJECT_TYPE gnome_canvas_item_get_type () +#define ELEMENTS(x) (sizeof (x) / sizeof (x[0])) + static GnomeCanvasItemClass *ethi_parent_class; +/* + * DnD icons + */ +static GdkColormap *dnd_colormap; +static GdkPixmap *remove_col_pixmap, *remove_col_mask; +static GdkPixmap *add_col_pixmap, *add_col_mask; + enum { ARG_0, ARG_TABLE_HEADER, @@ -32,6 +50,14 @@ enum { ARG_TABLE_FONTSET }; +static GtkTargetEntry ethi_drag_types [] = { + { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER }, +}; + +static GtkTargetEntry ethi_drop_types [] = { + { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER }, +}; + static void ethi_destroy (GtkObject *object) { @@ -151,6 +177,177 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) ethi_update (item, NULL, NULL, 0); } +static int +ethi_find_col_by_x (ETableHeaderItem *ethi, int x) +{ + const int cols = e_table_header_count (ethi->eth); + int x1 = ethi->x1; + int col; + + if (x < x1) + return -1; + + for (col = 0; col < cols; col++){ + ETableCol *ecol = e_table_header_get_column (ethi->eth, col); + + if ((x >= x1) && (x <= x1 + ecol->width)) + return col; + + x1 += ecol->width; + } + return -1; +} + +static void +ethi_remove_drop_marker (ETableHeaderItem *ethi) +{ + if (ethi->drag_mark == -1) + return; + + ethi->drag_mark = -1; + gtk_object_destroy (GTK_OBJECT (ethi->drag_mark_item)); + ethi->drag_mark_item = NULL; +} + +static void +ethi_add_drop_marker (ETableHeaderItem *ethi, int col) +{ + GnomeCanvasPoints *points; + int x; + + if (ethi->drag_mark == col) + return; + + if (ethi->drag_mark_item) + gtk_object_destroy (GTK_OBJECT (ethi->drag_mark_item)); + + ethi->drag_mark = col; + + ethi->drag_mark_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (ethi)->canvas->root), + gnome_canvas_group_get_type (), + "x", 0, + "y", 0, + NULL); + + points = gnome_canvas_points_new (3); + + x = e_table_header_col_diff (ethi->eth, 0, col); + + points->coords [0] = ethi->x1 + x - 5; + points->coords [1] = ethi->y1; + points->coords [2] = points->coords [0] + 10; + points->coords [3] = points->coords [1]; + points->coords [4] = ethi->x1 + x; + points->coords [5] = ethi->y1 + 5; + + gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (ethi->drag_mark_item), + gnome_canvas_polygon_get_type (), + "points", points, + "fill_color", "red", + NULL); + + points->coords [0] --; + points->coords [1] += ethi->height - 1; + points->coords [3] = points->coords [1]; + points->coords [5] = points->coords [1] - 6; + + gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (ethi->drag_mark_item), + gnome_canvas_polygon_get_type (), + "points", points, + "fill_color", "red", + NULL); + + gnome_canvas_points_unref (points); +} + +#define gray50_width 2 +#define gray50_height 2 +static char gray50_bits [] = { + 0x02, 0x01, }; + +static void +ethi_add_destroy_marker (ETableHeaderItem *ethi) +{ + double x1; + + if (ethi->remove_item) + gtk_object_destroy (GTK_OBJECT (ethi->remove_item)); + + if (!ethi->stipple) + ethi->stipple = gdk_bitmap_create_from_data (NULL, gray50_bits, gray50_width, gray50_height); + + x1 = ethi->x1 + (double) e_table_header_col_diff (ethi->eth, 0, ethi->drag_col); + ethi->remove_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (ethi)->canvas->root), + gnome_canvas_rect_get_type (), + "x1", x1 + 1, + "y1", (double) ethi->y1 + 1, + "x2", (double) x1 + e_table_header_col_diff (ethi->eth, ethi->drag_col, ethi->drag_col+1) - 2, + "y2", (double) ethi->y1 + ethi->height - 2, + "fill_color", "red", + "fill_stipple", ethi->stipple, + NULL); +} + +static void +ethi_remove_destroy_marker (ETableHeaderItem *ethi) +{ + if (!ethi->remove_item) + return; + + gtk_object_destroy (GTK_OBJECT (ethi->remove_item)); + ethi->remove_item = NULL; +} + +static gboolean +ethi_drag_motion (GtkObject *canvas, GdkDragContext *context, + gint x, gint y, guint time, + ETableHeaderItem *ethi) +{ + + if ((x >= ethi->x1) && (x <= (ethi->x1 + ethi->width)) && + (y >= ethi->y1) && (y <= (ethi->y1 + ethi->height))){ + int col; + + col = ethi_find_col_by_x (ethi, x); + + if (col != -1){ + ethi_remove_destroy_marker (ethi); + ethi_add_drop_marker (ethi, col); + } else { + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); + } + } else { + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); + } + + gdk_drag_status (context, context->suggested_action, time); + + return TRUE; +} + +static void +ethi_drag_end (GtkWidget *canvas, GdkDragContext *context, ETableHeaderItem *ethi) +{ + printf ("Ending\n"); + + ethi_remove_drop_marker (ethi); + ethi_remove_destroy_marker (ethi); + ethi->drag_col = -1; +} + +static void +ethi_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, ETableHeaderItem *ethi) +{ + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); +} + static void ethi_realize (GnomeCanvasItem *item) { @@ -171,19 +368,47 @@ ethi_realize (GnomeCanvasItem *item) if (!ethi->font) ethi_font_load (ethi, "fixed"); + + /* + * Now, configure DnD + */ + gtk_drag_dest_set (GTK_WIDGET (item->canvas), GTK_DEST_DEFAULT_ALL, + ethi_drop_types, ELEMENTS (ethi_drop_types), + GDK_ACTION_MOVE); + + ethi->drag_motion_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_motion", + GTK_SIGNAL_FUNC (ethi_drag_motion), ethi); + + ethi->drag_leave_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_leave", + GTK_SIGNAL_FUNC (ethi_drag_leave), ethi); + + ethi->drag_end_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_end", + GTK_SIGNAL_FUNC (ethi_drag_end), ethi); } static void ethi_unrealize (GnomeCanvasItem *item) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); - + gdk_gc_unref (ethi->gc); ethi->gc = NULL; gdk_cursor_destroy (ethi->normal_cursor); ethi->normal_cursor = NULL; + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_motion_id); + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_end_id); + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_leave_id); + + if (ethi->stipple){ + gdk_bitmap_unref (ethi->stipple); + ethi->stipple = NULL; + } + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize) (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item); } @@ -228,25 +453,21 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, } static void -ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height) +ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); GnomeCanvas *canvas = item->canvas; GdkGC *gc; const int cols = e_table_header_count (ethi->eth); - int x2 = x1 + width; - int col, total; - int x; - - total = 0; - x = -x1; + int x1, x2; + int col; #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++){ + x1 = x2 = ethi->x1; + for (col = 0; col < cols; col++, x1 = x2){ ETableCol *ecol = e_table_header_get_column (ethi->eth, col); int col_width; @@ -255,23 +476,19 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int wid else col_width = ecol->width; - if (x1 > total + col_width){ - total += col_width; - x += col_width; - continue; - } - - if (x2 < total) - return; + x2 += col_width; + + if (x1 > (x + width)) + break; + if (x2 < x) + continue; + gc = GTK_WIDGET (canvas)->style->bg_gc [GTK_STATE_ACTIVE]; draw_button (ethi, ecol, drawable, gc, GTK_WIDGET (canvas)->style, - x, ethi->y1 - y1, col_width, ethi->height); - - x += col_width; - total += col_width; + x1 - x, ethi->y1 - y, col_width, ethi->height); } } @@ -356,6 +573,35 @@ ethi_end_resize (ETableHeaderItem *ethi, int new_size) ethi_request_redraw (ethi); } +static gboolean +ethi_maybe_start_drag (ETableHeaderItem *ethi, GdkEventMotion *event) +{ + if (!ethi->maybe_drag) + return FALSE; + + if (MAX (abs (ethi->click_x - event->x), + abs (ethi->click_y - event->y)) <= 3) + return FALSE; + + return TRUE; +} + +static void +ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) +{ + GtkWidget *widget = GTK_WIDGET (GNOME_CANVAS_ITEM (ethi)->canvas); + GtkTargetList *list; + GdkDragContext *context; + + ethi->drag_col = ethi_find_col_by_x (ethi, event->motion.x); + if (ethi->drag_col == -1) + return; + + list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types)); + context = gtk_drag_begin (widget, list, GDK_ACTION_MOVE, 1, event); + ethi->maybe_drag = FALSE; +} + /* * Handles the events on the ETableHeaderItem, particularly it handles resizing */ @@ -405,6 +651,8 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) e_table_header_set_size (ethi->eth, ethi->resize_col, ethi->resize_width); ethi_request_redraw (ethi); + } else if (ethi_maybe_start_drag (ethi, &e->motion)){ + ethi_start_drag (ethi, e); } else set_cursor (ethi, x); break; @@ -430,6 +678,12 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) ethi->resize_width = ecol->width; ethi->resize_start_pos = start - ecol->width; ethi->resize_min_width = ecol->min_width; + } else { + if (e->button.button == 1){ + ethi->click_x = e->button.x; + ethi->click_y = e->button.y; + ethi->maybe_drag = TRUE; + } } break; @@ -439,8 +693,6 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (e->button.button != 1) break; - - printf ("Resize this guy\n"); break; case GDK_BUTTON_RELEASE: { @@ -453,6 +705,7 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (needs_ungrab) gnome_canvas_item_ungrab (item, e->button.time); + ethi->maybe_drag = FALSE; break; } @@ -487,6 +740,18 @@ ethi_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableHeaderItem::fontset", GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_TABLE_FONTSET); + + /* + * Create our pixmaps for DnD + */ + dnd_colormap = gtk_widget_get_default_colormap (); + remove_col_pixmap = gdk_pixmap_colormap_create_from_xpm_d ( + NULL, dnd_colormap, + &remove_col_mask, NULL, remove_col_xpm); + + add_col_pixmap = gdk_pixmap_colormap_create_from_xpm_d ( + NULL, dnd_colormap, + &add_col_mask, NULL, add_col_xpm); } static void @@ -500,6 +765,9 @@ ethi_init (GnomeCanvasItem *item) item->y1 = 0; item->x2 = 0; item->y2 = 0; + + ethi->drag_col = -1; + ethi->drag_mark = -1; } GtkType diff --git a/widgets/e-table-header-item.h b/widgets/e-table-header-item.h index ea2082018f..5522d24fae 100644 --- a/widgets/e-table-header-item.h +++ b/widgets/e-table-header-item.h @@ -34,6 +34,17 @@ typedef struct { * Ids */ int structure_change_id, dimension_change_id; + + /* + * For dragging columns + */ + guint maybe_drag:1; + guint dnd_ready:1; + int click_x, click_y; + int drag_col, drag_mark; + guint drag_motion_id, drag_end_id, drag_leave_id; + GnomeCanvasItem *drag_mark_item, *remove_item; + GdkBitmap *stipple; } ETableHeaderItem; typedef struct { diff --git a/widgets/e-table-header.c b/widgets/e-table-header.c index 576f609deb..375fd34c5d 100644 --- a/widgets/e-table-header.c +++ b/widgets/e-table-header.c @@ -172,8 +172,6 @@ e_table_header_count (ETableHeader *eth) int e_table_header_index (ETableHeader *eth, int col) { - int i; - g_return_val_if_fail (eth != NULL, -1); g_return_val_if_fail (E_IS_TABLE_HEADER (eth), -1); g_return_val_if_fail (col < eth->col_count, -1); @@ -316,3 +314,26 @@ e_table_header_set_size (ETableHeader *eth, int idx, int size) eth->columns [idx]->width = size; gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE], idx); } + +int +e_table_header_col_diff (ETableHeader *eth, int start_col, int end_col) +{ + int total, col; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0); + + { + const int max_col = eth->col_count; + + total = 0; + for (col = start_col; col < end_col; col++){ + + if (col == max_col) + break; + total += eth->columns [col]->width; + } + } + + return total; +} diff --git a/widgets/e-table-header.h b/widgets/e-table-header.h index 8965dee5c6..96e65fdc2f 100644 --- a/widgets/e-table-header.h +++ b/widgets/e-table-header.h @@ -55,6 +55,9 @@ void e_table_header_set_size (ETableHeader *eth, int idx, int size); void e_table_header_set_selection (ETableHeader *eth, gboolean allow_selection); +int e_table_header_col_diff (ETableHeader *eth, + int start_col, int end_col); + GList *e_table_header_get_selected_indexes(ETableHeader *eth); diff --git a/widgets/e-table-item.c b/widgets/e-table-item.c index ceb6adda95..bdeda14a7b 100644 --- a/widgets/e-table-item.c +++ b/widgets/e-table-item.c @@ -127,9 +127,12 @@ eti_remove_table_model (ETableItem *eti) gtk_signal_disconnect (GTK_OBJECT (eti->table_model), eti->table_model_change_id); + gtk_signal_disconnect (GTK_OBJECT (eti->table_model), + eti->table_model_row_change_id); gtk_object_unref (GTK_OBJECT (eti->table_model)); eti->table_model_change_id = 0; + eti->table_model_row_change_id = 0; eti->table_model = NULL; } @@ -171,7 +174,9 @@ eti_row_height (ETableItem *eti, int row) max_h = 0; for (col = 0; col < cols; col++){ - h = e_cell_height (eti->cell_views [col], col, row); + ETableCol *ecol = e_table_header_get_column (eti->header, col); + + h = e_cell_height (eti->cell_views [col], ecol->col_idx, col, row); if (h > max_h) max_h = h; @@ -225,8 +230,7 @@ eti_get_height (ETableItem *eti) static void eti_table_model_changed (ETableModel *table_model, ETableItem *eti) { - eti->cols = e_table_model_column_count (eti->table_model); - eti->rows = e_table_model_row_count (eti->table_model); + eti->rows = e_table_model_row_count (eti->table_model); if (eti->cell_views) eti->height = eti_get_height (eti); @@ -234,6 +238,7 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti) eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); } + /* * eti_request_redraw: * @@ -249,24 +254,6 @@ eti_request_redraw (ETableItem *eti) eti->y1 + eti->height + 1); } -/* - * Computes the distance from @start_col to @end_col in pixels. - */ -static int -eti_col_diff (ETableItem *eti, int start_col, int end_col) -{ - int col, total; - - total = 0; - for (col = start_col; col < end_col; col++){ - ETableCol *ecol = e_table_header_get_column (eti->header, col); - - total += ecol->width; - } - - return total; -} - /* * Computes the distance between @start_row and @end_row in pixels */ @@ -301,9 +288,9 @@ eti_request_region_redraw (ETableItem *eti, GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; int x1, y1, width, height; - x1 = eti_col_diff (eti, 0, start_col); + x1 = e_table_header_col_diff (eti->header, 0, start_col); y1 = eti_row_diff (eti, 0, start_row); - width = eti_col_diff (eti, start_col, end_col + 1); + width = e_table_header_col_diff (eti->header, start_col, end_col + 1); height = eti_row_diff (eti, start_row, end_row + 1); gnome_canvas_request_redraw (canvas, @@ -313,6 +300,17 @@ eti_request_region_redraw (ETableItem *eti, eti->y1 + y1 + height + 1 + border); } +static void +eti_table_model_row_changed (ETableModel *table_model, int row, ETableItem *eti) +{ + if (eti->renderers_can_change_size){ + eti_table_model_changed (table_model, eti); + return; + } + + eti_request_region_redraw (eti, 0, row, eti->cols, row, 0); +} + void e_table_item_redraw_range (ETableItem *eti, int start_col, int start_row, @@ -345,6 +343,10 @@ 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); + eti->table_model_row_change_id = gtk_signal_connect ( + GTK_OBJECT (table_model), "model_row_changed", + GTK_SIGNAL_FUNC (eti_table_model_row_changed), eti); + eti_table_model_changed (table_model, eti); } @@ -364,6 +366,7 @@ eti_header_structure_changed (ETableHeader *eth, ETableItem *eti) { eti_request_redraw (eti); + eti->cols = e_table_header_count (eti->header); eti->width = e_table_header_total_width (eti->header); eti_unrealize_cell_views (eti); eti_realize_cell_views (eti); @@ -380,7 +383,7 @@ eti_add_header_model (ETableItem *eti, ETableHeader *header) eti->header = header; gtk_object_ref (GTK_OBJECT (header)); - eti->width = e_table_header_total_width (header); + eti_header_structure_changed (header, eti); eti->header_dim_change_id = gtk_signal_connect ( GTK_OBJECT (header), "dimension_change", @@ -467,7 +470,8 @@ eti_init (GnomeCanvasItem *item) eti->height = 0; eti->length_threshold = -1; - + eti->renderers_can_change_size = 0; + eti->selection_mode = GTK_SELECTION_SINGLE; } @@ -540,32 +544,6 @@ eti_unrealize (GnomeCanvasItem *item) (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->unrealize)(item); } -static void -draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row, gboolean selected, - int x1, int y1, int x2, int y2) -{ - ECellView *ecell_view; - - ecell_view = eti->cell_views [col]; - - e_cell_draw (ecell_view, drawable, col, row, selected, x1, y1, x2, y2); - -#if 0 - { - GdkFont *font; - GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; - - font = GTK_WIDGET (canvas)->style->font; - - sprintf (text, "%d:%d\n", col, row); gdk_draw_line (drawable, eti->grid_gc, x1, y1, x2, y2); - gdk_draw_line (drawable, eti->grid_gc, x1, y2, x2, y1); - - sprintf (text, "%d:%d\n", col, row); - gdk_draw_text (drawable, font, eti->grid_gc, x1, y2, text, strlen (text)); - } -#endif -} - static void eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) { @@ -670,8 +648,10 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, for (col = first_col; col < last_col; col++){ ETableCol *ecol = e_table_header_get_column (eti->header, col); + ECellView *ecell_view = eti->cell_views [col]; - draw_cell (eti, drawable, col, row, selected, xd, yd, xd + ecol->width, yd + height); + e_cell_draw (ecell_view, drawable, ecol->col_idx, col, row, selected, + xd, yd, xd + ecol->width, yd + height); if (col == eti->focused_col && row == eti->focused_row){ f_x1 = xd; @@ -786,7 +766,8 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) { ETableItem *eti = E_TABLE_ITEM (item); ECellView *ecell_view; - + ETableCol *ecol; + switch (e->type){ case GDK_BUTTON_PRESS: case GDK_BUTTON_RELEASE: @@ -798,6 +779,8 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) return TRUE; if (eti->focused_row == row && eti->focused_col == col){ + + ecol = e_table_header_get_column (eti->header, col); ecell_view = eti->cell_views [col]; /* @@ -806,7 +789,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) e->button.x = x1; e->button.y = y1; - e_cell_event (ecell_view, e, col, row); + e_cell_event (ecell_view, e, ecol->col_idx, col, row); } else { /* * Focus the cell, and select the row @@ -826,6 +809,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) return TRUE; if (eti->focused_row == row && eti->focused_col == col){ + ecol = e_table_header_get_column (eti->header, col); ecell_view = eti->cell_views [col]; /* @@ -834,7 +818,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) e->button.x -= (x1 + eti->x1); e->button.y -= (y1 + eti->y1); - e_cell_event (ecell_view, e, col, row); + e_cell_event (ecell_view, e, ecol->col_idx, col, row); } break; } @@ -887,8 +871,9 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) } } + ecol = e_table_header_get_column (eti->header, eti->focused_col); ecell_view = eti->cell_views [eti->focused_col]; - e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row); + e_cell_event (ecell_view, e, ecol->col_idx, eti->focused_col, eti->focused_row); break; case GDK_KEY_RELEASE: @@ -897,7 +882,8 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (eti_editing (eti)){ ecell_view = eti->cell_views [eti->editing_col]; - e_cell_event (ecell_view, e, eti->editing_col, eti->editing_row); + ecol = e_table_header_get_column (eti->header, eti->editing_col); + e_cell_event (ecell_view, e, ecol->col_idx, eti->editing_col, eti->editing_row); } break; @@ -1125,25 +1111,34 @@ e_table_item_select_row (ETableItem *eti, int row) void e_table_item_enter_edit (ETableItem *eti, int col, int row) { + ETableCol *ecol; + g_return_if_fail (eti != NULL); g_return_if_fail (E_IS_TABLE_ITEM (eti)); eti->editing_col = col; eti->editing_row = row; - eti->edit_ctx = e_cell_enter_edit (eti->cell_views [col], col, row); + ecol = e_table_header_get_column (eti->header, col); + eti->edit_ctx = e_cell_enter_edit (eti->cell_views [col], ecol->col_idx, col, row); } void e_table_item_leave_edit (ETableItem *eti) { + ETableCol *ecol; + g_return_if_fail (eti != NULL); g_return_if_fail (E_IS_TABLE_ITEM (eti)); if (!eti_editing (eti)) return; - - e_cell_leave_edit (eti->cell_views [eti->editing_col], eti->editing_col, eti->editing_row, eti->edit_ctx); + + ecol = e_table_header_get_column (eti->header, eti->editing_col); + e_cell_leave_edit ( + eti->cell_views [eti->editing_col], + ecol->col_idx, eti->editing_col, + eti->editing_row, eti->edit_ctx); eti->editing_col = -1; eti->editing_row = -1; eti->edit_ctx = NULL; diff --git a/widgets/e-table-item.h b/widgets/e-table-item.h index 6c4d837310..e9125431b1 100644 --- a/widgets/e-table-item.h +++ b/widgets/e-table-item.h @@ -27,6 +27,7 @@ typedef struct { int header_dim_change_id; int header_structure_change_id; int table_model_change_id; + int table_model_row_change_id; GdkGC *fill_gc; GdkGC *grid_gc; @@ -36,6 +37,7 @@ typedef struct { unsigned int draw_grid:1; unsigned int draw_focus:1; unsigned int mode_spreadsheet:1; + unsigned int renderers_can_change_size:1; int focused_col, focused_row; diff --git a/widgets/e-table-model.c b/widgets/e-table-model.c index 60f762214f..9e397710ef 100644 --- a/widgets/e-table-model.c +++ b/widgets/e-table-model.c @@ -58,7 +58,16 @@ e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const g_return_if_fail (e_table_model != NULL); g_return_if_fail (E_IS_TABLE_MODEL (e_table_model)); - return ETM_CLASS (e_table_model)->set_value_at (e_table_model, col, row, data); + ETM_CLASS (e_table_model)->set_value_at (e_table_model, col, row, data); + + gtk_signal_emit (GTK_OBJECT (e_table_model), + e_table_model_signals [MODEL_ROW_CHANGED], row); + gtk_signal_emit (GTK_OBJECT (e_table_model), + e_table_model_signals [MODEL_CELL_CHANGED], col, row); + + /* + * Notice that "model_changed" is not emitted + */ } gboolean diff --git a/widgets/e-table-model.h b/widgets/e-table-model.h index 0749a39758..fb37731a8a 100644 --- a/widgets/e-table-model.h +++ b/widgets/e-table-model.h @@ -28,6 +28,12 @@ typedef struct { /* * Signals */ + + /* + * Major structural changes: model_changed + * Changes only in a row: row_changed + * Only changes in a cell: cell_changed + */ void (*model_changed) (ETableModel *etm); void (*model_row_changed) (ETableModel *etm, int row); void (*model_cell_changed) (ETableModel *etm, int col, int row); diff --git a/widgets/e-table-sorted.c b/widgets/e-table-sorted.c index 90773e9cdc..6bc55ad9dc 100644 --- a/widgets/e-table-sorted.c +++ b/widgets/e-table-sorted.c @@ -18,8 +18,6 @@ static ETableModelClass *ets_parent_class; static void ets_class_init (GtkObjectClass *klass) { - ETableModelClass *table_class = (ETableModelClass *) klass; - ets_parent_class = gtk_type_class (PARENT_TYPE); } diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog index be5207f31b..e4c9cc9ab8 100644 --- a/widgets/e-table/ChangeLog +++ b/widgets/e-table/ChangeLog @@ -1,3 +1,36 @@ +1999-12-09 Miguel de Icaza + + * e-table-header.c (e_table_header_col_diff): fix this routine. + +1999-12-04 Miguel de Icaza + + * e-table-header-item.c (ethi_event): Started drag and drop + support. + + * e-table-item.c (eti_table_model_changed): The columns are + controled by the Header, not by the TableModel. + + * e-table-header-item.c (ethi_draw): Fixed redraw logic to support + arbitrary header positioning. + + * e-cell.h: Revamped e-cell interface. We now provide the model + column and the view column to all methods (so that the methods can + talk to the view and to the model at the same time). + + * e-table-item.c: Update to new API + * e-cell-test.c: Update to new API + +1999-12-03 Miguel de Icaza + + * e-cell.c (e_cell_class_init): Provide emtpy methods for + enter_edit, and leave_edit. + + * e-table-item.c: Killed draw cell. + (eti_draw): Perform column mapping here. + (e_table_item_leave_edit): ditto. + (e_table_item_enter_edit): ditto. + (eti_event): ditto. + 1999-12-02 Miguel de Icaza * e-table-header.c (e_table_header_index): fixed api. diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am index 1b237dce70..677af55041 100644 --- a/widgets/e-table/Makefile.am +++ b/widgets/e-table/Makefile.am @@ -51,5 +51,7 @@ table_test_LDFLAGS = `gnome-config --libs gdk_pixbuf` EXTRA_DIST = \ sample.table \ + add-col.xpm \ check-empty.xpm \ - check-filled.xpm + check-filled.xpm \ + remove-col.xpm diff --git a/widgets/e-table/e-cell-text.c b/widgets/e-table/e-cell-text.c index d9d8a568db..828be6cc29 100644 --- a/widgets/e-table/e-cell-text.c +++ b/widgets/e-table/e-cell-text.c @@ -29,7 +29,7 @@ typedef struct { /* * Where the editing is taking place */ - int col, row; + int model_col, view_col, row; } CellEdit; typedef struct { @@ -48,9 +48,9 @@ typedef struct { static ECellClass *parent_class; static void -ect_queue_redraw (ECellTextView *text_view, int col, int row) +ect_queue_redraw (ECellTextView *text_view, int view_col, int view_row) { - e_table_item_redraw_range (text_view->eti, col, row, col, row); + e_table_item_redraw_range (text_view->eti, view_col, view_row, view_col, view_row); } /* @@ -62,7 +62,7 @@ ect_accept_edits (ECellTextView *text_view) const char *text = gtk_entry_get_text (text_view->edit->entry); CellEdit *edit = text_view->edit; - e_table_model_set_value_at (text_view->eti->table_model, edit->col, edit->row, text); + e_table_model_set_value_at (text_view->eti->table_model, edit->model_col, edit->row, text); } /* @@ -92,7 +92,7 @@ ect_stop_editing (ECellTextView *text_view) static void ect_cancel_edit (ECellTextView *text_view) { - ect_queue_redraw (text_view, text_view->edit->col, text_view->edit->row); + ect_queue_redraw (text_view, text_view->edit->view_col, text_view->edit->row); ect_stop_editing (text_view); } @@ -149,14 +149,14 @@ ect_unrealize (ECellView *ecv) */ static void ect_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { ECellText *ect = E_CELL_TEXT (ecell_view->ecell); ECellTextView *text_view = (ECellTextView *) ecell_view; GtkWidget *w = GTK_WIDGET (text_view->canvas); GdkRectangle rect; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); GdkFont *font = text_view->font; const int height = font->ascent + font->descent; int xoff; @@ -168,7 +168,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, if (text_view->edit){ CellEdit *edit = text_view->edit; - if ((edit->col == col) && (edit->row == row)) + if ((edit->view_col == view_col) && (edit->row == row)) edit_display = TRUE; } @@ -312,7 +312,7 @@ ect_edit_select_all (ECellTextView *text_view) * ECell::event method */ static gint -ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; @@ -327,7 +327,7 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) if (text_view->edit){ printf ("FIXME: Should handle click here\n"); } else - e_table_item_enter_edit (text_view->eti, col, row); + e_table_item_enter_edit (text_view->eti, view_col, row); break; case GDK_BUTTON_RELEASE: @@ -345,12 +345,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) } if (!text_view->edit){ - e_table_item_enter_edit (text_view->eti, col, row); + e_table_item_enter_edit (text_view->eti, view_col, row); ect_edit_select_all (text_view); } gtk_widget_event (GTK_WIDGET (text_view->edit->entry), event); - ect_queue_redraw (text_view, col, row); + ect_queue_redraw (text_view, view_col, row); break; case GDK_KEY_RELEASE: @@ -366,7 +366,7 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) * ECell::height method */ static int -ect_height (ECellView *ecell_view, int col, int row) +ect_height (ECellView *ecell_view, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; @@ -386,16 +386,17 @@ ect_entry_activate (GtkEntry *entry, ECellTextView *text_view) * ECellView::enter_edit method */ static void * -ect_enter_edit (ECellView *ecell_view, int col, int row) +ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); CellEdit *edit; edit = g_new (CellEdit, 1); text_view->edit = edit; - edit->col = col; + edit->model_col = model_col; + edit->view_col = view_col; edit->row = row; edit->entry = (GtkEntry *) gtk_entry_new (); @@ -412,7 +413,7 @@ ect_enter_edit (ECellView *ecell_view, int col, int row) gtk_widget_set_uposition (edit->entry_top, 20000, 20000); gtk_widget_show_all (edit->entry_top); - ect_queue_redraw (text_view, col, row); + ect_queue_redraw (text_view, view_col, row); return NULL; } @@ -421,7 +422,7 @@ ect_enter_edit (ECellView *ecell_view, int col, int row) * ECellView::leave_edit method */ static void -ect_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context) +ect_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context) { ECellTextView *text_view = (ECellTextView *) ecell_view; diff --git a/widgets/e-table/e-cell-toggle.c b/widgets/e-table/e-cell-toggle.c index 8e06d8d87d..ec6fa38a38 100644 --- a/widgets/e-table/e-cell-toggle.c +++ b/widgets/e-table/e-cell-toggle.c @@ -29,9 +29,9 @@ typedef struct { static ECellClass *parent_class; static void -etog_queue_redraw (ECellToggleView *text_view, int col, int row) +etog_queue_redraw (ECellToggleView *text_view, int view_col, int view_row) { - e_table_item_redraw_range (text_view->eti, col, row, col, row); + e_table_item_redraw_range (text_view->eti, view_col, view_row, view_col, view_row); } /* @@ -40,7 +40,6 @@ etog_queue_redraw (ECellToggleView *text_view, int col, int row) static ECellView * etog_realize (ECell *ecell, void *view) { - ECellToggle *eccb = E_CELL_TOGGLE (ecell); ECellToggleView *toggle_view = g_new0 (ECellToggleView, 1); ETableItem *eti = E_TABLE_ITEM (view); GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; @@ -72,7 +71,7 @@ etog_unrealize (ECellView *ecv) */ static void etog_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell); @@ -80,9 +79,8 @@ etog_draw (ECellView *ecell_view, GdkDrawable *drawable, GdkPixbuf *image; ArtPixBuf *art; int x, y, width, height; - gboolean free_image; const int value = GPOINTER_TO_INT ( - e_table_model_value_at (ecell_view->ecell->table_model, col, row)); + e_table_model_value_at (ecell_view->ecell->table_model, model_col, row)); if (value >= toggle->n_states){ g_warning ("Value from the table model is %d, the states we support are [0..%d)\n", @@ -166,7 +164,7 @@ etog_draw (ECellView *ecell_view, GdkDrawable *drawable, } static void -etog_set_value (ECellToggleView *toggle_view, int col, int row, int value) +etog_set_value (ECellToggleView *toggle_view, int model_col, int view_col, int row, int value) { ECell *ecell = toggle_view->cell_view.ecell; ECellToggle *toggle = E_CELL_TOGGLE (ecell); @@ -174,29 +172,28 @@ etog_set_value (ECellToggleView *toggle_view, int col, int row, int value) if (value >= toggle->n_states) value = 0; - e_table_model_set_value_at (ecell->table_model, col, row, GINT_TO_POINTER (value)); - etog_queue_redraw (toggle_view, col, row); + e_table_model_set_value_at (ecell->table_model, model_col, row, GINT_TO_POINTER (value)); + etog_queue_redraw (toggle_view, view_col, row); } /* * ECell::event method */ static gint -etog_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +etog_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { - ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell); ECellToggleView *toggle_view = (ECellToggleView *) ecell_view; - void *_value = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + void *_value = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); const int value = GPOINTER_TO_INT (_value); switch (event->type){ case GDK_BUTTON_RELEASE: - etog_set_value (toggle_view, col, row, value + 1); + etog_set_value (toggle_view, model_col, view_col, row, value + 1); return TRUE; case GDK_KEY_PRESS: if (event->key.keyval == GDK_space){ - etog_set_value (toggle_view, col, row, value + 1); + etog_set_value (toggle_view, model_col, view_col, row, value + 1); return TRUE; } return FALSE; @@ -211,7 +208,7 @@ etog_event (ECellView *ecell_view, GdkEvent *event, int col, int row) * ECell::height method */ static int -etog_height (ECellView *ecell_view, int col, int row) +etog_height (ECellView *ecell_view, int model_col, int view_col, int row) { ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell); diff --git a/widgets/e-table/e-cell.c b/widgets/e-table/e-cell.c index 2bc49f7a45..a4a03655dc 100644 --- a/widgets/e-table/e-cell.c +++ b/widgets/e-table/e-cell.c @@ -25,30 +25,30 @@ ec_unrealize (ECellView *e_cell) static void ec_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { g_error ("e-cell-draw invoked\n"); } static gint -ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +ec_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { g_error ("e-cell-event invoked\n"); return 0; } static gint -ec_height (ECellView *ecell_view, int col, int row) +ec_height (ECellView *ecell_view, int model_col, int view_col, int row) { g_error ("e-cell-event invoked\n"); return 0; } static void -ec_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2) +ec_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2) { - ecell_view->focus_col = col; + ecell_view->focus_col = view_col; ecell_view->focus_row = row; ecell_view->focus_x1 = x1; ecell_view->focus_y1 = y1; @@ -67,6 +67,17 @@ ec_unfocus (ECellView *ecell_view) ecell_view->focus_y2 = -1; } +static void * +ec_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) +{ + return NULL; +} + +static void +ec_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *context) +{ +} + static void e_cell_class_init (GtkObjectClass *object_class) { @@ -79,22 +90,23 @@ e_cell_class_init (GtkObjectClass *object_class) ecc->focus = ec_focus; ecc->unfocus = ec_unfocus; ecc->height = ec_height; + ecc->enter_edit = ec_enter_edit; + ecc->leave_edit = ec_leave_edit; } static void e_cell_init (GtkObject *object) { - ECell *e_cell = E_CELL (object); } 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_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->event ( - ecell_view, event, col, row); + ecell_view, event, model_col, view_col, row); } ECellView * @@ -112,29 +124,29 @@ e_cell_unrealize (ECellView *ecell_view) void e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, int x1, int y1, int x2, int y2) + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->draw ( - ecell_view, drawable, col, row, selected, x1, y1, x2, y2); + ecell_view, drawable, model_col, view_col, row, selected, x1, y1, x2, y2); } int -e_cell_height (ECellView *ecell_view, int col, int row) +e_cell_height (ECellView *ecell_view, int model_col, int view_col, int row) { return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->height ( - ecell_view, col, row); + ecell_view, model_col, view_col, row); } void * -e_cell_enter_edit (ECellView *ecell_view, int col, int row) +e_cell_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) { return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->enter_edit ( - ecell_view, col, row); + ecell_view, model_col, view_col, row); } void -e_cell_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context) +e_cell_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context) { E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->leave_edit ( - ecell_view, col, row, edit_context); + ecell_view, model_col, view_col, row, edit_context); } diff --git a/widgets/e-table/e-cell.h b/widgets/e-table/e-cell.h index b0f62d020c..f72f97e8dd 100644 --- a/widgets/e-table/e-cell.h +++ b/widgets/e-table/e-cell.h @@ -32,28 +32,31 @@ typedef struct { ECellView *(*realize) (ECell *ecell, void *view); void (*unrealize) (ECellView *e_cell_view); void (*draw) (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, int x1, int y1, int x2, int y2); - gint (*event) (ECellView *ecell_view, GdkEvent *event, int col, int row); - void (*focus) (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2); + int model_col, int view_col, int row, + gboolean selected, int x1, int y1, int x2, int y2); + gint (*event) (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row); + void (*focus) (ECellView *ecell_view, int model_col, int view_col, + int row, int x1, int y1, int x2, int y2); void (*unfocus) (ECellView *ecell_view); - int (*height) (ECellView *ecell_view, int col, int row); + int (*height) (ECellView *ecell_view, int model_col, int view_col, int row); - void *(*enter_edit)(ECellView *ecell_view, int col, int row); - void (*leave_edit)(ECellView *ecell_view, int col, int row, void *context); + void *(*enter_edit)(ECellView *ecell_view, int model_col, int view_col, int row); + void (*leave_edit)(ECellView *ecell_view, int model_col, int view_col, int row, void *context); } ECellClass; GtkType e_cell_get_type (void); -void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row); +void e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row); ECellView *e_cell_realize (ECell *ecell, void *view); void e_cell_unrealize (ECellView *ecell_view); void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, + int x1, int y1, int x2, int y2); +void e_cell_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2); -void e_cell_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2); void e_cell_unfocus (ECellView *ecell_view); -int e_cell_height (ECellView *ecell_view, int col, int row); +int e_cell_height (ECellView *ecell_view, int model_col, int view_col, int row); -void *e_cell_enter_edit(ECellView *ecell_view, int col, int row); -void e_cell_leave_edit(ECellView *ecell_view, int col, int row, void *edit_context); +void *e_cell_enter_edit(ECellView *ecell_view, int model_col, int view_col, int row); +void e_cell_leave_edit(ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context); #endif /* _E_CELL_H_ */ diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c index 5368f10602..0b5be9b84a 100644 --- a/widgets/e-table/e-table-header-item.c +++ b/widgets/e-table/e-table-header-item.c @@ -8,10 +8,19 @@ */ #include #include +#include +#include +#include +#include +#include #include "e-table-header.h" #include "e-table-header-item.h" +#include "e-table-col-dnd.h" #include "e-cursors.h" +#include "add-col.xpm" +#include "remove-col.xpm" + /* Padding above and below of the string in the header display */ #define PADDING 4 @@ -22,8 +31,17 @@ #define PARENT_OBJECT_TYPE gnome_canvas_item_get_type () +#define ELEMENTS(x) (sizeof (x) / sizeof (x[0])) + static GnomeCanvasItemClass *ethi_parent_class; +/* + * DnD icons + */ +static GdkColormap *dnd_colormap; +static GdkPixmap *remove_col_pixmap, *remove_col_mask; +static GdkPixmap *add_col_pixmap, *add_col_mask; + enum { ARG_0, ARG_TABLE_HEADER, @@ -32,6 +50,14 @@ enum { ARG_TABLE_FONTSET }; +static GtkTargetEntry ethi_drag_types [] = { + { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER }, +}; + +static GtkTargetEntry ethi_drop_types [] = { + { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER }, +}; + static void ethi_destroy (GtkObject *object) { @@ -151,6 +177,177 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) ethi_update (item, NULL, NULL, 0); } +static int +ethi_find_col_by_x (ETableHeaderItem *ethi, int x) +{ + const int cols = e_table_header_count (ethi->eth); + int x1 = ethi->x1; + int col; + + if (x < x1) + return -1; + + for (col = 0; col < cols; col++){ + ETableCol *ecol = e_table_header_get_column (ethi->eth, col); + + if ((x >= x1) && (x <= x1 + ecol->width)) + return col; + + x1 += ecol->width; + } + return -1; +} + +static void +ethi_remove_drop_marker (ETableHeaderItem *ethi) +{ + if (ethi->drag_mark == -1) + return; + + ethi->drag_mark = -1; + gtk_object_destroy (GTK_OBJECT (ethi->drag_mark_item)); + ethi->drag_mark_item = NULL; +} + +static void +ethi_add_drop_marker (ETableHeaderItem *ethi, int col) +{ + GnomeCanvasPoints *points; + int x; + + if (ethi->drag_mark == col) + return; + + if (ethi->drag_mark_item) + gtk_object_destroy (GTK_OBJECT (ethi->drag_mark_item)); + + ethi->drag_mark = col; + + ethi->drag_mark_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (ethi)->canvas->root), + gnome_canvas_group_get_type (), + "x", 0, + "y", 0, + NULL); + + points = gnome_canvas_points_new (3); + + x = e_table_header_col_diff (ethi->eth, 0, col); + + points->coords [0] = ethi->x1 + x - 5; + points->coords [1] = ethi->y1; + points->coords [2] = points->coords [0] + 10; + points->coords [3] = points->coords [1]; + points->coords [4] = ethi->x1 + x; + points->coords [5] = ethi->y1 + 5; + + gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (ethi->drag_mark_item), + gnome_canvas_polygon_get_type (), + "points", points, + "fill_color", "red", + NULL); + + points->coords [0] --; + points->coords [1] += ethi->height - 1; + points->coords [3] = points->coords [1]; + points->coords [5] = points->coords [1] - 6; + + gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (ethi->drag_mark_item), + gnome_canvas_polygon_get_type (), + "points", points, + "fill_color", "red", + NULL); + + gnome_canvas_points_unref (points); +} + +#define gray50_width 2 +#define gray50_height 2 +static char gray50_bits [] = { + 0x02, 0x01, }; + +static void +ethi_add_destroy_marker (ETableHeaderItem *ethi) +{ + double x1; + + if (ethi->remove_item) + gtk_object_destroy (GTK_OBJECT (ethi->remove_item)); + + if (!ethi->stipple) + ethi->stipple = gdk_bitmap_create_from_data (NULL, gray50_bits, gray50_width, gray50_height); + + x1 = ethi->x1 + (double) e_table_header_col_diff (ethi->eth, 0, ethi->drag_col); + ethi->remove_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (ethi)->canvas->root), + gnome_canvas_rect_get_type (), + "x1", x1 + 1, + "y1", (double) ethi->y1 + 1, + "x2", (double) x1 + e_table_header_col_diff (ethi->eth, ethi->drag_col, ethi->drag_col+1) - 2, + "y2", (double) ethi->y1 + ethi->height - 2, + "fill_color", "red", + "fill_stipple", ethi->stipple, + NULL); +} + +static void +ethi_remove_destroy_marker (ETableHeaderItem *ethi) +{ + if (!ethi->remove_item) + return; + + gtk_object_destroy (GTK_OBJECT (ethi->remove_item)); + ethi->remove_item = NULL; +} + +static gboolean +ethi_drag_motion (GtkObject *canvas, GdkDragContext *context, + gint x, gint y, guint time, + ETableHeaderItem *ethi) +{ + + if ((x >= ethi->x1) && (x <= (ethi->x1 + ethi->width)) && + (y >= ethi->y1) && (y <= (ethi->y1 + ethi->height))){ + int col; + + col = ethi_find_col_by_x (ethi, x); + + if (col != -1){ + ethi_remove_destroy_marker (ethi); + ethi_add_drop_marker (ethi, col); + } else { + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); + } + } else { + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); + } + + gdk_drag_status (context, context->suggested_action, time); + + return TRUE; +} + +static void +ethi_drag_end (GtkWidget *canvas, GdkDragContext *context, ETableHeaderItem *ethi) +{ + printf ("Ending\n"); + + ethi_remove_drop_marker (ethi); + ethi_remove_destroy_marker (ethi); + ethi->drag_col = -1; +} + +static void +ethi_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, ETableHeaderItem *ethi) +{ + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); +} + static void ethi_realize (GnomeCanvasItem *item) { @@ -171,19 +368,47 @@ ethi_realize (GnomeCanvasItem *item) if (!ethi->font) ethi_font_load (ethi, "fixed"); + + /* + * Now, configure DnD + */ + gtk_drag_dest_set (GTK_WIDGET (item->canvas), GTK_DEST_DEFAULT_ALL, + ethi_drop_types, ELEMENTS (ethi_drop_types), + GDK_ACTION_MOVE); + + ethi->drag_motion_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_motion", + GTK_SIGNAL_FUNC (ethi_drag_motion), ethi); + + ethi->drag_leave_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_leave", + GTK_SIGNAL_FUNC (ethi_drag_leave), ethi); + + ethi->drag_end_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_end", + GTK_SIGNAL_FUNC (ethi_drag_end), ethi); } static void ethi_unrealize (GnomeCanvasItem *item) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); - + gdk_gc_unref (ethi->gc); ethi->gc = NULL; gdk_cursor_destroy (ethi->normal_cursor); ethi->normal_cursor = NULL; + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_motion_id); + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_end_id); + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_leave_id); + + if (ethi->stipple){ + gdk_bitmap_unref (ethi->stipple); + ethi->stipple = NULL; + } + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize) (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item); } @@ -228,25 +453,21 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, } static void -ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height) +ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); GnomeCanvas *canvas = item->canvas; GdkGC *gc; const int cols = e_table_header_count (ethi->eth); - int x2 = x1 + width; - int col, total; - int x; - - total = 0; - x = -x1; + int x1, x2; + int col; #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++){ + x1 = x2 = ethi->x1; + for (col = 0; col < cols; col++, x1 = x2){ ETableCol *ecol = e_table_header_get_column (ethi->eth, col); int col_width; @@ -255,23 +476,19 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int wid else col_width = ecol->width; - if (x1 > total + col_width){ - total += col_width; - x += col_width; - continue; - } - - if (x2 < total) - return; + x2 += col_width; + + if (x1 > (x + width)) + break; + if (x2 < x) + continue; + gc = GTK_WIDGET (canvas)->style->bg_gc [GTK_STATE_ACTIVE]; draw_button (ethi, ecol, drawable, gc, GTK_WIDGET (canvas)->style, - x, ethi->y1 - y1, col_width, ethi->height); - - x += col_width; - total += col_width; + x1 - x, ethi->y1 - y, col_width, ethi->height); } } @@ -356,6 +573,35 @@ ethi_end_resize (ETableHeaderItem *ethi, int new_size) ethi_request_redraw (ethi); } +static gboolean +ethi_maybe_start_drag (ETableHeaderItem *ethi, GdkEventMotion *event) +{ + if (!ethi->maybe_drag) + return FALSE; + + if (MAX (abs (ethi->click_x - event->x), + abs (ethi->click_y - event->y)) <= 3) + return FALSE; + + return TRUE; +} + +static void +ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) +{ + GtkWidget *widget = GTK_WIDGET (GNOME_CANVAS_ITEM (ethi)->canvas); + GtkTargetList *list; + GdkDragContext *context; + + ethi->drag_col = ethi_find_col_by_x (ethi, event->motion.x); + if (ethi->drag_col == -1) + return; + + list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types)); + context = gtk_drag_begin (widget, list, GDK_ACTION_MOVE, 1, event); + ethi->maybe_drag = FALSE; +} + /* * Handles the events on the ETableHeaderItem, particularly it handles resizing */ @@ -405,6 +651,8 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) e_table_header_set_size (ethi->eth, ethi->resize_col, ethi->resize_width); ethi_request_redraw (ethi); + } else if (ethi_maybe_start_drag (ethi, &e->motion)){ + ethi_start_drag (ethi, e); } else set_cursor (ethi, x); break; @@ -430,6 +678,12 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) ethi->resize_width = ecol->width; ethi->resize_start_pos = start - ecol->width; ethi->resize_min_width = ecol->min_width; + } else { + if (e->button.button == 1){ + ethi->click_x = e->button.x; + ethi->click_y = e->button.y; + ethi->maybe_drag = TRUE; + } } break; @@ -439,8 +693,6 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (e->button.button != 1) break; - - printf ("Resize this guy\n"); break; case GDK_BUTTON_RELEASE: { @@ -453,6 +705,7 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (needs_ungrab) gnome_canvas_item_ungrab (item, e->button.time); + ethi->maybe_drag = FALSE; break; } @@ -487,6 +740,18 @@ ethi_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableHeaderItem::fontset", GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_TABLE_FONTSET); + + /* + * Create our pixmaps for DnD + */ + dnd_colormap = gtk_widget_get_default_colormap (); + remove_col_pixmap = gdk_pixmap_colormap_create_from_xpm_d ( + NULL, dnd_colormap, + &remove_col_mask, NULL, remove_col_xpm); + + add_col_pixmap = gdk_pixmap_colormap_create_from_xpm_d ( + NULL, dnd_colormap, + &add_col_mask, NULL, add_col_xpm); } static void @@ -500,6 +765,9 @@ ethi_init (GnomeCanvasItem *item) item->y1 = 0; item->x2 = 0; item->y2 = 0; + + ethi->drag_col = -1; + ethi->drag_mark = -1; } GtkType diff --git a/widgets/e-table/e-table-header-item.h b/widgets/e-table/e-table-header-item.h index ea2082018f..5522d24fae 100644 --- a/widgets/e-table/e-table-header-item.h +++ b/widgets/e-table/e-table-header-item.h @@ -34,6 +34,17 @@ typedef struct { * Ids */ int structure_change_id, dimension_change_id; + + /* + * For dragging columns + */ + guint maybe_drag:1; + guint dnd_ready:1; + int click_x, click_y; + int drag_col, drag_mark; + guint drag_motion_id, drag_end_id, drag_leave_id; + GnomeCanvasItem *drag_mark_item, *remove_item; + GdkBitmap *stipple; } ETableHeaderItem; typedef struct { diff --git a/widgets/e-table/e-table-header.c b/widgets/e-table/e-table-header.c index 576f609deb..375fd34c5d 100644 --- a/widgets/e-table/e-table-header.c +++ b/widgets/e-table/e-table-header.c @@ -172,8 +172,6 @@ e_table_header_count (ETableHeader *eth) int e_table_header_index (ETableHeader *eth, int col) { - int i; - g_return_val_if_fail (eth != NULL, -1); g_return_val_if_fail (E_IS_TABLE_HEADER (eth), -1); g_return_val_if_fail (col < eth->col_count, -1); @@ -316,3 +314,26 @@ e_table_header_set_size (ETableHeader *eth, int idx, int size) eth->columns [idx]->width = size; gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE], idx); } + +int +e_table_header_col_diff (ETableHeader *eth, int start_col, int end_col) +{ + int total, col; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0); + + { + const int max_col = eth->col_count; + + total = 0; + for (col = start_col; col < end_col; col++){ + + if (col == max_col) + break; + total += eth->columns [col]->width; + } + } + + return total; +} diff --git a/widgets/e-table/e-table-header.h b/widgets/e-table/e-table-header.h index 8965dee5c6..96e65fdc2f 100644 --- a/widgets/e-table/e-table-header.h +++ b/widgets/e-table/e-table-header.h @@ -55,6 +55,9 @@ void e_table_header_set_size (ETableHeader *eth, int idx, int size); void e_table_header_set_selection (ETableHeader *eth, gboolean allow_selection); +int e_table_header_col_diff (ETableHeader *eth, + int start_col, int end_col); + GList *e_table_header_get_selected_indexes(ETableHeader *eth); diff --git a/widgets/e-table/e-table-item.c b/widgets/e-table/e-table-item.c index ceb6adda95..bdeda14a7b 100644 --- a/widgets/e-table/e-table-item.c +++ b/widgets/e-table/e-table-item.c @@ -127,9 +127,12 @@ eti_remove_table_model (ETableItem *eti) gtk_signal_disconnect (GTK_OBJECT (eti->table_model), eti->table_model_change_id); + gtk_signal_disconnect (GTK_OBJECT (eti->table_model), + eti->table_model_row_change_id); gtk_object_unref (GTK_OBJECT (eti->table_model)); eti->table_model_change_id = 0; + eti->table_model_row_change_id = 0; eti->table_model = NULL; } @@ -171,7 +174,9 @@ eti_row_height (ETableItem *eti, int row) max_h = 0; for (col = 0; col < cols; col++){ - h = e_cell_height (eti->cell_views [col], col, row); + ETableCol *ecol = e_table_header_get_column (eti->header, col); + + h = e_cell_height (eti->cell_views [col], ecol->col_idx, col, row); if (h > max_h) max_h = h; @@ -225,8 +230,7 @@ eti_get_height (ETableItem *eti) static void eti_table_model_changed (ETableModel *table_model, ETableItem *eti) { - eti->cols = e_table_model_column_count (eti->table_model); - eti->rows = e_table_model_row_count (eti->table_model); + eti->rows = e_table_model_row_count (eti->table_model); if (eti->cell_views) eti->height = eti_get_height (eti); @@ -234,6 +238,7 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti) eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); } + /* * eti_request_redraw: * @@ -249,24 +254,6 @@ eti_request_redraw (ETableItem *eti) eti->y1 + eti->height + 1); } -/* - * Computes the distance from @start_col to @end_col in pixels. - */ -static int -eti_col_diff (ETableItem *eti, int start_col, int end_col) -{ - int col, total; - - total = 0; - for (col = start_col; col < end_col; col++){ - ETableCol *ecol = e_table_header_get_column (eti->header, col); - - total += ecol->width; - } - - return total; -} - /* * Computes the distance between @start_row and @end_row in pixels */ @@ -301,9 +288,9 @@ eti_request_region_redraw (ETableItem *eti, GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; int x1, y1, width, height; - x1 = eti_col_diff (eti, 0, start_col); + x1 = e_table_header_col_diff (eti->header, 0, start_col); y1 = eti_row_diff (eti, 0, start_row); - width = eti_col_diff (eti, start_col, end_col + 1); + width = e_table_header_col_diff (eti->header, start_col, end_col + 1); height = eti_row_diff (eti, start_row, end_row + 1); gnome_canvas_request_redraw (canvas, @@ -313,6 +300,17 @@ eti_request_region_redraw (ETableItem *eti, eti->y1 + y1 + height + 1 + border); } +static void +eti_table_model_row_changed (ETableModel *table_model, int row, ETableItem *eti) +{ + if (eti->renderers_can_change_size){ + eti_table_model_changed (table_model, eti); + return; + } + + eti_request_region_redraw (eti, 0, row, eti->cols, row, 0); +} + void e_table_item_redraw_range (ETableItem *eti, int start_col, int start_row, @@ -345,6 +343,10 @@ 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); + eti->table_model_row_change_id = gtk_signal_connect ( + GTK_OBJECT (table_model), "model_row_changed", + GTK_SIGNAL_FUNC (eti_table_model_row_changed), eti); + eti_table_model_changed (table_model, eti); } @@ -364,6 +366,7 @@ eti_header_structure_changed (ETableHeader *eth, ETableItem *eti) { eti_request_redraw (eti); + eti->cols = e_table_header_count (eti->header); eti->width = e_table_header_total_width (eti->header); eti_unrealize_cell_views (eti); eti_realize_cell_views (eti); @@ -380,7 +383,7 @@ eti_add_header_model (ETableItem *eti, ETableHeader *header) eti->header = header; gtk_object_ref (GTK_OBJECT (header)); - eti->width = e_table_header_total_width (header); + eti_header_structure_changed (header, eti); eti->header_dim_change_id = gtk_signal_connect ( GTK_OBJECT (header), "dimension_change", @@ -467,7 +470,8 @@ eti_init (GnomeCanvasItem *item) eti->height = 0; eti->length_threshold = -1; - + eti->renderers_can_change_size = 0; + eti->selection_mode = GTK_SELECTION_SINGLE; } @@ -540,32 +544,6 @@ eti_unrealize (GnomeCanvasItem *item) (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->unrealize)(item); } -static void -draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row, gboolean selected, - int x1, int y1, int x2, int y2) -{ - ECellView *ecell_view; - - ecell_view = eti->cell_views [col]; - - e_cell_draw (ecell_view, drawable, col, row, selected, x1, y1, x2, y2); - -#if 0 - { - GdkFont *font; - GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; - - font = GTK_WIDGET (canvas)->style->font; - - sprintf (text, "%d:%d\n", col, row); gdk_draw_line (drawable, eti->grid_gc, x1, y1, x2, y2); - gdk_draw_line (drawable, eti->grid_gc, x1, y2, x2, y1); - - sprintf (text, "%d:%d\n", col, row); - gdk_draw_text (drawable, font, eti->grid_gc, x1, y2, text, strlen (text)); - } -#endif -} - static void eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) { @@ -670,8 +648,10 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, for (col = first_col; col < last_col; col++){ ETableCol *ecol = e_table_header_get_column (eti->header, col); + ECellView *ecell_view = eti->cell_views [col]; - draw_cell (eti, drawable, col, row, selected, xd, yd, xd + ecol->width, yd + height); + e_cell_draw (ecell_view, drawable, ecol->col_idx, col, row, selected, + xd, yd, xd + ecol->width, yd + height); if (col == eti->focused_col && row == eti->focused_row){ f_x1 = xd; @@ -786,7 +766,8 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) { ETableItem *eti = E_TABLE_ITEM (item); ECellView *ecell_view; - + ETableCol *ecol; + switch (e->type){ case GDK_BUTTON_PRESS: case GDK_BUTTON_RELEASE: @@ -798,6 +779,8 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) return TRUE; if (eti->focused_row == row && eti->focused_col == col){ + + ecol = e_table_header_get_column (eti->header, col); ecell_view = eti->cell_views [col]; /* @@ -806,7 +789,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) e->button.x = x1; e->button.y = y1; - e_cell_event (ecell_view, e, col, row); + e_cell_event (ecell_view, e, ecol->col_idx, col, row); } else { /* * Focus the cell, and select the row @@ -826,6 +809,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) return TRUE; if (eti->focused_row == row && eti->focused_col == col){ + ecol = e_table_header_get_column (eti->header, col); ecell_view = eti->cell_views [col]; /* @@ -834,7 +818,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) e->button.x -= (x1 + eti->x1); e->button.y -= (y1 + eti->y1); - e_cell_event (ecell_view, e, col, row); + e_cell_event (ecell_view, e, ecol->col_idx, col, row); } break; } @@ -887,8 +871,9 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) } } + ecol = e_table_header_get_column (eti->header, eti->focused_col); ecell_view = eti->cell_views [eti->focused_col]; - e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row); + e_cell_event (ecell_view, e, ecol->col_idx, eti->focused_col, eti->focused_row); break; case GDK_KEY_RELEASE: @@ -897,7 +882,8 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (eti_editing (eti)){ ecell_view = eti->cell_views [eti->editing_col]; - e_cell_event (ecell_view, e, eti->editing_col, eti->editing_row); + ecol = e_table_header_get_column (eti->header, eti->editing_col); + e_cell_event (ecell_view, e, ecol->col_idx, eti->editing_col, eti->editing_row); } break; @@ -1125,25 +1111,34 @@ e_table_item_select_row (ETableItem *eti, int row) void e_table_item_enter_edit (ETableItem *eti, int col, int row) { + ETableCol *ecol; + g_return_if_fail (eti != NULL); g_return_if_fail (E_IS_TABLE_ITEM (eti)); eti->editing_col = col; eti->editing_row = row; - eti->edit_ctx = e_cell_enter_edit (eti->cell_views [col], col, row); + ecol = e_table_header_get_column (eti->header, col); + eti->edit_ctx = e_cell_enter_edit (eti->cell_views [col], ecol->col_idx, col, row); } void e_table_item_leave_edit (ETableItem *eti) { + ETableCol *ecol; + g_return_if_fail (eti != NULL); g_return_if_fail (E_IS_TABLE_ITEM (eti)); if (!eti_editing (eti)) return; - - e_cell_leave_edit (eti->cell_views [eti->editing_col], eti->editing_col, eti->editing_row, eti->edit_ctx); + + ecol = e_table_header_get_column (eti->header, eti->editing_col); + e_cell_leave_edit ( + eti->cell_views [eti->editing_col], + ecol->col_idx, eti->editing_col, + eti->editing_row, eti->edit_ctx); eti->editing_col = -1; eti->editing_row = -1; eti->edit_ctx = NULL; diff --git a/widgets/e-table/e-table-item.h b/widgets/e-table/e-table-item.h index 6c4d837310..e9125431b1 100644 --- a/widgets/e-table/e-table-item.h +++ b/widgets/e-table/e-table-item.h @@ -27,6 +27,7 @@ typedef struct { int header_dim_change_id; int header_structure_change_id; int table_model_change_id; + int table_model_row_change_id; GdkGC *fill_gc; GdkGC *grid_gc; @@ -36,6 +37,7 @@ typedef struct { unsigned int draw_grid:1; unsigned int draw_focus:1; unsigned int mode_spreadsheet:1; + unsigned int renderers_can_change_size:1; int focused_col, focused_row; diff --git a/widgets/e-table/e-table-model.c b/widgets/e-table/e-table-model.c index 60f762214f..9e397710ef 100644 --- a/widgets/e-table/e-table-model.c +++ b/widgets/e-table/e-table-model.c @@ -58,7 +58,16 @@ e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const g_return_if_fail (e_table_model != NULL); g_return_if_fail (E_IS_TABLE_MODEL (e_table_model)); - return ETM_CLASS (e_table_model)->set_value_at (e_table_model, col, row, data); + ETM_CLASS (e_table_model)->set_value_at (e_table_model, col, row, data); + + gtk_signal_emit (GTK_OBJECT (e_table_model), + e_table_model_signals [MODEL_ROW_CHANGED], row); + gtk_signal_emit (GTK_OBJECT (e_table_model), + e_table_model_signals [MODEL_CELL_CHANGED], col, row); + + /* + * Notice that "model_changed" is not emitted + */ } gboolean diff --git a/widgets/e-table/e-table-model.h b/widgets/e-table/e-table-model.h index 0749a39758..fb37731a8a 100644 --- a/widgets/e-table/e-table-model.h +++ b/widgets/e-table/e-table-model.h @@ -28,6 +28,12 @@ typedef struct { /* * Signals */ + + /* + * Major structural changes: model_changed + * Changes only in a row: row_changed + * Only changes in a cell: cell_changed + */ void (*model_changed) (ETableModel *etm); void (*model_row_changed) (ETableModel *etm, int row); void (*model_cell_changed) (ETableModel *etm, int col, int row); diff --git a/widgets/e-table/e-table-sorted.c b/widgets/e-table/e-table-sorted.c index 90773e9cdc..6bc55ad9dc 100644 --- a/widgets/e-table/e-table-sorted.c +++ b/widgets/e-table/e-table-sorted.c @@ -18,8 +18,6 @@ static ETableModelClass *ets_parent_class; static void ets_class_init (GtkObjectClass *klass) { - ETableModelClass *table_class = (ETableModelClass *) klass; - ets_parent_class = gtk_type_class (PARENT_TYPE); } diff --git a/widgets/e-table/table-test.c b/widgets/e-table/table-test.c index 32d726dd06..e60dd893fe 100644 --- a/widgets/e-table/table-test.c +++ b/widgets/e-table/table-test.c @@ -9,6 +9,7 @@ #include #include #include +#include "e-cursors.h" int main (int argc, char *argv []) @@ -32,7 +33,6 @@ main (int argc, char *argv []) table_browser_test (); multi_cols_test (); check_test (); - gtk_main (); e_cursors_shutdown (); diff --git a/widgets/e-table/test-check.c b/widgets/e-table/test-check.c index d0b10d7f32..9968426327 100644 --- a/widgets/e-table/test-check.c +++ b/widgets/e-table/test-check.c @@ -90,7 +90,6 @@ check_test (void) ETableHeader *e_table_header; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_check; - int i; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); diff --git a/widgets/e-table/test-cols.c b/widgets/e-table/test-cols.c index 63033df569..4406c6b3b9 100644 --- a/widgets/e-table/test-cols.c +++ b/widgets/e-table/test-cols.c @@ -87,7 +87,7 @@ multi_cols_test (void) { GtkWidget *canvas, *window; ETableModel *e_table_model; - ETableHeader *e_table_header; + ETableHeader *e_table_header, *e_table_header_multiple; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_toggle; int i; @@ -122,13 +122,20 @@ multi_cols_test (void) g_free (images); } - col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_equal, TRUE); - e_table_header_add_column (e_table_header, col_0, 0); - col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_equal, TRUE); - e_table_header_add_column (e_table_header, col_1, 1); + e_table_header_add_column (e_table_header, col_1, 0); + col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_equal, TRUE); + e_table_header_add_column (e_table_header, col_0, 1); + /* + * Second test + */ + e_table_header_multiple = e_table_header_new (); + e_table_header_add_column (e_table_header_multiple, col_0, 0); + e_table_header_add_column (e_table_header_multiple, col_1, 1); + e_table_header_add_column (e_table_header_multiple, col_1, 2); + /* * GUI */ @@ -140,6 +147,7 @@ multi_cols_test (void) gtk_container_add (GTK_CONTAINER (window), canvas); gtk_widget_show_all (window); + gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_header_item_get_type (), @@ -160,6 +168,25 @@ multi_cols_test (void) "spreadsheet", TRUE, NULL); + gnome_canvas_item_new ( + gnome_canvas_root (GNOME_CANVAS (canvas)), + e_table_header_item_get_type (), + "ETableHeader", e_table_header_multiple, + "x", 300, + "y", 0, + NULL); + gnome_canvas_item_new ( + gnome_canvas_root (GNOME_CANVAS (canvas)), + e_table_item_get_type (), + "ETableHeader", e_table_header_multiple, + "ETableModel", e_table_model, + "x", 300, + "y", 30, + "drawgrid", TRUE, + "drawfocus", TRUE, + "spreadsheet", TRUE, + NULL); + } diff --git a/widgets/table-test.c b/widgets/table-test.c index 32d726dd06..e60dd893fe 100644 --- a/widgets/table-test.c +++ b/widgets/table-test.c @@ -9,6 +9,7 @@ #include #include #include +#include "e-cursors.h" int main (int argc, char *argv []) @@ -32,7 +33,6 @@ main (int argc, char *argv []) table_browser_test (); multi_cols_test (); check_test (); - gtk_main (); e_cursors_shutdown (); diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c index d9d8a568db..828be6cc29 100644 --- a/widgets/table/e-cell-text.c +++ b/widgets/table/e-cell-text.c @@ -29,7 +29,7 @@ typedef struct { /* * Where the editing is taking place */ - int col, row; + int model_col, view_col, row; } CellEdit; typedef struct { @@ -48,9 +48,9 @@ typedef struct { static ECellClass *parent_class; static void -ect_queue_redraw (ECellTextView *text_view, int col, int row) +ect_queue_redraw (ECellTextView *text_view, int view_col, int view_row) { - e_table_item_redraw_range (text_view->eti, col, row, col, row); + e_table_item_redraw_range (text_view->eti, view_col, view_row, view_col, view_row); } /* @@ -62,7 +62,7 @@ ect_accept_edits (ECellTextView *text_view) const char *text = gtk_entry_get_text (text_view->edit->entry); CellEdit *edit = text_view->edit; - e_table_model_set_value_at (text_view->eti->table_model, edit->col, edit->row, text); + e_table_model_set_value_at (text_view->eti->table_model, edit->model_col, edit->row, text); } /* @@ -92,7 +92,7 @@ ect_stop_editing (ECellTextView *text_view) static void ect_cancel_edit (ECellTextView *text_view) { - ect_queue_redraw (text_view, text_view->edit->col, text_view->edit->row); + ect_queue_redraw (text_view, text_view->edit->view_col, text_view->edit->row); ect_stop_editing (text_view); } @@ -149,14 +149,14 @@ ect_unrealize (ECellView *ecv) */ static void ect_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { ECellText *ect = E_CELL_TEXT (ecell_view->ecell); ECellTextView *text_view = (ECellTextView *) ecell_view; GtkWidget *w = GTK_WIDGET (text_view->canvas); GdkRectangle rect; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); GdkFont *font = text_view->font; const int height = font->ascent + font->descent; int xoff; @@ -168,7 +168,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, if (text_view->edit){ CellEdit *edit = text_view->edit; - if ((edit->col == col) && (edit->row == row)) + if ((edit->view_col == view_col) && (edit->row == row)) edit_display = TRUE; } @@ -312,7 +312,7 @@ ect_edit_select_all (ECellTextView *text_view) * ECell::event method */ static gint -ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; @@ -327,7 +327,7 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) if (text_view->edit){ printf ("FIXME: Should handle click here\n"); } else - e_table_item_enter_edit (text_view->eti, col, row); + e_table_item_enter_edit (text_view->eti, view_col, row); break; case GDK_BUTTON_RELEASE: @@ -345,12 +345,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) } if (!text_view->edit){ - e_table_item_enter_edit (text_view->eti, col, row); + e_table_item_enter_edit (text_view->eti, view_col, row); ect_edit_select_all (text_view); } gtk_widget_event (GTK_WIDGET (text_view->edit->entry), event); - ect_queue_redraw (text_view, col, row); + ect_queue_redraw (text_view, view_col, row); break; case GDK_KEY_RELEASE: @@ -366,7 +366,7 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row) * ECell::height method */ static int -ect_height (ECellView *ecell_view, int col, int row) +ect_height (ECellView *ecell_view, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; @@ -386,16 +386,17 @@ ect_entry_activate (GtkEntry *entry, ECellTextView *text_view) * ECellView::enter_edit method */ static void * -ect_enter_edit (ECellView *ecell_view, int col, int row) +ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; - const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); CellEdit *edit; edit = g_new (CellEdit, 1); text_view->edit = edit; - edit->col = col; + edit->model_col = model_col; + edit->view_col = view_col; edit->row = row; edit->entry = (GtkEntry *) gtk_entry_new (); @@ -412,7 +413,7 @@ ect_enter_edit (ECellView *ecell_view, int col, int row) gtk_widget_set_uposition (edit->entry_top, 20000, 20000); gtk_widget_show_all (edit->entry_top); - ect_queue_redraw (text_view, col, row); + ect_queue_redraw (text_view, view_col, row); return NULL; } @@ -421,7 +422,7 @@ ect_enter_edit (ECellView *ecell_view, int col, int row) * ECellView::leave_edit method */ static void -ect_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context) +ect_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context) { ECellTextView *text_view = (ECellTextView *) ecell_view; diff --git a/widgets/table/e-cell-toggle.c b/widgets/table/e-cell-toggle.c index 8e06d8d87d..ec6fa38a38 100644 --- a/widgets/table/e-cell-toggle.c +++ b/widgets/table/e-cell-toggle.c @@ -29,9 +29,9 @@ typedef struct { static ECellClass *parent_class; static void -etog_queue_redraw (ECellToggleView *text_view, int col, int row) +etog_queue_redraw (ECellToggleView *text_view, int view_col, int view_row) { - e_table_item_redraw_range (text_view->eti, col, row, col, row); + e_table_item_redraw_range (text_view->eti, view_col, view_row, view_col, view_row); } /* @@ -40,7 +40,6 @@ etog_queue_redraw (ECellToggleView *text_view, int col, int row) static ECellView * etog_realize (ECell *ecell, void *view) { - ECellToggle *eccb = E_CELL_TOGGLE (ecell); ECellToggleView *toggle_view = g_new0 (ECellToggleView, 1); ETableItem *eti = E_TABLE_ITEM (view); GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; @@ -72,7 +71,7 @@ etog_unrealize (ECellView *ecv) */ static void etog_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell); @@ -80,9 +79,8 @@ etog_draw (ECellView *ecell_view, GdkDrawable *drawable, GdkPixbuf *image; ArtPixBuf *art; int x, y, width, height; - gboolean free_image; const int value = GPOINTER_TO_INT ( - e_table_model_value_at (ecell_view->ecell->table_model, col, row)); + e_table_model_value_at (ecell_view->ecell->table_model, model_col, row)); if (value >= toggle->n_states){ g_warning ("Value from the table model is %d, the states we support are [0..%d)\n", @@ -166,7 +164,7 @@ etog_draw (ECellView *ecell_view, GdkDrawable *drawable, } static void -etog_set_value (ECellToggleView *toggle_view, int col, int row, int value) +etog_set_value (ECellToggleView *toggle_view, int model_col, int view_col, int row, int value) { ECell *ecell = toggle_view->cell_view.ecell; ECellToggle *toggle = E_CELL_TOGGLE (ecell); @@ -174,29 +172,28 @@ etog_set_value (ECellToggleView *toggle_view, int col, int row, int value) if (value >= toggle->n_states) value = 0; - e_table_model_set_value_at (ecell->table_model, col, row, GINT_TO_POINTER (value)); - etog_queue_redraw (toggle_view, col, row); + e_table_model_set_value_at (ecell->table_model, model_col, row, GINT_TO_POINTER (value)); + etog_queue_redraw (toggle_view, view_col, row); } /* * ECell::event method */ static gint -etog_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +etog_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { - ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell); ECellToggleView *toggle_view = (ECellToggleView *) ecell_view; - void *_value = e_table_model_value_at (ecell_view->ecell->table_model, col, row); + void *_value = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row); const int value = GPOINTER_TO_INT (_value); switch (event->type){ case GDK_BUTTON_RELEASE: - etog_set_value (toggle_view, col, row, value + 1); + etog_set_value (toggle_view, model_col, view_col, row, value + 1); return TRUE; case GDK_KEY_PRESS: if (event->key.keyval == GDK_space){ - etog_set_value (toggle_view, col, row, value + 1); + etog_set_value (toggle_view, model_col, view_col, row, value + 1); return TRUE; } return FALSE; @@ -211,7 +208,7 @@ etog_event (ECellView *ecell_view, GdkEvent *event, int col, int row) * ECell::height method */ static int -etog_height (ECellView *ecell_view, int col, int row) +etog_height (ECellView *ecell_view, int model_col, int view_col, int row) { ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell); diff --git a/widgets/table/e-cell.c b/widgets/table/e-cell.c index 2bc49f7a45..a4a03655dc 100644 --- a/widgets/table/e-cell.c +++ b/widgets/table/e-cell.c @@ -25,30 +25,30 @@ ec_unrealize (ECellView *e_cell) static void ec_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { g_error ("e-cell-draw invoked\n"); } static gint -ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row) +ec_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { g_error ("e-cell-event invoked\n"); return 0; } static gint -ec_height (ECellView *ecell_view, int col, int row) +ec_height (ECellView *ecell_view, int model_col, int view_col, int row) { g_error ("e-cell-event invoked\n"); return 0; } static void -ec_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2) +ec_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2) { - ecell_view->focus_col = col; + ecell_view->focus_col = view_col; ecell_view->focus_row = row; ecell_view->focus_x1 = x1; ecell_view->focus_y1 = y1; @@ -67,6 +67,17 @@ ec_unfocus (ECellView *ecell_view) ecell_view->focus_y2 = -1; } +static void * +ec_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) +{ + return NULL; +} + +static void +ec_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *context) +{ +} + static void e_cell_class_init (GtkObjectClass *object_class) { @@ -79,22 +90,23 @@ e_cell_class_init (GtkObjectClass *object_class) ecc->focus = ec_focus; ecc->unfocus = ec_unfocus; ecc->height = ec_height; + ecc->enter_edit = ec_enter_edit; + ecc->leave_edit = ec_leave_edit; } static void e_cell_init (GtkObject *object) { - ECell *e_cell = E_CELL (object); } 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_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row) { E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->event ( - ecell_view, event, col, row); + ecell_view, event, model_col, view_col, row); } ECellView * @@ -112,29 +124,29 @@ e_cell_unrealize (ECellView *ecell_view) void e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, int x1, int y1, int x2, int y2) + int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2) { E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->draw ( - ecell_view, drawable, col, row, selected, x1, y1, x2, y2); + ecell_view, drawable, model_col, view_col, row, selected, x1, y1, x2, y2); } int -e_cell_height (ECellView *ecell_view, int col, int row) +e_cell_height (ECellView *ecell_view, int model_col, int view_col, int row) { return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->height ( - ecell_view, col, row); + ecell_view, model_col, view_col, row); } void * -e_cell_enter_edit (ECellView *ecell_view, int col, int row) +e_cell_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) { return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->enter_edit ( - ecell_view, col, row); + ecell_view, model_col, view_col, row); } void -e_cell_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context) +e_cell_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context) { E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->leave_edit ( - ecell_view, col, row, edit_context); + ecell_view, model_col, view_col, row, edit_context); } diff --git a/widgets/table/e-cell.h b/widgets/table/e-cell.h index b0f62d020c..f72f97e8dd 100644 --- a/widgets/table/e-cell.h +++ b/widgets/table/e-cell.h @@ -32,28 +32,31 @@ typedef struct { ECellView *(*realize) (ECell *ecell, void *view); void (*unrealize) (ECellView *e_cell_view); void (*draw) (ECellView *ecell_view, GdkDrawable *drawable, - int col, int row, gboolean selected, int x1, int y1, int x2, int y2); - gint (*event) (ECellView *ecell_view, GdkEvent *event, int col, int row); - void (*focus) (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2); + int model_col, int view_col, int row, + gboolean selected, int x1, int y1, int x2, int y2); + gint (*event) (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row); + void (*focus) (ECellView *ecell_view, int model_col, int view_col, + int row, int x1, int y1, int x2, int y2); void (*unfocus) (ECellView *ecell_view); - int (*height) (ECellView *ecell_view, int col, int row); + int (*height) (ECellView *ecell_view, int model_col, int view_col, int row); - void *(*enter_edit)(ECellView *ecell_view, int col, int row); - void (*leave_edit)(ECellView *ecell_view, int col, int row, void *context); + void *(*enter_edit)(ECellView *ecell_view, int model_col, int view_col, int row); + void (*leave_edit)(ECellView *ecell_view, int model_col, int view_col, int row, void *context); } ECellClass; GtkType e_cell_get_type (void); -void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row); +void e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row); ECellView *e_cell_realize (ECell *ecell, void *view); void e_cell_unrealize (ECellView *ecell_view); void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr, - int col, int row, gboolean selected, + int model_col, int view_col, int row, gboolean selected, + int x1, int y1, int x2, int y2); +void e_cell_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2); -void e_cell_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2); void e_cell_unfocus (ECellView *ecell_view); -int e_cell_height (ECellView *ecell_view, int col, int row); +int e_cell_height (ECellView *ecell_view, int model_col, int view_col, int row); -void *e_cell_enter_edit(ECellView *ecell_view, int col, int row); -void e_cell_leave_edit(ECellView *ecell_view, int col, int row, void *edit_context); +void *e_cell_enter_edit(ECellView *ecell_view, int model_col, int view_col, int row); +void e_cell_leave_edit(ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context); #endif /* _E_CELL_H_ */ diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c index 5368f10602..0b5be9b84a 100644 --- a/widgets/table/e-table-header-item.c +++ b/widgets/table/e-table-header-item.c @@ -8,10 +8,19 @@ */ #include #include +#include +#include +#include +#include +#include #include "e-table-header.h" #include "e-table-header-item.h" +#include "e-table-col-dnd.h" #include "e-cursors.h" +#include "add-col.xpm" +#include "remove-col.xpm" + /* Padding above and below of the string in the header display */ #define PADDING 4 @@ -22,8 +31,17 @@ #define PARENT_OBJECT_TYPE gnome_canvas_item_get_type () +#define ELEMENTS(x) (sizeof (x) / sizeof (x[0])) + static GnomeCanvasItemClass *ethi_parent_class; +/* + * DnD icons + */ +static GdkColormap *dnd_colormap; +static GdkPixmap *remove_col_pixmap, *remove_col_mask; +static GdkPixmap *add_col_pixmap, *add_col_mask; + enum { ARG_0, ARG_TABLE_HEADER, @@ -32,6 +50,14 @@ enum { ARG_TABLE_FONTSET }; +static GtkTargetEntry ethi_drag_types [] = { + { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER }, +}; + +static GtkTargetEntry ethi_drop_types [] = { + { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER }, +}; + static void ethi_destroy (GtkObject *object) { @@ -151,6 +177,177 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) ethi_update (item, NULL, NULL, 0); } +static int +ethi_find_col_by_x (ETableHeaderItem *ethi, int x) +{ + const int cols = e_table_header_count (ethi->eth); + int x1 = ethi->x1; + int col; + + if (x < x1) + return -1; + + for (col = 0; col < cols; col++){ + ETableCol *ecol = e_table_header_get_column (ethi->eth, col); + + if ((x >= x1) && (x <= x1 + ecol->width)) + return col; + + x1 += ecol->width; + } + return -1; +} + +static void +ethi_remove_drop_marker (ETableHeaderItem *ethi) +{ + if (ethi->drag_mark == -1) + return; + + ethi->drag_mark = -1; + gtk_object_destroy (GTK_OBJECT (ethi->drag_mark_item)); + ethi->drag_mark_item = NULL; +} + +static void +ethi_add_drop_marker (ETableHeaderItem *ethi, int col) +{ + GnomeCanvasPoints *points; + int x; + + if (ethi->drag_mark == col) + return; + + if (ethi->drag_mark_item) + gtk_object_destroy (GTK_OBJECT (ethi->drag_mark_item)); + + ethi->drag_mark = col; + + ethi->drag_mark_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (ethi)->canvas->root), + gnome_canvas_group_get_type (), + "x", 0, + "y", 0, + NULL); + + points = gnome_canvas_points_new (3); + + x = e_table_header_col_diff (ethi->eth, 0, col); + + points->coords [0] = ethi->x1 + x - 5; + points->coords [1] = ethi->y1; + points->coords [2] = points->coords [0] + 10; + points->coords [3] = points->coords [1]; + points->coords [4] = ethi->x1 + x; + points->coords [5] = ethi->y1 + 5; + + gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (ethi->drag_mark_item), + gnome_canvas_polygon_get_type (), + "points", points, + "fill_color", "red", + NULL); + + points->coords [0] --; + points->coords [1] += ethi->height - 1; + points->coords [3] = points->coords [1]; + points->coords [5] = points->coords [1] - 6; + + gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (ethi->drag_mark_item), + gnome_canvas_polygon_get_type (), + "points", points, + "fill_color", "red", + NULL); + + gnome_canvas_points_unref (points); +} + +#define gray50_width 2 +#define gray50_height 2 +static char gray50_bits [] = { + 0x02, 0x01, }; + +static void +ethi_add_destroy_marker (ETableHeaderItem *ethi) +{ + double x1; + + if (ethi->remove_item) + gtk_object_destroy (GTK_OBJECT (ethi->remove_item)); + + if (!ethi->stipple) + ethi->stipple = gdk_bitmap_create_from_data (NULL, gray50_bits, gray50_width, gray50_height); + + x1 = ethi->x1 + (double) e_table_header_col_diff (ethi->eth, 0, ethi->drag_col); + ethi->remove_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (ethi)->canvas->root), + gnome_canvas_rect_get_type (), + "x1", x1 + 1, + "y1", (double) ethi->y1 + 1, + "x2", (double) x1 + e_table_header_col_diff (ethi->eth, ethi->drag_col, ethi->drag_col+1) - 2, + "y2", (double) ethi->y1 + ethi->height - 2, + "fill_color", "red", + "fill_stipple", ethi->stipple, + NULL); +} + +static void +ethi_remove_destroy_marker (ETableHeaderItem *ethi) +{ + if (!ethi->remove_item) + return; + + gtk_object_destroy (GTK_OBJECT (ethi->remove_item)); + ethi->remove_item = NULL; +} + +static gboolean +ethi_drag_motion (GtkObject *canvas, GdkDragContext *context, + gint x, gint y, guint time, + ETableHeaderItem *ethi) +{ + + if ((x >= ethi->x1) && (x <= (ethi->x1 + ethi->width)) && + (y >= ethi->y1) && (y <= (ethi->y1 + ethi->height))){ + int col; + + col = ethi_find_col_by_x (ethi, x); + + if (col != -1){ + ethi_remove_destroy_marker (ethi); + ethi_add_drop_marker (ethi, col); + } else { + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); + } + } else { + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); + } + + gdk_drag_status (context, context->suggested_action, time); + + return TRUE; +} + +static void +ethi_drag_end (GtkWidget *canvas, GdkDragContext *context, ETableHeaderItem *ethi) +{ + printf ("Ending\n"); + + ethi_remove_drop_marker (ethi); + ethi_remove_destroy_marker (ethi); + ethi->drag_col = -1; +} + +static void +ethi_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, ETableHeaderItem *ethi) +{ + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); +} + static void ethi_realize (GnomeCanvasItem *item) { @@ -171,19 +368,47 @@ ethi_realize (GnomeCanvasItem *item) if (!ethi->font) ethi_font_load (ethi, "fixed"); + + /* + * Now, configure DnD + */ + gtk_drag_dest_set (GTK_WIDGET (item->canvas), GTK_DEST_DEFAULT_ALL, + ethi_drop_types, ELEMENTS (ethi_drop_types), + GDK_ACTION_MOVE); + + ethi->drag_motion_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_motion", + GTK_SIGNAL_FUNC (ethi_drag_motion), ethi); + + ethi->drag_leave_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_leave", + GTK_SIGNAL_FUNC (ethi_drag_leave), ethi); + + ethi->drag_end_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_end", + GTK_SIGNAL_FUNC (ethi_drag_end), ethi); } static void ethi_unrealize (GnomeCanvasItem *item) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); - + gdk_gc_unref (ethi->gc); ethi->gc = NULL; gdk_cursor_destroy (ethi->normal_cursor); ethi->normal_cursor = NULL; + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_motion_id); + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_end_id); + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_leave_id); + + if (ethi->stipple){ + gdk_bitmap_unref (ethi->stipple); + ethi->stipple = NULL; + } + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize) (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item); } @@ -228,25 +453,21 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, } static void -ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height) +ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); GnomeCanvas *canvas = item->canvas; GdkGC *gc; const int cols = e_table_header_count (ethi->eth); - int x2 = x1 + width; - int col, total; - int x; - - total = 0; - x = -x1; + int x1, x2; + int col; #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++){ + x1 = x2 = ethi->x1; + for (col = 0; col < cols; col++, x1 = x2){ ETableCol *ecol = e_table_header_get_column (ethi->eth, col); int col_width; @@ -255,23 +476,19 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int wid else col_width = ecol->width; - if (x1 > total + col_width){ - total += col_width; - x += col_width; - continue; - } - - if (x2 < total) - return; + x2 += col_width; + + if (x1 > (x + width)) + break; + if (x2 < x) + continue; + gc = GTK_WIDGET (canvas)->style->bg_gc [GTK_STATE_ACTIVE]; draw_button (ethi, ecol, drawable, gc, GTK_WIDGET (canvas)->style, - x, ethi->y1 - y1, col_width, ethi->height); - - x += col_width; - total += col_width; + x1 - x, ethi->y1 - y, col_width, ethi->height); } } @@ -356,6 +573,35 @@ ethi_end_resize (ETableHeaderItem *ethi, int new_size) ethi_request_redraw (ethi); } +static gboolean +ethi_maybe_start_drag (ETableHeaderItem *ethi, GdkEventMotion *event) +{ + if (!ethi->maybe_drag) + return FALSE; + + if (MAX (abs (ethi->click_x - event->x), + abs (ethi->click_y - event->y)) <= 3) + return FALSE; + + return TRUE; +} + +static void +ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) +{ + GtkWidget *widget = GTK_WIDGET (GNOME_CANVAS_ITEM (ethi)->canvas); + GtkTargetList *list; + GdkDragContext *context; + + ethi->drag_col = ethi_find_col_by_x (ethi, event->motion.x); + if (ethi->drag_col == -1) + return; + + list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types)); + context = gtk_drag_begin (widget, list, GDK_ACTION_MOVE, 1, event); + ethi->maybe_drag = FALSE; +} + /* * Handles the events on the ETableHeaderItem, particularly it handles resizing */ @@ -405,6 +651,8 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) e_table_header_set_size (ethi->eth, ethi->resize_col, ethi->resize_width); ethi_request_redraw (ethi); + } else if (ethi_maybe_start_drag (ethi, &e->motion)){ + ethi_start_drag (ethi, e); } else set_cursor (ethi, x); break; @@ -430,6 +678,12 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) ethi->resize_width = ecol->width; ethi->resize_start_pos = start - ecol->width; ethi->resize_min_width = ecol->min_width; + } else { + if (e->button.button == 1){ + ethi->click_x = e->button.x; + ethi->click_y = e->button.y; + ethi->maybe_drag = TRUE; + } } break; @@ -439,8 +693,6 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (e->button.button != 1) break; - - printf ("Resize this guy\n"); break; case GDK_BUTTON_RELEASE: { @@ -453,6 +705,7 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (needs_ungrab) gnome_canvas_item_ungrab (item, e->button.time); + ethi->maybe_drag = FALSE; break; } @@ -487,6 +740,18 @@ ethi_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableHeaderItem::fontset", GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_TABLE_FONTSET); + + /* + * Create our pixmaps for DnD + */ + dnd_colormap = gtk_widget_get_default_colormap (); + remove_col_pixmap = gdk_pixmap_colormap_create_from_xpm_d ( + NULL, dnd_colormap, + &remove_col_mask, NULL, remove_col_xpm); + + add_col_pixmap = gdk_pixmap_colormap_create_from_xpm_d ( + NULL, dnd_colormap, + &add_col_mask, NULL, add_col_xpm); } static void @@ -500,6 +765,9 @@ ethi_init (GnomeCanvasItem *item) item->y1 = 0; item->x2 = 0; item->y2 = 0; + + ethi->drag_col = -1; + ethi->drag_mark = -1; } GtkType diff --git a/widgets/table/e-table-header-item.h b/widgets/table/e-table-header-item.h index ea2082018f..5522d24fae 100644 --- a/widgets/table/e-table-header-item.h +++ b/widgets/table/e-table-header-item.h @@ -34,6 +34,17 @@ typedef struct { * Ids */ int structure_change_id, dimension_change_id; + + /* + * For dragging columns + */ + guint maybe_drag:1; + guint dnd_ready:1; + int click_x, click_y; + int drag_col, drag_mark; + guint drag_motion_id, drag_end_id, drag_leave_id; + GnomeCanvasItem *drag_mark_item, *remove_item; + GdkBitmap *stipple; } ETableHeaderItem; typedef struct { diff --git a/widgets/table/e-table-header.c b/widgets/table/e-table-header.c index 576f609deb..375fd34c5d 100644 --- a/widgets/table/e-table-header.c +++ b/widgets/table/e-table-header.c @@ -172,8 +172,6 @@ e_table_header_count (ETableHeader *eth) int e_table_header_index (ETableHeader *eth, int col) { - int i; - g_return_val_if_fail (eth != NULL, -1); g_return_val_if_fail (E_IS_TABLE_HEADER (eth), -1); g_return_val_if_fail (col < eth->col_count, -1); @@ -316,3 +314,26 @@ e_table_header_set_size (ETableHeader *eth, int idx, int size) eth->columns [idx]->width = size; gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE], idx); } + +int +e_table_header_col_diff (ETableHeader *eth, int start_col, int end_col) +{ + int total, col; + + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0); + + { + const int max_col = eth->col_count; + + total = 0; + for (col = start_col; col < end_col; col++){ + + if (col == max_col) + break; + total += eth->columns [col]->width; + } + } + + return total; +} diff --git a/widgets/table/e-table-header.h b/widgets/table/e-table-header.h index 8965dee5c6..96e65fdc2f 100644 --- a/widgets/table/e-table-header.h +++ b/widgets/table/e-table-header.h @@ -55,6 +55,9 @@ void e_table_header_set_size (ETableHeader *eth, int idx, int size); void e_table_header_set_selection (ETableHeader *eth, gboolean allow_selection); +int e_table_header_col_diff (ETableHeader *eth, + int start_col, int end_col); + GList *e_table_header_get_selected_indexes(ETableHeader *eth); diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c index ceb6adda95..bdeda14a7b 100644 --- a/widgets/table/e-table-item.c +++ b/widgets/table/e-table-item.c @@ -127,9 +127,12 @@ eti_remove_table_model (ETableItem *eti) gtk_signal_disconnect (GTK_OBJECT (eti->table_model), eti->table_model_change_id); + gtk_signal_disconnect (GTK_OBJECT (eti->table_model), + eti->table_model_row_change_id); gtk_object_unref (GTK_OBJECT (eti->table_model)); eti->table_model_change_id = 0; + eti->table_model_row_change_id = 0; eti->table_model = NULL; } @@ -171,7 +174,9 @@ eti_row_height (ETableItem *eti, int row) max_h = 0; for (col = 0; col < cols; col++){ - h = e_cell_height (eti->cell_views [col], col, row); + ETableCol *ecol = e_table_header_get_column (eti->header, col); + + h = e_cell_height (eti->cell_views [col], ecol->col_idx, col, row); if (h > max_h) max_h = h; @@ -225,8 +230,7 @@ eti_get_height (ETableItem *eti) static void eti_table_model_changed (ETableModel *table_model, ETableItem *eti) { - eti->cols = e_table_model_column_count (eti->table_model); - eti->rows = e_table_model_row_count (eti->table_model); + eti->rows = e_table_model_row_count (eti->table_model); if (eti->cell_views) eti->height = eti_get_height (eti); @@ -234,6 +238,7 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti) eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); } + /* * eti_request_redraw: * @@ -249,24 +254,6 @@ eti_request_redraw (ETableItem *eti) eti->y1 + eti->height + 1); } -/* - * Computes the distance from @start_col to @end_col in pixels. - */ -static int -eti_col_diff (ETableItem *eti, int start_col, int end_col) -{ - int col, total; - - total = 0; - for (col = start_col; col < end_col; col++){ - ETableCol *ecol = e_table_header_get_column (eti->header, col); - - total += ecol->width; - } - - return total; -} - /* * Computes the distance between @start_row and @end_row in pixels */ @@ -301,9 +288,9 @@ eti_request_region_redraw (ETableItem *eti, GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; int x1, y1, width, height; - x1 = eti_col_diff (eti, 0, start_col); + x1 = e_table_header_col_diff (eti->header, 0, start_col); y1 = eti_row_diff (eti, 0, start_row); - width = eti_col_diff (eti, start_col, end_col + 1); + width = e_table_header_col_diff (eti->header, start_col, end_col + 1); height = eti_row_diff (eti, start_row, end_row + 1); gnome_canvas_request_redraw (canvas, @@ -313,6 +300,17 @@ eti_request_region_redraw (ETableItem *eti, eti->y1 + y1 + height + 1 + border); } +static void +eti_table_model_row_changed (ETableModel *table_model, int row, ETableItem *eti) +{ + if (eti->renderers_can_change_size){ + eti_table_model_changed (table_model, eti); + return; + } + + eti_request_region_redraw (eti, 0, row, eti->cols, row, 0); +} + void e_table_item_redraw_range (ETableItem *eti, int start_col, int start_row, @@ -345,6 +343,10 @@ 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); + eti->table_model_row_change_id = gtk_signal_connect ( + GTK_OBJECT (table_model), "model_row_changed", + GTK_SIGNAL_FUNC (eti_table_model_row_changed), eti); + eti_table_model_changed (table_model, eti); } @@ -364,6 +366,7 @@ eti_header_structure_changed (ETableHeader *eth, ETableItem *eti) { eti_request_redraw (eti); + eti->cols = e_table_header_count (eti->header); eti->width = e_table_header_total_width (eti->header); eti_unrealize_cell_views (eti); eti_realize_cell_views (eti); @@ -380,7 +383,7 @@ eti_add_header_model (ETableItem *eti, ETableHeader *header) eti->header = header; gtk_object_ref (GTK_OBJECT (header)); - eti->width = e_table_header_total_width (header); + eti_header_structure_changed (header, eti); eti->header_dim_change_id = gtk_signal_connect ( GTK_OBJECT (header), "dimension_change", @@ -467,7 +470,8 @@ eti_init (GnomeCanvasItem *item) eti->height = 0; eti->length_threshold = -1; - + eti->renderers_can_change_size = 0; + eti->selection_mode = GTK_SELECTION_SINGLE; } @@ -540,32 +544,6 @@ eti_unrealize (GnomeCanvasItem *item) (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->unrealize)(item); } -static void -draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row, gboolean selected, - int x1, int y1, int x2, int y2) -{ - ECellView *ecell_view; - - ecell_view = eti->cell_views [col]; - - e_cell_draw (ecell_view, drawable, col, row, selected, x1, y1, x2, y2); - -#if 0 - { - GdkFont *font; - GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas; - - font = GTK_WIDGET (canvas)->style->font; - - sprintf (text, "%d:%d\n", col, row); gdk_draw_line (drawable, eti->grid_gc, x1, y1, x2, y2); - gdk_draw_line (drawable, eti->grid_gc, x1, y2, x2, y1); - - sprintf (text, "%d:%d\n", col, row); - gdk_draw_text (drawable, font, eti->grid_gc, x1, y2, text, strlen (text)); - } -#endif -} - static void eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) { @@ -670,8 +648,10 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, for (col = first_col; col < last_col; col++){ ETableCol *ecol = e_table_header_get_column (eti->header, col); + ECellView *ecell_view = eti->cell_views [col]; - draw_cell (eti, drawable, col, row, selected, xd, yd, xd + ecol->width, yd + height); + e_cell_draw (ecell_view, drawable, ecol->col_idx, col, row, selected, + xd, yd, xd + ecol->width, yd + height); if (col == eti->focused_col && row == eti->focused_row){ f_x1 = xd; @@ -786,7 +766,8 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) { ETableItem *eti = E_TABLE_ITEM (item); ECellView *ecell_view; - + ETableCol *ecol; + switch (e->type){ case GDK_BUTTON_PRESS: case GDK_BUTTON_RELEASE: @@ -798,6 +779,8 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) return TRUE; if (eti->focused_row == row && eti->focused_col == col){ + + ecol = e_table_header_get_column (eti->header, col); ecell_view = eti->cell_views [col]; /* @@ -806,7 +789,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) e->button.x = x1; e->button.y = y1; - e_cell_event (ecell_view, e, col, row); + e_cell_event (ecell_view, e, ecol->col_idx, col, row); } else { /* * Focus the cell, and select the row @@ -826,6 +809,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) return TRUE; if (eti->focused_row == row && eti->focused_col == col){ + ecol = e_table_header_get_column (eti->header, col); ecell_view = eti->cell_views [col]; /* @@ -834,7 +818,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) e->button.x -= (x1 + eti->x1); e->button.y -= (y1 + eti->y1); - e_cell_event (ecell_view, e, col, row); + e_cell_event (ecell_view, e, ecol->col_idx, col, row); } break; } @@ -887,8 +871,9 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) } } + ecol = e_table_header_get_column (eti->header, eti->focused_col); ecell_view = eti->cell_views [eti->focused_col]; - e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row); + e_cell_event (ecell_view, e, ecol->col_idx, eti->focused_col, eti->focused_row); break; case GDK_KEY_RELEASE: @@ -897,7 +882,8 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (eti_editing (eti)){ ecell_view = eti->cell_views [eti->editing_col]; - e_cell_event (ecell_view, e, eti->editing_col, eti->editing_row); + ecol = e_table_header_get_column (eti->header, eti->editing_col); + e_cell_event (ecell_view, e, ecol->col_idx, eti->editing_col, eti->editing_row); } break; @@ -1125,25 +1111,34 @@ e_table_item_select_row (ETableItem *eti, int row) void e_table_item_enter_edit (ETableItem *eti, int col, int row) { + ETableCol *ecol; + g_return_if_fail (eti != NULL); g_return_if_fail (E_IS_TABLE_ITEM (eti)); eti->editing_col = col; eti->editing_row = row; - eti->edit_ctx = e_cell_enter_edit (eti->cell_views [col], col, row); + ecol = e_table_header_get_column (eti->header, col); + eti->edit_ctx = e_cell_enter_edit (eti->cell_views [col], ecol->col_idx, col, row); } void e_table_item_leave_edit (ETableItem *eti) { + ETableCol *ecol; + g_return_if_fail (eti != NULL); g_return_if_fail (E_IS_TABLE_ITEM (eti)); if (!eti_editing (eti)) return; - - e_cell_leave_edit (eti->cell_views [eti->editing_col], eti->editing_col, eti->editing_row, eti->edit_ctx); + + ecol = e_table_header_get_column (eti->header, eti->editing_col); + e_cell_leave_edit ( + eti->cell_views [eti->editing_col], + ecol->col_idx, eti->editing_col, + eti->editing_row, eti->edit_ctx); eti->editing_col = -1; eti->editing_row = -1; eti->edit_ctx = NULL; diff --git a/widgets/table/e-table-item.h b/widgets/table/e-table-item.h index 6c4d837310..e9125431b1 100644 --- a/widgets/table/e-table-item.h +++ b/widgets/table/e-table-item.h @@ -27,6 +27,7 @@ typedef struct { int header_dim_change_id; int header_structure_change_id; int table_model_change_id; + int table_model_row_change_id; GdkGC *fill_gc; GdkGC *grid_gc; @@ -36,6 +37,7 @@ typedef struct { unsigned int draw_grid:1; unsigned int draw_focus:1; unsigned int mode_spreadsheet:1; + unsigned int renderers_can_change_size:1; int focused_col, focused_row; diff --git a/widgets/table/e-table-model.c b/widgets/table/e-table-model.c index 60f762214f..9e397710ef 100644 --- a/widgets/table/e-table-model.c +++ b/widgets/table/e-table-model.c @@ -58,7 +58,16 @@ e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const g_return_if_fail (e_table_model != NULL); g_return_if_fail (E_IS_TABLE_MODEL (e_table_model)); - return ETM_CLASS (e_table_model)->set_value_at (e_table_model, col, row, data); + ETM_CLASS (e_table_model)->set_value_at (e_table_model, col, row, data); + + gtk_signal_emit (GTK_OBJECT (e_table_model), + e_table_model_signals [MODEL_ROW_CHANGED], row); + gtk_signal_emit (GTK_OBJECT (e_table_model), + e_table_model_signals [MODEL_CELL_CHANGED], col, row); + + /* + * Notice that "model_changed" is not emitted + */ } gboolean diff --git a/widgets/table/e-table-model.h b/widgets/table/e-table-model.h index 0749a39758..fb37731a8a 100644 --- a/widgets/table/e-table-model.h +++ b/widgets/table/e-table-model.h @@ -28,6 +28,12 @@ typedef struct { /* * Signals */ + + /* + * Major structural changes: model_changed + * Changes only in a row: row_changed + * Only changes in a cell: cell_changed + */ void (*model_changed) (ETableModel *etm); void (*model_row_changed) (ETableModel *etm, int row); void (*model_cell_changed) (ETableModel *etm, int col, int row); diff --git a/widgets/table/e-table-sorted.c b/widgets/table/e-table-sorted.c index 90773e9cdc..6bc55ad9dc 100644 --- a/widgets/table/e-table-sorted.c +++ b/widgets/table/e-table-sorted.c @@ -18,8 +18,6 @@ static ETableModelClass *ets_parent_class; static void ets_class_init (GtkObjectClass *klass) { - ETableModelClass *table_class = (ETableModelClass *) klass; - ets_parent_class = gtk_type_class (PARENT_TYPE); } diff --git a/widgets/table/table-test.c b/widgets/table/table-test.c index 32d726dd06..e60dd893fe 100644 --- a/widgets/table/table-test.c +++ b/widgets/table/table-test.c @@ -9,6 +9,7 @@ #include #include #include +#include "e-cursors.h" int main (int argc, char *argv []) @@ -32,7 +33,6 @@ main (int argc, char *argv []) table_browser_test (); multi_cols_test (); check_test (); - gtk_main (); e_cursors_shutdown (); diff --git a/widgets/table/test-check.c b/widgets/table/test-check.c index d0b10d7f32..9968426327 100644 --- a/widgets/table/test-check.c +++ b/widgets/table/test-check.c @@ -90,7 +90,6 @@ check_test (void) ETableHeader *e_table_header; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_check; - int i; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); diff --git a/widgets/table/test-cols.c b/widgets/table/test-cols.c index 63033df569..4406c6b3b9 100644 --- a/widgets/table/test-cols.c +++ b/widgets/table/test-cols.c @@ -87,7 +87,7 @@ multi_cols_test (void) { GtkWidget *canvas, *window; ETableModel *e_table_model; - ETableHeader *e_table_header; + ETableHeader *e_table_header, *e_table_header_multiple; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_toggle; int i; @@ -122,13 +122,20 @@ multi_cols_test (void) g_free (images); } - col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_equal, TRUE); - e_table_header_add_column (e_table_header, col_0, 0); - col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_equal, TRUE); - e_table_header_add_column (e_table_header, col_1, 1); + e_table_header_add_column (e_table_header, col_1, 0); + col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_equal, TRUE); + e_table_header_add_column (e_table_header, col_0, 1); + /* + * Second test + */ + e_table_header_multiple = e_table_header_new (); + e_table_header_add_column (e_table_header_multiple, col_0, 0); + e_table_header_add_column (e_table_header_multiple, col_1, 1); + e_table_header_add_column (e_table_header_multiple, col_1, 2); + /* * GUI */ @@ -140,6 +147,7 @@ multi_cols_test (void) gtk_container_add (GTK_CONTAINER (window), canvas); gtk_widget_show_all (window); + gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_header_item_get_type (), @@ -160,6 +168,25 @@ multi_cols_test (void) "spreadsheet", TRUE, NULL); + gnome_canvas_item_new ( + gnome_canvas_root (GNOME_CANVAS (canvas)), + e_table_header_item_get_type (), + "ETableHeader", e_table_header_multiple, + "x", 300, + "y", 0, + NULL); + gnome_canvas_item_new ( + gnome_canvas_root (GNOME_CANVAS (canvas)), + e_table_item_get_type (), + "ETableHeader", e_table_header_multiple, + "ETableModel", e_table_model, + "x", 300, + "y", 30, + "drawgrid", TRUE, + "drawfocus", TRUE, + "spreadsheet", TRUE, + NULL); + } diff --git a/widgets/test-check.c b/widgets/test-check.c index d0b10d7f32..9968426327 100644 --- a/widgets/test-check.c +++ b/widgets/test-check.c @@ -90,7 +90,6 @@ check_test (void) ETableHeader *e_table_header; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_check; - int i; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); diff --git a/widgets/test-cols.c b/widgets/test-cols.c index 63033df569..4406c6b3b9 100644 --- a/widgets/test-cols.c +++ b/widgets/test-cols.c @@ -87,7 +87,7 @@ multi_cols_test (void) { GtkWidget *canvas, *window; ETableModel *e_table_model; - ETableHeader *e_table_header; + ETableHeader *e_table_header, *e_table_header_multiple; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_toggle; int i; @@ -122,13 +122,20 @@ multi_cols_test (void) g_free (images); } - col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_equal, TRUE); - e_table_header_add_column (e_table_header, col_0, 0); - col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_equal, TRUE); - e_table_header_add_column (e_table_header, col_1, 1); + e_table_header_add_column (e_table_header, col_1, 0); + col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_equal, TRUE); + e_table_header_add_column (e_table_header, col_0, 1); + /* + * Second test + */ + e_table_header_multiple = e_table_header_new (); + e_table_header_add_column (e_table_header_multiple, col_0, 0); + e_table_header_add_column (e_table_header_multiple, col_1, 1); + e_table_header_add_column (e_table_header_multiple, col_1, 2); + /* * GUI */ @@ -140,6 +147,7 @@ multi_cols_test (void) gtk_container_add (GTK_CONTAINER (window), canvas); gtk_widget_show_all (window); + gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_header_item_get_type (), @@ -160,6 +168,25 @@ multi_cols_test (void) "spreadsheet", TRUE, NULL); + gnome_canvas_item_new ( + gnome_canvas_root (GNOME_CANVAS (canvas)), + e_table_header_item_get_type (), + "ETableHeader", e_table_header_multiple, + "x", 300, + "y", 0, + NULL); + gnome_canvas_item_new ( + gnome_canvas_root (GNOME_CANVAS (canvas)), + e_table_item_get_type (), + "ETableHeader", e_table_header_multiple, + "ETableModel", e_table_model, + "x", 300, + "y", 30, + "drawgrid", TRUE, + "drawfocus", TRUE, + "spreadsheet", TRUE, + NULL); + } -- cgit v1.2.3