aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--widgets/ChangeLog33
-rw-r--r--widgets/Makefile.am4
-rw-r--r--widgets/e-cell-text.c37
-rw-r--r--widgets/e-cell-toggle.c27
-rw-r--r--widgets/e-cell.c44
-rw-r--r--widgets/e-cell.h27
-rw-r--r--widgets/e-table-header-item.c316
-rw-r--r--widgets/e-table-header-item.h11
-rw-r--r--widgets/e-table-header.c25
-rw-r--r--widgets/e-table-header.h3
-rw-r--r--widgets/e-table-item.c115
-rw-r--r--widgets/e-table-item.h2
-rw-r--r--widgets/e-table-model.c11
-rw-r--r--widgets/e-table-model.h6
-rw-r--r--widgets/e-table-sorted.c2
-rw-r--r--widgets/e-table/ChangeLog33
-rw-r--r--widgets/e-table/Makefile.am4
-rw-r--r--widgets/e-table/e-cell-text.c37
-rw-r--r--widgets/e-table/e-cell-toggle.c27
-rw-r--r--widgets/e-table/e-cell.c44
-rw-r--r--widgets/e-table/e-cell.h27
-rw-r--r--widgets/e-table/e-table-header-item.c316
-rw-r--r--widgets/e-table/e-table-header-item.h11
-rw-r--r--widgets/e-table/e-table-header.c25
-rw-r--r--widgets/e-table/e-table-header.h3
-rw-r--r--widgets/e-table/e-table-item.c115
-rw-r--r--widgets/e-table/e-table-item.h2
-rw-r--r--widgets/e-table/e-table-model.c11
-rw-r--r--widgets/e-table/e-table-model.h6
-rw-r--r--widgets/e-table/e-table-sorted.c2
-rw-r--r--widgets/e-table/table-test.c2
-rw-r--r--widgets/e-table/test-check.c1
-rw-r--r--widgets/e-table/test-cols.c37
-rw-r--r--widgets/table-test.c2
-rw-r--r--widgets/table/e-cell-text.c37
-rw-r--r--widgets/table/e-cell-toggle.c27
-rw-r--r--widgets/table/e-cell.c44
-rw-r--r--widgets/table/e-cell.h27
-rw-r--r--widgets/table/e-table-header-item.c316
-rw-r--r--widgets/table/e-table-header-item.h11
-rw-r--r--widgets/table/e-table-header.c25
-rw-r--r--widgets/table/e-table-header.h3
-rw-r--r--widgets/table/e-table-item.c115
-rw-r--r--widgets/table/e-table-item.h2
-rw-r--r--widgets/table/e-table-model.c11
-rw-r--r--widgets/table/e-table-model.h6
-rw-r--r--widgets/table/e-table-sorted.c2
-rw-r--r--widgets/table/table-test.c2
-rw-r--r--widgets/table/test-check.c1
-rw-r--r--widgets/table/test-cols.c37
-rw-r--r--widgets/test-check.c1
-rw-r--r--widgets/test-cols.c37
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);
+
}