aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiguel de Icaza <miguel@gnu.org>1999-11-30 13:50:54 +0800
committerArturo Espinosa <unammx@src.gnome.org>1999-11-30 13:50:54 +0800
commitc50636dba333983e99deeb76338bbec3390a1fbe (patch)
treec89789be25d6ec51dfa37ea7051f203617439911
parent6e69c396983498a6ff78a33928ad5fec98c8513f (diff)
downloadgsoc2013-evolution-c50636dba333983e99deeb76338bbec3390a1fbe.tar
gsoc2013-evolution-c50636dba333983e99deeb76338bbec3390a1fbe.tar.gz
gsoc2013-evolution-c50636dba333983e99deeb76338bbec3390a1fbe.tar.bz2
gsoc2013-evolution-c50636dba333983e99deeb76338bbec3390a1fbe.tar.lz
gsoc2013-evolution-c50636dba333983e99deeb76338bbec3390a1fbe.tar.xz
gsoc2013-evolution-c50636dba333983e99deeb76338bbec3390a1fbe.tar.zst
gsoc2013-evolution-c50636dba333983e99deeb76338bbec3390a1fbe.zip
New file. Implement a multi-state image toggle cell object.
1999-11-29 Miguel de Icaza <miguel@gnu.org> * e-cell-toggle.c, e-cell-toggle.h: New file. Implement a multi-state image toggle cell object. * e-cell-text.c (ect_leave_edit): Handle the case of us calling leave edit manually. (ect_stop_editing): Leave manually editing here. (ect_draw): Add one pixel to the border for left and right; Handle off-screen cursor (must be improved). (ect_edit_select_all): New function. (ect_event): Select all text on editing start * e-table-item.c (eti_event): Map mouse events and dispatch them. (eti_event): Add spreadsheet mode for editing; Enter editing only with visual characters; Leave editing mode when a different row has been selected. (eti_get_height): Fix the computation for this; Fix logic for the length_threshold. (eti_draw): Add borders on all sides of the box; Only draw focus if the cell is not being edited. svn path=/trunk/; revision=1445
-rw-r--r--widgets/ChangeLog23
-rw-r--r--widgets/e-cell-checkbox.c185
-rw-r--r--widgets/e-cell-checkbox.h25
-rw-r--r--widgets/e-cell-text.c74
-rw-r--r--widgets/e-cell-toggle.c204
-rw-r--r--widgets/e-cell-toggle.h37
-rw-r--r--widgets/e-table-item.c177
-rw-r--r--widgets/e-table-item.h2
-rw-r--r--widgets/e-table/ChangeLog23
-rw-r--r--widgets/e-table/e-cell-checkbox.c185
-rw-r--r--widgets/e-table/e-cell-checkbox.h25
-rw-r--r--widgets/e-table/e-cell-text.c74
-rw-r--r--widgets/e-table/e-cell-toggle.c204
-rw-r--r--widgets/e-table/e-cell-toggle.h37
-rw-r--r--widgets/e-table/e-table-item.c177
-rw-r--r--widgets/e-table/e-table-item.h2
-rw-r--r--widgets/e-table/table-test.c1
-rw-r--r--widgets/table-test.c1
-rw-r--r--widgets/table/e-cell-checkbox.c185
-rw-r--r--widgets/table/e-cell-checkbox.h25
-rw-r--r--widgets/table/e-cell-text.c74
-rw-r--r--widgets/table/e-cell-toggle.c204
-rw-r--r--widgets/table/e-cell-toggle.h37
-rw-r--r--widgets/table/e-table-item.c177
-rw-r--r--widgets/table/e-table-item.h2
-rw-r--r--widgets/table/table-test.c1
26 files changed, 1993 insertions, 168 deletions
diff --git a/widgets/ChangeLog b/widgets/ChangeLog
index 7972994a79..fbb2ed0a86 100644
--- a/widgets/ChangeLog
+++ b/widgets/ChangeLog
@@ -1,3 +1,26 @@
+1999-11-29 Miguel de Icaza <miguel@gnu.org>
+
+ * e-cell-toggle.c, e-cell-toggle.h: New file. Implement a
+ multi-state image toggle cell object.
+
+ * e-cell-text.c (ect_leave_edit): Handle the case of us calling
+ leave edit manually.
+ (ect_stop_editing): Leave manually editing here.
+ (ect_draw): Add one pixel to the border for left and right;
+ Handle off-screen cursor (must be improved).
+ (ect_edit_select_all): New function.
+ (ect_event): Select all text on editing start
+
+ * e-table-item.c (eti_event): Map mouse events and dispatch them.
+ (eti_event): Add spreadsheet mode for editing; Enter editing only
+ with visual characters;
+ Leave editing mode when a different row has been selected.
+ (eti_get_height): Fix the computation for this; Fix logic for the
+ length_threshold.
+
+ (eti_draw): Add borders on all sides of the box;
+ Only draw focus if the cell is not being edited.
+
1999-11-28 Miguel de Icaza <miguel@gnu.org>
* e-table-item.c (eti_draw): Focus inside, not outside.
diff --git a/widgets/e-cell-checkbox.c b/widgets/e-cell-checkbox.c
new file mode 100644
index 0000000000..db74464d5c
--- /dev/null
+++ b/widgets/e-cell-checkbox.c
@@ -0,0 +1,185 @@
+/*
+ * e-cell-checkbox.c: Checkbox cell renderer
+ *
+ * Author:
+ * Miguel de Icaza (miguel@kernel.org)
+ *
+ * (C) 1999 Helix Code, Inc
+ */
+#include <config.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <libgnomeui/gnome-canvas.h>
+#include "e-cell-checkbox.h"
+#include "e-util.h"
+#include "e-table-item.h"
+
+#define PARENT_TYPE e_cell_get_type()
+
+typedef struct {
+ ECellView cell_view;
+ GdkGC *gc;
+ GnomeCanvas *canvas;
+ ETableItem *eti;
+} ECellCheckboxView;
+
+static ECellClass *parent_class;
+
+static void
+eccb_queue_redraw (ECellCheckboxView *text_view, int col, int row)
+{
+ e_table_item_redraw_range (text_view->eti, col, row, col, row);
+}
+
+/*
+ * ECell::realize method
+ */
+static ECellView *
+eecb_realize (ECell *ecell, void *view)
+{
+ ECellCheckbox *eccb = E_CELL_CHECKBOX (ecell);
+ ECellCheckboxView *check_view = g_new0 (ECellCheckboxView, 1);
+ ETableItem *eti = E_TABLE_ITEM (view);
+ GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
+
+ check_view->cell_view.ecell = ecell;
+ check_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window);
+ check_view->eti = eti;
+ check_view->canvas = canvas;
+
+ return (ECellView *) check_view;
+}
+
+/*
+ * ECell::unrealize method
+ */
+static void
+eecb_unrealize (ECellView *ecv)
+{
+ ECellCheckboxView *check_view = (ECellCheckboxView *) ecv;
+
+ gdk_gc_unref (check_view->gc);
+ text_view->gc = NULL;
+
+ g_free (check_view);
+}
+
+/*
+ * ECell::draw method
+ */
+static void
+eecb_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int col, int row, gboolean selected,
+ int x1, int y1, int x2, int y2)
+{
+}
+
+/*
+ * ECell::event method
+ */
+static gint
+eecb_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
+{
+ ECellCheckboxView *text_view = (ECellCheckboxView *) ecell_view;
+
+ switch (event->type){
+ case GDK_BUTTON_PRESS:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+
+ printf ("Button pressed at %g %g\n", event->button.x, event->button.y);
+ if (text_view->edit){
+ printf ("FIXME: Should handle click here\n");
+ } else
+ e_table_item_enter_edit (text_view->eti, col, row);
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+ printf ("Button released at %g %g\n", event->button.x, event->button.y);
+ return TRUE;
+
+ case GDK_KEY_PRESS:
+ if (event->key.keyval == GDK_Escape){
+ eecb_cancel_edit (text_view);
+ return TRUE;
+ }
+
+ if (!text_view->edit){
+ e_table_item_enter_edit (text_view->eti, col, row);
+ eecb_edit_seleecb_all (text_view);
+ }
+
+ gtk_widget_event (GTK_WIDGET (text_view->edit->entry), event);
+ eecb_queue_redraw (text_view, col, row);
+ break;
+
+ case GDK_KEY_RELEASE:
+ break;
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * ECell::height method
+ */
+static int
+eecb_height (ECellView *ecell_view, int col, int row)
+{
+ return 10;
+}
+
+/*
+ * ECellView::enter_edit method
+ */
+static void *
+eecb_enter_edit (ECellView *ecell_view, int col, int row)
+{
+}
+
+/*
+ * ECellView::leave_edit method
+ */
+static void
+eecb_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context)
+{
+}
+
+static void
+e_cell_checkbox_class_init (GtkObjectClass *object_class)
+{
+ ECellClass *ecc = (ECellClass *) object_class;
+
+ ecc->realize = eecb_realize;
+ ecc->unrealize = eecb_unrealize;
+ ecc->draw = eecb_draw;
+ ecc->event = eecb_event;
+ ecc->height = eecb_height;
+ ecc->enter_edit = eecb_enter_edit;
+ ecc->leave_edit = eecb_leave_edit;
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+}
+
+E_MAKE_TYPE(e_cell_text, "ECellCheckbox", ECellCheckbox, e_cell_checkbox_class_init, NULL, PARENT_TYPE);
+
+ECell *
+e_cell_checkbox_new (ETableModel *etm)
+{
+ ECellCheckbox *eccb = gtk_type_new (e_cell_checkbox_get_type ());
+
+ E_CELL (eccb)->table_model = etm;
+
+ return (ECell *) eccb;
+}
diff --git a/widgets/e-cell-checkbox.h b/widgets/e-cell-checkbox.h
new file mode 100644
index 0000000000..6c85fbff21
--- /dev/null
+++ b/widgets/e-cell-checkbox.h
@@ -0,0 +1,25 @@
+#ifndef _E_CELL_CHECKBOX_H_
+#define _E_CELL_CHECKBOX_H_
+
+#include <libgnomeui/gnome-canvas.h>
+#include "e-cell.h"
+
+#define E_CELL_CHECKBOX_TYPE (e_cell_checkbox_get_type ())
+#define E_CELL_CHECKBOX(o) (GTK_CHECK_CAST ((o), E_CELL_CHECKBOX_TYPE, ECellCheckbox))
+#define E_CELL_CHECKBOX_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_CHECKBOX_TYPE, ECellCheckboxClass))
+#define E_IS_CELL_CHECKBOX(o) (GTK_CHECK_TYPE ((o), E_CELL_CHECKBOX_TYPE))
+#define E_IS_CELL_CHECKBOX_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_CHECKBOX_TYPE))
+
+typedef struct {
+ ECell parent;
+} ECellCheckbox;
+
+typedef struct {
+ ECellClass parent_class;
+} ECellCheckboxClass;
+
+GtkType e_cell_checkbox_get_type (void);
+ECell *e_cell_checkbox_new (ETableModel *model);
+
+#endif /* _E_CELL_CHECKBOX_H_ */
+
diff --git a/widgets/e-cell-text.c b/widgets/e-cell-text.c
index f0501ab4cb..b18c179ca5 100644
--- a/widgets/e-cell-text.c
+++ b/widgets/e-cell-text.c
@@ -82,6 +82,8 @@ ect_stop_editing (ECellTextView *text_view)
g_free (edit);
text_view->edit = NULL;
+
+ e_table_item_leave_edit (text_view->eti);
}
/*
@@ -166,8 +168,6 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
if (text_view->edit){
CellEdit *edit = text_view->edit;
- printf ("We are editing a cell [%d %d %d %d]\n", col, row, edit->col, edit->row);
-
if ((edit->col == col) && (edit->row == row))
edit_display = TRUE;
}
@@ -192,11 +192,6 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
text_wc [text_wc_len] = 0;
/*
- * Find a good spot for painting
- */
- xoff = 0;
-
- /*
* Paint
*/
gdk_gc_set_foreground (text_view->gc, &w->style->base [GTK_STATE_NORMAL]);
@@ -208,11 +203,23 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
GdkGC *gc = text_view->gc;
const int y = y2 - font->descent - ((y2-y1-height)/2);
int px, i;
+
+ /*
+ * Border
+ */
+ x1 += 2;
+ x2--;
px = x1;
- printf ("Cursor at: %d\n", cursor_pos);
-
+ /*
+ * If the cursor is outside the visible range
+ *
+ * FIXME: we really want a better behaviour.
+ */
+ if ((px + left_len) > x2)
+ px -= left_len - (x2-x1);
+
for (i = 0; *text_wc; text_wc++, i++){
gdk_draw_text_wc (
drawable, font, gc, px, y, text_wc, 1);
@@ -240,6 +247,12 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
*/
GdkColor *background, *foreground;
int width;
+
+ /*
+ * Border
+ */
+ x1++;
+ x2--;
/*
* Compute draw mode
@@ -285,6 +298,17 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
}
/*
+ * Selects the entire string
+ */
+static void
+ect_edit_select_all (ECellTextView *text_view)
+{
+ g_assert (text_view->edit);
+
+ gtk_editable_select_region (GTK_EDITABLE (text_view->edit->entry), 0, -1);
+}
+
+/*
* ECell::event method
*/
static gint
@@ -294,6 +318,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
switch (event->type){
case GDK_BUTTON_PRESS:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+
+ printf ("Button pressed at %g %g\n", event->button.x, event->button.y);
if (text_view->edit){
printf ("FIXME: Should handle click here\n");
} else
@@ -301,6 +331,11 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
break;
case GDK_BUTTON_RELEASE:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+ printf ("Button released at %g %g\n", event->button.x, event->button.y);
return TRUE;
case GDK_KEY_PRESS:
@@ -309,8 +344,10 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
return TRUE;
}
- if (!text_view->edit)
+ if (!text_view->edit){
e_table_item_enter_edit (text_view->eti, 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);
@@ -355,10 +392,11 @@ ect_enter_edit (ECellView *ecell_view, int col, int row)
const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row);
CellEdit *edit;
- printf ("Entering edit mode! [%d %d]\n", col, row);
-
edit = g_new (CellEdit, 1);
text_view->edit = edit;
+
+ edit->col = col;
+ edit->row = row;
edit->entry = (GtkEntry *) gtk_entry_new ();
gtk_entry_set_text (edit->entry, str);
@@ -387,10 +425,14 @@ ect_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context)
{
ECellTextView *text_view = (ECellTextView *) ecell_view;
- printf ("Leaving edit mode!\n");
-
- ect_accept_edits (text_view);
- ect_stop_editing (text_view);
+ if (text_view->edit){
+ ect_accept_edits (text_view);
+ ect_stop_editing (text_view);
+ } else {
+ /*
+ * We did invoke this leave edit internally
+ */
+ }
}
/*
diff --git a/widgets/e-cell-toggle.c b/widgets/e-cell-toggle.c
new file mode 100644
index 0000000000..33e4d283ee
--- /dev/null
+++ b/widgets/e-cell-toggle.c
@@ -0,0 +1,204 @@
+/*
+ * e-cell-toggle.c: Multi-state image toggle cell object.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@kernel.org)
+ *
+ * (C) 1999 Helix Code, Inc
+ */
+#include <config.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <libgnomeui/gnome-canvas.h>
+#include "e-cell-toggle.h"
+#include "e-util.h"
+#include "e-table-item.h"
+
+#define PARENT_TYPE e_cell_get_type()
+
+Typedef struct {
+ ECellView cell_view;
+ GdkGC *gc;
+ GnomeCanvas *canvas;
+ ETableItem *eti;
+} ECellToggleView;
+
+static ECellClass *parent_class;
+
+static void
+etog_queue_redraw (ECellToggleView *text_view, int col, int row)
+{
+ e_table_item_redraw_range (text_view->eti, col, row, col, row);
+}
+
+/*
+ * ECell::realize method
+ */
+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;
+
+ toggle_view->cell_view.ecell = ecell;
+ toggle_view->eti = eti;
+ toggle_view->canvas = canvas;
+
+ return (ECellView *) toggle_view;
+}
+
+/*
+ * ECell::unrealize method
+ */
+static void
+etog_unrealize (ECellView *ecv)
+{
+ ECellToggleView *toggle_view = (ECellToggleView *) ecv;
+
+ g_free (toggle_view);
+}
+
+/*
+ * ECell::draw method
+ */
+static void
+etog_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int col, int row, gboolean selected,
+ int x1, int y1, int x2, int y2)
+{
+ ECellToggle *toggle = E_CELL_TOGGLE (e_cell_view->ecell);
+ ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
+ GdkPixbuf *image;
+ const int value = e_table_model_value_at (ecell_view->ecell->table_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",
+ value, toggle->n_states);
+ return;
+ }
+
+ image = toggle->images [value];
+
+}
+
+static void
+etog_set_value (ECellToggleView *toggle_view, int col, int row, int value)
+{
+ ECell *ecell = toggle_view->cell_view.ecell
+ ECellToggle *toggle = E_CELL_TOGGLE (ecell);
+
+ if (value >= toggle->n_vals)
+ value = 0;
+
+ e_table_model_set_value_at (ecell->table_model, col, row, value);
+ etog_queue_redraw (toggle_view, col, row);
+}
+
+/*
+ * ECell::event method
+ */
+static gint
+etog_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
+{
+ ECellToggle *toggle = E_CELL_TOGGLE (e_cell_view->ecell);
+ ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
+ int value = e_table_model_value_at (e_cell_view->ecell->table_model, col, row);
+
+ switch (event->type){
+ case GDK_BUTTON_RELEASE:
+ etog_set_value (toggle_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);
+ return TRUE;
+ }
+ return FALSE;
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * ECell::height method
+ */
+static int
+etog_height (ECellView *ecell_view, int col, int row)
+{
+ ECellToggle *toggle = E_CELL_TOGGLE (e_cell_view->ecell);
+
+ return toggle->height;
+}
+
+static void
+etog_destroy (GtkObject *object)
+{
+ ECellToggle *etog = E_CELL_TOGGLE (object);
+ int i;
+
+ for (i = 0; i < etog->n_states; i++)
+ gdk_pixbuf_unref (etog->images [i]);
+
+ g_free (etog->images);
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+e_cell_toggle_class_init (GtkObjectClass *object_class)
+{
+ ECellClass *ecc = (ECellClass *) object_class;
+
+ object_class->destroy = etog_destroy;
+
+ ecc->realize = etog_realize;
+ ecc->unrealize = etog_unrealize;
+ ecc->draw = etog_draw;
+ ecc->event = etog_event;
+ ecc->height = etog_height;
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+}
+
+E_MAKE_TYPE(e_cell_text, "ECellToggle", ECellToggle, e_cell_toggle_class_init, NULL, PARENT_TYPE);
+
+void
+e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_states, GdkPixbuf **images)
+{
+ int max_height = 0;
+
+ E_CELL (etog)->table_model = etm;
+
+ etog->border = border;
+ etog->n_states = n_states;
+
+ etog->images = g_new (GdkPixbuf *, n_states);
+
+ for (i = 0; i < n_states; i++){
+ etog->images [i] = images [i];
+ gdk_pixbuf_ref (images [i]);
+
+ if (images [i]->art_pixbuf->height > max_height)
+ max_height = images [i]->art_pixbuf->height;
+ }
+
+ etog->height = max_height;
+}
+
+ECell *
+e_cell_toggle_new (ETableModel *etm, int border, int n_states, GdkPixbuf **images)
+{
+ ECellToggle *etog = gtk_type_new (e_cell_toggle_get_type ());
+
+ e_cell_toggle_construct (etog, etm, border, n_states, images);
+
+ return (ECell *) etog;
+}
diff --git a/widgets/e-cell-toggle.h b/widgets/e-cell-toggle.h
new file mode 100644
index 0000000000..3cd99f5d04
--- /dev/null
+++ b/widgets/e-cell-toggle.h
@@ -0,0 +1,37 @@
+#ifndef _E_CELL_TOGGLE_H_
+#define _E_CELL_TOGGLE_H_
+
+#include <libgnomeui/gnome-canvas.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "e-cell.h"
+
+#define E_CELL_TOGGLE_TYPE (e_cell_toggle_get_type ())
+#define E_CELL_TOGGLE(o) (GTK_CHECK_CAST ((o), E_CELL_TOGGLE_TYPE, ECellToggle))
+#define E_CELL_TOGGLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_TOGGLE_TYPE, ECellToggleClass))
+#define E_IS_CELL_TOGGLE(o) (GTK_CHECK_TYPE ((o), E_CELL_TOGGLE_TYPE))
+#define E_IS_CELL_TOGGLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_TOGGLE_TYPE))
+
+typedef struct {
+ ECell parent;
+
+ int border;
+ int n_states;
+ GdkPixbuf **images;
+
+ int height;
+} ECellToggle;
+
+typedef struct {
+ ECellClass parent_class;
+} ECellToggleClass;
+
+GtkType e_cell_toggle_get_type (void);
+ECell *e_cell_toggle_new (ETableModel *model, int border,
+ int n_states,
+ GdkPibux **images);
+void e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm,
+ int border, int n_states, GdkPixbuf **images);
+
+#endif /* _E_CELL_TOGGLE_H_ */
+
+
diff --git a/widgets/e-table-item.c b/widgets/e-table-item.c
index 5816acfb23..ceb6adda95 100644
--- a/widgets/e-table-item.c
+++ b/widgets/e-table-item.c
@@ -38,9 +38,19 @@ enum {
ARG_TABLE_Y,
ARG_TABLE_DRAW_GRID,
ARG_TABLE_DRAW_FOCUS,
+ ARG_MODE_SPREADSHEET,
ARG_LENGHT_THRESHOLD
};
+static gboolean
+eti_editing (ETableItem *eti)
+{
+ if (eti->editing_col == -1)
+ return FALSE;
+ else
+ return TRUE;
+}
+
/*
* During realization, we have to invoke the per-ecell realize routine
* (On our current setup, we have one e-cell per column.
@@ -186,23 +196,26 @@ eti_get_height (ETableItem *eti)
{
const int rows = eti->rows;
int row;
- int height = 0;
+ int height;
if (rows == 0)
return 0;
-
- if (rows > eti->length_threshold){
- height = eti_row_height (eti, 0) * rows;
- return height;
+ if (eti->length_threshold != -1){
+ if (rows > eti->length_threshold){
+ height = (eti_row_height (eti, 0) + 1) * rows;
+
+ /*
+ * 1 pixel at the top
+ */
+ return height + 1;
+ }
}
-
+
+ height = 1;
for (row = 0; row < rows; row++)
- height += eti_row_height (eti, row);
+ height += eti_row_height (eti, row) + 1;
- /* Add division lines pixels */
- height += rows;
-
return height;
}
@@ -434,6 +447,10 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
case ARG_TABLE_DRAW_FOCUS:
eti->draw_focus = GTK_VALUE_BOOL (*arg);
break;
+
+ case ARG_MODE_SPREADSHEET:
+ eti->mode_spreadsheet = GTK_VALUE_BOOL (*arg);
+ break;
}
eti_update (item, NULL, NULL, 0);
}
@@ -445,6 +462,8 @@ eti_init (GnomeCanvasItem *item)
eti->focused_col = -1;
eti->focused_row = -1;
+ eti->editing_col = -1;
+ eti->editing_row = -1;
eti->height = 0;
eti->length_threshold = -1;
@@ -476,8 +495,12 @@ eti_realize (GnomeCanvasItem *item)
gdk_gc_ref (canvas_widget->style->white_gc);
eti->grid_gc = gdk_gc_new (window);
- gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]);
-
+#if 0
+ /* This sets it to gray */
+/* gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]); */
+#else
+ gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->black);
+#endif
eti->focus_gc = gdk_gc_new (window);
gdk_gc_set_foreground (eti->focus_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]);
gdk_gc_set_background (eti->focus_gc, &canvas_widget->style->fg [GTK_STATE_NORMAL]);
@@ -560,9 +583,11 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
/*
* Clear the background
*/
+#if 0
gdk_draw_rectangle (
drawable, eti->fill_gc, TRUE,
eti->x1 - x, eti->y1 - y, eti->width, eti->height);
+#endif
/*
* First column to draw, last column to draw
@@ -597,8 +622,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
*/
first_row = -1;
y_offset = 0;
- y1 = y2 = eti->y1;
- for (row = eti->top_item; row < rows; row++, y1 = y2){
+ y1 = y2 = eti->y1 + 1;
+ for (row = 0; row < rows; row++, y1 = y2){
y2 += eti_row_height (eti, row) + 1;
@@ -624,6 +649,14 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
yd = y_offset;
f_x1 = f_x2 = f_y1 = f_y2 = -1;
f_found = FALSE;
+
+ if (eti->draw_grid && first_row == 0){
+ gdk_draw_line (
+ drawable, eti->grid_gc,
+ eti->x1 - x, yd, eti->x1 + eti->width - x, yd);
+ }
+ yd++;
+
for (row = first_row; row < last_row; row++){
int xd, height;
gboolean selected;
@@ -650,25 +683,30 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
xd += ecol->width;
}
- yd += height + 1;
+ yd += height;
if (eti->draw_grid)
gdk_draw_line (
drawable, eti->grid_gc,
- eti->x1 - x, yd -1, eti->x1 + eti->width - x, yd -1);
+ eti->x1 - x, yd, eti->x1 + eti->width - x, yd);
+ yd++;
}
if (eti->draw_grid){
int xd = x_offset;
- for (col = first_col; col < last_col; col++){
+ for (col = first_col; col <= last_col; col++){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
gdk_draw_line (
drawable, eti->grid_gc,
- xd, y_offset, xd, yd);
+ xd, y_offset, xd, yd - 1);
- xd += ecol->width;
+ /*
+ * This looks wierd, but it is to draw the last line
+ */
+ if (ecol)
+ xd += ecol->width;
}
}
@@ -676,9 +714,11 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
* Draw focus
*/
if (f_found && eti->draw_focus){
- gdk_draw_rectangle (
- drawable, eti->focus_gc, FALSE,
- f_x1 + 1, f_y1, f_x2 - f_x1 - 2, f_y2 - f_y1 - 1);
+
+ if (!eti_editing (eti))
+ gdk_draw_rectangle (
+ drawable, eti->focus_gc, FALSE,
+ f_x1 + 1, f_y1, f_x2 - f_x1 - 2, f_y2 - f_y1 - 1);
}
}
@@ -692,14 +732,14 @@ eti_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
}
static gboolean
-find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
+find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res, gdouble *x1_res, gdouble *y1_res)
{
const int cols = eti->cols;
const int rows = eti->rows;
gdouble x1, y1, x2, y2;
int col, row;
- /* FIXME: inneficient, fix later */
+ /* FIXME: this routine is inneficient, fix later */
x -= eti->x1;
y -= eti->y1;
@@ -717,6 +757,8 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
continue;
*col_res = col;
+ if (x1_res)
+ *x1_res = x - x1;
break;
}
@@ -731,6 +773,8 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
continue;
*row_res = row;
+ if (y1_res)
+ *y1_res = y - y1;
break;
}
@@ -748,63 +792,113 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
case GDK_BUTTON_RELEASE:
case GDK_2BUTTON_PRESS: {
int col, row;
+ gdouble x1, y1;
- if (!find_cell (eti, e->button.x, e->button.y, &col, &row))
+ if (!find_cell (eti, e->button.x, e->button.y, &col, &row, &x1, &y1))
return TRUE;
if (eti->focused_row == row && eti->focused_col == col){
ecell_view = eti->cell_views [col];
+ /*
+ * Adjust the event positions
+ */
+ e->button.x = x1;
+ e->button.y = y1;
+
e_cell_event (ecell_view, e, col, row);
} else {
/*
* Focus the cell, and select the row
*/
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, col, row);
e_table_item_select_row (eti, row);
}
break;
}
+
+ case GDK_MOTION_NOTIFY: {
+ int col, row;
+ double x1, y1;
+
+ if (!find_cell (eti, e->button.x, e->button.y, &col, &row, &x1, &y1))
+ return TRUE;
+
+ if (eti->focused_row == row && eti->focused_col == col){
+ ecell_view = eti->cell_views [col];
+
+ /*
+ * Adjust the event positions
+ */
+ e->button.x -= (x1 + eti->x1);
+ e->button.y -= (y1 + eti->y1);
+
+ e_cell_event (ecell_view, e, col, row);
+ }
+ break;
+ }
case GDK_KEY_PRESS:
- printf ("KEYPRESS!\n");
-
if (eti->focused_col == -1)
return FALSE;
switch (e->key.keyval){
case GDK_Left:
- if (eti->focused_col > 0)
+ if (!eti->mode_spreadsheet && eti_editing (eti))
+ break;
+
+ if (eti->focused_col > 0){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row);
- break;
+ }
+ return TRUE;
case GDK_Right:
- if ((eti->focused_col + 1) < eti->cols)
+ if (!eti->mode_spreadsheet && eti_editing (eti))
+ break;
+
+ if ((eti->focused_col + 1) < eti->cols){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row);
- break;
+ }
+ return TRUE;
case GDK_Up:
- if (eti->focused_row > 0)
+ if (eti->focused_row > 0){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1);
- break;
+ }
+ return TRUE;
case GDK_Down:
- if ((eti->focused_row + 1) < eti->rows)
+ if ((eti->focused_row + 1) < eti->rows){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1);
- break;
-
+ }
+ return TRUE;
default:
+ if (!eti_editing (eti)){
+ if ((e->key.state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)) != 0)
+ return 0;
+
+ if (!(e->key.keyval >= 0x20 && e->key.keyval <= 0xff))
+ return 0;
+ }
}
+
ecell_view = eti->cell_views [eti->focused_col];
e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
break;
-
+
case GDK_KEY_RELEASE:
if (eti->focused_col == -1)
return FALSE;
- ecell_view = eti->cell_views [eti->focused_col];
- e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
+ if (eti_editing (eti)){
+ ecell_view = eti->cell_views [eti->editing_col];
+ e_cell_event (ecell_view, e, eti->editing_col, eti->editing_row);
+ }
break;
default:
@@ -860,6 +954,8 @@ eti_class_init (GtkObjectClass *object_class)
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID);
gtk_object_add_arg_type ("ETableItem::drawfocus", GTK_TYPE_BOOL,
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_FOCUS);
+ gtk_object_add_arg_type ("ETableItem::spreadsheet", GTK_TYPE_BOOL,
+ GTK_ARG_WRITABLE, ARG_MODE_SPREADSHEET);
eti_signals [ROW_SELECTION] =
gtk_signal_new ("row_selection",
@@ -1044,6 +1140,9 @@ e_table_item_leave_edit (ETableItem *eti)
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);
eti->editing_col = -1;
eti->editing_row = -1;
diff --git a/widgets/e-table-item.h b/widgets/e-table-item.h
index 3f3d2a7d4d..6c4d837310 100644
--- a/widgets/e-table-item.h
+++ b/widgets/e-table-item.h
@@ -19,7 +19,6 @@ typedef struct {
int x1, y1;
int width, height;
- int top_item;
int cols, rows;
/*
@@ -36,6 +35,7 @@ typedef struct {
unsigned int draw_grid:1;
unsigned int draw_focus:1;
+ unsigned int mode_spreadsheet:1;
int focused_col, focused_row;
diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog
index 7972994a79..fbb2ed0a86 100644
--- a/widgets/e-table/ChangeLog
+++ b/widgets/e-table/ChangeLog
@@ -1,3 +1,26 @@
+1999-11-29 Miguel de Icaza <miguel@gnu.org>
+
+ * e-cell-toggle.c, e-cell-toggle.h: New file. Implement a
+ multi-state image toggle cell object.
+
+ * e-cell-text.c (ect_leave_edit): Handle the case of us calling
+ leave edit manually.
+ (ect_stop_editing): Leave manually editing here.
+ (ect_draw): Add one pixel to the border for left and right;
+ Handle off-screen cursor (must be improved).
+ (ect_edit_select_all): New function.
+ (ect_event): Select all text on editing start
+
+ * e-table-item.c (eti_event): Map mouse events and dispatch them.
+ (eti_event): Add spreadsheet mode for editing; Enter editing only
+ with visual characters;
+ Leave editing mode when a different row has been selected.
+ (eti_get_height): Fix the computation for this; Fix logic for the
+ length_threshold.
+
+ (eti_draw): Add borders on all sides of the box;
+ Only draw focus if the cell is not being edited.
+
1999-11-28 Miguel de Icaza <miguel@gnu.org>
* e-table-item.c (eti_draw): Focus inside, not outside.
diff --git a/widgets/e-table/e-cell-checkbox.c b/widgets/e-table/e-cell-checkbox.c
new file mode 100644
index 0000000000..db74464d5c
--- /dev/null
+++ b/widgets/e-table/e-cell-checkbox.c
@@ -0,0 +1,185 @@
+/*
+ * e-cell-checkbox.c: Checkbox cell renderer
+ *
+ * Author:
+ * Miguel de Icaza (miguel@kernel.org)
+ *
+ * (C) 1999 Helix Code, Inc
+ */
+#include <config.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <libgnomeui/gnome-canvas.h>
+#include "e-cell-checkbox.h"
+#include "e-util.h"
+#include "e-table-item.h"
+
+#define PARENT_TYPE e_cell_get_type()
+
+typedef struct {
+ ECellView cell_view;
+ GdkGC *gc;
+ GnomeCanvas *canvas;
+ ETableItem *eti;
+} ECellCheckboxView;
+
+static ECellClass *parent_class;
+
+static void
+eccb_queue_redraw (ECellCheckboxView *text_view, int col, int row)
+{
+ e_table_item_redraw_range (text_view->eti, col, row, col, row);
+}
+
+/*
+ * ECell::realize method
+ */
+static ECellView *
+eecb_realize (ECell *ecell, void *view)
+{
+ ECellCheckbox *eccb = E_CELL_CHECKBOX (ecell);
+ ECellCheckboxView *check_view = g_new0 (ECellCheckboxView, 1);
+ ETableItem *eti = E_TABLE_ITEM (view);
+ GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
+
+ check_view->cell_view.ecell = ecell;
+ check_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window);
+ check_view->eti = eti;
+ check_view->canvas = canvas;
+
+ return (ECellView *) check_view;
+}
+
+/*
+ * ECell::unrealize method
+ */
+static void
+eecb_unrealize (ECellView *ecv)
+{
+ ECellCheckboxView *check_view = (ECellCheckboxView *) ecv;
+
+ gdk_gc_unref (check_view->gc);
+ text_view->gc = NULL;
+
+ g_free (check_view);
+}
+
+/*
+ * ECell::draw method
+ */
+static void
+eecb_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int col, int row, gboolean selected,
+ int x1, int y1, int x2, int y2)
+{
+}
+
+/*
+ * ECell::event method
+ */
+static gint
+eecb_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
+{
+ ECellCheckboxView *text_view = (ECellCheckboxView *) ecell_view;
+
+ switch (event->type){
+ case GDK_BUTTON_PRESS:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+
+ printf ("Button pressed at %g %g\n", event->button.x, event->button.y);
+ if (text_view->edit){
+ printf ("FIXME: Should handle click here\n");
+ } else
+ e_table_item_enter_edit (text_view->eti, col, row);
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+ printf ("Button released at %g %g\n", event->button.x, event->button.y);
+ return TRUE;
+
+ case GDK_KEY_PRESS:
+ if (event->key.keyval == GDK_Escape){
+ eecb_cancel_edit (text_view);
+ return TRUE;
+ }
+
+ if (!text_view->edit){
+ e_table_item_enter_edit (text_view->eti, col, row);
+ eecb_edit_seleecb_all (text_view);
+ }
+
+ gtk_widget_event (GTK_WIDGET (text_view->edit->entry), event);
+ eecb_queue_redraw (text_view, col, row);
+ break;
+
+ case GDK_KEY_RELEASE:
+ break;
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * ECell::height method
+ */
+static int
+eecb_height (ECellView *ecell_view, int col, int row)
+{
+ return 10;
+}
+
+/*
+ * ECellView::enter_edit method
+ */
+static void *
+eecb_enter_edit (ECellView *ecell_view, int col, int row)
+{
+}
+
+/*
+ * ECellView::leave_edit method
+ */
+static void
+eecb_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context)
+{
+}
+
+static void
+e_cell_checkbox_class_init (GtkObjectClass *object_class)
+{
+ ECellClass *ecc = (ECellClass *) object_class;
+
+ ecc->realize = eecb_realize;
+ ecc->unrealize = eecb_unrealize;
+ ecc->draw = eecb_draw;
+ ecc->event = eecb_event;
+ ecc->height = eecb_height;
+ ecc->enter_edit = eecb_enter_edit;
+ ecc->leave_edit = eecb_leave_edit;
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+}
+
+E_MAKE_TYPE(e_cell_text, "ECellCheckbox", ECellCheckbox, e_cell_checkbox_class_init, NULL, PARENT_TYPE);
+
+ECell *
+e_cell_checkbox_new (ETableModel *etm)
+{
+ ECellCheckbox *eccb = gtk_type_new (e_cell_checkbox_get_type ());
+
+ E_CELL (eccb)->table_model = etm;
+
+ return (ECell *) eccb;
+}
diff --git a/widgets/e-table/e-cell-checkbox.h b/widgets/e-table/e-cell-checkbox.h
new file mode 100644
index 0000000000..6c85fbff21
--- /dev/null
+++ b/widgets/e-table/e-cell-checkbox.h
@@ -0,0 +1,25 @@
+#ifndef _E_CELL_CHECKBOX_H_
+#define _E_CELL_CHECKBOX_H_
+
+#include <libgnomeui/gnome-canvas.h>
+#include "e-cell.h"
+
+#define E_CELL_CHECKBOX_TYPE (e_cell_checkbox_get_type ())
+#define E_CELL_CHECKBOX(o) (GTK_CHECK_CAST ((o), E_CELL_CHECKBOX_TYPE, ECellCheckbox))
+#define E_CELL_CHECKBOX_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_CHECKBOX_TYPE, ECellCheckboxClass))
+#define E_IS_CELL_CHECKBOX(o) (GTK_CHECK_TYPE ((o), E_CELL_CHECKBOX_TYPE))
+#define E_IS_CELL_CHECKBOX_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_CHECKBOX_TYPE))
+
+typedef struct {
+ ECell parent;
+} ECellCheckbox;
+
+typedef struct {
+ ECellClass parent_class;
+} ECellCheckboxClass;
+
+GtkType e_cell_checkbox_get_type (void);
+ECell *e_cell_checkbox_new (ETableModel *model);
+
+#endif /* _E_CELL_CHECKBOX_H_ */
+
diff --git a/widgets/e-table/e-cell-text.c b/widgets/e-table/e-cell-text.c
index f0501ab4cb..b18c179ca5 100644
--- a/widgets/e-table/e-cell-text.c
+++ b/widgets/e-table/e-cell-text.c
@@ -82,6 +82,8 @@ ect_stop_editing (ECellTextView *text_view)
g_free (edit);
text_view->edit = NULL;
+
+ e_table_item_leave_edit (text_view->eti);
}
/*
@@ -166,8 +168,6 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
if (text_view->edit){
CellEdit *edit = text_view->edit;
- printf ("We are editing a cell [%d %d %d %d]\n", col, row, edit->col, edit->row);
-
if ((edit->col == col) && (edit->row == row))
edit_display = TRUE;
}
@@ -192,11 +192,6 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
text_wc [text_wc_len] = 0;
/*
- * Find a good spot for painting
- */
- xoff = 0;
-
- /*
* Paint
*/
gdk_gc_set_foreground (text_view->gc, &w->style->base [GTK_STATE_NORMAL]);
@@ -208,11 +203,23 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
GdkGC *gc = text_view->gc;
const int y = y2 - font->descent - ((y2-y1-height)/2);
int px, i;
+
+ /*
+ * Border
+ */
+ x1 += 2;
+ x2--;
px = x1;
- printf ("Cursor at: %d\n", cursor_pos);
-
+ /*
+ * If the cursor is outside the visible range
+ *
+ * FIXME: we really want a better behaviour.
+ */
+ if ((px + left_len) > x2)
+ px -= left_len - (x2-x1);
+
for (i = 0; *text_wc; text_wc++, i++){
gdk_draw_text_wc (
drawable, font, gc, px, y, text_wc, 1);
@@ -240,6 +247,12 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
*/
GdkColor *background, *foreground;
int width;
+
+ /*
+ * Border
+ */
+ x1++;
+ x2--;
/*
* Compute draw mode
@@ -285,6 +298,17 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
}
/*
+ * Selects the entire string
+ */
+static void
+ect_edit_select_all (ECellTextView *text_view)
+{
+ g_assert (text_view->edit);
+
+ gtk_editable_select_region (GTK_EDITABLE (text_view->edit->entry), 0, -1);
+}
+
+/*
* ECell::event method
*/
static gint
@@ -294,6 +318,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
switch (event->type){
case GDK_BUTTON_PRESS:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+
+ printf ("Button pressed at %g %g\n", event->button.x, event->button.y);
if (text_view->edit){
printf ("FIXME: Should handle click here\n");
} else
@@ -301,6 +331,11 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
break;
case GDK_BUTTON_RELEASE:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+ printf ("Button released at %g %g\n", event->button.x, event->button.y);
return TRUE;
case GDK_KEY_PRESS:
@@ -309,8 +344,10 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
return TRUE;
}
- if (!text_view->edit)
+ if (!text_view->edit){
e_table_item_enter_edit (text_view->eti, 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);
@@ -355,10 +392,11 @@ ect_enter_edit (ECellView *ecell_view, int col, int row)
const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row);
CellEdit *edit;
- printf ("Entering edit mode! [%d %d]\n", col, row);
-
edit = g_new (CellEdit, 1);
text_view->edit = edit;
+
+ edit->col = col;
+ edit->row = row;
edit->entry = (GtkEntry *) gtk_entry_new ();
gtk_entry_set_text (edit->entry, str);
@@ -387,10 +425,14 @@ ect_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context)
{
ECellTextView *text_view = (ECellTextView *) ecell_view;
- printf ("Leaving edit mode!\n");
-
- ect_accept_edits (text_view);
- ect_stop_editing (text_view);
+ if (text_view->edit){
+ ect_accept_edits (text_view);
+ ect_stop_editing (text_view);
+ } else {
+ /*
+ * We did invoke this leave edit internally
+ */
+ }
}
/*
diff --git a/widgets/e-table/e-cell-toggle.c b/widgets/e-table/e-cell-toggle.c
new file mode 100644
index 0000000000..33e4d283ee
--- /dev/null
+++ b/widgets/e-table/e-cell-toggle.c
@@ -0,0 +1,204 @@
+/*
+ * e-cell-toggle.c: Multi-state image toggle cell object.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@kernel.org)
+ *
+ * (C) 1999 Helix Code, Inc
+ */
+#include <config.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <libgnomeui/gnome-canvas.h>
+#include "e-cell-toggle.h"
+#include "e-util.h"
+#include "e-table-item.h"
+
+#define PARENT_TYPE e_cell_get_type()
+
+Typedef struct {
+ ECellView cell_view;
+ GdkGC *gc;
+ GnomeCanvas *canvas;
+ ETableItem *eti;
+} ECellToggleView;
+
+static ECellClass *parent_class;
+
+static void
+etog_queue_redraw (ECellToggleView *text_view, int col, int row)
+{
+ e_table_item_redraw_range (text_view->eti, col, row, col, row);
+}
+
+/*
+ * ECell::realize method
+ */
+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;
+
+ toggle_view->cell_view.ecell = ecell;
+ toggle_view->eti = eti;
+ toggle_view->canvas = canvas;
+
+ return (ECellView *) toggle_view;
+}
+
+/*
+ * ECell::unrealize method
+ */
+static void
+etog_unrealize (ECellView *ecv)
+{
+ ECellToggleView *toggle_view = (ECellToggleView *) ecv;
+
+ g_free (toggle_view);
+}
+
+/*
+ * ECell::draw method
+ */
+static void
+etog_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int col, int row, gboolean selected,
+ int x1, int y1, int x2, int y2)
+{
+ ECellToggle *toggle = E_CELL_TOGGLE (e_cell_view->ecell);
+ ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
+ GdkPixbuf *image;
+ const int value = e_table_model_value_at (ecell_view->ecell->table_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",
+ value, toggle->n_states);
+ return;
+ }
+
+ image = toggle->images [value];
+
+}
+
+static void
+etog_set_value (ECellToggleView *toggle_view, int col, int row, int value)
+{
+ ECell *ecell = toggle_view->cell_view.ecell
+ ECellToggle *toggle = E_CELL_TOGGLE (ecell);
+
+ if (value >= toggle->n_vals)
+ value = 0;
+
+ e_table_model_set_value_at (ecell->table_model, col, row, value);
+ etog_queue_redraw (toggle_view, col, row);
+}
+
+/*
+ * ECell::event method
+ */
+static gint
+etog_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
+{
+ ECellToggle *toggle = E_CELL_TOGGLE (e_cell_view->ecell);
+ ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
+ int value = e_table_model_value_at (e_cell_view->ecell->table_model, col, row);
+
+ switch (event->type){
+ case GDK_BUTTON_RELEASE:
+ etog_set_value (toggle_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);
+ return TRUE;
+ }
+ return FALSE;
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * ECell::height method
+ */
+static int
+etog_height (ECellView *ecell_view, int col, int row)
+{
+ ECellToggle *toggle = E_CELL_TOGGLE (e_cell_view->ecell);
+
+ return toggle->height;
+}
+
+static void
+etog_destroy (GtkObject *object)
+{
+ ECellToggle *etog = E_CELL_TOGGLE (object);
+ int i;
+
+ for (i = 0; i < etog->n_states; i++)
+ gdk_pixbuf_unref (etog->images [i]);
+
+ g_free (etog->images);
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+e_cell_toggle_class_init (GtkObjectClass *object_class)
+{
+ ECellClass *ecc = (ECellClass *) object_class;
+
+ object_class->destroy = etog_destroy;
+
+ ecc->realize = etog_realize;
+ ecc->unrealize = etog_unrealize;
+ ecc->draw = etog_draw;
+ ecc->event = etog_event;
+ ecc->height = etog_height;
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+}
+
+E_MAKE_TYPE(e_cell_text, "ECellToggle", ECellToggle, e_cell_toggle_class_init, NULL, PARENT_TYPE);
+
+void
+e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_states, GdkPixbuf **images)
+{
+ int max_height = 0;
+
+ E_CELL (etog)->table_model = etm;
+
+ etog->border = border;
+ etog->n_states = n_states;
+
+ etog->images = g_new (GdkPixbuf *, n_states);
+
+ for (i = 0; i < n_states; i++){
+ etog->images [i] = images [i];
+ gdk_pixbuf_ref (images [i]);
+
+ if (images [i]->art_pixbuf->height > max_height)
+ max_height = images [i]->art_pixbuf->height;
+ }
+
+ etog->height = max_height;
+}
+
+ECell *
+e_cell_toggle_new (ETableModel *etm, int border, int n_states, GdkPixbuf **images)
+{
+ ECellToggle *etog = gtk_type_new (e_cell_toggle_get_type ());
+
+ e_cell_toggle_construct (etog, etm, border, n_states, images);
+
+ return (ECell *) etog;
+}
diff --git a/widgets/e-table/e-cell-toggle.h b/widgets/e-table/e-cell-toggle.h
new file mode 100644
index 0000000000..3cd99f5d04
--- /dev/null
+++ b/widgets/e-table/e-cell-toggle.h
@@ -0,0 +1,37 @@
+#ifndef _E_CELL_TOGGLE_H_
+#define _E_CELL_TOGGLE_H_
+
+#include <libgnomeui/gnome-canvas.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "e-cell.h"
+
+#define E_CELL_TOGGLE_TYPE (e_cell_toggle_get_type ())
+#define E_CELL_TOGGLE(o) (GTK_CHECK_CAST ((o), E_CELL_TOGGLE_TYPE, ECellToggle))
+#define E_CELL_TOGGLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_TOGGLE_TYPE, ECellToggleClass))
+#define E_IS_CELL_TOGGLE(o) (GTK_CHECK_TYPE ((o), E_CELL_TOGGLE_TYPE))
+#define E_IS_CELL_TOGGLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_TOGGLE_TYPE))
+
+typedef struct {
+ ECell parent;
+
+ int border;
+ int n_states;
+ GdkPixbuf **images;
+
+ int height;
+} ECellToggle;
+
+typedef struct {
+ ECellClass parent_class;
+} ECellToggleClass;
+
+GtkType e_cell_toggle_get_type (void);
+ECell *e_cell_toggle_new (ETableModel *model, int border,
+ int n_states,
+ GdkPibux **images);
+void e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm,
+ int border, int n_states, GdkPixbuf **images);
+
+#endif /* _E_CELL_TOGGLE_H_ */
+
+
diff --git a/widgets/e-table/e-table-item.c b/widgets/e-table/e-table-item.c
index 5816acfb23..ceb6adda95 100644
--- a/widgets/e-table/e-table-item.c
+++ b/widgets/e-table/e-table-item.c
@@ -38,9 +38,19 @@ enum {
ARG_TABLE_Y,
ARG_TABLE_DRAW_GRID,
ARG_TABLE_DRAW_FOCUS,
+ ARG_MODE_SPREADSHEET,
ARG_LENGHT_THRESHOLD
};
+static gboolean
+eti_editing (ETableItem *eti)
+{
+ if (eti->editing_col == -1)
+ return FALSE;
+ else
+ return TRUE;
+}
+
/*
* During realization, we have to invoke the per-ecell realize routine
* (On our current setup, we have one e-cell per column.
@@ -186,23 +196,26 @@ eti_get_height (ETableItem *eti)
{
const int rows = eti->rows;
int row;
- int height = 0;
+ int height;
if (rows == 0)
return 0;
-
- if (rows > eti->length_threshold){
- height = eti_row_height (eti, 0) * rows;
- return height;
+ if (eti->length_threshold != -1){
+ if (rows > eti->length_threshold){
+ height = (eti_row_height (eti, 0) + 1) * rows;
+
+ /*
+ * 1 pixel at the top
+ */
+ return height + 1;
+ }
}
-
+
+ height = 1;
for (row = 0; row < rows; row++)
- height += eti_row_height (eti, row);
+ height += eti_row_height (eti, row) + 1;
- /* Add division lines pixels */
- height += rows;
-
return height;
}
@@ -434,6 +447,10 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
case ARG_TABLE_DRAW_FOCUS:
eti->draw_focus = GTK_VALUE_BOOL (*arg);
break;
+
+ case ARG_MODE_SPREADSHEET:
+ eti->mode_spreadsheet = GTK_VALUE_BOOL (*arg);
+ break;
}
eti_update (item, NULL, NULL, 0);
}
@@ -445,6 +462,8 @@ eti_init (GnomeCanvasItem *item)
eti->focused_col = -1;
eti->focused_row = -1;
+ eti->editing_col = -1;
+ eti->editing_row = -1;
eti->height = 0;
eti->length_threshold = -1;
@@ -476,8 +495,12 @@ eti_realize (GnomeCanvasItem *item)
gdk_gc_ref (canvas_widget->style->white_gc);
eti->grid_gc = gdk_gc_new (window);
- gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]);
-
+#if 0
+ /* This sets it to gray */
+/* gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]); */
+#else
+ gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->black);
+#endif
eti->focus_gc = gdk_gc_new (window);
gdk_gc_set_foreground (eti->focus_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]);
gdk_gc_set_background (eti->focus_gc, &canvas_widget->style->fg [GTK_STATE_NORMAL]);
@@ -560,9 +583,11 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
/*
* Clear the background
*/
+#if 0
gdk_draw_rectangle (
drawable, eti->fill_gc, TRUE,
eti->x1 - x, eti->y1 - y, eti->width, eti->height);
+#endif
/*
* First column to draw, last column to draw
@@ -597,8 +622,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
*/
first_row = -1;
y_offset = 0;
- y1 = y2 = eti->y1;
- for (row = eti->top_item; row < rows; row++, y1 = y2){
+ y1 = y2 = eti->y1 + 1;
+ for (row = 0; row < rows; row++, y1 = y2){
y2 += eti_row_height (eti, row) + 1;
@@ -624,6 +649,14 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
yd = y_offset;
f_x1 = f_x2 = f_y1 = f_y2 = -1;
f_found = FALSE;
+
+ if (eti->draw_grid && first_row == 0){
+ gdk_draw_line (
+ drawable, eti->grid_gc,
+ eti->x1 - x, yd, eti->x1 + eti->width - x, yd);
+ }
+ yd++;
+
for (row = first_row; row < last_row; row++){
int xd, height;
gboolean selected;
@@ -650,25 +683,30 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
xd += ecol->width;
}
- yd += height + 1;
+ yd += height;
if (eti->draw_grid)
gdk_draw_line (
drawable, eti->grid_gc,
- eti->x1 - x, yd -1, eti->x1 + eti->width - x, yd -1);
+ eti->x1 - x, yd, eti->x1 + eti->width - x, yd);
+ yd++;
}
if (eti->draw_grid){
int xd = x_offset;
- for (col = first_col; col < last_col; col++){
+ for (col = first_col; col <= last_col; col++){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
gdk_draw_line (
drawable, eti->grid_gc,
- xd, y_offset, xd, yd);
+ xd, y_offset, xd, yd - 1);
- xd += ecol->width;
+ /*
+ * This looks wierd, but it is to draw the last line
+ */
+ if (ecol)
+ xd += ecol->width;
}
}
@@ -676,9 +714,11 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
* Draw focus
*/
if (f_found && eti->draw_focus){
- gdk_draw_rectangle (
- drawable, eti->focus_gc, FALSE,
- f_x1 + 1, f_y1, f_x2 - f_x1 - 2, f_y2 - f_y1 - 1);
+
+ if (!eti_editing (eti))
+ gdk_draw_rectangle (
+ drawable, eti->focus_gc, FALSE,
+ f_x1 + 1, f_y1, f_x2 - f_x1 - 2, f_y2 - f_y1 - 1);
}
}
@@ -692,14 +732,14 @@ eti_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
}
static gboolean
-find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
+find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res, gdouble *x1_res, gdouble *y1_res)
{
const int cols = eti->cols;
const int rows = eti->rows;
gdouble x1, y1, x2, y2;
int col, row;
- /* FIXME: inneficient, fix later */
+ /* FIXME: this routine is inneficient, fix later */
x -= eti->x1;
y -= eti->y1;
@@ -717,6 +757,8 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
continue;
*col_res = col;
+ if (x1_res)
+ *x1_res = x - x1;
break;
}
@@ -731,6 +773,8 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
continue;
*row_res = row;
+ if (y1_res)
+ *y1_res = y - y1;
break;
}
@@ -748,63 +792,113 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
case GDK_BUTTON_RELEASE:
case GDK_2BUTTON_PRESS: {
int col, row;
+ gdouble x1, y1;
- if (!find_cell (eti, e->button.x, e->button.y, &col, &row))
+ if (!find_cell (eti, e->button.x, e->button.y, &col, &row, &x1, &y1))
return TRUE;
if (eti->focused_row == row && eti->focused_col == col){
ecell_view = eti->cell_views [col];
+ /*
+ * Adjust the event positions
+ */
+ e->button.x = x1;
+ e->button.y = y1;
+
e_cell_event (ecell_view, e, col, row);
} else {
/*
* Focus the cell, and select the row
*/
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, col, row);
e_table_item_select_row (eti, row);
}
break;
}
+
+ case GDK_MOTION_NOTIFY: {
+ int col, row;
+ double x1, y1;
+
+ if (!find_cell (eti, e->button.x, e->button.y, &col, &row, &x1, &y1))
+ return TRUE;
+
+ if (eti->focused_row == row && eti->focused_col == col){
+ ecell_view = eti->cell_views [col];
+
+ /*
+ * Adjust the event positions
+ */
+ e->button.x -= (x1 + eti->x1);
+ e->button.y -= (y1 + eti->y1);
+
+ e_cell_event (ecell_view, e, col, row);
+ }
+ break;
+ }
case GDK_KEY_PRESS:
- printf ("KEYPRESS!\n");
-
if (eti->focused_col == -1)
return FALSE;
switch (e->key.keyval){
case GDK_Left:
- if (eti->focused_col > 0)
+ if (!eti->mode_spreadsheet && eti_editing (eti))
+ break;
+
+ if (eti->focused_col > 0){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row);
- break;
+ }
+ return TRUE;
case GDK_Right:
- if ((eti->focused_col + 1) < eti->cols)
+ if (!eti->mode_spreadsheet && eti_editing (eti))
+ break;
+
+ if ((eti->focused_col + 1) < eti->cols){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row);
- break;
+ }
+ return TRUE;
case GDK_Up:
- if (eti->focused_row > 0)
+ if (eti->focused_row > 0){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1);
- break;
+ }
+ return TRUE;
case GDK_Down:
- if ((eti->focused_row + 1) < eti->rows)
+ if ((eti->focused_row + 1) < eti->rows){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1);
- break;
-
+ }
+ return TRUE;
default:
+ if (!eti_editing (eti)){
+ if ((e->key.state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)) != 0)
+ return 0;
+
+ if (!(e->key.keyval >= 0x20 && e->key.keyval <= 0xff))
+ return 0;
+ }
}
+
ecell_view = eti->cell_views [eti->focused_col];
e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
break;
-
+
case GDK_KEY_RELEASE:
if (eti->focused_col == -1)
return FALSE;
- ecell_view = eti->cell_views [eti->focused_col];
- e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
+ if (eti_editing (eti)){
+ ecell_view = eti->cell_views [eti->editing_col];
+ e_cell_event (ecell_view, e, eti->editing_col, eti->editing_row);
+ }
break;
default:
@@ -860,6 +954,8 @@ eti_class_init (GtkObjectClass *object_class)
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID);
gtk_object_add_arg_type ("ETableItem::drawfocus", GTK_TYPE_BOOL,
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_FOCUS);
+ gtk_object_add_arg_type ("ETableItem::spreadsheet", GTK_TYPE_BOOL,
+ GTK_ARG_WRITABLE, ARG_MODE_SPREADSHEET);
eti_signals [ROW_SELECTION] =
gtk_signal_new ("row_selection",
@@ -1044,6 +1140,9 @@ e_table_item_leave_edit (ETableItem *eti)
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);
eti->editing_col = -1;
eti->editing_row = -1;
diff --git a/widgets/e-table/e-table-item.h b/widgets/e-table/e-table-item.h
index 3f3d2a7d4d..6c4d837310 100644
--- a/widgets/e-table/e-table-item.h
+++ b/widgets/e-table/e-table-item.h
@@ -19,7 +19,6 @@ typedef struct {
int x1, y1;
int width, height;
- int top_item;
int cols, rows;
/*
@@ -36,6 +35,7 @@ typedef struct {
unsigned int draw_grid:1;
unsigned int draw_focus:1;
+ unsigned int mode_spreadsheet:1;
int focused_col, focused_row;
diff --git a/widgets/e-table/table-test.c b/widgets/e-table/table-test.c
index f677e9e2d1..4ff03016b4 100644
--- a/widgets/e-table/table-test.c
+++ b/widgets/e-table/table-test.c
@@ -237,6 +237,7 @@ main (int argc, char *argv [])
"y", 30,
"drawgrid", TRUE,
"drawfocus", TRUE,
+ "spreadsheet", TRUE,
NULL);
gtk_main ();
diff --git a/widgets/table-test.c b/widgets/table-test.c
index f677e9e2d1..4ff03016b4 100644
--- a/widgets/table-test.c
+++ b/widgets/table-test.c
@@ -237,6 +237,7 @@ main (int argc, char *argv [])
"y", 30,
"drawgrid", TRUE,
"drawfocus", TRUE,
+ "spreadsheet", TRUE,
NULL);
gtk_main ();
diff --git a/widgets/table/e-cell-checkbox.c b/widgets/table/e-cell-checkbox.c
new file mode 100644
index 0000000000..db74464d5c
--- /dev/null
+++ b/widgets/table/e-cell-checkbox.c
@@ -0,0 +1,185 @@
+/*
+ * e-cell-checkbox.c: Checkbox cell renderer
+ *
+ * Author:
+ * Miguel de Icaza (miguel@kernel.org)
+ *
+ * (C) 1999 Helix Code, Inc
+ */
+#include <config.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <libgnomeui/gnome-canvas.h>
+#include "e-cell-checkbox.h"
+#include "e-util.h"
+#include "e-table-item.h"
+
+#define PARENT_TYPE e_cell_get_type()
+
+typedef struct {
+ ECellView cell_view;
+ GdkGC *gc;
+ GnomeCanvas *canvas;
+ ETableItem *eti;
+} ECellCheckboxView;
+
+static ECellClass *parent_class;
+
+static void
+eccb_queue_redraw (ECellCheckboxView *text_view, int col, int row)
+{
+ e_table_item_redraw_range (text_view->eti, col, row, col, row);
+}
+
+/*
+ * ECell::realize method
+ */
+static ECellView *
+eecb_realize (ECell *ecell, void *view)
+{
+ ECellCheckbox *eccb = E_CELL_CHECKBOX (ecell);
+ ECellCheckboxView *check_view = g_new0 (ECellCheckboxView, 1);
+ ETableItem *eti = E_TABLE_ITEM (view);
+ GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
+
+ check_view->cell_view.ecell = ecell;
+ check_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window);
+ check_view->eti = eti;
+ check_view->canvas = canvas;
+
+ return (ECellView *) check_view;
+}
+
+/*
+ * ECell::unrealize method
+ */
+static void
+eecb_unrealize (ECellView *ecv)
+{
+ ECellCheckboxView *check_view = (ECellCheckboxView *) ecv;
+
+ gdk_gc_unref (check_view->gc);
+ text_view->gc = NULL;
+
+ g_free (check_view);
+}
+
+/*
+ * ECell::draw method
+ */
+static void
+eecb_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int col, int row, gboolean selected,
+ int x1, int y1, int x2, int y2)
+{
+}
+
+/*
+ * ECell::event method
+ */
+static gint
+eecb_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
+{
+ ECellCheckboxView *text_view = (ECellCheckboxView *) ecell_view;
+
+ switch (event->type){
+ case GDK_BUTTON_PRESS:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+
+ printf ("Button pressed at %g %g\n", event->button.x, event->button.y);
+ if (text_view->edit){
+ printf ("FIXME: Should handle click here\n");
+ } else
+ e_table_item_enter_edit (text_view->eti, col, row);
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+ printf ("Button released at %g %g\n", event->button.x, event->button.y);
+ return TRUE;
+
+ case GDK_KEY_PRESS:
+ if (event->key.keyval == GDK_Escape){
+ eecb_cancel_edit (text_view);
+ return TRUE;
+ }
+
+ if (!text_view->edit){
+ e_table_item_enter_edit (text_view->eti, col, row);
+ eecb_edit_seleecb_all (text_view);
+ }
+
+ gtk_widget_event (GTK_WIDGET (text_view->edit->entry), event);
+ eecb_queue_redraw (text_view, col, row);
+ break;
+
+ case GDK_KEY_RELEASE:
+ break;
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * ECell::height method
+ */
+static int
+eecb_height (ECellView *ecell_view, int col, int row)
+{
+ return 10;
+}
+
+/*
+ * ECellView::enter_edit method
+ */
+static void *
+eecb_enter_edit (ECellView *ecell_view, int col, int row)
+{
+}
+
+/*
+ * ECellView::leave_edit method
+ */
+static void
+eecb_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context)
+{
+}
+
+static void
+e_cell_checkbox_class_init (GtkObjectClass *object_class)
+{
+ ECellClass *ecc = (ECellClass *) object_class;
+
+ ecc->realize = eecb_realize;
+ ecc->unrealize = eecb_unrealize;
+ ecc->draw = eecb_draw;
+ ecc->event = eecb_event;
+ ecc->height = eecb_height;
+ ecc->enter_edit = eecb_enter_edit;
+ ecc->leave_edit = eecb_leave_edit;
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+}
+
+E_MAKE_TYPE(e_cell_text, "ECellCheckbox", ECellCheckbox, e_cell_checkbox_class_init, NULL, PARENT_TYPE);
+
+ECell *
+e_cell_checkbox_new (ETableModel *etm)
+{
+ ECellCheckbox *eccb = gtk_type_new (e_cell_checkbox_get_type ());
+
+ E_CELL (eccb)->table_model = etm;
+
+ return (ECell *) eccb;
+}
diff --git a/widgets/table/e-cell-checkbox.h b/widgets/table/e-cell-checkbox.h
new file mode 100644
index 0000000000..6c85fbff21
--- /dev/null
+++ b/widgets/table/e-cell-checkbox.h
@@ -0,0 +1,25 @@
+#ifndef _E_CELL_CHECKBOX_H_
+#define _E_CELL_CHECKBOX_H_
+
+#include <libgnomeui/gnome-canvas.h>
+#include "e-cell.h"
+
+#define E_CELL_CHECKBOX_TYPE (e_cell_checkbox_get_type ())
+#define E_CELL_CHECKBOX(o) (GTK_CHECK_CAST ((o), E_CELL_CHECKBOX_TYPE, ECellCheckbox))
+#define E_CELL_CHECKBOX_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_CHECKBOX_TYPE, ECellCheckboxClass))
+#define E_IS_CELL_CHECKBOX(o) (GTK_CHECK_TYPE ((o), E_CELL_CHECKBOX_TYPE))
+#define E_IS_CELL_CHECKBOX_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_CHECKBOX_TYPE))
+
+typedef struct {
+ ECell parent;
+} ECellCheckbox;
+
+typedef struct {
+ ECellClass parent_class;
+} ECellCheckboxClass;
+
+GtkType e_cell_checkbox_get_type (void);
+ECell *e_cell_checkbox_new (ETableModel *model);
+
+#endif /* _E_CELL_CHECKBOX_H_ */
+
diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c
index f0501ab4cb..b18c179ca5 100644
--- a/widgets/table/e-cell-text.c
+++ b/widgets/table/e-cell-text.c
@@ -82,6 +82,8 @@ ect_stop_editing (ECellTextView *text_view)
g_free (edit);
text_view->edit = NULL;
+
+ e_table_item_leave_edit (text_view->eti);
}
/*
@@ -166,8 +168,6 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
if (text_view->edit){
CellEdit *edit = text_view->edit;
- printf ("We are editing a cell [%d %d %d %d]\n", col, row, edit->col, edit->row);
-
if ((edit->col == col) && (edit->row == row))
edit_display = TRUE;
}
@@ -192,11 +192,6 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
text_wc [text_wc_len] = 0;
/*
- * Find a good spot for painting
- */
- xoff = 0;
-
- /*
* Paint
*/
gdk_gc_set_foreground (text_view->gc, &w->style->base [GTK_STATE_NORMAL]);
@@ -208,11 +203,23 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
GdkGC *gc = text_view->gc;
const int y = y2 - font->descent - ((y2-y1-height)/2);
int px, i;
+
+ /*
+ * Border
+ */
+ x1 += 2;
+ x2--;
px = x1;
- printf ("Cursor at: %d\n", cursor_pos);
-
+ /*
+ * If the cursor is outside the visible range
+ *
+ * FIXME: we really want a better behaviour.
+ */
+ if ((px + left_len) > x2)
+ px -= left_len - (x2-x1);
+
for (i = 0; *text_wc; text_wc++, i++){
gdk_draw_text_wc (
drawable, font, gc, px, y, text_wc, 1);
@@ -240,6 +247,12 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
*/
GdkColor *background, *foreground;
int width;
+
+ /*
+ * Border
+ */
+ x1++;
+ x2--;
/*
* Compute draw mode
@@ -285,6 +298,17 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
}
/*
+ * Selects the entire string
+ */
+static void
+ect_edit_select_all (ECellTextView *text_view)
+{
+ g_assert (text_view->edit);
+
+ gtk_editable_select_region (GTK_EDITABLE (text_view->edit->entry), 0, -1);
+}
+
+/*
* ECell::event method
*/
static gint
@@ -294,6 +318,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
switch (event->type){
case GDK_BUTTON_PRESS:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+
+ printf ("Button pressed at %g %g\n", event->button.x, event->button.y);
if (text_view->edit){
printf ("FIXME: Should handle click here\n");
} else
@@ -301,6 +331,11 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
break;
case GDK_BUTTON_RELEASE:
+ /*
+ * Adjust for the border we use
+ */
+ event->button.x++;
+ printf ("Button released at %g %g\n", event->button.x, event->button.y);
return TRUE;
case GDK_KEY_PRESS:
@@ -309,8 +344,10 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
return TRUE;
}
- if (!text_view->edit)
+ if (!text_view->edit){
e_table_item_enter_edit (text_view->eti, 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);
@@ -355,10 +392,11 @@ ect_enter_edit (ECellView *ecell_view, int col, int row)
const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row);
CellEdit *edit;
- printf ("Entering edit mode! [%d %d]\n", col, row);
-
edit = g_new (CellEdit, 1);
text_view->edit = edit;
+
+ edit->col = col;
+ edit->row = row;
edit->entry = (GtkEntry *) gtk_entry_new ();
gtk_entry_set_text (edit->entry, str);
@@ -387,10 +425,14 @@ ect_leave_edit (ECellView *ecell_view, int col, int row, void *edit_context)
{
ECellTextView *text_view = (ECellTextView *) ecell_view;
- printf ("Leaving edit mode!\n");
-
- ect_accept_edits (text_view);
- ect_stop_editing (text_view);
+ if (text_view->edit){
+ ect_accept_edits (text_view);
+ ect_stop_editing (text_view);
+ } else {
+ /*
+ * We did invoke this leave edit internally
+ */
+ }
}
/*
diff --git a/widgets/table/e-cell-toggle.c b/widgets/table/e-cell-toggle.c
new file mode 100644
index 0000000000..33e4d283ee
--- /dev/null
+++ b/widgets/table/e-cell-toggle.c
@@ -0,0 +1,204 @@
+/*
+ * e-cell-toggle.c: Multi-state image toggle cell object.
+ *
+ * Author:
+ * Miguel de Icaza (miguel@kernel.org)
+ *
+ * (C) 1999 Helix Code, Inc
+ */
+#include <config.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <libgnomeui/gnome-canvas.h>
+#include "e-cell-toggle.h"
+#include "e-util.h"
+#include "e-table-item.h"
+
+#define PARENT_TYPE e_cell_get_type()
+
+Typedef struct {
+ ECellView cell_view;
+ GdkGC *gc;
+ GnomeCanvas *canvas;
+ ETableItem *eti;
+} ECellToggleView;
+
+static ECellClass *parent_class;
+
+static void
+etog_queue_redraw (ECellToggleView *text_view, int col, int row)
+{
+ e_table_item_redraw_range (text_view->eti, col, row, col, row);
+}
+
+/*
+ * ECell::realize method
+ */
+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;
+
+ toggle_view->cell_view.ecell = ecell;
+ toggle_view->eti = eti;
+ toggle_view->canvas = canvas;
+
+ return (ECellView *) toggle_view;
+}
+
+/*
+ * ECell::unrealize method
+ */
+static void
+etog_unrealize (ECellView *ecv)
+{
+ ECellToggleView *toggle_view = (ECellToggleView *) ecv;
+
+ g_free (toggle_view);
+}
+
+/*
+ * ECell::draw method
+ */
+static void
+etog_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int col, int row, gboolean selected,
+ int x1, int y1, int x2, int y2)
+{
+ ECellToggle *toggle = E_CELL_TOGGLE (e_cell_view->ecell);
+ ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
+ GdkPixbuf *image;
+ const int value = e_table_model_value_at (ecell_view->ecell->table_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",
+ value, toggle->n_states);
+ return;
+ }
+
+ image = toggle->images [value];
+
+}
+
+static void
+etog_set_value (ECellToggleView *toggle_view, int col, int row, int value)
+{
+ ECell *ecell = toggle_view->cell_view.ecell
+ ECellToggle *toggle = E_CELL_TOGGLE (ecell);
+
+ if (value >= toggle->n_vals)
+ value = 0;
+
+ e_table_model_set_value_at (ecell->table_model, col, row, value);
+ etog_queue_redraw (toggle_view, col, row);
+}
+
+/*
+ * ECell::event method
+ */
+static gint
+etog_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
+{
+ ECellToggle *toggle = E_CELL_TOGGLE (e_cell_view->ecell);
+ ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
+ int value = e_table_model_value_at (e_cell_view->ecell->table_model, col, row);
+
+ switch (event->type){
+ case GDK_BUTTON_RELEASE:
+ etog_set_value (toggle_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);
+ return TRUE;
+ }
+ return FALSE;
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * ECell::height method
+ */
+static int
+etog_height (ECellView *ecell_view, int col, int row)
+{
+ ECellToggle *toggle = E_CELL_TOGGLE (e_cell_view->ecell);
+
+ return toggle->height;
+}
+
+static void
+etog_destroy (GtkObject *object)
+{
+ ECellToggle *etog = E_CELL_TOGGLE (object);
+ int i;
+
+ for (i = 0; i < etog->n_states; i++)
+ gdk_pixbuf_unref (etog->images [i]);
+
+ g_free (etog->images);
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+e_cell_toggle_class_init (GtkObjectClass *object_class)
+{
+ ECellClass *ecc = (ECellClass *) object_class;
+
+ object_class->destroy = etog_destroy;
+
+ ecc->realize = etog_realize;
+ ecc->unrealize = etog_unrealize;
+ ecc->draw = etog_draw;
+ ecc->event = etog_event;
+ ecc->height = etog_height;
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+}
+
+E_MAKE_TYPE(e_cell_text, "ECellToggle", ECellToggle, e_cell_toggle_class_init, NULL, PARENT_TYPE);
+
+void
+e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_states, GdkPixbuf **images)
+{
+ int max_height = 0;
+
+ E_CELL (etog)->table_model = etm;
+
+ etog->border = border;
+ etog->n_states = n_states;
+
+ etog->images = g_new (GdkPixbuf *, n_states);
+
+ for (i = 0; i < n_states; i++){
+ etog->images [i] = images [i];
+ gdk_pixbuf_ref (images [i]);
+
+ if (images [i]->art_pixbuf->height > max_height)
+ max_height = images [i]->art_pixbuf->height;
+ }
+
+ etog->height = max_height;
+}
+
+ECell *
+e_cell_toggle_new (ETableModel *etm, int border, int n_states, GdkPixbuf **images)
+{
+ ECellToggle *etog = gtk_type_new (e_cell_toggle_get_type ());
+
+ e_cell_toggle_construct (etog, etm, border, n_states, images);
+
+ return (ECell *) etog;
+}
diff --git a/widgets/table/e-cell-toggle.h b/widgets/table/e-cell-toggle.h
new file mode 100644
index 0000000000..3cd99f5d04
--- /dev/null
+++ b/widgets/table/e-cell-toggle.h
@@ -0,0 +1,37 @@
+#ifndef _E_CELL_TOGGLE_H_
+#define _E_CELL_TOGGLE_H_
+
+#include <libgnomeui/gnome-canvas.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "e-cell.h"
+
+#define E_CELL_TOGGLE_TYPE (e_cell_toggle_get_type ())
+#define E_CELL_TOGGLE(o) (GTK_CHECK_CAST ((o), E_CELL_TOGGLE_TYPE, ECellToggle))
+#define E_CELL_TOGGLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_TOGGLE_TYPE, ECellToggleClass))
+#define E_IS_CELL_TOGGLE(o) (GTK_CHECK_TYPE ((o), E_CELL_TOGGLE_TYPE))
+#define E_IS_CELL_TOGGLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_TOGGLE_TYPE))
+
+typedef struct {
+ ECell parent;
+
+ int border;
+ int n_states;
+ GdkPixbuf **images;
+
+ int height;
+} ECellToggle;
+
+typedef struct {
+ ECellClass parent_class;
+} ECellToggleClass;
+
+GtkType e_cell_toggle_get_type (void);
+ECell *e_cell_toggle_new (ETableModel *model, int border,
+ int n_states,
+ GdkPibux **images);
+void e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm,
+ int border, int n_states, GdkPixbuf **images);
+
+#endif /* _E_CELL_TOGGLE_H_ */
+
+
diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c
index 5816acfb23..ceb6adda95 100644
--- a/widgets/table/e-table-item.c
+++ b/widgets/table/e-table-item.c
@@ -38,9 +38,19 @@ enum {
ARG_TABLE_Y,
ARG_TABLE_DRAW_GRID,
ARG_TABLE_DRAW_FOCUS,
+ ARG_MODE_SPREADSHEET,
ARG_LENGHT_THRESHOLD
};
+static gboolean
+eti_editing (ETableItem *eti)
+{
+ if (eti->editing_col == -1)
+ return FALSE;
+ else
+ return TRUE;
+}
+
/*
* During realization, we have to invoke the per-ecell realize routine
* (On our current setup, we have one e-cell per column.
@@ -186,23 +196,26 @@ eti_get_height (ETableItem *eti)
{
const int rows = eti->rows;
int row;
- int height = 0;
+ int height;
if (rows == 0)
return 0;
-
- if (rows > eti->length_threshold){
- height = eti_row_height (eti, 0) * rows;
- return height;
+ if (eti->length_threshold != -1){
+ if (rows > eti->length_threshold){
+ height = (eti_row_height (eti, 0) + 1) * rows;
+
+ /*
+ * 1 pixel at the top
+ */
+ return height + 1;
+ }
}
-
+
+ height = 1;
for (row = 0; row < rows; row++)
- height += eti_row_height (eti, row);
+ height += eti_row_height (eti, row) + 1;
- /* Add division lines pixels */
- height += rows;
-
return height;
}
@@ -434,6 +447,10 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
case ARG_TABLE_DRAW_FOCUS:
eti->draw_focus = GTK_VALUE_BOOL (*arg);
break;
+
+ case ARG_MODE_SPREADSHEET:
+ eti->mode_spreadsheet = GTK_VALUE_BOOL (*arg);
+ break;
}
eti_update (item, NULL, NULL, 0);
}
@@ -445,6 +462,8 @@ eti_init (GnomeCanvasItem *item)
eti->focused_col = -1;
eti->focused_row = -1;
+ eti->editing_col = -1;
+ eti->editing_row = -1;
eti->height = 0;
eti->length_threshold = -1;
@@ -476,8 +495,12 @@ eti_realize (GnomeCanvasItem *item)
gdk_gc_ref (canvas_widget->style->white_gc);
eti->grid_gc = gdk_gc_new (window);
- gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]);
-
+#if 0
+ /* This sets it to gray */
+/* gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]); */
+#else
+ gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->black);
+#endif
eti->focus_gc = gdk_gc_new (window);
gdk_gc_set_foreground (eti->focus_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]);
gdk_gc_set_background (eti->focus_gc, &canvas_widget->style->fg [GTK_STATE_NORMAL]);
@@ -560,9 +583,11 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
/*
* Clear the background
*/
+#if 0
gdk_draw_rectangle (
drawable, eti->fill_gc, TRUE,
eti->x1 - x, eti->y1 - y, eti->width, eti->height);
+#endif
/*
* First column to draw, last column to draw
@@ -597,8 +622,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
*/
first_row = -1;
y_offset = 0;
- y1 = y2 = eti->y1;
- for (row = eti->top_item; row < rows; row++, y1 = y2){
+ y1 = y2 = eti->y1 + 1;
+ for (row = 0; row < rows; row++, y1 = y2){
y2 += eti_row_height (eti, row) + 1;
@@ -624,6 +649,14 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
yd = y_offset;
f_x1 = f_x2 = f_y1 = f_y2 = -1;
f_found = FALSE;
+
+ if (eti->draw_grid && first_row == 0){
+ gdk_draw_line (
+ drawable, eti->grid_gc,
+ eti->x1 - x, yd, eti->x1 + eti->width - x, yd);
+ }
+ yd++;
+
for (row = first_row; row < last_row; row++){
int xd, height;
gboolean selected;
@@ -650,25 +683,30 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
xd += ecol->width;
}
- yd += height + 1;
+ yd += height;
if (eti->draw_grid)
gdk_draw_line (
drawable, eti->grid_gc,
- eti->x1 - x, yd -1, eti->x1 + eti->width - x, yd -1);
+ eti->x1 - x, yd, eti->x1 + eti->width - x, yd);
+ yd++;
}
if (eti->draw_grid){
int xd = x_offset;
- for (col = first_col; col < last_col; col++){
+ for (col = first_col; col <= last_col; col++){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
gdk_draw_line (
drawable, eti->grid_gc,
- xd, y_offset, xd, yd);
+ xd, y_offset, xd, yd - 1);
- xd += ecol->width;
+ /*
+ * This looks wierd, but it is to draw the last line
+ */
+ if (ecol)
+ xd += ecol->width;
}
}
@@ -676,9 +714,11 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
* Draw focus
*/
if (f_found && eti->draw_focus){
- gdk_draw_rectangle (
- drawable, eti->focus_gc, FALSE,
- f_x1 + 1, f_y1, f_x2 - f_x1 - 2, f_y2 - f_y1 - 1);
+
+ if (!eti_editing (eti))
+ gdk_draw_rectangle (
+ drawable, eti->focus_gc, FALSE,
+ f_x1 + 1, f_y1, f_x2 - f_x1 - 2, f_y2 - f_y1 - 1);
}
}
@@ -692,14 +732,14 @@ eti_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
}
static gboolean
-find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
+find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res, gdouble *x1_res, gdouble *y1_res)
{
const int cols = eti->cols;
const int rows = eti->rows;
gdouble x1, y1, x2, y2;
int col, row;
- /* FIXME: inneficient, fix later */
+ /* FIXME: this routine is inneficient, fix later */
x -= eti->x1;
y -= eti->y1;
@@ -717,6 +757,8 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
continue;
*col_res = col;
+ if (x1_res)
+ *x1_res = x - x1;
break;
}
@@ -731,6 +773,8 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
continue;
*row_res = row;
+ if (y1_res)
+ *y1_res = y - y1;
break;
}
@@ -748,63 +792,113 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
case GDK_BUTTON_RELEASE:
case GDK_2BUTTON_PRESS: {
int col, row;
+ gdouble x1, y1;
- if (!find_cell (eti, e->button.x, e->button.y, &col, &row))
+ if (!find_cell (eti, e->button.x, e->button.y, &col, &row, &x1, &y1))
return TRUE;
if (eti->focused_row == row && eti->focused_col == col){
ecell_view = eti->cell_views [col];
+ /*
+ * Adjust the event positions
+ */
+ e->button.x = x1;
+ e->button.y = y1;
+
e_cell_event (ecell_view, e, col, row);
} else {
/*
* Focus the cell, and select the row
*/
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, col, row);
e_table_item_select_row (eti, row);
}
break;
}
+
+ case GDK_MOTION_NOTIFY: {
+ int col, row;
+ double x1, y1;
+
+ if (!find_cell (eti, e->button.x, e->button.y, &col, &row, &x1, &y1))
+ return TRUE;
+
+ if (eti->focused_row == row && eti->focused_col == col){
+ ecell_view = eti->cell_views [col];
+
+ /*
+ * Adjust the event positions
+ */
+ e->button.x -= (x1 + eti->x1);
+ e->button.y -= (y1 + eti->y1);
+
+ e_cell_event (ecell_view, e, col, row);
+ }
+ break;
+ }
case GDK_KEY_PRESS:
- printf ("KEYPRESS!\n");
-
if (eti->focused_col == -1)
return FALSE;
switch (e->key.keyval){
case GDK_Left:
- if (eti->focused_col > 0)
+ if (!eti->mode_spreadsheet && eti_editing (eti))
+ break;
+
+ if (eti->focused_col > 0){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row);
- break;
+ }
+ return TRUE;
case GDK_Right:
- if ((eti->focused_col + 1) < eti->cols)
+ if (!eti->mode_spreadsheet && eti_editing (eti))
+ break;
+
+ if ((eti->focused_col + 1) < eti->cols){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row);
- break;
+ }
+ return TRUE;
case GDK_Up:
- if (eti->focused_row > 0)
+ if (eti->focused_row > 0){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1);
- break;
+ }
+ return TRUE;
case GDK_Down:
- if ((eti->focused_row + 1) < eti->rows)
+ if ((eti->focused_row + 1) < eti->rows){
+ e_table_item_leave_edit (eti);
e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1);
- break;
-
+ }
+ return TRUE;
default:
+ if (!eti_editing (eti)){
+ if ((e->key.state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)) != 0)
+ return 0;
+
+ if (!(e->key.keyval >= 0x20 && e->key.keyval <= 0xff))
+ return 0;
+ }
}
+
ecell_view = eti->cell_views [eti->focused_col];
e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
break;
-
+
case GDK_KEY_RELEASE:
if (eti->focused_col == -1)
return FALSE;
- ecell_view = eti->cell_views [eti->focused_col];
- e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
+ if (eti_editing (eti)){
+ ecell_view = eti->cell_views [eti->editing_col];
+ e_cell_event (ecell_view, e, eti->editing_col, eti->editing_row);
+ }
break;
default:
@@ -860,6 +954,8 @@ eti_class_init (GtkObjectClass *object_class)
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID);
gtk_object_add_arg_type ("ETableItem::drawfocus", GTK_TYPE_BOOL,
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_FOCUS);
+ gtk_object_add_arg_type ("ETableItem::spreadsheet", GTK_TYPE_BOOL,
+ GTK_ARG_WRITABLE, ARG_MODE_SPREADSHEET);
eti_signals [ROW_SELECTION] =
gtk_signal_new ("row_selection",
@@ -1044,6 +1140,9 @@ e_table_item_leave_edit (ETableItem *eti)
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);
eti->editing_col = -1;
eti->editing_row = -1;
diff --git a/widgets/table/e-table-item.h b/widgets/table/e-table-item.h
index 3f3d2a7d4d..6c4d837310 100644
--- a/widgets/table/e-table-item.h
+++ b/widgets/table/e-table-item.h
@@ -19,7 +19,6 @@ typedef struct {
int x1, y1;
int width, height;
- int top_item;
int cols, rows;
/*
@@ -36,6 +35,7 @@ typedef struct {
unsigned int draw_grid:1;
unsigned int draw_focus:1;
+ unsigned int mode_spreadsheet:1;
int focused_col, focused_row;
diff --git a/widgets/table/table-test.c b/widgets/table/table-test.c
index f677e9e2d1..4ff03016b4 100644
--- a/widgets/table/table-test.c
+++ b/widgets/table/table-test.c
@@ -237,6 +237,7 @@ main (int argc, char *argv [])
"y", 30,
"drawgrid", TRUE,
"drawfocus", TRUE,
+ "spreadsheet", TRUE,
NULL);
gtk_main ();