diff options
52 files changed, 1599 insertions, 473 deletions
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 <miguel@gnu.org> + + * e-table-header.c (e_table_header_col_diff): fix this routine. + +1999-12-04 Miguel de Icaza <miguel@gnu.org> + + * 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 <miguel@gnu.org> + + * 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 <miguel@gnu.org> * 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 <config.h> #include <gtk/gtksignal.h> +#include <gtk/gtkdnd.h> +#include <libgnomeui/gnome-canvas.h> +#include <libgnomeui/gnome-canvas-util.h> +#include <libgnomeui/gnome-canvas-polygon.h> +#include <libgnomeui/gnome-canvas-rect-ellipse.h> #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: * @@ -250,24 +255,6 @@ eti_request_redraw (ETableItem *eti) } /* - * 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 */ static int @@ -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; } @@ -541,32 +545,6 @@ eti_unrealize (GnomeCanvasItem *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) { ETableItem *eti = E_TABLE_ITEM (item); @@ -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 <miguel@gnu.org> + + * e-table-header.c (e_table_header_col_diff): fix this routine. + +1999-12-04 Miguel de Icaza <miguel@gnu.org> + + * 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 <miguel@gnu.org> + + * 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 <miguel@gnu.org> * 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 <config.h> #include <gtk/gtksignal.h> +#include <gtk/gtkdnd.h> +#include <libgnomeui/gnome-canvas.h> +#include <libgnomeui/gnome-canvas-util.h> +#include <libgnomeui/gnome-canvas-polygon.h> +#include <libgnomeui/gnome-canvas-rect-ellipse.h> #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: * @@ -250,24 +255,6 @@ eti_request_redraw (ETableItem *eti) } /* - * 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 */ static int @@ -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; } @@ -541,32 +545,6 @@ eti_unrealize (GnomeCanvasItem *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) { ETableItem *eti = E_TABLE_ITEM (item); @@ -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 <string.h> #include <fcntl.h> #include <gnome.h> +#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,14 +122,21 @@ 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 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); @@ -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 <string.h> #include <fcntl.h> #include <gnome.h> +#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 <config.h> #include <gtk/gtksignal.h> +#include <gtk/gtkdnd.h> +#include <libgnomeui/gnome-canvas.h> +#include <libgnomeui/gnome-canvas-util.h> +#include <libgnomeui/gnome-canvas-polygon.h> +#include <libgnomeui/gnome-canvas-rect-ellipse.h> #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: * @@ -250,24 +255,6 @@ eti_request_redraw (ETableItem *eti) } /* - * 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 */ static int @@ -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; } @@ -541,32 +545,6 @@ eti_unrealize (GnomeCanvasItem *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) { ETableItem *eti = E_TABLE_ITEM (item); @@ -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 <string.h> #include <fcntl.h> #include <gnome.h> +#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,14 +122,21 @@ 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 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); @@ -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,14 +122,21 @@ 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 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); @@ -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); + } |