aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiguel de Icaza <miguel@gnu.org>1999-11-28 11:12:22 +0800
committerArturo Espinosa <unammx@src.gnome.org>1999-11-28 11:12:22 +0800
commit8d75b6689bdf5dc7c1efad65867cba2a656f2dcc (patch)
treeb023c7f3a14daa812fd46882017f307cef2cb36f
parentbe9d0c05dbf3a8f10333ee6dc839673afb5befa5 (diff)
downloadgsoc2013-evolution-8d75b6689bdf5dc7c1efad65867cba2a656f2dcc.tar.gz
gsoc2013-evolution-8d75b6689bdf5dc7c1efad65867cba2a656f2dcc.tar.zst
gsoc2013-evolution-8d75b6689bdf5dc7c1efad65867cba2a656f2dcc.zip
beginning of the keyboard navigation.
1999-11-27 Miguel de Icaza <miguel@gnu.org> * e-table-item.c (eti_event): beginning of the keyboard navigation. * e-table-model.c (e_table_model_row_changed): new function. (e_table_model_cell_changed): new function. (e_table_model_class_init): New signals. * e-table-item.c (eti_request_region_redraw): x2, y2 offsets were wrong. (eti_select): Repaint selected region. (eti_request_region_redraw): Fix range. (eti_draw): Correct offset computation here. (e_table_item_class_init): New method: row_selection, handles the selection. Now it implement GTK_SELECTION_SINGLE and GTK_SELECTION_MULTIPLE. Focusing and selection should be correct now. svn path=/trunk/; revision=1441
-rw-r--r--widgets/ChangeLog20
-rw-r--r--widgets/e-cell-text.c14
-rw-r--r--widgets/e-cell.c9
-rw-r--r--widgets/e-cell.h7
-rw-r--r--widgets/e-table-col.c10
-rw-r--r--widgets/e-table-group.c4
-rw-r--r--widgets/e-table-header-item.c2
-rw-r--r--widgets/e-table-header.c5
-rw-r--r--widgets/e-table-item.c386
-rw-r--r--widgets/e-table-item.h27
-rw-r--r--widgets/e-table-model.c128
-rw-r--r--widgets/e-table-model.h14
-rw-r--r--widgets/e-table-sorted.c2
-rw-r--r--widgets/e-table/ChangeLog20
-rw-r--r--widgets/e-table/e-cell-text.c14
-rw-r--r--widgets/e-table/e-cell.c9
-rw-r--r--widgets/e-table/e-cell.h7
-rw-r--r--widgets/e-table/e-table-col.c10
-rw-r--r--widgets/e-table/e-table-group.c4
-rw-r--r--widgets/e-table/e-table-header-item.c2
-rw-r--r--widgets/e-table/e-table-header.c5
-rw-r--r--widgets/e-table/e-table-item.c386
-rw-r--r--widgets/e-table/e-table-item.h27
-rw-r--r--widgets/e-table/e-table-model.c128
-rw-r--r--widgets/e-table/e-table-model.h14
-rw-r--r--widgets/e-table/e-table-sorted.c2
-rw-r--r--widgets/e-table/table-test.c4
-rw-r--r--widgets/table-test.c4
-rw-r--r--widgets/table/e-cell-text.c14
-rw-r--r--widgets/table/e-cell.c9
-rw-r--r--widgets/table/e-cell.h7
-rw-r--r--widgets/table/e-table-col.c10
-rw-r--r--widgets/table/e-table-group.c4
-rw-r--r--widgets/table/e-table-header-item.c2
-rw-r--r--widgets/table/e-table-header.c5
-rw-r--r--widgets/table/e-table-item.c386
-rw-r--r--widgets/table/e-table-item.h27
-rw-r--r--widgets/table/e-table-model.c128
-rw-r--r--widgets/table/e-table-model.h14
-rw-r--r--widgets/table/e-table-sorted.c2
-rw-r--r--widgets/table/table-test.c4
41 files changed, 1435 insertions, 441 deletions
diff --git a/widgets/ChangeLog b/widgets/ChangeLog
index 8df0c6966d..20d4c1e3d7 100644
--- a/widgets/ChangeLog
+++ b/widgets/ChangeLog
@@ -1,3 +1,23 @@
+1999-11-27 Miguel de Icaza <miguel@gnu.org>
+
+ * e-table-item.c (eti_event): beginning of the keyboard navigation.
+
+ * e-table-model.c (e_table_model_row_changed): new function.
+ (e_table_model_cell_changed): new function.
+ (e_table_model_class_init): New signals.
+
+ * e-table-item.c (eti_request_region_redraw): x2, y2 offsets were
+ wrong.
+ (eti_select): Repaint selected region.
+ (eti_request_region_redraw): Fix range.
+ (eti_draw): Correct offset computation here.
+ (e_table_item_class_init): New method: row_selection, handles the
+ selection.
+
+ Now it implement GTK_SELECTION_SINGLE and GTK_SELECTION_MULTIPLE.
+
+ Focusing and selection should be correct now.
+
1999-11-26 Miguel de Icaza <miguel@gnu.org>
* e-table-item.c (eti_realize): Compute height using the ecell
diff --git a/widgets/e-cell-text.c b/widgets/e-cell-text.c
index da26302664..a997d745d3 100644
--- a/widgets/e-cell-text.c
+++ b/widgets/e-cell-text.c
@@ -64,13 +64,14 @@ ect_unrealize (ECellView *ecv)
}
static void
-ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
+ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int 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;
GdkRectangle rect;
const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row);
- int selected = e_table_model_get_selected_row (ecell_view->ecell->table_model) == row;
int xoff, w;
rect.x = x1;
@@ -94,6 +95,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1
xoff = ((x2 - x1) - gdk_text_width (text_view->font, str, strlen (str))) / 2;
break;
default:
+ xoff = 0;
g_warning ("Can not handle GTK_JUSTIFY_FILL");
break;
}
@@ -135,12 +137,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
switch (event->type){
case GDK_BUTTON_PRESS:
- if (e_table_model_get_selected_row (ecell->table_model) == row)
- e_cell_text_start_editing (ect, col, row);
- else
- e_table_model_select_row (ecell->table_model, row);
return TRUE;
+
+ default:
+ break;
}
+ return FALSE;
}
static int
diff --git a/widgets/e-cell.c b/widgets/e-cell.c
index 8a8897c22a..9caa31f2ca 100644
--- a/widgets/e-cell.c
+++ b/widgets/e-cell.c
@@ -24,7 +24,9 @@ ec_unrealize (ECellView *e_cell)
}
static void
-ec_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
+ec_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int col, int row, gboolean selected,
+ int x1, int y1, int x2, int y2)
{
g_warning ("e-cell-draw invoked\n");
}
@@ -33,6 +35,7 @@ static gint
ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
{
g_warning ("e-cell-event invoked\n");
+ return 0;
}
static gint
@@ -109,10 +112,10 @@ e_cell_unrealize (ECellView *ecell_view)
void
e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable,
- int col, int row, int x1, int y1, int x2, int y2)
+ int 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, x1, y1, x2, y2);
+ ecell_view, drawable, col, row, selected, x1, y1, x2, y2);
}
int
diff --git a/widgets/e-cell.h b/widgets/e-cell.h
index e57f341098..9cd62f3909 100644
--- a/widgets/e-cell.h
+++ b/widgets/e-cell.h
@@ -32,7 +32,7 @@ typedef struct {
ECellView *(*realize) (ECell *, GnomeCanvas *canvas);
void (*unrealize) (ECellView *);
void (*draw) (ECellView *ecell_view, GdkDrawable *drawable,
- int col, int row, int x1, int y1, int x2, int y2);
+ 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, int col, int row, int x1, int y1, int x2, int y2);
void (*unfocus) (ECellView *ecell);
@@ -43,8 +43,9 @@ GtkType e_cell_get_type (void);
void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row);
ECellView *e_cell_realize (ECell *ecell, GnomeCanvas *canvas);
void e_cell_unrealize (ECellView *ecell_view);
-void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
- int col, int row, int x1, int y1, int x2, int y2);
+void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
+ int col, int row, gboolean selected,
+ 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);
diff --git a/widgets/e-table-col.c b/widgets/e-table-col.c
index 4c61cddd0f..3ffc45a2ed 100644
--- a/widgets/e-table-col.c
+++ b/widgets/e-table-col.c
@@ -17,11 +17,11 @@ e_table_col_new (const char *id, int width, int min_width,
{
ETableCol *etc;
- g_return_if_fail (id != NULL);
- g_return_if_fail (width >= 0);
- g_return_if_fail (min_width >= 0);
- g_return_if_fail (width >= min_width);
- g_return_if_fail (compare != NULL);
+ g_return_val_if_fail (id != NULL, NULL);
+ g_return_val_if_fail (width >= 0, NULL);
+ g_return_val_if_fail (min_width >= 0, NULL);
+ g_return_val_if_fail (width >= min_width, NULL);
+ g_return_val_if_fail (compare != NULL, NULL);
etc = g_new (ETableCol, 1);
diff --git a/widgets/e-table-group.c b/widgets/e-table-group.c
index bc751229a4..b1e681d255 100644
--- a/widgets/e-table-group.c
+++ b/widgets/e-table-group.c
@@ -76,10 +76,11 @@ e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
etg->u.children = g_slist_append (etg->u.children, child);
}
+#if 0
int
e_table_group_size (ETableGroup *etg)
{
- g_return_if_fail (etg != NULL);
+ g_return_val_if_fail (etg != NULL, 0);
if (etg->is_leaf)
return e_table_model_height (etg->u.table);
@@ -96,3 +97,4 @@ e_table_group_size (ETableGroup *etg)
}
}
+#endif
diff --git a/widgets/e-table-header-item.c b/widgets/e-table-header-item.c
index 2ee8e2d619..1be7e7097b 100644
--- a/widgets/e-table-header-item.c
+++ b/widgets/e-table-header-item.c
@@ -7,6 +7,7 @@
* Copyright 1999, Helix Code, Inc.
*/
#include <config.h>
+#include <gtk/gtksignal.h>
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-cursors.h"
@@ -124,7 +125,6 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableHeaderItem *ethi;
- int v;
item = GNOME_CANVAS_ITEM (o);
ethi = E_TABLE_HEADER_ITEM (o);
diff --git a/widgets/e-table-header.c b/widgets/e-table-header.c
index 2279bf4ba6..5900c5ca4f 100644
--- a/widgets/e-table-header.c
+++ b/widgets/e-table-header.c
@@ -121,8 +121,6 @@ eth_update_offsets (ETableHeader *eth)
void
e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos)
{
- ETableCol **new_ptr;
-
g_return_if_fail (eth != NULL);
g_return_if_fail (E_IS_TABLE_HEADER (eth));
g_return_if_fail (tc != NULL);
@@ -204,7 +202,6 @@ ETableCol **
e_table_header_get_columns (ETableHeader *eth)
{
ETableCol **ret;
- int i;
g_return_val_if_fail (eth != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
@@ -226,7 +223,7 @@ e_table_header_selection_ok (ETableHeader *eth)
}
int
-ve_table_header_get_selected (ETableHeader *eth)
+e_table_header_get_selected (ETableHeader *eth)
{
int i;
int selected = 0;
diff --git a/widgets/e-table-item.c b/widgets/e-table-item.c
index 3b35f6c156..a561fbfd15 100644
--- a/widgets/e-table-item.c
+++ b/widgets/e-table-item.c
@@ -1,20 +1,36 @@
/*
- * E-table-item.c: A view of a Table.
+ * E-table-item.c: A GnomeCanvasItem that is a view of an ETableModel.
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
* Copyright 1999, Helix Code, Inc.
+ *
+ * TODO:
+ * Add a border to the thing, so that focusing works properly.
+ *
*/
#include <config.h>
+#include <stdio.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
#include "e-table-item.h"
#include "e-cell.h"
#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
+#define FOCUSED_BORDER 2
+
static GnomeCanvasItemClass *eti_parent_class;
enum {
+ ROW_SELECTION,
+ LAST_SIGNAL
+};
+
+static gint eti_signals [LAST_SIGNAL] = { 0, };
+
+enum {
ARG_0,
ARG_TABLE_HEADER,
ARG_TABLE_MODEL,
@@ -24,6 +40,14 @@ enum {
ARG_LENGHT_THRESHOLD
};
+/*
+ * During realization, we have to invoke the per-ecell realize routine
+ * (On our current setup, we have one e-cell per column.
+ *
+ * We might want to optimize this to only realize the unique e-cells:
+ * ie, a strings-only table, uses the same e-cell for every column, and
+ * we might want to avoid realizing each e-cell.
+ */
static void
eti_realize_cell_views (ETableItem *eti)
{
@@ -43,14 +67,16 @@ eti_realize_cell_views (ETableItem *eti)
}
}
+/*
+ * During unrealization: we invoke every e-cell (one per column in the current
+ * setup) to dispose all resources allocated
+ */
static void
eti_unrealize_cell_views (ETableItem *eti)
{
int i;
for (i = 0; i < eti->n_cells; i++){
- ETableCol *col = e_table_header_get_column (eti->header, i);
-
e_cell_unrealize (eti->cell_views [i]);
eti->cell_views [i] = NULL;
}
@@ -59,6 +85,9 @@ eti_unrealize_cell_views (ETableItem *eti)
}
+/*
+ * GnomeCanvasItem::update method
+ */
static void
eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
{
@@ -75,14 +104,21 @@ eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
}
+/*
+ * eti_remove_table_model:
+ *
+ * Invoked to release the table model associated with this ETableItem
+ */
static void
eti_remove_table_model (ETableItem *eti)
{
if (!eti->table_model)
return;
- gtk_signal_disconnect (eti->table_model_change_id);
- gtk_signal_disconnect (eti->table_model_selection_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
+ eti->table_model_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
+ eti->table_model_selection_id);
gtk_object_unref (GTK_OBJECT (eti->table_model));
eti->table_model_change_id = 0;
@@ -90,14 +126,21 @@ eti_remove_table_model (ETableItem *eti)
eti->table_model = NULL;
}
+/*
+ * eti_remove_header_model:
+ *
+ * Invoked to release the header model associated with this ETableItem
+ */
static void
eti_remove_header_model (ETableItem *eti)
{
if (!eti->header)
return;
- gtk_signal_disconnect (eti->header_structure_change_id);
- gtk_signal_disconnect (eti->header_dim_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->header),
+ eti->header_structure_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->header),
+ eti->header_dim_change_id);
gtk_object_unref (GTK_OBJECT (eti->header));
eti->header_structure_change_id = 0;
@@ -105,6 +148,12 @@ eti_remove_header_model (ETableItem *eti)
eti->header = NULL;
}
+/*
+ * eti_row_height:
+ *
+ * Returns the height used by row @row. This does not include the one-pixel
+ * used as a separator between rows
+ */
static int
eti_row_height (ETableItem *eti, int row)
{
@@ -123,6 +172,18 @@ eti_row_height (ETableItem *eti, int row)
return max_h;
}
+/*
+ * eti_get_height:
+ *
+ * Returns the height of the ETableItem.
+ *
+ * The ETableItem might compute the whole height by asking every row its
+ * size. There is a special mode (designed to work when there are too
+ * many rows in the table that performing the previous step could take
+ * too long) set by the ETableItem->length_threshold that would determine
+ * when the height is computed by using the first row as the size for
+ * every other row in the ETableItem.
+ */
static int
eti_get_height (ETableItem *eti)
{
@@ -148,6 +209,9 @@ eti_get_height (ETableItem *eti)
return height;
}
+/*
+ * Callback routine: invoked when the ETableModel has suffered a change
+ */
static void
eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
{
@@ -160,6 +224,11 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
}
+/*
+ * eti_request_redraw:
+ *
+ * Queues a canvas redraw for the entire ETableItem.
+ */
static void
eti_request_redraw (ETableItem *eti)
{
@@ -170,6 +239,9 @@ eti_request_redraw (ETableItem *eti)
eti->y1 + eti->height + 1);
}
+/*
+ * Computes the distance from @start_col to @end_col in pixels.
+ */
static int
eti_col_diff (ETableItem *eti, int start_col, int end_col)
{
@@ -185,6 +257,9 @@ eti_col_diff (ETableItem *eti, int start_col, int end_col)
return total;
}
+/*
+ * Computes the distance between @start_row and @end_row in pixels
+ */
static int
eti_row_diff (ETableItem *eti, int start_row, int end_row)
{
@@ -198,28 +273,38 @@ eti_row_diff (ETableItem *eti, int start_row, int end_row)
return total;
}
+/*
+ * eti_request_region_redraw:
+ *
+ * Request a canvas redraw on the range (start_col, start_row) to (end_col, end_row).
+ * This is inclusive (ie, you can use: 0,0-0,0 to redraw the first cell).
+ *
+ * The @border argument is a number of pixels around the region that should also be queued
+ * for redraw. This is typically used by the focus routines to queue a redraw for the
+ * border as well.
+ */
static void
-eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row)
+eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row, int border)
{
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
int x1, y1, width, height;
- int col, row;
x1 = eti_col_diff (eti, 0, start_col);
y1 = eti_row_diff (eti, 0, start_row);
- width = eti_col_diff (eti, start_col, end_col);
- height = eti_row_diff (eti, start_col, end_row);
-
+ width = eti_col_diff (eti, start_col, end_col + 1);
+ height = eti_row_diff (eti, start_row, end_row + 1);
+
gnome_canvas_request_redraw (canvas,
- eti->x1 + x1, eti->y1 + y1,
- eti->y1 + width + 1,
- eti->x1 + height + 1);
+ eti->x1 + x1 - border,
+ eti->y1 + y1 - border,
+ eti->x1 + x1 + width + 1 + border,
+ eti->y1 + y1 + height + 1 + border);
}
static void
eti_table_model_row_selection (ETableModel *table_model, int row, gboolean selected, ETableItem *eti)
{
- eti_request_region_redraw (eti, 0, row, eti->cols, row);
+ eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
}
static void
@@ -282,6 +367,9 @@ eti_add_header_model (ETableItem *eti, ETableHeader *header)
GTK_SIGNAL_FUNC (eti_header_structure_changed), eti);
}
+/*
+ * GtkObject::destroy method
+ */
static void
eti_destroy (GtkObject *object)
{
@@ -289,6 +377,8 @@ eti_destroy (GtkObject *object)
eti_remove_header_model (eti);
eti_remove_table_model (eti);
+
+ g_slist_free (eti->selection);
if (GTK_OBJECT_CLASS (eti_parent_class)->destroy)
(*GTK_OBJECT_CLASS (eti_parent_class)->destroy) (object);
@@ -299,7 +389,6 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableItem *eti;
- int v;
item = GNOME_CANVAS_ITEM (o);
eti = E_TABLE_ITEM (o);
@@ -343,6 +432,8 @@ eti_init (GnomeCanvasItem *item)
eti->height = 0;
eti->length_threshold = -1;
+
+ eti->selection_mode = GTK_SELECTION_SINGLE;
}
static void
@@ -355,13 +446,24 @@ eti_realize (GnomeCanvasItem *item)
if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)
(*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)(item);
+ /*
+ * Gdk Resource allocation
+ */
window = canvas_widget->window;
-
+
eti->fill_gc = canvas_widget->style->white_gc;
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]);
+ eti->focus_gc = gdk_gc_new (window);
+ gdk_gc_set_foreground (eti->focus_gc, &canvas_widget->style->black);
+ gdk_gc_set_line_attributes (eti->focus_gc, 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
+
+ /*
+ *
+ */
eti_realize_cell_views (eti);
eti->height = eti_get_height (eti);
@@ -377,7 +479,9 @@ eti_unrealize (GnomeCanvasItem *item)
eti->fill_gc = NULL;
gdk_gc_unref (eti->grid_gc);
eti->grid_gc = NULL;
-
+ gdk_gc_unref (eti->focus_gc);
+ eti->focus_gc = NULL;
+
eti_unrealize_cell_views (eti);
eti->height = 0;
@@ -387,26 +491,28 @@ eti_unrealize (GnomeCanvasItem *item)
}
static void
-draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row,
+draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
- GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
ECellView *ecell_view;
- GdkFont *font;
- char text [40];
-
- font = GTK_WIDGET (canvas)->style->font;
ecell_view = eti->cell_views [col];
- e_cell_draw (ecell_view, drawable, col, row, x1, y1, x2, y2);
+ 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
}
@@ -420,7 +526,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
int first_col, last_col, x_offset;
int first_row, last_row, y_offset, yd;
int x1, x2;
- int heights;
+ int f_x1, f_x2, f_y1, f_y2;
+ gboolean f_found;
printf ("Rect: %d %d %d %d\n", x, y, width, height);
/*
@@ -435,7 +542,7 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
*/
first_col = -1;
last_col = x_offset = 0;
- x1 = eti->x1;
+ x1 = x2 = eti->x1;
for (col = 0; col < cols; col++, x1 = x2){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
@@ -465,9 +572,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
y_offset = 0;
y1 = y2 = eti->y1;
for (row = eti->top_item; row < rows; row++, y1 = y2){
- int xd;
- y2 += eti_row_height (eti, row);
+ y2 += eti_row_height (eti, row) + 1;
if (y1 > y + height)
break;
@@ -489,24 +595,49 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
* Draw cells
*/
yd = y_offset;
+ f_x1 = f_x2 = f_y1 = f_y2 = -1;
+ f_found = FALSE;
for (row = first_row; row < last_row; row++){
int xd, height;
+ gboolean selected;
height = eti_row_height (eti, row);
xd = x_offset;
printf ("paint: %d %d\n", yd, yd + height);
+
+ selected = g_slist_find (eti->selection, GINT_TO_POINTER (row)) != NULL;
+
for (col = first_col; col < last_col; col++){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
- draw_cell (eti, drawable, col, row, xd, yd, xd + ecol->width, yd + height);
+ draw_cell (eti, drawable, col, row, selected, xd, yd, xd + ecol->width, yd + height);
+ if (col == eti->focused_col && row == eti->focused_row){
+ f_x1 = xd;
+ f_x2 = xd + ecol->width;
+ f_y1 = yd;
+ f_y2 = yd + height;
+ f_found = TRUE;
+ }
+
xd += ecol->width;
}
yd += height + 1;
gdk_draw_line (drawable, eti->grid_gc,
eti->x1 - x, yd -1, eti->x1 + eti->width - x, yd -1);
}
+
+ /*
+ * Draw focus
+ */
+ if (f_found){
+ printf ("FOUD: %d %d %d %d!\n",
+ f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
+ gdk_draw_rectangle (
+ drawable, eti->focus_gc, FALSE,
+ f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
+ }
}
static double
@@ -547,7 +678,7 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
break;
}
- y1 = 0;
+ y1 = y2 = 0;
for (row = 0; row < rows; row++, y1 = y2){
if (y < y1)
return FALSE;
@@ -564,13 +695,6 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
return TRUE;
}
-static void
-eti_select (ETableItem *eti, int col, int row)
-{
- eti->selected_col = col;
- eti->selected_row = row;
-}
-
static int
eti_event (GnomeCanvasItem *item, GdkEvent *e)
{
@@ -586,22 +710,56 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
if (!find_cell (eti, e->button.x, e->button.y, &col, &row))
return TRUE;
- if (eti->selected_row == row && eti->selected_col == col){
+ if (eti->focused_row == row && eti->focused_col == col){
ecell_view = eti->cell_views [col];
e_cell_event (ecell_view, e, col, row);
- } else
- eti_select (eti, col, row);
+ } else {
+ /*
+ * Focus the cell, and select the row
+ */
+ e_table_item_focus (eti, col, row);
+ e_table_item_select_row (eti, row);
+ }
break;
}
case GDK_KEY_PRESS:
- case GDK_KEY_RELEASE:
if (eti->focused_col == -1)
return FALSE;
+ switch (e->key.keyval){
+ case GDK_Left:
+ if (eti->focused_col > 0)
+ e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row);
+ break;
+
+ case GDK_Right:
+ if ((eti->focused_col + 1) < eti->cols)
+ e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row);
+ break;
+
+ case GDK_Up:
+ if (eti->focused_row > 0)
+ e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1);
+ break;
+
+ case GDK_Down:
+ if ((eti->focused_row + 1) < eti->rows)
+ e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1);
+ break;
+
+ default:
+ }
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);
break;
@@ -610,12 +768,27 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
}
return TRUE;
}
+
+/*
+ * ETableItem::row_selection method
+ */
+static void
+eti_row_selection (ETableItem *eti, int row, gboolean selected)
+{
+ eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
+ if (selected)
+ eti->selection = g_slist_prepend (eti->selection, GINT_TO_POINTER (row));
+ else
+ eti->selection = g_slist_remove (eti->selection, GINT_TO_POINTER (row));
+}
+
static void
eti_class_init (GtkObjectClass *object_class)
{
GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
-
+ ETableItemClass *eti_class = (ETableItemClass *) object_class;
+
eti_parent_class = gtk_type_class (PARENT_OBJECT_TYPE);
object_class->destroy = eti_destroy;
@@ -627,7 +800,9 @@ eti_class_init (GtkObjectClass *object_class)
item_class->draw = eti_draw;
item_class->point = eti_point;
item_class->event = eti_event;
-
+
+ eti_class->row_selection = eti_row_selection;
+
gtk_object_add_arg_type ("ETableItem::ETableHeader", GTK_TYPE_POINTER,
GTK_ARG_WRITABLE, ARG_TABLE_HEADER);
gtk_object_add_arg_type ("ETableItem::ETableModel", GTK_TYPE_POINTER,
@@ -638,6 +813,17 @@ eti_class_init (GtkObjectClass *object_class)
GTK_ARG_WRITABLE, ARG_TABLE_Y);
gtk_object_add_arg_type ("ETableItem::drawgrid", GTK_TYPE_BOOL,
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID);
+
+ eti_signals [ROW_SELECTION] =
+ gtk_signal_new ("row_selection",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableItemClass, row_selection),
+ gtk_marshal_NONE__INT_INT,
+ GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, eti_signals, LAST_SIGNAL);
+
}
GtkType
@@ -666,16 +852,124 @@ e_table_item_get_type (void)
void
e_table_item_focus (ETableItem *eti, int col, int row)
{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
if (eti->focused_col != -1)
e_table_item_unfocus (eti);
eti->focused_col = col;
- eti->focused_row = row;
+ eti->focused_row = row;
+
+ eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
}
void
e_table_item_unfocus (ETableItem *eti)
{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ if (eti->focused_row == -1)
+ return;
+
+ {
+ const int col = eti->focused_col;
+ const int row = eti->focused_row;
+
+ eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
+ }
eti->focused_col = -1;
eti->focused_row = -1;
}
+
+const GSList *
+e_table_item_get_selection (ETableItem *eti)
+{
+ g_return_val_if_fail (eti != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_ITEM (eti), NULL);
+
+ return eti->selection;
+}
+
+GtkSelectionMode
+e_table_item_get_selection_mode (ETableItem *eti)
+{
+ g_return_val_if_fail (eti != NULL, GTK_SELECTION_SINGLE);
+ g_return_val_if_fail (E_IS_TABLE_ITEM (eti), GTK_SELECTION_SINGLE);
+
+ return eti->selection_mode;
+}
+
+void
+e_table_item_set_selection_mode (ETableItem *eti, GtkSelectionMode selection_mode)
+{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ if (selection_mode == GTK_SELECTION_BROWSE ||
+ selection_mode == GTK_SELECTION_EXTENDED){
+ g_error ("GTK_SELECTION_BROWSE and GTK_SELECTION_EXTENDED are not implemented");
+ }
+
+ eti->selection_mode = selection_mode;
+}
+
+gboolean
+e_table_item_is_row_selected (ETableItem *eti, int row)
+{
+ g_return_val_if_fail (eti != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_ITEM (eti), FALSE);
+
+ if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void
+e_table_item_unselect_row (ETableItem *eti, int row)
+{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ if (e_table_item_is_row_selected (eti, row)){
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ row, 0);
+ }
+}
+
+void
+e_table_item_select_row (ETableItem *eti, int row)
+{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ switch (eti->selection_mode){
+ case GTK_SELECTION_SINGLE:
+ if (eti->selection){
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ GPOINTER_TO_INT (eti->selection->data), 0);
+ }
+ g_slist_free (eti->selection);
+ eti->selection = NULL;
+
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ GINT_TO_POINTER (row), 1);
+ break;
+
+ case GTK_SELECTION_MULTIPLE:
+ if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
+ return;
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ GINT_TO_POINTER (row), 1);
+ break;
+
+ default:
+
+ }
+}
diff --git a/widgets/e-table-item.h b/widgets/e-table-item.h
index fc36363413..17d422ddf5 100644
--- a/widgets/e-table-item.h
+++ b/widgets/e-table-item.h
@@ -32,6 +32,7 @@ typedef struct {
GdkGC *fill_gc;
GdkGC *grid_gc;
+ GdkGC *focus_gc;
unsigned int draw_grid:1;
@@ -49,15 +50,39 @@ typedef struct {
*/
int length_threshold;
- int selected_col, selected_row;
+ GSList *selection;
+ GtkSelectionMode selection_mode;
} ETableItem;
typedef struct {
GnomeCanvasItemClass parent_class;
+
+ void (*row_selection) (ETableItem *eti, int row, gboolean selected);
} ETableItemClass;
GtkType e_table_item_get_type (void);
+
+/*
+ * Focus
+ */
void e_table_item_focus (ETableItem *eti, int col, int row);
void e_table_item_unfocus (ETableItem *eti);
+/*
+ * Selection
+ */
+void e_table_item_select_row (ETableItem *e_table_Item, int row);
+void e_table_item_unselect_row (ETableItem *e_table_Item, int row);
+
+/*
+ * Handling the selection
+ */
+const GSList*e_table_item_get_selection (ETableItem *e_table_Item);
+
+GtkSelectionMode e_table_item_get_selection_mode (ETableItem *e_table_Item);
+void e_table_item_set_selection_mode (ETableItem *e_table_Item,
+ GtkSelectionMode selection_mode);
+gboolean e_table_item_is_row_selected (ETableItem *e_table_Item,
+ int row);
+
#endif /* _E_TABLE_ITEM_H_ */
diff --git a/widgets/e-table-model.c b/widgets/e-table-model.c
index 3aa4e4be47..288c20f20e 100644
--- a/widgets/e-table-model.c
+++ b/widgets/e-table-model.c
@@ -16,55 +16,71 @@ static GtkObjectClass *e_table_model_parent_class;
enum {
MODEL_CHANGED,
+ MODEL_ROW_CHANGED,
+ MODEL_CELL_CHANGED,
ROW_SELECTION,
LAST_SIGNAL
};
-static guint etm_signals [LAST_SIGNAL] = { 0, };
+static guint e_table_model_signals [LAST_SIGNAL] = { 0, };
int
-e_table_model_column_count (ETableModel *etable)
+e_table_model_column_count (ETableModel *e_table_model)
{
- return ETM_CLASS (etable)->column_count (etable);
+ g_return_val_if_fail (e_table_model != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
+
+ return ETM_CLASS (e_table_model)->column_count (e_table_model);
}
const char *
-e_table_model_column_name (ETableModel *etable, int col)
+e_table_model_column_name (ETableModel *e_table_model, int col)
{
- return ETM_CLASS (etable)->column_name (etable, col);
+ g_return_val_if_fail (e_table_model != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
+
+ return ETM_CLASS (e_table_model)->column_name (e_table_model, col);
}
int
-e_table_model_row_count (ETableModel *etable)
+e_table_model_row_count (ETableModel *e_table_model)
{
- return ETM_CLASS (etable)->row_count (etable);
+ g_return_val_if_fail (e_table_model != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
+
+ return ETM_CLASS (e_table_model)->row_count (e_table_model);
}
void *
-e_table_model_value_at (ETableModel *etable, int col, int row)
+e_table_model_value_at (ETableModel *e_table_model, int col, int row)
{
- return ETM_CLASS (etable)->value_at (etable, col, row);
+ g_return_val_if_fail (e_table_model != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
+
+ return ETM_CLASS (e_table_model)->value_at (e_table_model, col, row);
}
void
-e_table_model_set_value_at (ETableModel *etable, int col, int row, void *data)
+e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data)
{
- return ETM_CLASS (etable)->set_value_at (etable, col, row, data);
+ 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);
}
gboolean
-e_table_model_is_cell_editable (ETableModel *etable, int col, int row)
+e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row)
{
- return ETM_CLASS (etable)->is_cell_editable (etable, col, row);
+ g_return_val_if_fail (e_table_model != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), FALSE);
+
+ return ETM_CLASS (e_table_model)->is_cell_editable (e_table_model, col, row);
}
static void
e_table_model_destroy (GtkObject *object)
{
- GSList *l;
-
- ETableModel *etable = (ETableModel *) object;
-
if (e_table_model_parent_class->destroy)
(*e_table_model_parent_class->destroy)(object);
}
@@ -76,7 +92,7 @@ e_table_model_class_init (GtkObjectClass *object_class)
object_class->destroy = e_table_model_destroy;
- etm_signals [MODEL_CHANGED] =
+ e_table_model_signals [MODEL_CHANGED] =
gtk_signal_new ("model_changed",
GTK_RUN_LAST,
object_class->type,
@@ -84,21 +100,23 @@ e_table_model_class_init (GtkObjectClass *object_class)
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
- etm_signals [ROW_SELECTION] =
- gtk_signal_new ("row_selection",
+ e_table_model_signals [MODEL_ROW_CHANGED] =
+ gtk_signal_new ("model_row_changed",
GTK_RUN_LAST,
object_class->type,
- GTK_SIGNAL_OFFSET (ETableModelClass, row_selection),
+ GTK_SIGNAL_OFFSET (ETableModelClass, model_row_changed),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+
+ e_table_model_signals [MODEL_CELL_CHANGED] =
+ gtk_signal_new ("model_cell_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableModelClass, model_cell_changed),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
-
- gtk_object_class_add_signals (object_class, etm_signals, LAST_SIGNAL);
-}
-static void
-e_table_model_init (ETableModel *etm)
-{
- etm->row_selected = -1;
+ gtk_object_class_add_signals (object_class, e_table_model_signals, LAST_SIGNAL);
}
GtkType
@@ -112,7 +130,7 @@ e_table_model_get_type (void)
sizeof (ETableModel),
sizeof (ETableModelClass),
(GtkClassInitFunc) e_table_model_class_init,
- (GtkObjectInitFunc) e_table_model_init,
+ (GtkObjectInitFunc) NULL,
NULL, /* reserved 1 */
NULL, /* reserved 2 */
(GtkClassInitFunc) NULL
@@ -127,53 +145,31 @@ e_table_model_get_type (void)
void
e_table_model_changed (ETableModel *e_table_model)
{
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
+
gtk_signal_emit (GTK_OBJECT (e_table_model),
- etm_signals [MODEL_CHANGED]);
+ e_table_model_signals [MODEL_CHANGED]);
}
-#if 0
-int
-e_table_model_max_col_width (ETableModel *etm, int col)
+void
+e_table_model_row_changed (ETableModel *e_table_model, int row)
{
- const int nvals = e_table_model_row_count (etm);
- int max = 0;
- int row;
-
- for (row = 0; row < nvals; row++){
- int w;
-
- w = e_table_model_cell_width (etm, col, i);
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
- if (w > max)
- max = w;
- }
-
- return max;
+ gtk_signal_emit (GTK_OBJECT (e_table_model),
+ e_table_model_signals [MODEL_ROW_CHANGED], row);
}
-#endif
void
-e_table_model_select_row (ETableModel *etm, int row)
+e_table_model_cell_changed (ETableModel *e_table_model, int col, int row)
{
- gtk_signal_emit (GTK_OBJECT (etm), etm_signals [ROW_SELECTION], row, 1);
- etm->row_selected = row;
-}
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
-void
-e_table_model_unselect_row (ETableModel *etm, int row)
-{
- if (etm->row_selected != -1){
- gtk_signal_emit (
- GTK_OBJECT (etm), etm_signals [ROW_SELECTION],
- etm->row_selected, 0);
- }
-
- etm->row_selected = -1;
+ gtk_signal_emit (GTK_OBJECT (e_table_model),
+ e_table_model_signals [MODEL_CELL_CHANGED], col, row);
}
-gint
-e_table_model_get_selected_row (ETableModel *etm)
-{
- return etm->row_selected;
-}
diff --git a/widgets/e-table-model.h b/widgets/e-table-model.h
index d8de9e819e..ea5d31493d 100644
--- a/widgets/e-table-model.h
+++ b/widgets/e-table-model.h
@@ -11,9 +11,6 @@
typedef struct {
GtkObject base;
-
- /* Temporary. I swear */
- int row_selected;
} ETableModel;
typedef struct {
@@ -32,8 +29,9 @@ typedef struct {
/*
* Signals
*/
- void (*model_changed) (ETableModel *etm);
- void (*row_selection) (ETableModel *etc, int row, gboolean selected);
+ void (*model_changed) (ETableModel *etm);
+ void (*model_row_changed) (ETableModel *etm, int row);
+ void (*model_cell_changed) (ETableModel *etm, int col, int row);
} ETableModelClass;
GtkType e_table_model_get_type (void);
@@ -45,13 +43,13 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col,
void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data);
gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row);
-void e_table_model_select_row (ETableModel *e_table_model, int row);
-gint e_table_model_get_selected_row (ETableModel *e_table_model);
-
/*
* Routines for emitting signals on the e_table
*/
void e_table_model_changed (ETableModel *e_table_model);
+void e_table_model_row_changed (ETableModel *e_table_model, int row);
+void e_table_model_cell_changed (ETableModel *e_table_model, int col, int row);
#endif /* _E_TABLE_MODEL_H_ */
+
diff --git a/widgets/e-table-sorted.c b/widgets/e-table-sorted.c
index be19de2efb..90773e9cdc 100644
--- a/widgets/e-table-sorted.c
+++ b/widgets/e-table-sorted.c
@@ -30,7 +30,6 @@ static ETableSorted *sort_ets;
static int
my_sort (const void *a, const void *b)
{
- GCompareFunc comp;
ETableModel *source = E_TABLE_SUBSET (sort_ets)->source;
const int *ia = (const int *) a;
const int *ib = (const int *) b;
@@ -59,7 +58,6 @@ e_table_sorted_new (ETableModel *source, int col, GCompareFunc compare)
ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE);
ETableSubset *etss = E_TABLE_SUBSET (ets);
const int nvals = e_table_model_row_count (source);
- unsigned int *buffer;
int i;
if (e_table_subset_construct (etss, source, nvals) == NULL){
diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog
index 8df0c6966d..20d4c1e3d7 100644
--- a/widgets/e-table/ChangeLog
+++ b/widgets/e-table/ChangeLog
@@ -1,3 +1,23 @@
+1999-11-27 Miguel de Icaza <miguel@gnu.org>
+
+ * e-table-item.c (eti_event): beginning of the keyboard navigation.
+
+ * e-table-model.c (e_table_model_row_changed): new function.
+ (e_table_model_cell_changed): new function.
+ (e_table_model_class_init): New signals.
+
+ * e-table-item.c (eti_request_region_redraw): x2, y2 offsets were
+ wrong.
+ (eti_select): Repaint selected region.
+ (eti_request_region_redraw): Fix range.
+ (eti_draw): Correct offset computation here.
+ (e_table_item_class_init): New method: row_selection, handles the
+ selection.
+
+ Now it implement GTK_SELECTION_SINGLE and GTK_SELECTION_MULTIPLE.
+
+ Focusing and selection should be correct now.
+
1999-11-26 Miguel de Icaza <miguel@gnu.org>
* e-table-item.c (eti_realize): Compute height using the ecell
diff --git a/widgets/e-table/e-cell-text.c b/widgets/e-table/e-cell-text.c
index da26302664..a997d745d3 100644
--- a/widgets/e-table/e-cell-text.c
+++ b/widgets/e-table/e-cell-text.c
@@ -64,13 +64,14 @@ ect_unrealize (ECellView *ecv)
}
static void
-ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
+ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int 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;
GdkRectangle rect;
const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row);
- int selected = e_table_model_get_selected_row (ecell_view->ecell->table_model) == row;
int xoff, w;
rect.x = x1;
@@ -94,6 +95,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1
xoff = ((x2 - x1) - gdk_text_width (text_view->font, str, strlen (str))) / 2;
break;
default:
+ xoff = 0;
g_warning ("Can not handle GTK_JUSTIFY_FILL");
break;
}
@@ -135,12 +137,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
switch (event->type){
case GDK_BUTTON_PRESS:
- if (e_table_model_get_selected_row (ecell->table_model) == row)
- e_cell_text_start_editing (ect, col, row);
- else
- e_table_model_select_row (ecell->table_model, row);
return TRUE;
+
+ default:
+ break;
}
+ return FALSE;
}
static int
diff --git a/widgets/e-table/e-cell.c b/widgets/e-table/e-cell.c
index 8a8897c22a..9caa31f2ca 100644
--- a/widgets/e-table/e-cell.c
+++ b/widgets/e-table/e-cell.c
@@ -24,7 +24,9 @@ ec_unrealize (ECellView *e_cell)
}
static void
-ec_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
+ec_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int col, int row, gboolean selected,
+ int x1, int y1, int x2, int y2)
{
g_warning ("e-cell-draw invoked\n");
}
@@ -33,6 +35,7 @@ static gint
ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
{
g_warning ("e-cell-event invoked\n");
+ return 0;
}
static gint
@@ -109,10 +112,10 @@ e_cell_unrealize (ECellView *ecell_view)
void
e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable,
- int col, int row, int x1, int y1, int x2, int y2)
+ int 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, x1, y1, x2, y2);
+ ecell_view, drawable, col, row, selected, x1, y1, x2, y2);
}
int
diff --git a/widgets/e-table/e-cell.h b/widgets/e-table/e-cell.h
index e57f341098..9cd62f3909 100644
--- a/widgets/e-table/e-cell.h
+++ b/widgets/e-table/e-cell.h
@@ -32,7 +32,7 @@ typedef struct {
ECellView *(*realize) (ECell *, GnomeCanvas *canvas);
void (*unrealize) (ECellView *);
void (*draw) (ECellView *ecell_view, GdkDrawable *drawable,
- int col, int row, int x1, int y1, int x2, int y2);
+ 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, int col, int row, int x1, int y1, int x2, int y2);
void (*unfocus) (ECellView *ecell);
@@ -43,8 +43,9 @@ GtkType e_cell_get_type (void);
void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row);
ECellView *e_cell_realize (ECell *ecell, GnomeCanvas *canvas);
void e_cell_unrealize (ECellView *ecell_view);
-void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
- int col, int row, int x1, int y1, int x2, int y2);
+void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
+ int col, int row, gboolean selected,
+ 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);
diff --git a/widgets/e-table/e-table-col.c b/widgets/e-table/e-table-col.c
index 4c61cddd0f..3ffc45a2ed 100644
--- a/widgets/e-table/e-table-col.c
+++ b/widgets/e-table/e-table-col.c
@@ -17,11 +17,11 @@ e_table_col_new (const char *id, int width, int min_width,
{
ETableCol *etc;
- g_return_if_fail (id != NULL);
- g_return_if_fail (width >= 0);
- g_return_if_fail (min_width >= 0);
- g_return_if_fail (width >= min_width);
- g_return_if_fail (compare != NULL);
+ g_return_val_if_fail (id != NULL, NULL);
+ g_return_val_if_fail (width >= 0, NULL);
+ g_return_val_if_fail (min_width >= 0, NULL);
+ g_return_val_if_fail (width >= min_width, NULL);
+ g_return_val_if_fail (compare != NULL, NULL);
etc = g_new (ETableCol, 1);
diff --git a/widgets/e-table/e-table-group.c b/widgets/e-table/e-table-group.c
index bc751229a4..b1e681d255 100644
--- a/widgets/e-table/e-table-group.c
+++ b/widgets/e-table/e-table-group.c
@@ -76,10 +76,11 @@ e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
etg->u.children = g_slist_append (etg->u.children, child);
}
+#if 0
int
e_table_group_size (ETableGroup *etg)
{
- g_return_if_fail (etg != NULL);
+ g_return_val_if_fail (etg != NULL, 0);
if (etg->is_leaf)
return e_table_model_height (etg->u.table);
@@ -96,3 +97,4 @@ e_table_group_size (ETableGroup *etg)
}
}
+#endif
diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c
index 2ee8e2d619..1be7e7097b 100644
--- a/widgets/e-table/e-table-header-item.c
+++ b/widgets/e-table/e-table-header-item.c
@@ -7,6 +7,7 @@
* Copyright 1999, Helix Code, Inc.
*/
#include <config.h>
+#include <gtk/gtksignal.h>
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-cursors.h"
@@ -124,7 +125,6 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableHeaderItem *ethi;
- int v;
item = GNOME_CANVAS_ITEM (o);
ethi = E_TABLE_HEADER_ITEM (o);
diff --git a/widgets/e-table/e-table-header.c b/widgets/e-table/e-table-header.c
index 2279bf4ba6..5900c5ca4f 100644
--- a/widgets/e-table/e-table-header.c
+++ b/widgets/e-table/e-table-header.c
@@ -121,8 +121,6 @@ eth_update_offsets (ETableHeader *eth)
void
e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos)
{
- ETableCol **new_ptr;
-
g_return_if_fail (eth != NULL);
g_return_if_fail (E_IS_TABLE_HEADER (eth));
g_return_if_fail (tc != NULL);
@@ -204,7 +202,6 @@ ETableCol **
e_table_header_get_columns (ETableHeader *eth)
{
ETableCol **ret;
- int i;
g_return_val_if_fail (eth != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
@@ -226,7 +223,7 @@ e_table_header_selection_ok (ETableHeader *eth)
}
int
-ve_table_header_get_selected (ETableHeader *eth)
+e_table_header_get_selected (ETableHeader *eth)
{
int i;
int selected = 0;
diff --git a/widgets/e-table/e-table-item.c b/widgets/e-table/e-table-item.c
index 3b35f6c156..a561fbfd15 100644
--- a/widgets/e-table/e-table-item.c
+++ b/widgets/e-table/e-table-item.c
@@ -1,20 +1,36 @@
/*
- * E-table-item.c: A view of a Table.
+ * E-table-item.c: A GnomeCanvasItem that is a view of an ETableModel.
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
* Copyright 1999, Helix Code, Inc.
+ *
+ * TODO:
+ * Add a border to the thing, so that focusing works properly.
+ *
*/
#include <config.h>
+#include <stdio.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
#include "e-table-item.h"
#include "e-cell.h"
#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
+#define FOCUSED_BORDER 2
+
static GnomeCanvasItemClass *eti_parent_class;
enum {
+ ROW_SELECTION,
+ LAST_SIGNAL
+};
+
+static gint eti_signals [LAST_SIGNAL] = { 0, };
+
+enum {
ARG_0,
ARG_TABLE_HEADER,
ARG_TABLE_MODEL,
@@ -24,6 +40,14 @@ enum {
ARG_LENGHT_THRESHOLD
};
+/*
+ * During realization, we have to invoke the per-ecell realize routine
+ * (On our current setup, we have one e-cell per column.
+ *
+ * We might want to optimize this to only realize the unique e-cells:
+ * ie, a strings-only table, uses the same e-cell for every column, and
+ * we might want to avoid realizing each e-cell.
+ */
static void
eti_realize_cell_views (ETableItem *eti)
{
@@ -43,14 +67,16 @@ eti_realize_cell_views (ETableItem *eti)
}
}
+/*
+ * During unrealization: we invoke every e-cell (one per column in the current
+ * setup) to dispose all resources allocated
+ */
static void
eti_unrealize_cell_views (ETableItem *eti)
{
int i;
for (i = 0; i < eti->n_cells; i++){
- ETableCol *col = e_table_header_get_column (eti->header, i);
-
e_cell_unrealize (eti->cell_views [i]);
eti->cell_views [i] = NULL;
}
@@ -59,6 +85,9 @@ eti_unrealize_cell_views (ETableItem *eti)
}
+/*
+ * GnomeCanvasItem::update method
+ */
static void
eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
{
@@ -75,14 +104,21 @@ eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
}
+/*
+ * eti_remove_table_model:
+ *
+ * Invoked to release the table model associated with this ETableItem
+ */
static void
eti_remove_table_model (ETableItem *eti)
{
if (!eti->table_model)
return;
- gtk_signal_disconnect (eti->table_model_change_id);
- gtk_signal_disconnect (eti->table_model_selection_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
+ eti->table_model_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
+ eti->table_model_selection_id);
gtk_object_unref (GTK_OBJECT (eti->table_model));
eti->table_model_change_id = 0;
@@ -90,14 +126,21 @@ eti_remove_table_model (ETableItem *eti)
eti->table_model = NULL;
}
+/*
+ * eti_remove_header_model:
+ *
+ * Invoked to release the header model associated with this ETableItem
+ */
static void
eti_remove_header_model (ETableItem *eti)
{
if (!eti->header)
return;
- gtk_signal_disconnect (eti->header_structure_change_id);
- gtk_signal_disconnect (eti->header_dim_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->header),
+ eti->header_structure_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->header),
+ eti->header_dim_change_id);
gtk_object_unref (GTK_OBJECT (eti->header));
eti->header_structure_change_id = 0;
@@ -105,6 +148,12 @@ eti_remove_header_model (ETableItem *eti)
eti->header = NULL;
}
+/*
+ * eti_row_height:
+ *
+ * Returns the height used by row @row. This does not include the one-pixel
+ * used as a separator between rows
+ */
static int
eti_row_height (ETableItem *eti, int row)
{
@@ -123,6 +172,18 @@ eti_row_height (ETableItem *eti, int row)
return max_h;
}
+/*
+ * eti_get_height:
+ *
+ * Returns the height of the ETableItem.
+ *
+ * The ETableItem might compute the whole height by asking every row its
+ * size. There is a special mode (designed to work when there are too
+ * many rows in the table that performing the previous step could take
+ * too long) set by the ETableItem->length_threshold that would determine
+ * when the height is computed by using the first row as the size for
+ * every other row in the ETableItem.
+ */
static int
eti_get_height (ETableItem *eti)
{
@@ -148,6 +209,9 @@ eti_get_height (ETableItem *eti)
return height;
}
+/*
+ * Callback routine: invoked when the ETableModel has suffered a change
+ */
static void
eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
{
@@ -160,6 +224,11 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
}
+/*
+ * eti_request_redraw:
+ *
+ * Queues a canvas redraw for the entire ETableItem.
+ */
static void
eti_request_redraw (ETableItem *eti)
{
@@ -170,6 +239,9 @@ eti_request_redraw (ETableItem *eti)
eti->y1 + eti->height + 1);
}
+/*
+ * Computes the distance from @start_col to @end_col in pixels.
+ */
static int
eti_col_diff (ETableItem *eti, int start_col, int end_col)
{
@@ -185,6 +257,9 @@ eti_col_diff (ETableItem *eti, int start_col, int end_col)
return total;
}
+/*
+ * Computes the distance between @start_row and @end_row in pixels
+ */
static int
eti_row_diff (ETableItem *eti, int start_row, int end_row)
{
@@ -198,28 +273,38 @@ eti_row_diff (ETableItem *eti, int start_row, int end_row)
return total;
}
+/*
+ * eti_request_region_redraw:
+ *
+ * Request a canvas redraw on the range (start_col, start_row) to (end_col, end_row).
+ * This is inclusive (ie, you can use: 0,0-0,0 to redraw the first cell).
+ *
+ * The @border argument is a number of pixels around the region that should also be queued
+ * for redraw. This is typically used by the focus routines to queue a redraw for the
+ * border as well.
+ */
static void
-eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row)
+eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row, int border)
{
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
int x1, y1, width, height;
- int col, row;
x1 = eti_col_diff (eti, 0, start_col);
y1 = eti_row_diff (eti, 0, start_row);
- width = eti_col_diff (eti, start_col, end_col);
- height = eti_row_diff (eti, start_col, end_row);
-
+ width = eti_col_diff (eti, start_col, end_col + 1);
+ height = eti_row_diff (eti, start_row, end_row + 1);
+
gnome_canvas_request_redraw (canvas,
- eti->x1 + x1, eti->y1 + y1,
- eti->y1 + width + 1,
- eti->x1 + height + 1);
+ eti->x1 + x1 - border,
+ eti->y1 + y1 - border,
+ eti->x1 + x1 + width + 1 + border,
+ eti->y1 + y1 + height + 1 + border);
}
static void
eti_table_model_row_selection (ETableModel *table_model, int row, gboolean selected, ETableItem *eti)
{
- eti_request_region_redraw (eti, 0, row, eti->cols, row);
+ eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
}
static void
@@ -282,6 +367,9 @@ eti_add_header_model (ETableItem *eti, ETableHeader *header)
GTK_SIGNAL_FUNC (eti_header_structure_changed), eti);
}
+/*
+ * GtkObject::destroy method
+ */
static void
eti_destroy (GtkObject *object)
{
@@ -289,6 +377,8 @@ eti_destroy (GtkObject *object)
eti_remove_header_model (eti);
eti_remove_table_model (eti);
+
+ g_slist_free (eti->selection);
if (GTK_OBJECT_CLASS (eti_parent_class)->destroy)
(*GTK_OBJECT_CLASS (eti_parent_class)->destroy) (object);
@@ -299,7 +389,6 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableItem *eti;
- int v;
item = GNOME_CANVAS_ITEM (o);
eti = E_TABLE_ITEM (o);
@@ -343,6 +432,8 @@ eti_init (GnomeCanvasItem *item)
eti->height = 0;
eti->length_threshold = -1;
+
+ eti->selection_mode = GTK_SELECTION_SINGLE;
}
static void
@@ -355,13 +446,24 @@ eti_realize (GnomeCanvasItem *item)
if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)
(*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)(item);
+ /*
+ * Gdk Resource allocation
+ */
window = canvas_widget->window;
-
+
eti->fill_gc = canvas_widget->style->white_gc;
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]);
+ eti->focus_gc = gdk_gc_new (window);
+ gdk_gc_set_foreground (eti->focus_gc, &canvas_widget->style->black);
+ gdk_gc_set_line_attributes (eti->focus_gc, 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
+
+ /*
+ *
+ */
eti_realize_cell_views (eti);
eti->height = eti_get_height (eti);
@@ -377,7 +479,9 @@ eti_unrealize (GnomeCanvasItem *item)
eti->fill_gc = NULL;
gdk_gc_unref (eti->grid_gc);
eti->grid_gc = NULL;
-
+ gdk_gc_unref (eti->focus_gc);
+ eti->focus_gc = NULL;
+
eti_unrealize_cell_views (eti);
eti->height = 0;
@@ -387,26 +491,28 @@ eti_unrealize (GnomeCanvasItem *item)
}
static void
-draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row,
+draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
- GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
ECellView *ecell_view;
- GdkFont *font;
- char text [40];
-
- font = GTK_WIDGET (canvas)->style->font;
ecell_view = eti->cell_views [col];
- e_cell_draw (ecell_view, drawable, col, row, x1, y1, x2, y2);
+ 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
}
@@ -420,7 +526,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
int first_col, last_col, x_offset;
int first_row, last_row, y_offset, yd;
int x1, x2;
- int heights;
+ int f_x1, f_x2, f_y1, f_y2;
+ gboolean f_found;
printf ("Rect: %d %d %d %d\n", x, y, width, height);
/*
@@ -435,7 +542,7 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
*/
first_col = -1;
last_col = x_offset = 0;
- x1 = eti->x1;
+ x1 = x2 = eti->x1;
for (col = 0; col < cols; col++, x1 = x2){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
@@ -465,9 +572,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
y_offset = 0;
y1 = y2 = eti->y1;
for (row = eti->top_item; row < rows; row++, y1 = y2){
- int xd;
- y2 += eti_row_height (eti, row);
+ y2 += eti_row_height (eti, row) + 1;
if (y1 > y + height)
break;
@@ -489,24 +595,49 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
* Draw cells
*/
yd = y_offset;
+ f_x1 = f_x2 = f_y1 = f_y2 = -1;
+ f_found = FALSE;
for (row = first_row; row < last_row; row++){
int xd, height;
+ gboolean selected;
height = eti_row_height (eti, row);
xd = x_offset;
printf ("paint: %d %d\n", yd, yd + height);
+
+ selected = g_slist_find (eti->selection, GINT_TO_POINTER (row)) != NULL;
+
for (col = first_col; col < last_col; col++){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
- draw_cell (eti, drawable, col, row, xd, yd, xd + ecol->width, yd + height);
+ draw_cell (eti, drawable, col, row, selected, xd, yd, xd + ecol->width, yd + height);
+ if (col == eti->focused_col && row == eti->focused_row){
+ f_x1 = xd;
+ f_x2 = xd + ecol->width;
+ f_y1 = yd;
+ f_y2 = yd + height;
+ f_found = TRUE;
+ }
+
xd += ecol->width;
}
yd += height + 1;
gdk_draw_line (drawable, eti->grid_gc,
eti->x1 - x, yd -1, eti->x1 + eti->width - x, yd -1);
}
+
+ /*
+ * Draw focus
+ */
+ if (f_found){
+ printf ("FOUD: %d %d %d %d!\n",
+ f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
+ gdk_draw_rectangle (
+ drawable, eti->focus_gc, FALSE,
+ f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
+ }
}
static double
@@ -547,7 +678,7 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
break;
}
- y1 = 0;
+ y1 = y2 = 0;
for (row = 0; row < rows; row++, y1 = y2){
if (y < y1)
return FALSE;
@@ -564,13 +695,6 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
return TRUE;
}
-static void
-eti_select (ETableItem *eti, int col, int row)
-{
- eti->selected_col = col;
- eti->selected_row = row;
-}
-
static int
eti_event (GnomeCanvasItem *item, GdkEvent *e)
{
@@ -586,22 +710,56 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
if (!find_cell (eti, e->button.x, e->button.y, &col, &row))
return TRUE;
- if (eti->selected_row == row && eti->selected_col == col){
+ if (eti->focused_row == row && eti->focused_col == col){
ecell_view = eti->cell_views [col];
e_cell_event (ecell_view, e, col, row);
- } else
- eti_select (eti, col, row);
+ } else {
+ /*
+ * Focus the cell, and select the row
+ */
+ e_table_item_focus (eti, col, row);
+ e_table_item_select_row (eti, row);
+ }
break;
}
case GDK_KEY_PRESS:
- case GDK_KEY_RELEASE:
if (eti->focused_col == -1)
return FALSE;
+ switch (e->key.keyval){
+ case GDK_Left:
+ if (eti->focused_col > 0)
+ e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row);
+ break;
+
+ case GDK_Right:
+ if ((eti->focused_col + 1) < eti->cols)
+ e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row);
+ break;
+
+ case GDK_Up:
+ if (eti->focused_row > 0)
+ e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1);
+ break;
+
+ case GDK_Down:
+ if ((eti->focused_row + 1) < eti->rows)
+ e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1);
+ break;
+
+ default:
+ }
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);
break;
@@ -610,12 +768,27 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
}
return TRUE;
}
+
+/*
+ * ETableItem::row_selection method
+ */
+static void
+eti_row_selection (ETableItem *eti, int row, gboolean selected)
+{
+ eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
+ if (selected)
+ eti->selection = g_slist_prepend (eti->selection, GINT_TO_POINTER (row));
+ else
+ eti->selection = g_slist_remove (eti->selection, GINT_TO_POINTER (row));
+}
+
static void
eti_class_init (GtkObjectClass *object_class)
{
GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
-
+ ETableItemClass *eti_class = (ETableItemClass *) object_class;
+
eti_parent_class = gtk_type_class (PARENT_OBJECT_TYPE);
object_class->destroy = eti_destroy;
@@ -627,7 +800,9 @@ eti_class_init (GtkObjectClass *object_class)
item_class->draw = eti_draw;
item_class->point = eti_point;
item_class->event = eti_event;
-
+
+ eti_class->row_selection = eti_row_selection;
+
gtk_object_add_arg_type ("ETableItem::ETableHeader", GTK_TYPE_POINTER,
GTK_ARG_WRITABLE, ARG_TABLE_HEADER);
gtk_object_add_arg_type ("ETableItem::ETableModel", GTK_TYPE_POINTER,
@@ -638,6 +813,17 @@ eti_class_init (GtkObjectClass *object_class)
GTK_ARG_WRITABLE, ARG_TABLE_Y);
gtk_object_add_arg_type ("ETableItem::drawgrid", GTK_TYPE_BOOL,
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID);
+
+ eti_signals [ROW_SELECTION] =
+ gtk_signal_new ("row_selection",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableItemClass, row_selection),
+ gtk_marshal_NONE__INT_INT,
+ GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, eti_signals, LAST_SIGNAL);
+
}
GtkType
@@ -666,16 +852,124 @@ e_table_item_get_type (void)
void
e_table_item_focus (ETableItem *eti, int col, int row)
{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
if (eti->focused_col != -1)
e_table_item_unfocus (eti);
eti->focused_col = col;
- eti->focused_row = row;
+ eti->focused_row = row;
+
+ eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
}
void
e_table_item_unfocus (ETableItem *eti)
{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ if (eti->focused_row == -1)
+ return;
+
+ {
+ const int col = eti->focused_col;
+ const int row = eti->focused_row;
+
+ eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
+ }
eti->focused_col = -1;
eti->focused_row = -1;
}
+
+const GSList *
+e_table_item_get_selection (ETableItem *eti)
+{
+ g_return_val_if_fail (eti != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_ITEM (eti), NULL);
+
+ return eti->selection;
+}
+
+GtkSelectionMode
+e_table_item_get_selection_mode (ETableItem *eti)
+{
+ g_return_val_if_fail (eti != NULL, GTK_SELECTION_SINGLE);
+ g_return_val_if_fail (E_IS_TABLE_ITEM (eti), GTK_SELECTION_SINGLE);
+
+ return eti->selection_mode;
+}
+
+void
+e_table_item_set_selection_mode (ETableItem *eti, GtkSelectionMode selection_mode)
+{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ if (selection_mode == GTK_SELECTION_BROWSE ||
+ selection_mode == GTK_SELECTION_EXTENDED){
+ g_error ("GTK_SELECTION_BROWSE and GTK_SELECTION_EXTENDED are not implemented");
+ }
+
+ eti->selection_mode = selection_mode;
+}
+
+gboolean
+e_table_item_is_row_selected (ETableItem *eti, int row)
+{
+ g_return_val_if_fail (eti != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_ITEM (eti), FALSE);
+
+ if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void
+e_table_item_unselect_row (ETableItem *eti, int row)
+{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ if (e_table_item_is_row_selected (eti, row)){
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ row, 0);
+ }
+}
+
+void
+e_table_item_select_row (ETableItem *eti, int row)
+{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ switch (eti->selection_mode){
+ case GTK_SELECTION_SINGLE:
+ if (eti->selection){
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ GPOINTER_TO_INT (eti->selection->data), 0);
+ }
+ g_slist_free (eti->selection);
+ eti->selection = NULL;
+
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ GINT_TO_POINTER (row), 1);
+ break;
+
+ case GTK_SELECTION_MULTIPLE:
+ if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
+ return;
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ GINT_TO_POINTER (row), 1);
+ break;
+
+ default:
+
+ }
+}
diff --git a/widgets/e-table/e-table-item.h b/widgets/e-table/e-table-item.h
index fc36363413..17d422ddf5 100644
--- a/widgets/e-table/e-table-item.h
+++ b/widgets/e-table/e-table-item.h
@@ -32,6 +32,7 @@ typedef struct {
GdkGC *fill_gc;
GdkGC *grid_gc;
+ GdkGC *focus_gc;
unsigned int draw_grid:1;
@@ -49,15 +50,39 @@ typedef struct {
*/
int length_threshold;
- int selected_col, selected_row;
+ GSList *selection;
+ GtkSelectionMode selection_mode;
} ETableItem;
typedef struct {
GnomeCanvasItemClass parent_class;
+
+ void (*row_selection) (ETableItem *eti, int row, gboolean selected);
} ETableItemClass;
GtkType e_table_item_get_type (void);
+
+/*
+ * Focus
+ */
void e_table_item_focus (ETableItem *eti, int col, int row);
void e_table_item_unfocus (ETableItem *eti);
+/*
+ * Selection
+ */
+void e_table_item_select_row (ETableItem *e_table_Item, int row);
+void e_table_item_unselect_row (ETableItem *e_table_Item, int row);
+
+/*
+ * Handling the selection
+ */
+const GSList*e_table_item_get_selection (ETableItem *e_table_Item);
+
+GtkSelectionMode e_table_item_get_selection_mode (ETableItem *e_table_Item);
+void e_table_item_set_selection_mode (ETableItem *e_table_Item,
+ GtkSelectionMode selection_mode);
+gboolean e_table_item_is_row_selected (ETableItem *e_table_Item,
+ int row);
+
#endif /* _E_TABLE_ITEM_H_ */
diff --git a/widgets/e-table/e-table-model.c b/widgets/e-table/e-table-model.c
index 3aa4e4be47..288c20f20e 100644
--- a/widgets/e-table/e-table-model.c
+++ b/widgets/e-table/e-table-model.c
@@ -16,55 +16,71 @@ static GtkObjectClass *e_table_model_parent_class;
enum {
MODEL_CHANGED,
+ MODEL_ROW_CHANGED,
+ MODEL_CELL_CHANGED,
ROW_SELECTION,
LAST_SIGNAL
};
-static guint etm_signals [LAST_SIGNAL] = { 0, };
+static guint e_table_model_signals [LAST_SIGNAL] = { 0, };
int
-e_table_model_column_count (ETableModel *etable)
+e_table_model_column_count (ETableModel *e_table_model)
{
- return ETM_CLASS (etable)->column_count (etable);
+ g_return_val_if_fail (e_table_model != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
+
+ return ETM_CLASS (e_table_model)->column_count (e_table_model);
}
const char *
-e_table_model_column_name (ETableModel *etable, int col)
+e_table_model_column_name (ETableModel *e_table_model, int col)
{
- return ETM_CLASS (etable)->column_name (etable, col);
+ g_return_val_if_fail (e_table_model != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
+
+ return ETM_CLASS (e_table_model)->column_name (e_table_model, col);
}
int
-e_table_model_row_count (ETableModel *etable)
+e_table_model_row_count (ETableModel *e_table_model)
{
- return ETM_CLASS (etable)->row_count (etable);
+ g_return_val_if_fail (e_table_model != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
+
+ return ETM_CLASS (e_table_model)->row_count (e_table_model);
}
void *
-e_table_model_value_at (ETableModel *etable, int col, int row)
+e_table_model_value_at (ETableModel *e_table_model, int col, int row)
{
- return ETM_CLASS (etable)->value_at (etable, col, row);
+ g_return_val_if_fail (e_table_model != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
+
+ return ETM_CLASS (e_table_model)->value_at (e_table_model, col, row);
}
void
-e_table_model_set_value_at (ETableModel *etable, int col, int row, void *data)
+e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data)
{
- return ETM_CLASS (etable)->set_value_at (etable, col, row, data);
+ 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);
}
gboolean
-e_table_model_is_cell_editable (ETableModel *etable, int col, int row)
+e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row)
{
- return ETM_CLASS (etable)->is_cell_editable (etable, col, row);
+ g_return_val_if_fail (e_table_model != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), FALSE);
+
+ return ETM_CLASS (e_table_model)->is_cell_editable (e_table_model, col, row);
}
static void
e_table_model_destroy (GtkObject *object)
{
- GSList *l;
-
- ETableModel *etable = (ETableModel *) object;
-
if (e_table_model_parent_class->destroy)
(*e_table_model_parent_class->destroy)(object);
}
@@ -76,7 +92,7 @@ e_table_model_class_init (GtkObjectClass *object_class)
object_class->destroy = e_table_model_destroy;
- etm_signals [MODEL_CHANGED] =
+ e_table_model_signals [MODEL_CHANGED] =
gtk_signal_new ("model_changed",
GTK_RUN_LAST,
object_class->type,
@@ -84,21 +100,23 @@ e_table_model_class_init (GtkObjectClass *object_class)
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
- etm_signals [ROW_SELECTION] =
- gtk_signal_new ("row_selection",
+ e_table_model_signals [MODEL_ROW_CHANGED] =
+ gtk_signal_new ("model_row_changed",
GTK_RUN_LAST,
object_class->type,
- GTK_SIGNAL_OFFSET (ETableModelClass, row_selection),
+ GTK_SIGNAL_OFFSET (ETableModelClass, model_row_changed),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+
+ e_table_model_signals [MODEL_CELL_CHANGED] =
+ gtk_signal_new ("model_cell_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableModelClass, model_cell_changed),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
-
- gtk_object_class_add_signals (object_class, etm_signals, LAST_SIGNAL);
-}
-static void
-e_table_model_init (ETableModel *etm)
-{
- etm->row_selected = -1;
+ gtk_object_class_add_signals (object_class, e_table_model_signals, LAST_SIGNAL);
}
GtkType
@@ -112,7 +130,7 @@ e_table_model_get_type (void)
sizeof (ETableModel),
sizeof (ETableModelClass),
(GtkClassInitFunc) e_table_model_class_init,
- (GtkObjectInitFunc) e_table_model_init,
+ (GtkObjectInitFunc) NULL,
NULL, /* reserved 1 */
NULL, /* reserved 2 */
(GtkClassInitFunc) NULL
@@ -127,53 +145,31 @@ e_table_model_get_type (void)
void
e_table_model_changed (ETableModel *e_table_model)
{
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
+
gtk_signal_emit (GTK_OBJECT (e_table_model),
- etm_signals [MODEL_CHANGED]);
+ e_table_model_signals [MODEL_CHANGED]);
}
-#if 0
-int
-e_table_model_max_col_width (ETableModel *etm, int col)
+void
+e_table_model_row_changed (ETableModel *e_table_model, int row)
{
- const int nvals = e_table_model_row_count (etm);
- int max = 0;
- int row;
-
- for (row = 0; row < nvals; row++){
- int w;
-
- w = e_table_model_cell_width (etm, col, i);
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
- if (w > max)
- max = w;
- }
-
- return max;
+ gtk_signal_emit (GTK_OBJECT (e_table_model),
+ e_table_model_signals [MODEL_ROW_CHANGED], row);
}
-#endif
void
-e_table_model_select_row (ETableModel *etm, int row)
+e_table_model_cell_changed (ETableModel *e_table_model, int col, int row)
{
- gtk_signal_emit (GTK_OBJECT (etm), etm_signals [ROW_SELECTION], row, 1);
- etm->row_selected = row;
-}
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
-void
-e_table_model_unselect_row (ETableModel *etm, int row)
-{
- if (etm->row_selected != -1){
- gtk_signal_emit (
- GTK_OBJECT (etm), etm_signals [ROW_SELECTION],
- etm->row_selected, 0);
- }
-
- etm->row_selected = -1;
+ gtk_signal_emit (GTK_OBJECT (e_table_model),
+ e_table_model_signals [MODEL_CELL_CHANGED], col, row);
}
-gint
-e_table_model_get_selected_row (ETableModel *etm)
-{
- return etm->row_selected;
-}
diff --git a/widgets/e-table/e-table-model.h b/widgets/e-table/e-table-model.h
index d8de9e819e..ea5d31493d 100644
--- a/widgets/e-table/e-table-model.h
+++ b/widgets/e-table/e-table-model.h
@@ -11,9 +11,6 @@
typedef struct {
GtkObject base;
-
- /* Temporary. I swear */
- int row_selected;
} ETableModel;
typedef struct {
@@ -32,8 +29,9 @@ typedef struct {
/*
* Signals
*/
- void (*model_changed) (ETableModel *etm);
- void (*row_selection) (ETableModel *etc, int row, gboolean selected);
+ void (*model_changed) (ETableModel *etm);
+ void (*model_row_changed) (ETableModel *etm, int row);
+ void (*model_cell_changed) (ETableModel *etm, int col, int row);
} ETableModelClass;
GtkType e_table_model_get_type (void);
@@ -45,13 +43,13 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col,
void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data);
gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row);
-void e_table_model_select_row (ETableModel *e_table_model, int row);
-gint e_table_model_get_selected_row (ETableModel *e_table_model);
-
/*
* Routines for emitting signals on the e_table
*/
void e_table_model_changed (ETableModel *e_table_model);
+void e_table_model_row_changed (ETableModel *e_table_model, int row);
+void e_table_model_cell_changed (ETableModel *e_table_model, int col, int row);
#endif /* _E_TABLE_MODEL_H_ */
+
diff --git a/widgets/e-table/e-table-sorted.c b/widgets/e-table/e-table-sorted.c
index be19de2efb..90773e9cdc 100644
--- a/widgets/e-table/e-table-sorted.c
+++ b/widgets/e-table/e-table-sorted.c
@@ -30,7 +30,6 @@ static ETableSorted *sort_ets;
static int
my_sort (const void *a, const void *b)
{
- GCompareFunc comp;
ETableModel *source = E_TABLE_SUBSET (sort_ets)->source;
const int *ia = (const int *) a;
const int *ib = (const int *) b;
@@ -59,7 +58,6 @@ e_table_sorted_new (ETableModel *source, int col, GCompareFunc compare)
ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE);
ETableSubset *etss = E_TABLE_SUBSET (ets);
const int nvals = e_table_model_row_count (source);
- unsigned int *buffer;
int i;
if (e_table_subset_construct (etss, source, nvals) == NULL){
diff --git a/widgets/e-table/table-test.c b/widgets/e-table/table-test.c
index 73be9e5ecd..3517ecf692 100644
--- a/widgets/e-table/table-test.c
+++ b/widgets/e-table/table-test.c
@@ -12,6 +12,8 @@
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-table-item.h"
+#include "e-cursors.h"
+#include "e-cell-text.h"
char buffer [1024];
char **column_labels;
@@ -157,7 +159,7 @@ set_value_at (ETableModel *etc, int col, int row, void *val, void *data)
g_free (table_data [row][col]);
table_data [row][col] = g_strdup (val);
- printf ("Value at %d,%d set to %s\n", col, row, val);
+ printf ("Value at %d,%d set to %s\n", col, row, (char *) val);
}
static gboolean
diff --git a/widgets/table-test.c b/widgets/table-test.c
index 73be9e5ecd..3517ecf692 100644
--- a/widgets/table-test.c
+++ b/widgets/table-test.c
@@ -12,6 +12,8 @@
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-table-item.h"
+#include "e-cursors.h"
+#include "e-cell-text.h"
char buffer [1024];
char **column_labels;
@@ -157,7 +159,7 @@ set_value_at (ETableModel *etc, int col, int row, void *val, void *data)
g_free (table_data [row][col]);
table_data [row][col] = g_strdup (val);
- printf ("Value at %d,%d set to %s\n", col, row, val);
+ printf ("Value at %d,%d set to %s\n", col, row, (char *) val);
}
static gboolean
diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c
index da26302664..a997d745d3 100644
--- a/widgets/table/e-cell-text.c
+++ b/widgets/table/e-cell-text.c
@@ -64,13 +64,14 @@ ect_unrealize (ECellView *ecv)
}
static void
-ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
+ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int 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;
GdkRectangle rect;
const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row);
- int selected = e_table_model_get_selected_row (ecell_view->ecell->table_model) == row;
int xoff, w;
rect.x = x1;
@@ -94,6 +95,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1
xoff = ((x2 - x1) - gdk_text_width (text_view->font, str, strlen (str))) / 2;
break;
default:
+ xoff = 0;
g_warning ("Can not handle GTK_JUSTIFY_FILL");
break;
}
@@ -135,12 +137,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
switch (event->type){
case GDK_BUTTON_PRESS:
- if (e_table_model_get_selected_row (ecell->table_model) == row)
- e_cell_text_start_editing (ect, col, row);
- else
- e_table_model_select_row (ecell->table_model, row);
return TRUE;
+
+ default:
+ break;
}
+ return FALSE;
}
static int
diff --git a/widgets/table/e-cell.c b/widgets/table/e-cell.c
index 8a8897c22a..9caa31f2ca 100644
--- a/widgets/table/e-cell.c
+++ b/widgets/table/e-cell.c
@@ -24,7 +24,9 @@ ec_unrealize (ECellView *e_cell)
}
static void
-ec_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
+ec_draw (ECellView *ecell_view, GdkDrawable *drawable,
+ int col, int row, gboolean selected,
+ int x1, int y1, int x2, int y2)
{
g_warning ("e-cell-draw invoked\n");
}
@@ -33,6 +35,7 @@ static gint
ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
{
g_warning ("e-cell-event invoked\n");
+ return 0;
}
static gint
@@ -109,10 +112,10 @@ e_cell_unrealize (ECellView *ecell_view)
void
e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable,
- int col, int row, int x1, int y1, int x2, int y2)
+ int 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, x1, y1, x2, y2);
+ ecell_view, drawable, col, row, selected, x1, y1, x2, y2);
}
int
diff --git a/widgets/table/e-cell.h b/widgets/table/e-cell.h
index e57f341098..9cd62f3909 100644
--- a/widgets/table/e-cell.h
+++ b/widgets/table/e-cell.h
@@ -32,7 +32,7 @@ typedef struct {
ECellView *(*realize) (ECell *, GnomeCanvas *canvas);
void (*unrealize) (ECellView *);
void (*draw) (ECellView *ecell_view, GdkDrawable *drawable,
- int col, int row, int x1, int y1, int x2, int y2);
+ 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, int col, int row, int x1, int y1, int x2, int y2);
void (*unfocus) (ECellView *ecell);
@@ -43,8 +43,9 @@ GtkType e_cell_get_type (void);
void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row);
ECellView *e_cell_realize (ECell *ecell, GnomeCanvas *canvas);
void e_cell_unrealize (ECellView *ecell_view);
-void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
- int col, int row, int x1, int y1, int x2, int y2);
+void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
+ int col, int row, gboolean selected,
+ 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);
diff --git a/widgets/table/e-table-col.c b/widgets/table/e-table-col.c
index 4c61cddd0f..3ffc45a2ed 100644
--- a/widgets/table/e-table-col.c
+++ b/widgets/table/e-table-col.c
@@ -17,11 +17,11 @@ e_table_col_new (const char *id, int width, int min_width,
{
ETableCol *etc;
- g_return_if_fail (id != NULL);
- g_return_if_fail (width >= 0);
- g_return_if_fail (min_width >= 0);
- g_return_if_fail (width >= min_width);
- g_return_if_fail (compare != NULL);
+ g_return_val_if_fail (id != NULL, NULL);
+ g_return_val_if_fail (width >= 0, NULL);
+ g_return_val_if_fail (min_width >= 0, NULL);
+ g_return_val_if_fail (width >= min_width, NULL);
+ g_return_val_if_fail (compare != NULL, NULL);
etc = g_new (ETableCol, 1);
diff --git a/widgets/table/e-table-group.c b/widgets/table/e-table-group.c
index bc751229a4..b1e681d255 100644
--- a/widgets/table/e-table-group.c
+++ b/widgets/table/e-table-group.c
@@ -76,10 +76,11 @@ e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
etg->u.children = g_slist_append (etg->u.children, child);
}
+#if 0
int
e_table_group_size (ETableGroup *etg)
{
- g_return_if_fail (etg != NULL);
+ g_return_val_if_fail (etg != NULL, 0);
if (etg->is_leaf)
return e_table_model_height (etg->u.table);
@@ -96,3 +97,4 @@ e_table_group_size (ETableGroup *etg)
}
}
+#endif
diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c
index 2ee8e2d619..1be7e7097b 100644
--- a/widgets/table/e-table-header-item.c
+++ b/widgets/table/e-table-header-item.c
@@ -7,6 +7,7 @@
* Copyright 1999, Helix Code, Inc.
*/
#include <config.h>
+#include <gtk/gtksignal.h>
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-cursors.h"
@@ -124,7 +125,6 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableHeaderItem *ethi;
- int v;
item = GNOME_CANVAS_ITEM (o);
ethi = E_TABLE_HEADER_ITEM (o);
diff --git a/widgets/table/e-table-header.c b/widgets/table/e-table-header.c
index 2279bf4ba6..5900c5ca4f 100644
--- a/widgets/table/e-table-header.c
+++ b/widgets/table/e-table-header.c
@@ -121,8 +121,6 @@ eth_update_offsets (ETableHeader *eth)
void
e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos)
{
- ETableCol **new_ptr;
-
g_return_if_fail (eth != NULL);
g_return_if_fail (E_IS_TABLE_HEADER (eth));
g_return_if_fail (tc != NULL);
@@ -204,7 +202,6 @@ ETableCol **
e_table_header_get_columns (ETableHeader *eth)
{
ETableCol **ret;
- int i;
g_return_val_if_fail (eth != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
@@ -226,7 +223,7 @@ e_table_header_selection_ok (ETableHeader *eth)
}
int
-ve_table_header_get_selected (ETableHeader *eth)
+e_table_header_get_selected (ETableHeader *eth)
{
int i;
int selected = 0;
diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c
index 3b35f6c156..a561fbfd15 100644
--- a/widgets/table/e-table-item.c
+++ b/widgets/table/e-table-item.c
@@ -1,20 +1,36 @@
/*
- * E-table-item.c: A view of a Table.
+ * E-table-item.c: A GnomeCanvasItem that is a view of an ETableModel.
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
* Copyright 1999, Helix Code, Inc.
+ *
+ * TODO:
+ * Add a border to the thing, so that focusing works properly.
+ *
*/
#include <config.h>
+#include <stdio.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
#include "e-table-item.h"
#include "e-cell.h"
#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
+#define FOCUSED_BORDER 2
+
static GnomeCanvasItemClass *eti_parent_class;
enum {
+ ROW_SELECTION,
+ LAST_SIGNAL
+};
+
+static gint eti_signals [LAST_SIGNAL] = { 0, };
+
+enum {
ARG_0,
ARG_TABLE_HEADER,
ARG_TABLE_MODEL,
@@ -24,6 +40,14 @@ enum {
ARG_LENGHT_THRESHOLD
};
+/*
+ * During realization, we have to invoke the per-ecell realize routine
+ * (On our current setup, we have one e-cell per column.
+ *
+ * We might want to optimize this to only realize the unique e-cells:
+ * ie, a strings-only table, uses the same e-cell for every column, and
+ * we might want to avoid realizing each e-cell.
+ */
static void
eti_realize_cell_views (ETableItem *eti)
{
@@ -43,14 +67,16 @@ eti_realize_cell_views (ETableItem *eti)
}
}
+/*
+ * During unrealization: we invoke every e-cell (one per column in the current
+ * setup) to dispose all resources allocated
+ */
static void
eti_unrealize_cell_views (ETableItem *eti)
{
int i;
for (i = 0; i < eti->n_cells; i++){
- ETableCol *col = e_table_header_get_column (eti->header, i);
-
e_cell_unrealize (eti->cell_views [i]);
eti->cell_views [i] = NULL;
}
@@ -59,6 +85,9 @@ eti_unrealize_cell_views (ETableItem *eti)
}
+/*
+ * GnomeCanvasItem::update method
+ */
static void
eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
{
@@ -75,14 +104,21 @@ eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
}
+/*
+ * eti_remove_table_model:
+ *
+ * Invoked to release the table model associated with this ETableItem
+ */
static void
eti_remove_table_model (ETableItem *eti)
{
if (!eti->table_model)
return;
- gtk_signal_disconnect (eti->table_model_change_id);
- gtk_signal_disconnect (eti->table_model_selection_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
+ eti->table_model_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
+ eti->table_model_selection_id);
gtk_object_unref (GTK_OBJECT (eti->table_model));
eti->table_model_change_id = 0;
@@ -90,14 +126,21 @@ eti_remove_table_model (ETableItem *eti)
eti->table_model = NULL;
}
+/*
+ * eti_remove_header_model:
+ *
+ * Invoked to release the header model associated with this ETableItem
+ */
static void
eti_remove_header_model (ETableItem *eti)
{
if (!eti->header)
return;
- gtk_signal_disconnect (eti->header_structure_change_id);
- gtk_signal_disconnect (eti->header_dim_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->header),
+ eti->header_structure_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (eti->header),
+ eti->header_dim_change_id);
gtk_object_unref (GTK_OBJECT (eti->header));
eti->header_structure_change_id = 0;
@@ -105,6 +148,12 @@ eti_remove_header_model (ETableItem *eti)
eti->header = NULL;
}
+/*
+ * eti_row_height:
+ *
+ * Returns the height used by row @row. This does not include the one-pixel
+ * used as a separator between rows
+ */
static int
eti_row_height (ETableItem *eti, int row)
{
@@ -123,6 +172,18 @@ eti_row_height (ETableItem *eti, int row)
return max_h;
}
+/*
+ * eti_get_height:
+ *
+ * Returns the height of the ETableItem.
+ *
+ * The ETableItem might compute the whole height by asking every row its
+ * size. There is a special mode (designed to work when there are too
+ * many rows in the table that performing the previous step could take
+ * too long) set by the ETableItem->length_threshold that would determine
+ * when the height is computed by using the first row as the size for
+ * every other row in the ETableItem.
+ */
static int
eti_get_height (ETableItem *eti)
{
@@ -148,6 +209,9 @@ eti_get_height (ETableItem *eti)
return height;
}
+/*
+ * Callback routine: invoked when the ETableModel has suffered a change
+ */
static void
eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
{
@@ -160,6 +224,11 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
}
+/*
+ * eti_request_redraw:
+ *
+ * Queues a canvas redraw for the entire ETableItem.
+ */
static void
eti_request_redraw (ETableItem *eti)
{
@@ -170,6 +239,9 @@ eti_request_redraw (ETableItem *eti)
eti->y1 + eti->height + 1);
}
+/*
+ * Computes the distance from @start_col to @end_col in pixels.
+ */
static int
eti_col_diff (ETableItem *eti, int start_col, int end_col)
{
@@ -185,6 +257,9 @@ eti_col_diff (ETableItem *eti, int start_col, int end_col)
return total;
}
+/*
+ * Computes the distance between @start_row and @end_row in pixels
+ */
static int
eti_row_diff (ETableItem *eti, int start_row, int end_row)
{
@@ -198,28 +273,38 @@ eti_row_diff (ETableItem *eti, int start_row, int end_row)
return total;
}
+/*
+ * eti_request_region_redraw:
+ *
+ * Request a canvas redraw on the range (start_col, start_row) to (end_col, end_row).
+ * This is inclusive (ie, you can use: 0,0-0,0 to redraw the first cell).
+ *
+ * The @border argument is a number of pixels around the region that should also be queued
+ * for redraw. This is typically used by the focus routines to queue a redraw for the
+ * border as well.
+ */
static void
-eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row)
+eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row, int border)
{
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
int x1, y1, width, height;
- int col, row;
x1 = eti_col_diff (eti, 0, start_col);
y1 = eti_row_diff (eti, 0, start_row);
- width = eti_col_diff (eti, start_col, end_col);
- height = eti_row_diff (eti, start_col, end_row);
-
+ width = eti_col_diff (eti, start_col, end_col + 1);
+ height = eti_row_diff (eti, start_row, end_row + 1);
+
gnome_canvas_request_redraw (canvas,
- eti->x1 + x1, eti->y1 + y1,
- eti->y1 + width + 1,
- eti->x1 + height + 1);
+ eti->x1 + x1 - border,
+ eti->y1 + y1 - border,
+ eti->x1 + x1 + width + 1 + border,
+ eti->y1 + y1 + height + 1 + border);
}
static void
eti_table_model_row_selection (ETableModel *table_model, int row, gboolean selected, ETableItem *eti)
{
- eti_request_region_redraw (eti, 0, row, eti->cols, row);
+ eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
}
static void
@@ -282,6 +367,9 @@ eti_add_header_model (ETableItem *eti, ETableHeader *header)
GTK_SIGNAL_FUNC (eti_header_structure_changed), eti);
}
+/*
+ * GtkObject::destroy method
+ */
static void
eti_destroy (GtkObject *object)
{
@@ -289,6 +377,8 @@ eti_destroy (GtkObject *object)
eti_remove_header_model (eti);
eti_remove_table_model (eti);
+
+ g_slist_free (eti->selection);
if (GTK_OBJECT_CLASS (eti_parent_class)->destroy)
(*GTK_OBJECT_CLASS (eti_parent_class)->destroy) (object);
@@ -299,7 +389,6 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableItem *eti;
- int v;
item = GNOME_CANVAS_ITEM (o);
eti = E_TABLE_ITEM (o);
@@ -343,6 +432,8 @@ eti_init (GnomeCanvasItem *item)
eti->height = 0;
eti->length_threshold = -1;
+
+ eti->selection_mode = GTK_SELECTION_SINGLE;
}
static void
@@ -355,13 +446,24 @@ eti_realize (GnomeCanvasItem *item)
if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)
(*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)(item);
+ /*
+ * Gdk Resource allocation
+ */
window = canvas_widget->window;
-
+
eti->fill_gc = canvas_widget->style->white_gc;
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]);
+ eti->focus_gc = gdk_gc_new (window);
+ gdk_gc_set_foreground (eti->focus_gc, &canvas_widget->style->black);
+ gdk_gc_set_line_attributes (eti->focus_gc, 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
+
+ /*
+ *
+ */
eti_realize_cell_views (eti);
eti->height = eti_get_height (eti);
@@ -377,7 +479,9 @@ eti_unrealize (GnomeCanvasItem *item)
eti->fill_gc = NULL;
gdk_gc_unref (eti->grid_gc);
eti->grid_gc = NULL;
-
+ gdk_gc_unref (eti->focus_gc);
+ eti->focus_gc = NULL;
+
eti_unrealize_cell_views (eti);
eti->height = 0;
@@ -387,26 +491,28 @@ eti_unrealize (GnomeCanvasItem *item)
}
static void
-draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row,
+draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
- GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
ECellView *ecell_view;
- GdkFont *font;
- char text [40];
-
- font = GTK_WIDGET (canvas)->style->font;
ecell_view = eti->cell_views [col];
- e_cell_draw (ecell_view, drawable, col, row, x1, y1, x2, y2);
+ 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
}
@@ -420,7 +526,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
int first_col, last_col, x_offset;
int first_row, last_row, y_offset, yd;
int x1, x2;
- int heights;
+ int f_x1, f_x2, f_y1, f_y2;
+ gboolean f_found;
printf ("Rect: %d %d %d %d\n", x, y, width, height);
/*
@@ -435,7 +542,7 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
*/
first_col = -1;
last_col = x_offset = 0;
- x1 = eti->x1;
+ x1 = x2 = eti->x1;
for (col = 0; col < cols; col++, x1 = x2){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
@@ -465,9 +572,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
y_offset = 0;
y1 = y2 = eti->y1;
for (row = eti->top_item; row < rows; row++, y1 = y2){
- int xd;
- y2 += eti_row_height (eti, row);
+ y2 += eti_row_height (eti, row) + 1;
if (y1 > y + height)
break;
@@ -489,24 +595,49 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
* Draw cells
*/
yd = y_offset;
+ f_x1 = f_x2 = f_y1 = f_y2 = -1;
+ f_found = FALSE;
for (row = first_row; row < last_row; row++){
int xd, height;
+ gboolean selected;
height = eti_row_height (eti, row);
xd = x_offset;
printf ("paint: %d %d\n", yd, yd + height);
+
+ selected = g_slist_find (eti->selection, GINT_TO_POINTER (row)) != NULL;
+
for (col = first_col; col < last_col; col++){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
- draw_cell (eti, drawable, col, row, xd, yd, xd + ecol->width, yd + height);
+ draw_cell (eti, drawable, col, row, selected, xd, yd, xd + ecol->width, yd + height);
+ if (col == eti->focused_col && row == eti->focused_row){
+ f_x1 = xd;
+ f_x2 = xd + ecol->width;
+ f_y1 = yd;
+ f_y2 = yd + height;
+ f_found = TRUE;
+ }
+
xd += ecol->width;
}
yd += height + 1;
gdk_draw_line (drawable, eti->grid_gc,
eti->x1 - x, yd -1, eti->x1 + eti->width - x, yd -1);
}
+
+ /*
+ * Draw focus
+ */
+ if (f_found){
+ printf ("FOUD: %d %d %d %d!\n",
+ f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
+ gdk_draw_rectangle (
+ drawable, eti->focus_gc, FALSE,
+ f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
+ }
}
static double
@@ -547,7 +678,7 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
break;
}
- y1 = 0;
+ y1 = y2 = 0;
for (row = 0; row < rows; row++, y1 = y2){
if (y < y1)
return FALSE;
@@ -564,13 +695,6 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
return TRUE;
}
-static void
-eti_select (ETableItem *eti, int col, int row)
-{
- eti->selected_col = col;
- eti->selected_row = row;
-}
-
static int
eti_event (GnomeCanvasItem *item, GdkEvent *e)
{
@@ -586,22 +710,56 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
if (!find_cell (eti, e->button.x, e->button.y, &col, &row))
return TRUE;
- if (eti->selected_row == row && eti->selected_col == col){
+ if (eti->focused_row == row && eti->focused_col == col){
ecell_view = eti->cell_views [col];
e_cell_event (ecell_view, e, col, row);
- } else
- eti_select (eti, col, row);
+ } else {
+ /*
+ * Focus the cell, and select the row
+ */
+ e_table_item_focus (eti, col, row);
+ e_table_item_select_row (eti, row);
+ }
break;
}
case GDK_KEY_PRESS:
- case GDK_KEY_RELEASE:
if (eti->focused_col == -1)
return FALSE;
+ switch (e->key.keyval){
+ case GDK_Left:
+ if (eti->focused_col > 0)
+ e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row);
+ break;
+
+ case GDK_Right:
+ if ((eti->focused_col + 1) < eti->cols)
+ e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row);
+ break;
+
+ case GDK_Up:
+ if (eti->focused_row > 0)
+ e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1);
+ break;
+
+ case GDK_Down:
+ if ((eti->focused_row + 1) < eti->rows)
+ e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1);
+ break;
+
+ default:
+ }
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);
break;
@@ -610,12 +768,27 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
}
return TRUE;
}
+
+/*
+ * ETableItem::row_selection method
+ */
+static void
+eti_row_selection (ETableItem *eti, int row, gboolean selected)
+{
+ eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
+ if (selected)
+ eti->selection = g_slist_prepend (eti->selection, GINT_TO_POINTER (row));
+ else
+ eti->selection = g_slist_remove (eti->selection, GINT_TO_POINTER (row));
+}
+
static void
eti_class_init (GtkObjectClass *object_class)
{
GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
-
+ ETableItemClass *eti_class = (ETableItemClass *) object_class;
+
eti_parent_class = gtk_type_class (PARENT_OBJECT_TYPE);
object_class->destroy = eti_destroy;
@@ -627,7 +800,9 @@ eti_class_init (GtkObjectClass *object_class)
item_class->draw = eti_draw;
item_class->point = eti_point;
item_class->event = eti_event;
-
+
+ eti_class->row_selection = eti_row_selection;
+
gtk_object_add_arg_type ("ETableItem::ETableHeader", GTK_TYPE_POINTER,
GTK_ARG_WRITABLE, ARG_TABLE_HEADER);
gtk_object_add_arg_type ("ETableItem::ETableModel", GTK_TYPE_POINTER,
@@ -638,6 +813,17 @@ eti_class_init (GtkObjectClass *object_class)
GTK_ARG_WRITABLE, ARG_TABLE_Y);
gtk_object_add_arg_type ("ETableItem::drawgrid", GTK_TYPE_BOOL,
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID);
+
+ eti_signals [ROW_SELECTION] =
+ gtk_signal_new ("row_selection",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableItemClass, row_selection),
+ gtk_marshal_NONE__INT_INT,
+ GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, eti_signals, LAST_SIGNAL);
+
}
GtkType
@@ -666,16 +852,124 @@ e_table_item_get_type (void)
void
e_table_item_focus (ETableItem *eti, int col, int row)
{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
if (eti->focused_col != -1)
e_table_item_unfocus (eti);
eti->focused_col = col;
- eti->focused_row = row;
+ eti->focused_row = row;
+
+ eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
}
void
e_table_item_unfocus (ETableItem *eti)
{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ if (eti->focused_row == -1)
+ return;
+
+ {
+ const int col = eti->focused_col;
+ const int row = eti->focused_row;
+
+ eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
+ }
eti->focused_col = -1;
eti->focused_row = -1;
}
+
+const GSList *
+e_table_item_get_selection (ETableItem *eti)
+{
+ g_return_val_if_fail (eti != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_ITEM (eti), NULL);
+
+ return eti->selection;
+}
+
+GtkSelectionMode
+e_table_item_get_selection_mode (ETableItem *eti)
+{
+ g_return_val_if_fail (eti != NULL, GTK_SELECTION_SINGLE);
+ g_return_val_if_fail (E_IS_TABLE_ITEM (eti), GTK_SELECTION_SINGLE);
+
+ return eti->selection_mode;
+}
+
+void
+e_table_item_set_selection_mode (ETableItem *eti, GtkSelectionMode selection_mode)
+{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ if (selection_mode == GTK_SELECTION_BROWSE ||
+ selection_mode == GTK_SELECTION_EXTENDED){
+ g_error ("GTK_SELECTION_BROWSE and GTK_SELECTION_EXTENDED are not implemented");
+ }
+
+ eti->selection_mode = selection_mode;
+}
+
+gboolean
+e_table_item_is_row_selected (ETableItem *eti, int row)
+{
+ g_return_val_if_fail (eti != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_ITEM (eti), FALSE);
+
+ if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void
+e_table_item_unselect_row (ETableItem *eti, int row)
+{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ if (e_table_item_is_row_selected (eti, row)){
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ row, 0);
+ }
+}
+
+void
+e_table_item_select_row (ETableItem *eti, int row)
+{
+ g_return_if_fail (eti != NULL);
+ g_return_if_fail (E_IS_TABLE_ITEM (eti));
+
+ switch (eti->selection_mode){
+ case GTK_SELECTION_SINGLE:
+ if (eti->selection){
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ GPOINTER_TO_INT (eti->selection->data), 0);
+ }
+ g_slist_free (eti->selection);
+ eti->selection = NULL;
+
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ GINT_TO_POINTER (row), 1);
+ break;
+
+ case GTK_SELECTION_MULTIPLE:
+ if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
+ return;
+ gtk_signal_emit (
+ GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
+ GINT_TO_POINTER (row), 1);
+ break;
+
+ default:
+
+ }
+}
diff --git a/widgets/table/e-table-item.h b/widgets/table/e-table-item.h
index fc36363413..17d422ddf5 100644
--- a/widgets/table/e-table-item.h
+++ b/widgets/table/e-table-item.h
@@ -32,6 +32,7 @@ typedef struct {
GdkGC *fill_gc;
GdkGC *grid_gc;
+ GdkGC *focus_gc;
unsigned int draw_grid:1;
@@ -49,15 +50,39 @@ typedef struct {
*/
int length_threshold;
- int selected_col, selected_row;
+ GSList *selection;
+ GtkSelectionMode selection_mode;
} ETableItem;
typedef struct {
GnomeCanvasItemClass parent_class;
+
+ void (*row_selection) (ETableItem *eti, int row, gboolean selected);
} ETableItemClass;
GtkType e_table_item_get_type (void);
+
+/*
+ * Focus
+ */
void e_table_item_focus (ETableItem *eti, int col, int row);
void e_table_item_unfocus (ETableItem *eti);
+/*
+ * Selection
+ */
+void e_table_item_select_row (ETableItem *e_table_Item, int row);
+void e_table_item_unselect_row (ETableItem *e_table_Item, int row);
+
+/*
+ * Handling the selection
+ */
+const GSList*e_table_item_get_selection (ETableItem *e_table_Item);
+
+GtkSelectionMode e_table_item_get_selection_mode (ETableItem *e_table_Item);
+void e_table_item_set_selection_mode (ETableItem *e_table_Item,
+ GtkSelectionMode selection_mode);
+gboolean e_table_item_is_row_selected (ETableItem *e_table_Item,
+ int row);
+
#endif /* _E_TABLE_ITEM_H_ */
diff --git a/widgets/table/e-table-model.c b/widgets/table/e-table-model.c
index 3aa4e4be47..288c20f20e 100644
--- a/widgets/table/e-table-model.c
+++ b/widgets/table/e-table-model.c
@@ -16,55 +16,71 @@ static GtkObjectClass *e_table_model_parent_class;
enum {
MODEL_CHANGED,
+ MODEL_ROW_CHANGED,
+ MODEL_CELL_CHANGED,
ROW_SELECTION,
LAST_SIGNAL
};
-static guint etm_signals [LAST_SIGNAL] = { 0, };
+static guint e_table_model_signals [LAST_SIGNAL] = { 0, };
int
-e_table_model_column_count (ETableModel *etable)
+e_table_model_column_count (ETableModel *e_table_model)
{
- return ETM_CLASS (etable)->column_count (etable);
+ g_return_val_if_fail (e_table_model != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
+
+ return ETM_CLASS (e_table_model)->column_count (e_table_model);
}
const char *
-e_table_model_column_name (ETableModel *etable, int col)
+e_table_model_column_name (ETableModel *e_table_model, int col)
{
- return ETM_CLASS (etable)->column_name (etable, col);
+ g_return_val_if_fail (e_table_model != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
+
+ return ETM_CLASS (e_table_model)->column_name (e_table_model, col);
}
int
-e_table_model_row_count (ETableModel *etable)
+e_table_model_row_count (ETableModel *e_table_model)
{
- return ETM_CLASS (etable)->row_count (etable);
+ g_return_val_if_fail (e_table_model != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
+
+ return ETM_CLASS (e_table_model)->row_count (e_table_model);
}
void *
-e_table_model_value_at (ETableModel *etable, int col, int row)
+e_table_model_value_at (ETableModel *e_table_model, int col, int row)
{
- return ETM_CLASS (etable)->value_at (etable, col, row);
+ g_return_val_if_fail (e_table_model != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
+
+ return ETM_CLASS (e_table_model)->value_at (e_table_model, col, row);
}
void
-e_table_model_set_value_at (ETableModel *etable, int col, int row, void *data)
+e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data)
{
- return ETM_CLASS (etable)->set_value_at (etable, col, row, data);
+ 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);
}
gboolean
-e_table_model_is_cell_editable (ETableModel *etable, int col, int row)
+e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row)
{
- return ETM_CLASS (etable)->is_cell_editable (etable, col, row);
+ g_return_val_if_fail (e_table_model != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), FALSE);
+
+ return ETM_CLASS (e_table_model)->is_cell_editable (e_table_model, col, row);
}
static void
e_table_model_destroy (GtkObject *object)
{
- GSList *l;
-
- ETableModel *etable = (ETableModel *) object;
-
if (e_table_model_parent_class->destroy)
(*e_table_model_parent_class->destroy)(object);
}
@@ -76,7 +92,7 @@ e_table_model_class_init (GtkObjectClass *object_class)
object_class->destroy = e_table_model_destroy;
- etm_signals [MODEL_CHANGED] =
+ e_table_model_signals [MODEL_CHANGED] =
gtk_signal_new ("model_changed",
GTK_RUN_LAST,
object_class->type,
@@ -84,21 +100,23 @@ e_table_model_class_init (GtkObjectClass *object_class)
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
- etm_signals [ROW_SELECTION] =
- gtk_signal_new ("row_selection",
+ e_table_model_signals [MODEL_ROW_CHANGED] =
+ gtk_signal_new ("model_row_changed",
GTK_RUN_LAST,
object_class->type,
- GTK_SIGNAL_OFFSET (ETableModelClass, row_selection),
+ GTK_SIGNAL_OFFSET (ETableModelClass, model_row_changed),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+
+ e_table_model_signals [MODEL_CELL_CHANGED] =
+ gtk_signal_new ("model_cell_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableModelClass, model_cell_changed),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
-
- gtk_object_class_add_signals (object_class, etm_signals, LAST_SIGNAL);
-}
-static void
-e_table_model_init (ETableModel *etm)
-{
- etm->row_selected = -1;
+ gtk_object_class_add_signals (object_class, e_table_model_signals, LAST_SIGNAL);
}
GtkType
@@ -112,7 +130,7 @@ e_table_model_get_type (void)
sizeof (ETableModel),
sizeof (ETableModelClass),
(GtkClassInitFunc) e_table_model_class_init,
- (GtkObjectInitFunc) e_table_model_init,
+ (GtkObjectInitFunc) NULL,
NULL, /* reserved 1 */
NULL, /* reserved 2 */
(GtkClassInitFunc) NULL
@@ -127,53 +145,31 @@ e_table_model_get_type (void)
void
e_table_model_changed (ETableModel *e_table_model)
{
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
+
gtk_signal_emit (GTK_OBJECT (e_table_model),
- etm_signals [MODEL_CHANGED]);
+ e_table_model_signals [MODEL_CHANGED]);
}
-#if 0
-int
-e_table_model_max_col_width (ETableModel *etm, int col)
+void
+e_table_model_row_changed (ETableModel *e_table_model, int row)
{
- const int nvals = e_table_model_row_count (etm);
- int max = 0;
- int row;
-
- for (row = 0; row < nvals; row++){
- int w;
-
- w = e_table_model_cell_width (etm, col, i);
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
- if (w > max)
- max = w;
- }
-
- return max;
+ gtk_signal_emit (GTK_OBJECT (e_table_model),
+ e_table_model_signals [MODEL_ROW_CHANGED], row);
}
-#endif
void
-e_table_model_select_row (ETableModel *etm, int row)
+e_table_model_cell_changed (ETableModel *e_table_model, int col, int row)
{
- gtk_signal_emit (GTK_OBJECT (etm), etm_signals [ROW_SELECTION], row, 1);
- etm->row_selected = row;
-}
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
-void
-e_table_model_unselect_row (ETableModel *etm, int row)
-{
- if (etm->row_selected != -1){
- gtk_signal_emit (
- GTK_OBJECT (etm), etm_signals [ROW_SELECTION],
- etm->row_selected, 0);
- }
-
- etm->row_selected = -1;
+ gtk_signal_emit (GTK_OBJECT (e_table_model),
+ e_table_model_signals [MODEL_CELL_CHANGED], col, row);
}
-gint
-e_table_model_get_selected_row (ETableModel *etm)
-{
- return etm->row_selected;
-}
diff --git a/widgets/table/e-table-model.h b/widgets/table/e-table-model.h
index d8de9e819e..ea5d31493d 100644
--- a/widgets/table/e-table-model.h
+++ b/widgets/table/e-table-model.h
@@ -11,9 +11,6 @@
typedef struct {
GtkObject base;
-
- /* Temporary. I swear */
- int row_selected;
} ETableModel;
typedef struct {
@@ -32,8 +29,9 @@ typedef struct {
/*
* Signals
*/
- void (*model_changed) (ETableModel *etm);
- void (*row_selection) (ETableModel *etc, int row, gboolean selected);
+ void (*model_changed) (ETableModel *etm);
+ void (*model_row_changed) (ETableModel *etm, int row);
+ void (*model_cell_changed) (ETableModel *etm, int col, int row);
} ETableModelClass;
GtkType e_table_model_get_type (void);
@@ -45,13 +43,13 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col,
void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data);
gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row);
-void e_table_model_select_row (ETableModel *e_table_model, int row);
-gint e_table_model_get_selected_row (ETableModel *e_table_model);
-
/*
* Routines for emitting signals on the e_table
*/
void e_table_model_changed (ETableModel *e_table_model);
+void e_table_model_row_changed (ETableModel *e_table_model, int row);
+void e_table_model_cell_changed (ETableModel *e_table_model, int col, int row);
#endif /* _E_TABLE_MODEL_H_ */
+
diff --git a/widgets/table/e-table-sorted.c b/widgets/table/e-table-sorted.c
index be19de2efb..90773e9cdc 100644
--- a/widgets/table/e-table-sorted.c
+++ b/widgets/table/e-table-sorted.c
@@ -30,7 +30,6 @@ static ETableSorted *sort_ets;
static int
my_sort (const void *a, const void *b)
{
- GCompareFunc comp;
ETableModel *source = E_TABLE_SUBSET (sort_ets)->source;
const int *ia = (const int *) a;
const int *ib = (const int *) b;
@@ -59,7 +58,6 @@ e_table_sorted_new (ETableModel *source, int col, GCompareFunc compare)
ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE);
ETableSubset *etss = E_TABLE_SUBSET (ets);
const int nvals = e_table_model_row_count (source);
- unsigned int *buffer;
int i;
if (e_table_subset_construct (etss, source, nvals) == NULL){
diff --git a/widgets/table/table-test.c b/widgets/table/table-test.c
index 73be9e5ecd..3517ecf692 100644
--- a/widgets/table/table-test.c
+++ b/widgets/table/table-test.c
@@ -12,6 +12,8 @@
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-table-item.h"
+#include "e-cursors.h"
+#include "e-cell-text.h"
char buffer [1024];
char **column_labels;
@@ -157,7 +159,7 @@ set_value_at (ETableModel *etc, int col, int row, void *val, void *data)
g_free (table_data [row][col]);
table_data [row][col] = g_strdup (val);
- printf ("Value at %d,%d set to %s\n", col, row, val);
+ printf ("Value at %d,%d set to %s\n", col, row, (char *) val);
}
static gboolean