[Fwd: [evolution-patches] new gal e-table a11y patches]



Hi,
The attached patch was committed into CVS HEAD for gal module. It includes some string changes.
   Thanks!
      Harry Lu
--- Begin Message ---
Hi, JP

Here is the new e-table a11y patches.

Regards,
Li
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/ChangeLog,v
retrieving revision 1.943
diff -u -r1.943 ChangeLog
--- ChangeLog	21 Dec 2004 20:47:40 -0000	1.943
+++ ChangeLog	27 Jan 2005 02:45:24 -0000
@@ -1,3 +1,52 @@
+2005-01-19  Li Yuan  <li yuan sun com>
+
+	* e-cell-combo.c: (e_cell_combo_init), (e_cell_combo_do_popup),
+	(e_cell_combo_list_button_press), (e_cell_combo_button_press),
+	(e_cell_combo_button_release), (e_cell_combo_key_press):
+	add an a11y name for the popup list.
+	make shortcut key ALT+Arrow work.
+	Fixes #70261
+	* e-cell-text.c: (e_cell_text_class_init), (_delete_selection),
+	(_insert): 
+	add "text_inserted" and "text_deleted" signals to notify the
+	text has been changed.
+	(e_cell_text_get_text_by_view):
+	new helper function to get the text being editted.
+	* e-cell-text.h:
+	add signal declaration.
+	* e-cell-toggle.c: (etog_draw):
+	add range check for negative values.
+	* e-cell-vbox.c: (e_cell_vbox_class_init):
+	* e-cell-vbox.h:
+	make ECellVboxView public since it will be used in a11y part.
+	* e-table-click-to-add.c: (etcta_style_set),
+	(create_rect_and_text), (etcta_realize), (etcta_class_init),
+	(e_table_click_to_add_commit):
+	add "style_set" signal to click_to_add and implement
+	the style_set function.
+	(etcta_init):
+	add a11y name to click to add.
+	* e-table-click-to-add.h:
+	add "style_set" signal to click_to_add and implement
+	the style_set function.
+	* e-table-config.c: (config_button_up), (config_button_down):
+	check whether the columns are empty.
+	* e-table-group-container.c:
+	* e-table-group-container.h:
+	make ETableGroupContainerChildNode public since it
+	will be used in a11y part.
+	* e-table-item.c: (eti_init):
+	init eti->cols.
+	(eti_event):
+	at GDK_KEY_PRESS event and GDK_Down key pressed, we check
+	view_col value before we pass it to eti_e_cell_event.
+	(eti_class_init):
+	call the new initialize function
+	* e-table.c: (table_canvas_focus_event_cb):
+	if canvas has a focused item but the etable does not
+	have a cursor row, just focus the first item after check
+	whether the click_to_add should get the focus.
+
 2004-12-21  JP Rosevear  <jpr novell com>
 
 	Fixes #29309
Index: e-cell-combo.c
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-cell-combo.c,v
retrieving revision 1.17
diff -u -r1.17 e-cell-combo.c
--- e-cell-combo.c	12 Aug 2004 05:10:42 -0000	1.17
+++ e-cell-combo.c	27 Jan 2005 02:45:27 -0000
@@ -56,6 +56,7 @@
 #include <string.h> /* strcmp() */
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
+#include <glib/gi18n.h>
 #include "gal/util/e-util.h"
 #include "gal/widgets/e-unicode.h"
 #include "e-table-item.h"
@@ -135,6 +136,7 @@
 e_cell_combo_init			(ECellCombo	*ecc)
 {
 	GtkWidget *frame;
+	AtkObject *a11y;
 
 	/* We create one popup window for the ECell, since there will only
 	   ever be one popup in use at a time. */
@@ -167,6 +169,9 @@
 					     gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (ecc->popup_scrolled_window)));
 	gtk_widget_show (ecc->popup_list);
 
+	a11y = gtk_widget_get_accessible (ecc->popup_list);
+	atk_object_set_name (a11y, _("popup list"));
+
 	g_signal_connect (ecc->popup_list,
 			  "selection_changed",
 			  G_CALLBACK (e_cell_combo_selection_changed),
@@ -291,6 +296,7 @@
 	if (error_code != 0)
 		g_warning ("Failed to get pointer grab (%i)", error_code);
 	gtk_grab_add (ecc->popup_window);
+	gdk_keyboard_grab (ecc->popup_list->window, TRUE, time);
 
 	return TRUE;
 }
@@ -522,6 +528,7 @@
 	e_cell_combo_update_cell (ecc);
 	gtk_grab_remove (ecc->popup_window);
 	gdk_pointer_ungrab (event->button.time);
+	gdk_keyboard_ungrab (event->button.time);
 	gtk_widget_hide (ecc->popup_window);
 
 	e_cell_popup_set_shown (E_CELL_POPUP (ecc), FALSE);
@@ -561,6 +568,7 @@
 
 	gtk_grab_remove (ecc->popup_window);
 	gdk_pointer_ungrab (event->button.time);
+	gdk_keyboard_ungrab (event->button.time);
 	gtk_widget_hide (ecc->popup_window);
 
 	e_cell_popup_set_shown (E_CELL_POPUP (ecc), FALSE);
@@ -602,6 +610,7 @@
 	   update the cell to reflect the new selection. */
 	gtk_grab_remove (ecc->popup_window);
 	gdk_pointer_ungrab (event->time);
+	gdk_keyboard_ungrab (event->time);
 	gtk_widget_hide (ecc->popup_window);
 
 	e_cell_popup_set_shown (E_CELL_POPUP (ecc), FALSE);
@@ -631,6 +640,7 @@
 
 	gtk_grab_remove (ecc->popup_window);
 	gdk_pointer_ungrab (event->time);
+	gdk_keyboard_ungrab (event->time);
 	gtk_widget_hide (ecc->popup_window);
 
 	e_cell_popup_set_shown (E_CELL_POPUP (ecc), FALSE);
Index: e-cell-text.c
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-cell-text.c,v
retrieving revision 1.137
diff -u -r1.137 e-cell-text.c
--- e-cell-text.c	10 Jun 2004 15:29:14 -0000	1.137
+++ e-cell-text.c	27 Jan 2005 02:45:34 -0000
@@ -59,6 +59,7 @@
 
 #define d(x)
 #define DO_SELECTION 1
+#define VIEW_TO_CELL(view) E_CELL_TEXT (((ECellView *)view)->ecell)
 
 #if d(!)0
 #define e_table_item_leave_edit_(x) (e_table_item_leave_edit((x)), g_print ("%s: e_table_item_leave_edit\n", __FUNCTION__))
@@ -94,6 +95,15 @@
 	E_SELECTION_CLIPBOARD
 };
 
+/* signals */
+enum {
+	TEXT_INSERTED,
+	TEXT_DELETED,
+	LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
 static GdkAtom clipboard_atom = GDK_NONE;
 
 #define PARENT_TYPE e_cell_get_type ()
@@ -1698,6 +1708,30 @@
 
 	parent_class = g_type_class_ref (PARENT_TYPE);
 
+	signals [TEXT_INSERTED] = 
+		g_signal_new ("text_inserted",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_FIRST,
+			      G_STRUCT_OFFSET (ECellTextClass, text_inserted),
+			      NULL, NULL,
+			      e_marshal_VOID__POINTER_INT_INT_INT_INT,
+			      G_TYPE_NONE, 5,
+			      G_TYPE_POINTER, G_TYPE_INT, G_TYPE_INT,
+			      G_TYPE_INT, G_TYPE_INT);
+
+	signals [TEXT_DELETED] = 
+		g_signal_new ("text_deleted",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_FIRST,
+			      G_STRUCT_OFFSET (ECellTextClass, text_deleted),
+			      NULL, NULL,
+			      e_marshal_VOID__POINTER_INT_INT_INT_INT,
+			      G_TYPE_NONE, 5,
+			      G_TYPE_POINTER, G_TYPE_INT, G_TYPE_INT,
+			      G_TYPE_INT, G_TYPE_INT);
+
+
+
 	g_object_class_install_property (object_class, PROP_STRIKEOUT_COLUMN,
 					 g_param_spec_int ("strikeout_column",
 							   _("Strikeout Column"),
@@ -2182,6 +2216,8 @@
 	memmove (sp, ep, length);
 
 	edit->selection_end = edit->selection_start;
+
+	g_signal_emit (VIEW_TO_CELL (text_view), signals[TEXT_DELETED], 0, text_view, edit->selection_start, ep-sp, edit->row, edit->model_col);
 }
 
 /* fixme: */
@@ -2209,6 +2245,8 @@
 
 	edit->selection_start += value;
 	edit->selection_end = edit->selection_start;
+
+	g_signal_emit (VIEW_TO_CELL (text_view), signals[TEXT_INSERTED], 0, text_view, edit->selection_end-value, value, edit->row, edit->model_col);
 }
 
 static void
@@ -2777,4 +2815,40 @@
 	command.action = E_TEP_DELETE;
 	command.position = E_TEP_SELECTION;
 	e_cell_text_view_command (edit->tep, &command, edit);
+}
+
+/**
+ * e_cell_text_get_text_by_view:
+ * @cell_view: the given cell view
+ * @col: column of the given cell in the model
+ * @row: row of the given cell in the model
+ * 
+ * Get the cell's text directly from CellEdit,
+ * during editting this cell, the cell's text value maybe inconsistant
+ * with the text got from table_model.
+ * The caller should free the text after using it.
+ *
+ * This API is most likely to be used by a11y implementations.
+ */
+char *
+e_cell_text_get_text_by_view (ECellView *cell_view, gint col, gint row)
+{
+	ECellTextView *ectv;
+	CellEdit *edit;
+	gchar	*ret, *model_text;
+
+	ectv = (ECellTextView *)cell_view;
+	edit = ectv->edit;
+	
+	if (edit && ectv->edit->row == row && ectv->edit->model_col == col) { /* being editted now */
+		ret = g_strdup (edit->text);
+	} else{
+		model_text = e_cell_text_get_text (E_CELL_TEXT (cell_view->ecell), 
+					     cell_view->e_table_model, col, row);
+		ret = g_strdup (model_text);
+		e_cell_text_free_text (E_CELL_TEXT (cell_view->ecell), model_text);
+	}
+
+	return ret;
+
 }
Index: e-cell-text.h
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-cell-text.h,v
retrieving revision 1.32
diff -u -r1.32 e-cell-text.h
--- e-cell-text.h	2 Dec 2003 07:20:04 -0000	1.32
+++ e-cell-text.h	27 Jan 2005 02:45:34 -0000
@@ -84,6 +84,9 @@
 	char *(*get_text)  (ECellText *cell, ETableModel *model, int col, int row);
 	void  (*free_text) (ECellText *cell, char *text);
 	void  (*set_value) (ECellText *cell, ETableModel *model, int col, int row, const char *text);
+	/* signal handlers */
+	void (*text_inserted) (ECellText *cell, ECellView *cell_view, int pos, int len, int row, int model_col);
+	void (*text_deleted)  (ECellText *cell, ECellView *cell_view, int pos, int len, int row, int model_col);
 } ECellTextClass;
 
 GType      e_cell_text_get_type (void);
@@ -115,6 +118,9 @@
 
 /* Deletes selected text */
 void e_cell_text_delete_selection (ECellView *cell_view, gint col, gint row);
+
+/* get text directly from view, both col and row are model format */
+char *e_cell_text_get_text_by_view (ECellView *cell_view, gint col, gint row);
 
 G_END_DECLS
 
Index: e-cell-toggle.c
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-cell-toggle.c,v
retrieving revision 1.40
diff -u -r1.40 e-cell-toggle.c
--- e-cell-toggle.c	10 Jun 2004 15:29:14 -0000	1.40
+++ e-cell-toggle.c	27 Jan 2005 02:45:35 -0000
@@ -201,7 +201,7 @@
 	
 	selected = flags & E_CELL_SELECTED;
 
-	if (value >= toggle->n_states){
+	if (value < 0 || value >= toggle->n_states){
 		g_warning ("Value from the table model is %d, the states we support are [0..%d)\n",
 			   value, toggle->n_states);
 		return;
Index: e-cell-vbox.c
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-cell-vbox.c,v
retrieving revision 1.4
diff -u -r1.4 e-cell-vbox.c
--- e-cell-vbox.c	17 Nov 2002 00:02:53 -0000	1.4
+++ e-cell-vbox.c	27 Jan 2005 02:45:36 -0000
@@ -42,18 +42,13 @@
 #include <gdk/gdkkeysyms.h>
 
 #include "gal/util/e-util.h"
+#include "gal/a11y/e-table/gal-a11y-e-cell-registry.h"
+#include "gal/a11y/e-table/gal-a11y-e-cell-vbox.h"
 #include "e-table-item.h"
 #include "e-cell-vbox.h"
 
 #define PARENT_TYPE e_cell_get_type ()
 
-typedef struct {
-	ECellView     cell_view;
-	int           subcell_view_count;
-	ECellView   **subcell_views;
-	int          *model_cols;
-} ECellVboxView;
-
 static ECellClass *parent_class;
 
 #define INDENT_AMOUNT 16
@@ -443,6 +438,8 @@
 #endif
 
 	parent_class = g_type_class_ref (PARENT_TYPE);
+
+	gal_a11y_e_cell_registry_add_cell_type (NULL, E_CELL_VBOX_TYPE, gal_a11y_e_cell_vbox_new);
 }
 
 static void
Index: e-cell-vbox.h
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-cell-vbox.h,v
retrieving revision 1.3
diff -u -r1.3 e-cell-vbox.h
--- e-cell-vbox.h	17 Nov 2002 00:02:53 -0000	1.3
+++ e-cell-vbox.h	27 Jan 2005 02:45:36 -0000
@@ -50,6 +50,13 @@
 } ECellVbox;
 
 typedef struct {
+	ECellView     cell_view;
+	int           subcell_view_count;
+	ECellView   **subcell_views;
+	int          *model_cols;
+} ECellVboxView;
+
+typedef struct {
 	ECellClass parent_class;
 } ECellVboxClass;
 
Index: e-table-click-to-add.c
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-table-click-to-add.c,v
retrieving revision 1.39
diff -u -r1.39 e-table-click-to-add.c
--- e-table-click-to-add.c	10 Jun 2004 15:29:14 -0000	1.39
+++ e-table-click-to-add.c	27 Jan 2005 02:45:36 -0000
@@ -29,7 +29,8 @@
 #include <libgnomecanvas/gnome-canvas-rect-ellipse.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <atk/atkregistry.h>
-
+#include <atk/atkutil.h>
+#include <atk/atkgobjectaccessible.h>
 #include "e-table-header.h"
 #include "e-table-click-to-add.h"
 #include "e-table-defines.h"
@@ -44,6 +45,7 @@
 
 enum {
 	CURSOR_CHANGE,
+	STYLE_SET,
 	LAST_SIGNAL
 };
 
@@ -73,6 +75,26 @@
 }
 
 static void
+etcta_style_set (ETableClickToAdd *etcta, GtkStyle *previous_style)
+{
+	GtkWidget *widget = GTK_WIDGET(GNOME_CANVAS_ITEM(etcta)->canvas);
+
+	if (etcta->rect) {
+		gnome_canvas_item_set (etcta->rect,
+					"outline_color_gdk", &widget->style->fg[GTK_STATE_NORMAL], 
+					"fill_color_gdk", &widget->style->bg[GTK_STATE_NORMAL],
+					NULL );
+
+	}
+
+	if (etcta->text)
+		gnome_canvas_item_set (etcta->text,
+					"fill_color_gdk", &widget->style->text[GTK_STATE_NORMAL],
+					NULL);
+
+}
+
+static void
 etcta_add_table_header (ETableClickToAdd *etcta, ETableHeader *header)
 {
 	etcta->eth = header;
@@ -215,6 +237,33 @@
 }
 
 static void
+create_rect_and_text (ETableClickToAdd *etcta)
+{
+	GtkWidget *widget = GTK_WIDGET (GNOME_CANVAS_ITEM(etcta)->canvas);
+
+	if (!etcta->rect)
+		etcta->rect = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etcta),
+					    gnome_canvas_rect_get_type(),
+					    "x1", (double) 0,
+					    "y1", (double) 0,
+					    "x2", (double) etcta->width - 1,
+					    "y2", (double) etcta->height - 1,
+					    "outline_color_gdk", &widget->style->fg[GTK_STATE_NORMAL], 
+					    "fill_color_gdk", &widget->style->bg[GTK_STATE_NORMAL],
+					    NULL);
+
+	if (!etcta->text)
+		etcta->text = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etcta),
+					    e_text_get_type(),
+					    "text", etcta->message ? etcta->message : "",
+					    "anchor", GTK_ANCHOR_NW,
+					    "width", etcta->width - 4,
+					    "draw_background", FALSE,
+					    "fill_color_gdk", &widget->style->text[GTK_STATE_NORMAL],
+					    NULL);
+}
+
+static void
 etcta_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
 	ETableClickToAdd *etcta;
@@ -248,23 +297,7 @@
 {
 	ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (item);
 
-	etcta->rect = gnome_canvas_item_new(GNOME_CANVAS_GROUP(item),
-					    gnome_canvas_rect_get_type(),
-					    "x1", (double) 0,
-					    "y1", (double) 0,
-					    "x2", (double) etcta->width - 1,
-					    "y2", (double) etcta->height - 1,
-					    "outline_color", "black", 
-					    "fill_color", "white",
-					    NULL);
-
-	etcta->text = gnome_canvas_item_new(GNOME_CANVAS_GROUP(item),
-					    e_text_get_type(),
-					    "text", etcta->message ? etcta->message : "",
-					    "anchor", GTK_ANCHOR_NW,
-					    "width", etcta->width - 4,
-					    "draw_background", FALSE,
-					    NULL);
+	create_rect_and_text (etcta);
 	e_canvas_item_move_absolute (etcta->text, 2, 2);
 
 	if (GNOME_CANVAS_ITEM_CLASS (etcta_parent_class)->realize)
@@ -448,6 +481,7 @@
 	etcta_parent_class = g_type_class_ref (PARENT_OBJECT_TYPE);
 
 	klass->cursor_change = NULL;
+	klass->style_set     = etcta_style_set;
 
 	object_class->dispose      = etcta_dispose;
 	object_class->set_property = etcta_set_property;
@@ -501,6 +535,16 @@
 			      e_marshal_VOID__INT_INT,
 			      G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
 
+	etcta_signals [STYLE_SET] =
+		g_signal_new ("style_set",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (ETableClickToAddClass, style_set),
+			      NULL, NULL,
+			      e_marshal_NONE__OBJECT,
+			      G_TYPE_NONE, 1, GTK_TYPE_STYLE);
+
+
 	atk_registry_set_factory_type (atk_get_default_registry (),
 					E_TABLE_CLICK_TO_ADD_TYPE,
 					gal_a11y_e_table_click_to_add_factory_get_type ());
@@ -511,6 +555,7 @@
 etcta_init (GnomeCanvasItem *item)
 {
 	ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (item);
+	AtkObject *a11y;
 
 	etcta->one = NULL;
 	etcta->model = NULL;
@@ -527,6 +572,12 @@
 			 G_CALLBACK (etcta_cursor_change), etcta);
 
 	e_canvas_item_set_reflow_callback(item, etcta_reflow);
+
+	/* create its a11y object at this time if accessibility is enabled*/
+	if (atk_get_root () != NULL) {
+        	a11y = atk_gobject_accessible_for_object (G_OBJECT (etcta));
+		atk_object_set_name (a11y, _("click to add"));
+	}
 }
 
 E_MAKE_TYPE(e_table_click_to_add, "ETableClickToAdd", ETableClickToAdd, etcta_class_init, etcta_init, PARENT_OBJECT_TYPE)
@@ -549,25 +600,6 @@
 		gtk_object_destroy(GTK_OBJECT (etcta->row));
 		etcta->row = NULL;
 	}
-	if (!etcta->rect) {
-		etcta->rect = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etcta),
-						    gnome_canvas_rect_get_type(),
-						    "x1", (double) 0,
-						    "y1", (double) 0,
-						    "x2", (double) etcta->width - 1,
-						    "y2", (double) etcta->height - 1,
-						    "outline_color", "black",
-						    "fill_color", "white",
-						    NULL);
-	}
-	if (!etcta->text) {
-		etcta->text = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etcta),
-						    e_text_get_type(),
-						    "text", etcta->message ? etcta->message : "",
-						    "anchor", GTK_ANCHOR_NW,
-						    "width", etcta->width - 4,
-						    "draw_background", FALSE,
-						    NULL);
-		e_canvas_item_move_absolute (etcta->text, 3, 3);
-	}
+	create_rect_and_text (etcta);
+	e_canvas_item_move_absolute (etcta->text, 3, 3);
 }
Index: e-table-click-to-add.h
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-table-click-to-add.h,v
retrieving revision 1.9
diff -u -r1.9 e-table-click-to-add.h
--- e-table-click-to-add.h	15 Nov 2002 02:22:00 -0000	1.9
+++ e-table-click-to-add.h	27 Jan 2005 02:45:37 -0000
@@ -66,6 +66,7 @@
 	 * signals
 	 */
 	void (*cursor_change) (ETableClickToAdd *etcta, gint row, gint col);
+	void (*style_set) (ETableClickToAdd *etcta, GtkStyle *previous_style);
 } ETableClickToAddClass;
 
 GType      e_table_click_to_add_get_type (void);
Index: e-table-config.c
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-table-config.c,v
retrieving revision 1.66
diff -u -r1.66 e-table-config.c
--- e-table-config.c	4 Aug 2004 09:16:19 -0000	1.66
+++ e-table-config.c	27 Jan 2005 02:45:38 -0000
@@ -947,6 +947,11 @@
 	int i;
 
 	e_table_selected_row_foreach (config->shown, add_column, &columns);
+
+	/* if no columns left, just return */
+	if (columns == NULL)
+		return;
+
 	columns = g_list_reverse (columns);
 
 	new_shown = g_new (int, config->temp_state->col_count);
@@ -997,6 +1002,11 @@
 	int i;
 
 	e_table_selected_row_foreach (config->shown, add_column, &columns);
+
+	/* if no columns left, just return */
+	if (columns == NULL)
+		return;
+
 
 	new_shown = g_new (int, config->temp_state->col_count);
 	new_expansions = g_new (double, config->temp_state->col_count);
Index: e-table-group-container.c
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-table-group-container.c,v
retrieving revision 1.66
diff -u -r1.66 e-table-group-container.c
--- e-table-group-container.c	8 Apr 2003 14:36:55 -0000	1.66
+++ e-table-group-container.c	27 Jan 2005 02:45:39 -0000
@@ -59,15 +59,6 @@
 	PROP_UNIFORM_ROW_HEIGHT
 };
 
-typedef struct {
-	ETableGroup *child;
-	void *key;
-	char *string;
-	GnomeCanvasItem *text;
-	GnomeCanvasItem *rect;
-	gint count;
-} ETableGroupContainerChildNode;
-
 static EPrintable *
 etgc_get_printable (ETableGroup *etg);
 
Index: e-table-group-container.h
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-table-group-container.h,v
retrieving revision 1.19
diff -u -r1.19 e-table-group-container.h
--- e-table-group-container.h	17 Nov 2002 00:02:53 -0000	1.19
+++ e-table-group-container.h	27 Jan 2005 02:45:39 -0000
@@ -84,6 +84,16 @@
 	ETableGroupClass parent_class;
 } ETableGroupContainerClass;
 
+typedef struct {
+        ETableGroup *child;
+        void *key;
+        char *string;
+        GnomeCanvasItem *text;
+        GnomeCanvasItem *rect;
+        gint count;
+} ETableGroupContainerChildNode;
+
+
 ETableGroup *e_table_group_container_new       (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader     *header,
 						ETableModel *model, ETableSortInfo *sort_info, int n);
 void         e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc,
Index: e-table-item.c
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-table-item.c,v
retrieving revision 1.237
diff -u -r1.237 e-table-item.c
--- e-table-item.c	10 Jun 2004 15:29:14 -0000	1.237
+++ e-table-item.c	27 Jan 2005 02:45:47 -0000
@@ -44,6 +44,7 @@
 #include "gal/widgets/e-canvas.h"
 #include "gal/widgets/e-canvas-utils.h"
 #include "gal/util/e-util.h"
+#include "gal/a11y/e-table/gal-a11y-e-table-item.h"
 #include "gal/util/e-i18n.h"
 #include <string.h>
 #include <stdlib.h>
@@ -1647,6 +1648,7 @@
 	eti->cursor_y2                 = -1;
 
 	eti->rows                      = -1;
+	eti->cols                      = -1;
 
 	eti->frozen_count              = 0;
 	eti->queue_show_cursor         = FALSE;
@@ -2669,9 +2671,10 @@
 		case GDK_KP_Down:
 			if ((e->key.state & GDK_MOD1_MASK)
 			    && ((e->key.keyval == GDK_Down ) || (e->key.keyval == GDK_KP_Down))) {
-				gint view_col = model_to_view_col(eti, cursor_col);
-				if (eti_e_cell_event (eti, eti->cell_views [view_col], e, ((GdkEventKey *)e)->time, cursor_col, view_col, model_to_view_row(eti, cursor_row),  E_CELL_CURSOR))
-					return TRUE;
+				gint view_col = model_to_view_col(eti, cursor_col);				
+				if ((view_col >= 0) && (view_col < eti->cols))
+					if (eti_e_cell_event (eti, eti->cell_views [view_col], e, ((GdkEventKey *)e)->time, cursor_col, view_col, model_to_view_row(eti, cursor_row),  E_CELL_CURSOR))
+						return TRUE;
 			} else
 			return_val = e_selection_model_key_press(E_SELECTION_MODEL (eti->selection), (GdkEventKey *) e);
 			break;
@@ -3124,10 +3127,8 @@
 			      G_TYPE_NONE, 1,
 			      G_TYPE_POINTER);
 
-        atk_registry_set_factory_type (atk_get_default_registry (),
-				       E_TABLE_ITEM_TYPE,
-				       gal_a11y_e_table_item_factory_get_type ());
-
+	/* A11y Init */
+	gal_a11y_e_table_item_init ();
 }
 
 E_MAKE_TYPE (e_table_item,
Index: e-table.c
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-table.c,v
retrieving revision 1.232
diff -u -r1.232 e-table.c
--- e-table.c	24 Nov 2004 10:34:55 -0000	1.232
+++ e-table.c	27 Jan 2005 02:45:53 -0000
@@ -1126,6 +1126,14 @@
         	focus_first_etable_item (etable->group);
 	} else if (canvas->focused_item) {
 		ESelectionModel *selection = (ESelectionModel *)etable->selection;
+
+		/* check whether click_to_add already got the focus */
+		if (etable->click_to_add) {
+			GnomeCanvasItem *row = E_TABLE_CLICK_TO_ADD(etable->click_to_add)->row;
+			if (canvas->focused_item == row)
+				return TRUE;
+		}
+
 		if (e_selection_model_cursor_row (selection) == -1)
 			focus_first_etable_item (etable->group);
 	}
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gal/ChangeLog,v
retrieving revision 1.903
diff -u -r1.903 ChangeLog
--- ChangeLog	11 Jan 2005 10:31:55 -0000	1.903
+++ ChangeLog	27 Jan 2005 03:27:22 -0000
@@ -1,3 +1,158 @@
+2005-01-19  Li Yuan  <li yuan sun com>
+
+	* gal/a11y/e-table/Makefile.am:
+	add gal-a11y-e-cell-vbox.h and gal-a11y-e-cell-vbox.c
+
+	* gal/a11y/e-table/gal-a11y-e-cell-popup.c:
+	(gal_a11y_e_cell_popup_new):
+	add i18n support to strings.
+
+	Fixes #70261
+	* gal/a11y/e-table/gal-a11y-e-cell-text.c:
+	(ect_dispose): disconnect the insert and the delete signal.
+	(ect_check):do some check works.
+	(ect_get_name), (ect_get_text),
+	(ect_get_character_at_offset), (ect_get_caret_offset),
+	(ect_get_character_count), (ect_get_n_selections),
+	(ect_get_selection), (ect_add_selection), (ect_set_caret_offset),
+	(ect_insert_text): use e_cell_text_get_text_by_view instead of
+	e_cell_text_get_text. make get_name work well when e-cell-text
+	is being edited.
+	(ect_do_action_edit): call e_table_item_enter_edit only when
+	the cell is editable.
+	(ect_text_inserted_cb), (ect_text_deleted_cb):
+	emit the text_changed::insert(delete) signal. make gnopernicus
+	know the text_changed.
+	(ect_class_init): add dispose function.
+	(ect_action_init): add the edit action.
+	(gal_a11y_e_cell_text_get_type): no ect_init function now.
+	(cell_text_destroyed): unref the atkobject.
+	(gal_a11y_e_cell_text_new): connect text_inserted and text_deleted
+	singals and make sure the state of editable is right.
+	
+	* gal/a11y/e-table/gal-a11y-e-cell-text.h:
+	add two signal handler id.
+	
+	* gal/a11y/e-table/gal-a11y-e-cell-toggle.c:
+	(gal_a11y_e_cell_toggle_dispose): fix #70261.
+	(model_change_cb): make gnopernicus to report state change signal.
+	(gal_a11y_e_cell_toggle_new):add i18n support to strings.
+
+	* gal/a11y/e-table/gal-a11y-e-cell-tree.c:
+	(gal_a11y_e_cell_tree_new):
+	add i18n support to strings.
+
+	Fixes #61688
+	* gal/a11y/e-table/gal-a11y-e-cell-vbox.c: (ecv_get_n_children),
+	(subcell_destroyed), (ecv_ref_child), (ecv_dispose),
+	(ecv_ref_accessible_at_point), (ecv_class_init), (ecv_init),
+	(ecv_atk_component_iface_init), (gal_a11y_e_cell_vbox_get_type),
+	(gal_a11y_e_cell_vbox_new):
+	* gal/a11y/e-table/gal-a11y-e-cell-vbox.h:
+	implement a11y object of ECellVbox.
+
+	Fixes #48976
+	* gal/a11y/e-table/gal-a11y-e-cell.c: 
+	function name are changed form eti_* to gal_a11y_e_cell_*
+	(is_valid): check if the cell is valid.
+	(gal_a11y_e_cell_dispose): make sure state_set is null.
+	(gal_a11y_e_cell_get_name): implement the get_name function.
+	(gal_a11y_e_cell_ref_state_set): add VISIBLE state.
+	(gal_a11y_e_cell_get_parent),
+	(gal_a11y_e_cell_get_index_in_parent),
+	(gal_a11y_e_cell_get_extents):  use e_tree_get_cell_geometry and
+	e_table_get_cell_geometry instead of e_table_item_get_cell_geometry.
+	(gal_a11y_e_cell_grab_focus): make grab_focus work with e-tree also.
+	(gal_a11y_e_cell_atk_component_iface_init),
+	(gal_a11y_e_cell_class_init): add get_name function.
+	(gal_a11y_e_cell_init): add some state to cell.
+	(idle_do_action): check if cell is valid.
+	(gal_a11y_e_cell_action_do_action): check if cell is valid.
+	(gal_a11y_e_cell_get_type), (gal_a11y_e_cell_construct):
+	ref e-table-item.
+	* gal/a11y/e-table/gal-a11y-e-table-click-to-add.c:
+	(etcta_get_description), (etcta_action_get_name): add i18n support to strings.
+	(etcta_get_name): if etcta has message, return it.
+	(etcta_ref_state_set): implement the ref_state_set function,
+	add SENSITIVE and SHOWING state.
+	(etcta_class_init):add ref_state_set function.
+	(etcta_selection_cursor_changed): call atk_focus_tracker_notify
+	to a11y-e-cell
+	(gal_a11y_e_table_click_to_add_new): connect
+	etcta_selection_cursor_changed to cursor_changed signal.
+
+	* gal/a11y/e-table/gal-a11y-e-table-item-factory.c:
+	(gal_a11y_e_table_item_factory_create_accessible):
+	parameters of gal_a11y_e_table_item_new have been changed.
+
+	Fixes #68675
+	Fixes #70324
+	Fixes #68681
+	Fixes #68627
+
+	* gal/a11y/e-table/gal-a11y-e-table-item.c:
+	remove the cell_data support.
+	(item_destroyed): add ATK_STATE_DEFUNCT state and unref selection.
+	(eti_ref_state_set): just ref state_set.
+	(eti_dispose): we have unref selection in item_destroyed.
+	remove the cell_data support.
+	(eti_ref_child): remove support for column header. use eti_ref_at
+	instead of atk_table_ref_at.
+	(eti_get_extents): add support for click to add.
+	(eti_ref_accessible_at_point): e-tree and e-table are different here.
+	(cell_destroyed): add a check and unref item. remove the cell_data support.
+	(eti_ref_at): if e-table-item has DEFUNCT state, return NULL. 
+	remove the cell_data support.
+	(eti_get_column_header): use column name as the a11y name. set it role
+	as ATK_ROLE_TABLE_COLUMN_HEADER.
+	(table_is_row_selected): use view_to_model_row to convert row when
+	uses source model.
+	(table_get_selected_rows): if e-table-item has DEFUNCT state, return 0.
+	(table_remove_row_selection): use view_to_model_row to convert row
+	when uses source model.
+	(eti_rows_inserted), (eti_rows_deleted): remove the cell_data support.
+	(eti_tree_model_node_changed_cb): emit visible-data-changed signal. for
+	the eti_clear_rows have been removed.
+	(eti_header_structure_changed): remove the cell_data support.
+	(eti_class_init): add eti_ref_state_set, remove eti_get_parent
+	and eti_get_index_in_parent.
+	(eti_init): init parent and index_in_parent.
+	(gal_a11y_e_table_item_new): add some states. get name form parents.
+	init role correctly. add FOCUSED state to focused cell. 
+	remove the cell_data support.
+	(eti_a11y_selection_changed_cb): if e-table-item has DEFUNCT state,
+	just return.
+	(eti_a11y_cursor_changed_cb): remove the FOCUESD state form the old cell.
+	(selection_add_selection): if it has been focused already, just return.
+	if another row was focused, clear it first.
+	(selection_ref_selection): use eti_ref_at instead of atk_table_ref_at.
+	(gal_a11y_e_table_item_init): add this function.
+
+	* gal/a11y/e-table/gal-a11y-e-table-item.h:
+	add gal_a11y_e_table_item_init and change the parameters of
+	gal_a11y_e_table_item_new.
+
+	* gal/a11y/e-table/gal-a11y-e-table.c: 
+	(find_first_table_item): find the first item of the group.
+	(eti_get_accessible), (find_table_item): find the first table item.
+	(init_child_item): ref every group's first item.
+	(et_ref_accessible_at_point): no need to call init_child_item here.
+	just ref the item.
+	(et_get_n_children): add support for multiple ETableItems.
+	(et_ref_child): add support for multiple ETableItems.
+	(et_get_layer): Set AtkLayer as ATK_LAYER_WIDGET for e-table.
+	(et_atk_component_iface_init): add et_get_layer function.
+	(gal_a11y_e_table_new):ref the a11y and widget, and unref it in
+	the idle function to avoid crash.
+
+	Fixes #71158
+	* gal/a11y/e-table/gal-a11y-e-tree.c: 
+	(init_child_item): just get the a11y object of the child item.
+	(et_get_layer): Set AtkLayer as ATK_LAYER_WIDGET for etree.
+	(et_atk_component_iface_init): add et_get_layer function.
+	* gal/util/e-marshal.list:
+	add support for the text_inserted and text_deleted signal.
+
 2005-01-10  JP Rosevear  <jpr novell com>
 
 	* configure.in: bump version
Index: gal/util/e-marshal.list
===================================================================
RCS file: /cvs/gnome/gal/gal/util/e-marshal.list,v
retrieving revision 1.5
diff -u -r1.5 e-marshal.list
--- gal/util/e-marshal.list	3 Apr 2003 06:06:20 -0000	1.5
+++ gal/util/e-marshal.list	27 Jan 2005 03:27:22 -0000
@@ -44,6 +44,7 @@
 NONE:POINTER,INT
 NONE:POINTER,INT,INT
 NONE:POINTER,INT,INT,INT
+NONE:POINTER,INT,INT,INT,INT
 NONE:POINTER,INT,OBJECT
 NONE:POINTER,POINTER
 NONE:POINTER,POINTER,INT
? gal/a11y/e-table/.gal-a11y-e-table-item.c.swp
Index: gal/a11y/e-table/Makefile.am
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/Makefile.am,v
retrieving revision 1.7
diff -u -r1.7 Makefile.am
--- gal/a11y/e-table/Makefile.am	17 Dec 2003 02:35:20 -0000	1.7
+++ gal/a11y/e-table/Makefile.am	27 Jan 2005 03:27:28 -0000
@@ -19,6 +19,7 @@
 	gal-a11y-e-cell-toggle.c		\
 	gal-a11y-e-cell-popup.c			\
 	gal-a11y-e-cell-registry.c		\
+	gal-a11y-e-cell-vbox.c			\
 	gal-a11y-e-table.c			\
 	gal-a11y-e-table-item.c			\
 	gal-a11y-e-table-item-factory.c		\
@@ -37,6 +38,7 @@
 	gal-a11y-e-cell-toggle.h		\
 	gal-a11y-e-cell-popup.h			\
 	gal-a11y-e-cell-registry.h		\
+	gal-a11y-e-cell-vbox.h			\
 	gal-a11y-e-table.h			\
 	gal-a11y-e-table-item.h			\
 	gal-a11y-e-table-click-to-add-factory.h	\
Index: gal/a11y/e-table/gal-a11y-e-cell-popup.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-cell-popup.c,v
retrieving revision 1.3
diff -u -r1.3 gal-a11y-e-cell-popup.c
--- gal/a11y/e-table/gal-a11y-e-cell-popup.c	10 Jun 2004 17:00:45 -0000	1.3
+++ gal/a11y/e-table/gal-a11y-e-cell-popup.c	27 Jan 2005 03:27:28 -0000
@@ -31,6 +31,7 @@
 #include <atk/atkobject.h>
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtkwidget.h>
+#include <glib/gi18n.h>
 
 static AtkObjectClass *parent_class = NULL;
 #define PARENT_TYPE (gal_a11y_e_cell_get_type ())
@@ -118,8 +119,8 @@
 	g_return_val_if_fail (a11y != NULL, NULL);
 	cell = GAL_A11Y_E_CELL(a11y);
 	gal_a11y_e_cell_add_action (cell, 
-				    "popup",	       /* action name*/
-				    "popup a child", /* action description */
+				    _("popup"),	       /* action name*/
+				    _("popup a child"), /* action description */
 				    "<Alt>Down",              /* action keybinding */
 				    popup_cell_action);
 
Index: gal/a11y/e-table/gal-a11y-e-cell-text.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-cell-text.c,v
retrieving revision 1.6
diff -u -r1.6 gal-a11y-e-cell-text.c
--- gal/a11y/e-table/gal-a11y-e-cell-text.c	10 Jun 2004 17:00:45 -0000	1.6
+++ gal/a11y/e-table/gal-a11y-e-cell-text.c	27 Jan 2005 03:27:30 -0000
@@ -15,18 +15,84 @@
 #include <atk/atktext.h>
 #include <atk/atkeditabletext.h>
 #include <atk/atkaction.h>
+#include <atk/atkstateset.h>
+#include <glib/gi18n.h>
 
 #define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTextClass))
 static AtkObjectClass *parent_class;
 #define PARENT_TYPE (gal_a11y_e_cell_get_type ())
 
 /* Static functions */
+static void
+ect_dispose (GObject *object)
+{
+	GObjectClass *g_class;
+	GalA11yECell *gaec = GAL_A11Y_E_CELL (object);
+	GalA11yECellText *gaet = GAL_A11Y_E_CELL_TEXT (object);
+
+	if (gaet->inserted_id != 0) {
+		ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
+
+		if (ect) {
+			g_signal_handler_disconnect (ect, gaet->inserted_id);
+			g_signal_handler_disconnect (ect, gaet->deleted_id);
+		}
+
+		gaet->inserted_id = 0;
+		gaet->deleted_id = 0;
+	}
+
+	g_class = (GObjectClass *)parent_class;
+	if (g_class->dispose)
+		g_class->dispose (object);
+
+}
+
+static gboolean
+ect_check (gpointer a11y)
+{
+	GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y);
+	ETableItem *item = gaec->item;
+
+	g_return_val_if_fail ((gaec->item != NULL), FALSE);
+	g_return_val_if_fail ((gaec->cell_view != NULL), FALSE);
+	g_return_val_if_fail ((gaec->cell_view->ecell != NULL), FALSE);
+
+	if (atk_state_set_contains_state (gaec->state_set, ATK_STATE_DEFUNCT))
+		return FALSE;
+
+	if (gaec->row < 0 || gaec->row >= item->rows
+		|| gaec->view_col <0 || gaec->view_col >= item->cols
+		|| gaec->model_col <0 || gaec->model_col >= e_table_model_column_count (item->table_model))
+		return FALSE;
+
+	if (!E_IS_CELL_TEXT (gaec->cell_view->ecell))
+		return FALSE;
+
+	return TRUE;
+}
+
 static G_CONST_RETURN gchar*
 ect_get_name (AtkObject * a11y)
 {
-	GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y);
-	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
-	return e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+	GalA11yECell *gaec;
+	char *name;
+
+	if (!ect_check (a11y))
+		return NULL;
+
+	gaec = GAL_A11Y_E_CELL (a11y);
+	name = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
+	if (name != NULL) {
+		ATK_OBJECT_CLASS (parent_class)->set_name (a11y, name);
+		g_free (name);
+	}
+
+	if (a11y->name != NULL && strcmp (a11y->name, "")) {
+		return a11y->name;
+	} else {
+		return parent_class->get_name (a11y);
+	}
 }
 
 static gchar *
@@ -35,9 +101,13 @@
 	      gint end_offset)
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
-	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
+	gchar *full_text;
 	gchar *ret_val;
-	gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+
+	if (!ect_check (text))
+		return NULL;
+
+	full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
 
 	if (end_offset == -1)
 		end_offset = strlen (full_text);
@@ -48,7 +118,7 @@
 
 	ret_val = g_strndup (full_text + start_offset, end_offset - start_offset);
 
-	e_cell_text_free_text (ect, full_text);
+	g_free (full_text);
 
 	return ret_val;
 }
@@ -80,13 +150,16 @@
 			     gint offset)
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
-	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
 	gunichar ret_val;
 	gchar *at_offset;
-	gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+
+	if (!ect_check (text))
+		return -1;
+
+	gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
 	at_offset = g_utf8_offset_to_pointer (full_text, offset);
 	ret_val = g_utf8_get_char_validated (at_offset, -1);
-	e_cell_text_free_text (ect, full_text);
+	g_free (full_text);
 
 	return ret_val;
 }
@@ -108,18 +181,17 @@
 ect_get_caret_offset (AtkText *text)
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
-	ECellText *ect = NULL;
 	gint start, end;
 
-	g_return_val_if_fail (gaec && gaec->cell_view && gaec->cell_view->ecell && E_IS_CELL_TEXT (gaec->cell_view->ecell), -1);
-	ect = E_CELL_TEXT (gaec->cell_view->ecell);
+	if (!ect_check (text))
+		return -1;
 
 	if (e_cell_text_get_selection (gaec->cell_view,
 				       gaec->view_col, gaec->row,
 				       &start, &end)) {
-		gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+		gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
 		end = g_utf8_pointer_to_offset (full_text, full_text + end);
-		e_cell_text_free_text (ect, full_text);
+		g_free (full_text);
 		
 		return end;
 	}
@@ -163,13 +235,15 @@
 ect_get_character_count (AtkText *text)
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
-	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
 	gint ret_val;
 
-	gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+	if (!ect_check (text))
+		return -1;
+
+	gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
 
 	ret_val = g_utf8_strlen (full_text, -1);
-	e_cell_text_free_text (ect, full_text);
+	g_free (full_text);
 	return ret_val;
 }
 
@@ -190,6 +264,10 @@
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
 	gint selection_start, selection_end;
+
+	if (!ect_check (text))
+		return 0;
+
 	if (e_cell_text_get_selection (gaec->cell_view,
 				       gaec->view_col, gaec->row,
 				       &selection_start,
@@ -207,7 +285,6 @@
 		   gint *end_offset)
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
-	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
 	gchar *ret_val;
 	gint selection_start, selection_end;
 
@@ -218,7 +295,7 @@
 					  &selection_end)
 	    && selection_start != selection_end) {
 		gint real_start, real_end, len;
-		gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+		gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
 		len = strlen (full_text);
 		real_start = MIN (selection_start, selection_end);
 		real_end   = MAX (selection_start, selection_end);
@@ -234,7 +311,7 @@
 			*start_offset = real_start;
 		if (end_offset)
 			*end_offset = real_end;
-		e_cell_text_free_text (ect, full_text);
+		g_free (full_text);
 	} else {
 		if (start_offset)
 			*start_offset = 0;
@@ -253,12 +330,11 @@
 		   gint end_offset)
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
-	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
 
 	if (start_offset != end_offset) {
 		gint real_start, real_end, len;
 		gchar *full_text =
-			e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+			e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
 
 		len = g_utf8_strlen (full_text, -1);
 		if (end_offset == -1)
@@ -272,7 +348,7 @@
 
 		real_start = g_utf8_offset_to_pointer (full_text, real_start) - full_text;
 		real_end   = g_utf8_offset_to_pointer (full_text, real_end) - full_text;
-		e_cell_text_free_text (ect, full_text);
+		g_free (full_text);
 
 		if (e_cell_text_set_selection (gaec->cell_view,
 					       gaec->view_col, gaec->row,
@@ -330,11 +406,10 @@
 		      gint offset)
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
-	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
 	gchar *full_text;
 	gint len;
 
-	full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+	full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
 
 	len = g_utf8_strlen (full_text, -1);
 	if (offset == -1)
@@ -344,7 +419,7 @@
 	
 	offset = g_utf8_offset_to_pointer (full_text, offset) - full_text;
 
-	e_cell_text_free_text (ect, full_text);
+	g_free (full_text);
 
 	return e_cell_text_set_selection (gaec->cell_view,
 					  gaec->view_col, gaec->row,
@@ -382,7 +457,7 @@
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
 	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
 
-	gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+	gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row);
 	gchar *result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position);
 
 	e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, result);
@@ -390,7 +465,7 @@
 	*position += length;
 
 	g_free (result);
-	e_cell_text_free_text (ect, full_text);
+	g_free (full_text);
 }
 
 static void
@@ -443,7 +518,43 @@
 ect_do_action_edit (AtkAction *action)
 {
 	GalA11yECell *a11y = GAL_A11Y_E_CELL (action);
-	e_table_item_enter_edit (a11y->item, a11y->view_col, a11y->row);
+	ETableModel *e_table_model = a11y->item->table_model;
+
+	if (e_table_model_is_cell_editable(e_table_model, a11y->model_col, a11y->row)) {
+		e_table_item_enter_edit (a11y->item, a11y->view_col, a11y->row);
+	}
+}
+
+/* text signal handlers */
+static void
+ect_text_inserted_cb (ECellText *text, ECellView *cell_view, int pos, int len, int row, int model_col, gpointer data)
+{
+	GalA11yECellText *gaet;
+	GalA11yECell *gaec;
+
+	if (!ect_check (data))
+		return;
+	gaet = GAL_A11Y_E_CELL_TEXT (data);
+	gaec = GAL_A11Y_E_CELL (data);
+
+	if (cell_view == gaec->cell_view && row == gaec->row && model_col == gaec->model_col) {
+		g_signal_emit_by_name (gaet, "text_changed::insert", pos, len);
+
+	}
+}
+
+static void
+ect_text_deleted_cb (ECellText *text, ECellView *cell_view, int pos, int len, int row, int model_col, gpointer data)
+{
+	GalA11yECellText *gaet;
+	GalA11yECell *gaec;
+	if (!ect_check (data))
+		return;
+	gaet = GAL_A11Y_E_CELL_TEXT (data);
+	gaec = GAL_A11Y_E_CELL (data);
+	if (cell_view == gaec->cell_view && row == gaec->row && model_col == gaec->model_col) {
+		g_signal_emit_by_name (gaet, "text_changed::delete", pos, len);
+	 }
 }
 
 static void
@@ -483,19 +594,25 @@
 static void
 ect_class_init (GalA11yECellTextClass *klass)
 {
-	AtkObjectClass *a11y      = ATK_OBJECT_CLASS (klass);   
+	AtkObjectClass *a11y      = ATK_OBJECT_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	
 	parent_class              = g_type_class_ref (PARENT_TYPE);
 	a11y->get_name            = ect_get_name;
+	object_class->dispose     = ect_dispose;
 }
 
 static void
-ect_init (GalA11yECellText *a11y)
+ect_action_init (GalA11yECellText *a11y)
 {
-	gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (a11y),
-				    "edit",
-				    "begin editing this cell",
+	GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y);
+	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
+	if (ect->editable && e_table_model_is_cell_editable (gaec->cell_view->e_table_model, gaec->model_col, gaec->row))
+		gal_a11y_e_cell_add_action (gaec,
+				    _("edit"),
+				    _("begin editing this cell"),
 				    NULL,
-				    (ACTION_FUNC)ect_do_action_edit);
+				    (ACTION_FUNC) ect_do_action_edit);
 }
 
 /**
@@ -522,7 +639,7 @@
 			NULL, /* class_data */
 			sizeof (GalA11yECellText),
 			0,
-			(GInstanceInitFunc) ect_init,
+			(GInstanceInitFunc) NULL,
 			NULL /* value_cell_text */
 		};
 
@@ -547,6 +664,14 @@
 	return type;
 }
 
+static void
+cell_text_destroyed (gpointer data)
+{
+	g_return_if_fail (GAL_A11Y_IS_E_CELL_TEXT (data));
+	
+	g_object_unref (data);
+}
+
 AtkObject *
 gal_a11y_e_cell_text_new (ETableItem *item,
 			  ECellView  *cell_view,
@@ -556,6 +681,9 @@
 			  int         row)
 {
 	AtkObject *a11y;
+	GalA11yECell *gaec;
+	GalA11yECellText *gaet;
+	ECellText *ect; 
 
 	a11y = g_object_new (gal_a11y_e_cell_text_get_type (), NULL);
 
@@ -566,5 +694,28 @@
 				   model_col,
 				   view_col,
 				   row);
+	gaet = GAL_A11Y_E_CELL_TEXT (a11y);
+
+	/* will be unrefed in cell_text_destroyed */
+	g_object_ref (a11y);
+
+	gaet->inserted_id = g_signal_connect (E_CELL_TEXT (((ECellView *)cell_view)->ecell),		  
+						"text_inserted", G_CALLBACK (ect_text_inserted_cb), a11y);
+	gaet->deleted_id = g_signal_connect (E_CELL_TEXT (((ECellView *)cell_view)->ecell), 
+					     "text_deleted", G_CALLBACK (ect_text_deleted_cb), a11y);
+
+	g_object_weak_ref (G_OBJECT (((ECellView *)cell_view)->ecell),
+			   (GWeakNotify) cell_text_destroyed,
+			   a11y);
+
+	ect_action_init (gaet);
+
+	ect = E_CELL_TEXT (cell_view->ecell);
+	gaec = GAL_A11Y_E_CELL (a11y);
+	if (ect->editable && e_table_model_is_cell_editable (gaec->cell_view->e_table_model, gaec->model_col, gaec->row))
+		gal_a11y_e_cell_add_state (gaec, ATK_STATE_EDITABLE, FALSE);
+	else
+		gal_a11y_e_cell_remove_state (gaec, ATK_STATE_EDITABLE, FALSE);
+
 	return a11y;
 }
Index: gal/a11y/e-table/gal-a11y-e-cell-text.h
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-cell-text.h,v
retrieving revision 1.1
diff -u -r1.1 gal-a11y-e-cell-text.h
--- gal/a11y/e-table/gal-a11y-e-cell-text.h	30 Nov 2002 07:54:15 -0000	1.1
+++ gal/a11y/e-table/gal-a11y-e-cell-text.h	27 Jan 2005 03:27:30 -0000
@@ -29,6 +29,8 @@
  **/
 struct _GalA11yECellText {
 	GalA11yECell object;
+	gint inserted_id;
+	gint deleted_id;
 };
 
 struct _GalA11yECellTextClass {
Index: gal/a11y/e-table/gal-a11y-e-cell-toggle.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-cell-toggle.c,v
retrieving revision 1.4
diff -u -r1.4 gal-a11y-e-cell-toggle.c
--- gal/a11y/e-table/gal-a11y-e-cell-toggle.c	10 Jun 2004 17:00:45 -0000	1.4
+++ gal/a11y/e-table/gal-a11y-e-cell-toggle.c	27 Jan 2005 03:27:30 -0000
@@ -2,6 +2,8 @@
 #include "gal-a11y-e-cell-toggle.h"
 #include <gal/e-table/e-cell-toggle.h>
 #include <gal/e-table/e-table-model.h>
+#include <atk/atkcomponent.h>
+#include <glib/gi18n.h>
 
 #define PARENT_TYPE  (gal_a11y_e_cell_get_type ())
 static GObjectClass *parent_class;
@@ -15,8 +17,10 @@
 
 	ETableModel *e_table_model = GAL_A11Y_E_CELL (a11y)->item->table_model;
 
-	if (e_table_model)
+	if (e_table_model && a11y->model_id > 0) {
 		g_signal_handler_disconnect (e_table_model, a11y->model_id);
+		a11y->model_id = 0;
+	}
 
 	if (parent_class->dispose)
 		parent_class->dispose (object);
@@ -91,8 +95,8 @@
 
 static void
 model_change_cb (ETableModel *etm,
-		 gint row,
 		 gint col,
+		 gint row,
 		 GalA11yECell *cell)
 {
 	gint value;
@@ -101,7 +105,10 @@
 
 	        value = GPOINTER_TO_INT (
 			e_table_model_value_at (cell->cell_view->e_table_model,
-						cell->model_col, cell->row));
+			 			cell->model_col, cell->row));
+		/* Cheat gnopernicus, or it will ignore the state change signal  */
+                atk_focus_tracker_notify (ATK_OBJECT (cell));
+
 		if (value)
 			gal_a11y_e_cell_add_state (cell, ATK_STATE_CHECKED, TRUE);
 		else
@@ -140,8 +147,8 @@
                                    row);
 
 	gal_a11y_e_cell_add_action (cell, 
-				    "toggle",	       /* action name*/
-				    "toggle the cell", /* action description */
+				    _("toggle"),	       /* action name*/
+				    _("toggle the cell"), /* action description */
 				    NULL,              /* action keybinding */
 				    toggle_cell_action);
 
Index: gal/a11y/e-table/gal-a11y-e-cell-tree.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-cell-tree.c,v
retrieving revision 1.3
diff -u -r1.3 gal-a11y-e-cell-tree.c
--- gal/a11y/e-table/gal-a11y-e-cell-tree.c	10 Jun 2004 17:00:45 -0000	1.3
+++ gal/a11y/e-table/gal-a11y-e-cell-tree.c	27 Jan 2005 03:27:30 -0000
@@ -14,6 +14,7 @@
 #include "gal/e-table/e-cell-tree.h"
 #include "gal/e-table/e-table.h"
 #include "gal/e-table/e-tree-table-adapter.h"
+#include <glib/gi18n.h>
 
 #define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTreeClass))
 static AtkObjectClass *a11y_parent_class;
@@ -164,14 +165,14 @@
 								    view_col,
 								    row);
 		gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (subcell_a11y),
-					    "expand",
-					    "expands the row in the ETree containing this cell",
+					    _("expand"),
+					    _("expands the row in the ETree containing this cell"),
 					    NULL,
 					    (ACTION_FUNC)ectr_do_action_expand);
 
 		gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (subcell_a11y),
-					    "collapse",
-					    "collapses the row in the ETree containing this cell",
+					    _("collapse"),
+					    _("collapses the row in the ETree containing this cell"),
 					    NULL,
 					    (ACTION_FUNC)ectr_do_action_collapse);
 
Index: gal/a11y/e-table/gal-a11y-e-cell-vbox.c
===================================================================
RCS file: gal/a11y/e-table/gal-a11y-e-cell-vbox.c
diff -N gal/a11y/e-table/gal-a11y-e-cell-vbox.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gal/a11y/e-table/gal-a11y-e-cell-vbox.c	27 Jan 2005 03:27:30 -0000
@@ -0,0 +1,214 @@
+/* Evolution Accessibility: gal-a11y-e-cell-vbox.c
+ *
+ * Copyright (C) 2004 Sun Microsystem, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Eric Zhao <eric zhao sun com> Sun Microsystem Inc., 2004
+ *
+ */
+#include "gal-a11y-e-cell-vbox.h"
+#include "gal-a11y-e-cell-registry.h"
+#include <gal/e-table/e-cell-vbox.h>
+#include <atk/atkcomponent.h>
+
+static GObjectClass *parent_class;
+static AtkComponentIface *component_parent_iface;
+#define PARENT_TYPE (gal_a11y_e_cell_get_type ())
+
+static gint
+ecv_get_n_children (AtkObject *a11y)
+{
+	g_return_val_if_fail (GAL_A11Y_IS_E_CELL_VBOX (a11y), 0);
+	GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (a11y);
+	return (gaev->a11y_subcell_count);
+}
+
+static void
+subcell_destroyed (gpointer data)
+{
+	GalA11yECell *cell;
+	AtkObject *parent;
+	GalA11yECellVbox *gaev;
+	
+	g_return_if_fail (GAL_A11Y_IS_E_CELL (data));
+	cell = GAL_A11Y_E_CELL (data);
+
+	parent = atk_object_get_parent (ATK_OBJECT (cell));
+	g_return_if_fail (GAL_A11Y_IS_E_CELL_VBOX (parent));
+	gaev = GAL_A11Y_E_CELL_VBOX (parent);
+
+	if (cell->view_col < gaev->a11y_subcell_count)
+		gaev->a11y_subcells[cell->view_col] = NULL;
+}
+
+static AtkObject*
+ecv_ref_child (AtkObject *a11y, gint i)
+{
+	GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (a11y);
+	GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y);
+	ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view);
+	AtkObject *ret;
+	if (i < gaev->a11y_subcell_count) {
+		if (gaev->a11y_subcells[i] == NULL) {
+			gint model_col, row;
+			row = gaec->row;
+			model_col = ecvv->model_cols[i];
+			ECellView *subcell_view = ecvv->subcell_views[i];
+			ret = gal_a11y_e_cell_registry_get_object (NULL,
+				gaec->item,
+				subcell_view,
+				a11y,
+				model_col,
+				gaec->view_col, /* FIXME should the view column use a fake one or the same as its parent? */
+				row);
+			gaev->a11y_subcells[i] = ret;
+			g_object_ref (ret);
+			g_object_weak_ref (G_OBJECT (ret),
+					(GWeakNotify) subcell_destroyed,
+					ret);
+		} else {
+			ret = (AtkObject *) gaev->a11y_subcells[i];
+			if (ATK_IS_OBJECT (ret))
+				g_object_ref (ret);
+			else
+				ret = NULL;
+		}
+	} else {
+		ret = NULL;
+	}
+
+	return ret;
+}
+
+static void
+ecv_dispose (GObject *object)
+{
+	GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (object);
+	if (gaev->a11y_subcells)
+		g_free (gaev->a11y_subcells);
+
+	if (parent_class->dispose)
+		parent_class->dispose (object);
+}
+
+/* AtkComponet interface */
+static AtkObject*
+ecv_ref_accessible_at_point (AtkComponent *component,
+			     gint x,
+			     gint y,
+			     AtkCoordType coord_type)
+{
+	gint x0, y0, width, height;
+	int subcell_height, i;
+
+	GalA11yECell *gaec = GAL_A11Y_E_CELL (component);
+	ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view);
+
+	atk_component_get_extents (component, &x0, &y0, &width, &height, coord_type);
+	x -= x0;
+	y -= y0;
+	if (x < 0 || x > width || y < 0 || y > height)
+		return NULL;
+
+	for (i = 0; i < ecvv->subcell_view_count; i++) {
+		subcell_height = e_cell_height (ecvv->subcell_views[i], ecvv->model_cols[i], gaec->view_col, gaec->row);
+		if ( 0 <= y && y <= subcell_height) {
+			return ecv_ref_child ((AtkObject *)component, i);
+		} else
+			y -= subcell_height;
+	}
+
+	return NULL;
+}
+
+static void
+ecv_class_init (GalA11yECellVboxClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	AtkObjectClass *a11y_class = ATK_OBJECT_CLASS (klass);
+	parent_class		   = g_type_class_ref (PARENT_TYPE);
+
+	object_class->dispose	   = ecv_dispose;
+
+	a11y_class->get_n_children = ecv_get_n_children;
+	a11y_class->ref_child	   = ecv_ref_child;
+}
+
+static void
+ecv_init (GalA11yECellVbox *a11y)
+{
+}
+
+static void
+ecv_atk_component_iface_init (AtkComponentIface *iface)
+{
+	component_parent_iface         = g_type_interface_peek_parent (iface);
+
+	iface->ref_accessible_at_point = ecv_ref_accessible_at_point;
+}
+
+GType
+gal_a11y_e_cell_vbox_get_type (void)
+{
+	static GType type = 0;
+	if (!type) {
+		GTypeInfo info = {
+			sizeof (GalA11yECellVboxClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) ecv_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL, /* class_data */
+			sizeof (GalA11yECellVbox),
+			0,
+			(GInstanceInitFunc) ecv_init,
+			NULL /* value_cell */
+		};
+
+		static const GInterfaceInfo atk_component_info = {
+			(GInterfaceInitFunc) ecv_atk_component_iface_init,
+			(GInterfaceFinalizeFunc) NULL,
+			NULL
+		};
+
+		type = g_type_register_static (PARENT_TYPE, "GalA11yECellVbox", &info, 0);
+		gal_a11y_e_cell_type_add_action_interface (type);
+		g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info);
+	}
+
+	return type;
+}
+
+AtkObject *gal_a11y_e_cell_vbox_new	(ETableItem *item,
+					 ECellView  *cell_view,
+					 AtkObject  *parent, 
+					 int         model_col, 
+					 int         view_col, 
+					 int         row)
+{
+	AtkObject *a11y;
+
+	a11y = g_object_new (gal_a11y_e_cell_vbox_get_type (), NULL);
+	
+	gal_a11y_e_cell_construct (a11y, item, cell_view, parent, model_col, view_col, row);
+
+	GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y);
+	GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (a11y);
+	ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view);
+	gaev->a11y_subcell_count = ecvv->subcell_view_count; 
+	gaev->a11y_subcells = g_malloc0 (sizeof(AtkObject *)*gaev->a11y_subcell_count);
+	return a11y;
+}
Index: gal/a11y/e-table/gal-a11y-e-cell-vbox.h
===================================================================
RCS file: gal/a11y/e-table/gal-a11y-e-cell-vbox.h
diff -N gal/a11y/e-table/gal-a11y-e-cell-vbox.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gal/a11y/e-table/gal-a11y-e-cell-vbox.h	27 Jan 2005 03:27:30 -0000
@@ -0,0 +1,64 @@
+/* Evolution Accessibility: gal-a11y-e-cell-vbox.h
+ *
+ * Copyright (C) 2004 Sun Microsystem, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Eric Zhao <eric zhao sun com> Sun Microsystem Inc., 2004
+ *
+ */
+#ifndef __GAL_A11Y_E_CELL_VBOX_H__
+#define __GAL_A11Y_E_CELL_VBOX_H__
+
+#include "gal-a11y-e-cell.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GAL_A11Y_TYPE_E_CELL_VBOX            (gal_a11y_e_cell_vbox_get_type ())
+#define GAL_A11Y_E_CELL_VBOX(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_VBOX, GalA11yECellVbox))
+#define GAL_A11Y_E_CELL_VBOX_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_E_CELL_VBOX, GalA11yECellVboxClass))
+#define GAL_A11Y_IS_E_CELL_VBOX(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_VBOX))
+#define GAL_A11Y_IS_E_CELL_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_VBOX))
+#define GAL_A11Y_E_CELL_VBOX_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAL_A11Y_TYPE_E_CELL_VBOX, GalA11yECellVboxClass))
+
+typedef struct _GalA11yECellVbox	GalA11yECellVbox;
+typedef struct _GalA11yECellVboxClass	GalA11yECellVboxClass;
+
+struct _GalA11yECellVbox
+{
+	GalA11yECell	object;
+	int 		a11y_subcell_count;
+	gpointer       *a11y_subcells;
+};
+
+struct _GalA11yECellVboxClass
+{
+	GalA11yECellClass parent_class;
+};
+
+GType gal_a11y_e_cell_vbox_get_type	(void);
+AtkObject *gal_a11y_e_cell_vbox_new	(ETableItem *item,
+					 ECellView  *cell_view,
+					 AtkObject  *parent, 
+					 int         model_col, 
+					 int         view_col, 
+					 int         row);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __GAL_A11Y_E_CELL_VBOX_H__ */
Index: gal/a11y/e-table/gal-a11y-e-cell.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-cell.c,v
retrieving revision 1.8
diff -u -r1.8 gal-a11y-e-cell.c
--- gal/a11y/e-table/gal-a11y-e-cell.c	10 Jun 2004 17:00:45 -0000	1.8
+++ gal/a11y/e-table/gal-a11y-e-cell.c	27 Jan 2005 03:27:30 -0000
@@ -7,7 +7,10 @@
  */
 
 #include <config.h>
+#include <string.h>
 #include "gal/e-table/e-table.h"
+#include "gal/e-table/e-tree.h"
+#include "gal-a11y-e-table-item.h"
 #include "gal-a11y-e-cell.h"
 #include "gal-a11y-util.h"
 #include <atk/atkobject.h>
@@ -15,6 +18,7 @@
 #include <atk/atkaction.h>
 #include <atk/atkstateset.h>
 #include <gtk/gtkwindow.h>
+#include <glib/gi18n.h>
 
 #define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellClass))
 static GObjectClass *parent_class;
@@ -39,8 +43,28 @@
 }
 #endif 
 
+static gboolean 
+is_valid (AtkObject *cell)
+{
+	GalA11yECell *a11y = GAL_A11Y_E_CELL (cell);
+	GalA11yETableItem *a11yItem = GAL_A11Y_E_TABLE_ITEM (a11y->parent);
+	AtkStateSet *item_ss;
+	gboolean ret = TRUE;
+
+	item_ss = atk_object_ref_state_set (ATK_OBJECT (a11yItem));
+	if (atk_state_set_contains_state (item_ss, ATK_STATE_DEFUNCT))
+		ret = FALSE;
+
+	g_object_unref (item_ss);
+
+	if (ret && atk_state_set_contains_state (a11y->state_set, ATK_STATE_DEFUNCT))
+		ret = FALSE;
+
+	return ret;
+}
+
 static void
-eti_dispose (GObject *object)
+gal_a11y_e_cell_dispose (GObject *object)
 {
 	GalA11yECell *a11y = GAL_A11Y_E_CELL (object);
 
@@ -53,43 +77,69 @@
 		g_object_unref (a11y->parent);
 #endif
 
-	if (a11y->state_set)
+	if (a11y->state_set) {
 		g_object_unref (a11y->state_set);
+		a11y->state_set = NULL;
+	}
 
 	if (parent_class->dispose)
 		parent_class->dispose (object);
+
 }
 
 /* Static functions */
+static G_CONST_RETURN gchar*
+gal_a11y_e_cell_get_name (AtkObject * a11y)
+{
+	GalA11yECell *cell = GAL_A11Y_E_CELL (a11y);
+        ETableCol *ecol;
+
+	if (a11y->name != NULL && strcmp (a11y->name, ""))
+		return a11y->name;
+
+	if (cell->item != NULL) {
+ 		ecol = e_table_header_get_column (cell->item->header, cell->view_col);
+		if (ecol != NULL)
+			return ecol->text;
+	}
+
+	return _("Table Cell");
+}
+
 static AtkStateSet *
-eti_ref_state_set (AtkObject *accessible)
+gal_a11y_e_cell_ref_state_set (AtkObject *accessible)
 {
 	GalA11yECell *cell = GAL_A11Y_E_CELL (accessible);
-	g_return_val_if_fail (cell->state_set, NULL);
 
+	g_return_val_if_fail (cell->state_set, NULL);
+                                                                              
 	g_object_ref(cell->state_set);
+
 	return cell->state_set;
 }
 
 static AtkObject*
-eti_get_parent (AtkObject *accessible)
+gal_a11y_e_cell_get_parent (AtkObject *accessible)
 {
 	GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible);
 	return a11y->parent;
 }
 
 static gint
-eti_get_index_in_parent (AtkObject *accessible)
+gal_a11y_e_cell_get_index_in_parent (AtkObject *accessible)
 {
 	GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible);
 
+	if (!is_valid (accessible))
+		return -1;
+
 	return a11y->row * a11y->item->cols + a11y->view_col;
 }
 
 
 /* Component IFace */
 static void
-eti_get_extents (AtkComponent *component,
+gal_a11y_e_cell_get_extents (AtkComponent *component,
 		gint *x,
 		gint *y,
 		gint *width,
@@ -97,6 +147,7 @@
 		AtkCoordType coord_type)
 {
 	GalA11yECell *a11y = GAL_A11Y_E_CELL (component);
+	GtkWidget *tableOrTree;
 	int row;
 	int col;
 	int xval;
@@ -105,14 +156,16 @@
 	row = a11y->row;
 	col = a11y->view_col;
 
-
-	e_table_item_get_cell_geometry (a11y->item,
-					&row, 
-					&col,
-					&xval,
-					&yval,
-					width,
-					height);
+	tableOrTree = gtk_widget_get_parent (GTK_WIDGET (a11y->item->parent.canvas));
+	if (E_IS_TREE (tableOrTree)) {
+		e_tree_get_cell_geometry (E_TREE (tableOrTree),
+					row, col, &xval, &yval,
+					width, height);
+	} else {
+		e_table_get_cell_geometry (E_TABLE (tableOrTree),
+					row, col, &xval, &yval,
+					width, height);
+	}
 
 	atk_component_get_position (ATK_COMPONENT (a11y->parent),
 				    x, y, coord_type);
@@ -123,22 +176,23 @@
 }
 
 static gboolean
-eti_grab_focus (AtkComponent *component)
+gal_a11y_e_cell_grab_focus (AtkComponent *component)
 {
 	GalA11yECell *a11y;
-	gint view_row;
-	GtkWidget *e_table, *toplevel;
+	gint index;
+	GtkWidget *toplevel;
+	GalA11yETableItem *a11yTableItem;
 
 	a11y = GAL_A11Y_E_CELL (component);
-	e_table = gtk_widget_get_parent (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas));
-	view_row = e_table_view_to_model_row (E_TABLE (e_table), a11y->row);
-
-	e_selection_model_select_single_row (a11y->item->selection, view_row);
-	e_selection_model_change_cursor (a11y->item->selection, view_row, a11y->view_col);
-
-	gtk_widget_grab_focus (e_table);
-	toplevel = gtk_widget_get_toplevel (e_table);
-	if (GTK_WIDGET_TOPLEVEL (toplevel))
+	a11yTableItem = GAL_A11Y_E_TABLE_ITEM (a11y->parent);
+	index = atk_object_get_index_in_parent (ATK_OBJECT (a11y));
+	
+	atk_selection_clear_selection (ATK_SELECTION (a11yTableItem));
+	atk_selection_add_selection (ATK_SELECTION (a11yTableItem), index);
+	
+	gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas));
+	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas));
+	if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
 		gtk_window_present (GTK_WINDOW (toplevel));
 
 	return TRUE;
@@ -147,29 +201,30 @@
 /* Table IFace */
 
 static void
-eti_atk_component_iface_init (AtkComponentIface *iface)
+gal_a11y_e_cell_atk_component_iface_init (AtkComponentIface *iface)
 {
-	iface->get_extents = eti_get_extents;
-	iface->grab_focus  = eti_grab_focus;
+	iface->get_extents = gal_a11y_e_cell_get_extents;
+	iface->grab_focus  = gal_a11y_e_cell_grab_focus;
 }
 
 static void
-eti_class_init (GalA11yECellClass *klass)
+gal_a11y_e_cell_class_init (GalA11yECellClass *klass)
 {
 	AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
 	parent_class                          = g_type_class_ref (PARENT_TYPE);
 
-	object_class->dispose                 = eti_dispose;
+	object_class->dispose                 = gal_a11y_e_cell_dispose;
 
-	atk_object_class->get_parent          = eti_get_parent;
-	atk_object_class->get_index_in_parent = eti_get_index_in_parent;
-	atk_object_class->ref_state_set       = eti_ref_state_set;
+	atk_object_class->get_parent          = gal_a11y_e_cell_get_parent;
+	atk_object_class->get_index_in_parent = gal_a11y_e_cell_get_index_in_parent;
+	atk_object_class->ref_state_set       = gal_a11y_e_cell_ref_state_set;
+	atk_object_class->get_name            = gal_a11y_e_cell_get_name;
 }
 
 static void
-eti_init (GalA11yECell *a11y)
+gal_a11y_e_cell_init (GalA11yECell *a11y)
 {
 	a11y->item = NULL;
 	a11y->cell_view = NULL;
@@ -181,6 +236,11 @@
 	a11y->state_set = atk_state_set_new ();
 	atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT);
 	atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED);
+	atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE);
+	atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE);
+	atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING);
+	atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE);
+	atk_state_set_add_state (a11y->state_set, ATK_STATE_VISIBLE);
 }
 
 
@@ -350,6 +410,10 @@
 	GalA11yECell *cell;
 
 	cell = GAL_A11Y_E_CELL (data);
+
+	if (!is_valid (ATK_OBJECT (cell)))
+		return FALSE;
+
 	cell->action_idle_handler = 0;
 	cell->action_func (cell);
                                                                                 
@@ -363,6 +427,9 @@
 	GalA11yECell *cell = GAL_A11Y_E_CELL(action);
 	ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index);
 
+	if (!is_valid (ATK_OBJECT (action)))
+		return FALSE;
+
 	if (info == NULL)
 		return FALSE;
 	g_return_val_if_fail (info->do_action_func, FALSE);
@@ -477,17 +544,17 @@
 			sizeof (GalA11yECellClass),
 			(GBaseInitFunc) NULL,
 			(GBaseFinalizeFunc) NULL,
-			(GClassInitFunc) eti_class_init,
+			(GClassInitFunc) gal_a11y_e_cell_class_init,
 			(GClassFinalizeFunc) NULL,
 			NULL, /* class_data */
 			sizeof (GalA11yECell),
 			0,
-			(GInstanceInitFunc) eti_init,
+			(GInstanceInitFunc) gal_a11y_e_cell_init,
 			NULL /* value_cell */
 		};
 
 		static const GInterfaceInfo atk_component_info = {
-			(GInterfaceInitFunc) eti_atk_component_iface_init,
+			(GInterfaceInitFunc) gal_a11y_e_cell_atk_component_iface_init,
 			(GInterfaceFinalizeFunc) NULL,
 			NULL
 		};
@@ -539,17 +606,16 @@
 	a11y->row       = row;
 	ATK_OBJECT (a11y) ->role	= ATK_ROLE_TABLE_CELL;
 
+	if (item)
+		g_object_ref (G_OBJECT (item)); 
+
 #if 0
 	if (parent)
 		g_object_ref (parent);
 
-	if (item)
-		g_object_ref (G_OBJECT (item)); /*,
-						  unref_item,
-						  a11y);*/
 	if (cell_view)
-		g_object_ref (G_OBJECT (cell_view)); /*,
-						  unref_cell,
-						  a11y);*/
+		g_object_ref (G_OBJECT (cell_view)); 
+
+
 #endif
 }
Index: gal/a11y/e-table/gal-a11y-e-table-click-to-add.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-table-click-to-add.c,v
retrieving revision 1.2
diff -u -r1.2 gal-a11y-e-table-click-to-add.c
--- gal/a11y/e-table/gal-a11y-e-table-click-to-add.c	10 Jun 2004 17:00:45 -0000	1.2
+++ gal/a11y/e-table/gal-a11y-e-table-click-to-add.c	27 Jan 2005 03:27:31 -0000
@@ -13,6 +13,7 @@
 #include <gal/e-table/e-table-click-to-add.h>
 #include <atk/atkcomponent.h>
 #include <atk/atkaction.h>
+#include <glib/gi18n.h>
 
 static AtkObjectClass *parent_class;
 static GType parent_type;
@@ -37,7 +38,7 @@
                              gint      i)
 {
 	if (i == 0)
-		return "click to add";
+		return _("click to add");
 
 	return NULL;
 }
@@ -46,7 +47,7 @@
 etcta_action_get_name (AtkAction *action, gint      i)
 {
 	if (i == 0)
-		return "click";
+		return _("click");
 
 	return NULL;
 }
@@ -104,9 +105,15 @@
 static G_CONST_RETURN gchar *
 etcta_get_name (AtkObject *obj)
 {
+	ETableClickToAdd * etcta;
+
 	g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD (obj), NULL);
 
-	return "click to add";
+	etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(obj)));
+	if (etcta && etcta->message != NULL)
+		return etcta->message;
+
+	return _("click to add");
 }
 
 static gint
@@ -140,6 +147,20 @@
 	return atk_obj;
 }
 
+static AtkStateSet *
+etcta_ref_state_set (AtkObject *accessible)
+{
+	AtkStateSet * state_set = NULL;
+
+	state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible);
+	if (state_set != NULL) {
+		atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);
+		atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
+	}
+
+	return state_set;
+}
+
 static void
 etcta_class_init (GalA11yETableClickToAddClass *klass)
 {
@@ -150,6 +171,7 @@
 	atk_object_class->get_name = etcta_get_name;
         atk_object_class->get_n_children = etcta_get_n_children;
         atk_object_class->ref_child = etcta_ref_child;
+        atk_object_class->ref_state_set = etcta_ref_state_set;
 }
 
 static void
@@ -241,6 +263,27 @@
 	return TRUE;
 }
 
+static void
+etcta_selection_cursor_changed (ESelectionModel *esm, gint row, gint col,
+			GalA11yETableClickToAdd *a11y)
+{
+	ETableClickToAdd *etcta;
+	AtkObject *row_a11y;
+
+	etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(a11y)));
+
+	if (etcta == NULL || etcta->row == NULL)
+		return;
+
+	row_a11y = atk_gobject_accessible_for_object (G_OBJECT(etcta->row));
+	if (row_a11y) {
+		AtkObject *cell_a11y = g_object_get_data (G_OBJECT(row_a11y), "gail-focus-object");
+		if (cell_a11y) {
+			atk_focus_tracker_notify (cell_a11y);
+		}
+	}
+}
+
 AtkObject *
 gal_a11y_e_table_click_to_add_new (GObject *widget)
 {
@@ -264,6 +307,9 @@
 
 	g_signal_connect_after (G_OBJECT(widget), "event",
 	    			G_CALLBACK (etcta_event), a11y);
+
+	g_signal_connect (etcta->selection, "cursor_changed",
+			G_CALLBACK (etcta_selection_cursor_changed), a11y);
 
 	return ATK_OBJECT (a11y);
 }
Index: gal/a11y/e-table/gal-a11y-e-table-item-factory.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-table-item-factory.c,v
retrieving revision 1.3
diff -u -r1.3 gal-a11y-e-table-item-factory.c
--- gal/a11y/e-table/gal-a11y-e-table-item-factory.c	10 Jun 2004 17:00:45 -0000	1.3
+++ gal/a11y/e-table/gal-a11y-e-table-item-factory.c	27 Jan 2005 03:27:31 -0000
@@ -31,7 +31,7 @@
 	AtkObject *accessible;
 
 	g_return_val_if_fail (E_IS_TABLE_ITEM(obj), NULL);
-	accessible = gal_a11y_e_table_item_new(NULL, E_TABLE_ITEM (obj), 0);
+	accessible = gal_a11y_e_table_item_new (E_TABLE_ITEM (obj));
                                                                                 
 	return accessible;
 }
Index: gal/a11y/e-table/gal-a11y-e-table-item.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-table-item.c,v
retrieving revision 1.14
diff -u -r1.14 gal-a11y-e-table-item.c
--- gal/a11y/e-table/gal-a11y-e-table-item.c	21 Jun 2004 12:02:31 -0000	1.14
+++ gal/a11y/e-table/gal-a11y-e-table-item.c	27 Jan 2005 03:27:43 -0000
@@ -10,11 +10,16 @@
 #include <config.h>
 #include <string.h>
 #include "gal-a11y-e-table-item.h"
+#include "gal-a11y-e-table-item-factory.h"
+#include "gal-a11y-e-table-click-to-add.h"
 #include "gal-a11y-e-cell-registry.h"
 #include "gal-a11y-e-cell.h"
 #include "gal-a11y-util.h"
 #include <gal/e-table/e-table-subset.h>
+#include <gal/widgets/e-selection-model.h>
+#include <gal/widgets/e-canvas.h>
 #include <gal/e-table/e-table.h>
+#include <gal/e-table/e-table-click-to-add.h>
 #include <gal/e-table/e-tree.h>
 
 #include <atk/atkobject.h>
@@ -34,15 +39,13 @@
 #define PARENT_TYPE (parent_type)
 
 struct _GalA11yETableItemPrivate {
-	AtkObject *parent;
-	gint index_in_parent;
 	gint cols;
 	gint rows;
-	gpointer *cell_data;
 	int selection_change_id;
 	int cursor_change_id;
 	ETableCol ** columns;
 	ESelectionModel *selection;
+	AtkStateSet *state_set;
 	GtkWidget *widget;
 };
 
@@ -50,17 +53,31 @@
 						     ESelectionModel *selection);
 static gboolean gal_a11y_e_table_item_unref_selection (GalA11yETableItem *a11y);
 
-static gpointer *eti_reinit_data (AtkTable *table, ETableItem *item);
+static AtkObject* eti_ref_at (AtkTable *table, gint row, gint column);
 
-#if 0
 static void
-unref_accessible (gpointer user_data, GObject *obj_loc)
+item_destroyed (GtkObject *item, gpointer user_data)
 {
 	GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (user_data);
-	GET_PRIVATE (a11y)->item = NULL;
-	g_object_unref (a11y);
+	GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y);
+
+	atk_state_set_add_state (priv->state_set, ATK_STATE_DEFUNCT);
+	atk_object_notify_state_change (ATK_OBJECT (a11y), ATK_STATE_DEFUNCT, TRUE);
+
+	if (priv->selection)
+		gal_a11y_e_table_item_unref_selection (a11y);
+
+}
+
+static AtkStateSet *
+eti_ref_state_set (AtkObject *accessible)
+{
+	GalA11yETableItemPrivate *priv = GET_PRIVATE (accessible);
+
+        g_object_ref(priv->state_set);
+
+        return priv->state_set;
 }
-#endif
 
 inline static gint
 view_to_model_row(ETableItem *eti, int row)
@@ -131,13 +148,6 @@
 	GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (object);
 	GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y);
 
-	priv->parent = NULL;
-
-	if ( priv->cell_data != NULL ) {
-		g_free(priv->cell_data);
-		priv->cell_data = NULL;
-	}
-
 	if (priv->columns) {
 		g_free(priv->columns);
 		priv->columns = NULL;
@@ -145,25 +155,9 @@
 
 	if (parent_class->dispose)
 		parent_class->dispose (object);
-	if (priv->selection)
-		gal_a11y_e_table_item_unref_selection (a11y);
 }
 
 /* Static functions */
-static AtkObject *
-eti_get_parent (AtkObject *accessible)
-{
-	GalA11yETableItem *a11y;
-
-	g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (accessible), NULL);
-	if (!eti_a11y_get_gobject (accessible))
-		/* defunct */
-		return NULL;
-
-	a11y = GAL_A11Y_E_TABLE_ITEM (accessible);
-	return GET_PRIVATE (a11y)->parent;
-}
-
 static gint
 eti_get_n_children (AtkObject *accessible)
 {
@@ -186,34 +180,12 @@
 	if (!item)
 		return NULL;
 
-	if (index < item->cols) {
-		AtkObject *child;
+	/* don't support column header now */
 
-		/* A column header is required */
-		child = atk_table_get_column_header (ATK_TABLE (accessible), index);
-		if (child)
-			g_object_ref (child);
-		return child;
-	}
-
-	index -= item->cols;
 	col = index % item->cols;
 	row = index / item->cols;
 
-	return atk_table_ref_at (ATK_TABLE (accessible), row, col);
-}
-
-static gint
-eti_get_index_in_parent (AtkObject *accessible)
-{
-	GalA11yETableItem *a11y;
-
-	g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (accessible), -1);
-	if (!eti_a11y_get_gobject (accessible))
-		return -1;
-
-	a11y = GAL_A11Y_E_TABLE_ITEM (accessible);
-	return GET_PRIVATE (a11y)->index_in_parent;
+	return eti_ref_at (ATK_TABLE (accessible), row, col);
 }
 
 static void
@@ -225,33 +197,25 @@
 		 AtkCoordType coord_type)
 {
 	ETableItem *item;
-	double real_width;
-	double real_height;
-	int fake_width;
-	int fake_height;
+	AtkObject *parent;
 
 	item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (component)));
 	if (!item)
 		return;
 
-	if (component_parent_iface &&
-	    component_parent_iface->get_extents)
-		component_parent_iface->get_extents (component,
-						     x,
-						     y,
-						     &fake_width,
-						     &fake_height,
-						     coord_type);
-
-	gtk_object_get (GTK_OBJECT (item),
-			"width", &real_width,
-			"height", &real_height,
-			NULL);
-
-	if (width)
-		*width = real_width;
-	if (height) 
-		*height = real_height;
+	parent = ATK_OBJECT (component)->accessible_parent;
+	if (parent && ATK_IS_COMPONENT (parent))
+		atk_component_get_extents (ATK_COMPONENT (parent), x, y, 
+					width, height,
+					coord_type);
+
+	if (parent && GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD (parent)) {
+		ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (parent)));
+		if (etcta) {
+			*width = etcta->width;
+			*height = etcta->height;
+		}
+	}
 }
 
 static AtkObject*
@@ -264,6 +228,7 @@
 	int col = -1;
 	int x_origin, y_origin;
 	ETableItem *item;
+	GtkWidget *tableOrTree;
 
 	item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (component)));
 	if (!item)
@@ -276,11 +241,15 @@
 	x -= x_origin;
 	y -= y_origin;
 
-	e_table_item_compute_location (item, &x, &y,
-				       &row, &col);
+	tableOrTree = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas));
+
+	if (E_IS_TREE(tableOrTree))
+		e_tree_get_cell_at (E_TREE (tableOrTree), x, y, &row, &col);
+	else
+		e_table_get_cell_at (E_TABLE (tableOrTree), x, y, &row, &col);
 
 	if (row != -1 && col != -1) {
-		return atk_table_ref_at (ATK_TABLE (component), row, col);
+		return eti_ref_at (ATK_TABLE (component), row, col);
 	} else {
 		return NULL;
 	}
@@ -290,23 +259,18 @@
 static void
 cell_destroyed (gpointer data)
 {
-	gint index;
-	GalA11yETableItem * item;
 	GalA11yECell * cell;
 
 	g_return_if_fail (GAL_A11Y_IS_E_CELL (data));
 	cell = GAL_A11Y_E_CELL (data);
-		
-	item = GAL_A11Y_E_TABLE_ITEM (atk_gobject_accessible_for_object (G_OBJECT (GAL_A11Y_E_CELL(data)->item)));
 
-	g_return_if_fail (item && GAL_A11Y_IS_E_TABLE_ITEM (item));
+	g_return_if_fail (cell->item && G_IS_OBJECT (cell->item));
 
-	g_return_if_fail (cell->row < GET_PRIVATE(item)->rows && cell->view_col < GET_PRIVATE(item)->cols);
+        if (cell->item) {
+                g_object_unref (cell->item);  
+                cell->item = NULL;
+        }
 
-	index = cell->row * cell->item->cols + cell->view_col;
-                                                                   
-	if (GET_PRIVATE (item)->cell_data && GET_PRIVATE (item)->cell_data [index] == data)
-		GET_PRIVATE (item)->cell_data [index] = NULL;
 }
 
 /* atk table */
@@ -315,6 +279,11 @@
 {
 	ETableItem *item;
 	AtkObject* ret;
+	GalA11yETableItemPrivate *priv = GET_PRIVATE (table);
+
+	if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+		return NULL;
+
 
 	item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
 	if (!item)
@@ -327,38 +296,23 @@
 	    item->cell_views_realized) {
 		ECellView *cell_view = item->cell_views[column];
 		ETableCol *ecol = e_table_header_get_column (item->header, column);
-		gpointer * cell_data;
-
-		cell_data = eti_reinit_data (table, item);
-		if (cell_data == NULL) 
-			return NULL;
-
-		if (cell_data[row*item->cols + column] == NULL) {
-			ret = gal_a11y_e_cell_registry_get_object (NULL,
+		ret = gal_a11y_e_cell_registry_get_object (NULL,
 							    item,
 							    cell_view,
 							    ATK_OBJECT (table),
 							    ecol->col_idx,
 							    column,
-							    row);
-			cell_data[row*item->cols + column] = ret;
-			if (ATK_IS_OBJECT (ret)) {
-				gal_a11y_e_cell_add_state(ret, ATK_STATE_SHOWING, FALSE);
-				gal_a11y_e_cell_add_state(ret, ATK_STATE_VISIBLE, FALSE);
-				g_object_weak_ref (G_OBJECT (ret),
-						   (GWeakNotify) cell_destroyed,
-						   ret);
-			} else
-				ret = NULL;
-		} else {
-			ret = (AtkObject *) cell_data[row*item->cols + column];
-			if (ATK_IS_OBJECT (ret)) {
-				g_object_ref (ret);
-			} else { 
-				ret = NULL;
-			}
-		}
-
+						   	    row);
+		if (ATK_IS_OBJECT (ret)) {
+			g_object_weak_ref (G_OBJECT (ret),
+					   (GWeakNotify) cell_destroyed,
+					   ret);
+			/* if current cell is focused, add FOCUSED state */
+			if (e_selection_model_cursor_row (item->selection) == GAL_A11Y_E_CELL (ret)->row && 
+					e_selection_model_cursor_col (item->selection) == GAL_A11Y_E_CELL (ret)->model_col)
+				gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (ret), ATK_STATE_FOCUSED, FALSE);
+		} else
+			ret = NULL;
 
 		return ret;
 	}
@@ -501,16 +455,21 @@
 	ETableItem *item;
 	ETableCol *ecol;
 	AtkObject *atk_obj = NULL;
-	ECell *ecell;
 
 	item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
 	if (!item)
 		return NULL;
 
 	ecol = e_table_header_get_column (item->header, column);
-	ecell = ecol->ecell;
-	if (ecell)
-		atk_obj = atk_gobject_accessible_for_object (G_OBJECT (ecell));
+	if (ecol) {
+		atk_obj = atk_gobject_accessible_for_object (G_OBJECT (ecol));
+		if (atk_obj) {
+			if (ecol->text)
+				atk_object_set_name (atk_obj, ecol->text);
+			atk_object_set_role (atk_obj, ATK_ROLE_TABLE_COLUMN_HEADER);
+		}
+	}
+
 	return atk_obj;
 }
 
@@ -541,12 +500,16 @@
 table_is_row_selected (AtkTable *table, gint row)
 {
 	ETableItem *item;
+	GalA11yETableItemPrivate *priv = GET_PRIVATE (table);
+
+	if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+		return FALSE;
 
 	item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
 	if (!item)
 		return FALSE;
 
-	return e_selection_model_is_row_selected(item->selection, row);
+	return e_selection_model_is_row_selected(item->selection, view_to_model_row (item, row));
 }
 
 static gboolean 
@@ -560,6 +523,10 @@
 {
 	ETableItem *item;
 	gint n_selected, row, index_selected;
+	GalA11yETableItemPrivate *priv = GET_PRIVATE (table);
+
+	if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+		return 0;
 
 	item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
 	if (!item)
@@ -601,6 +568,10 @@
 table_remove_row_selection (AtkTable *table, gint row)
 {
 	ETableItem *item;
+	GalA11yETableItemPrivate *priv = GET_PRIVATE (table);
+
+	if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+		return FALSE;
 
 	item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
 	if (!item)
@@ -608,7 +579,7 @@
 
 	if (!atk_table_is_row_selected (table, row))
 		return TRUE;
-	e_selection_model_toggle_single_row (item->selection, row);
+	e_selection_model_toggle_single_row (item->selection, view_to_model_row (item, row));
 	return TRUE;
 }
 
@@ -651,7 +622,6 @@
 		   AtkObject * table_item)
 {
 	gint n_cols,n_rows,i,j;
-	gpointer *cell_data;
 	GalA11yETableItem * item_a11y;
 	gint old_nrows;
 
@@ -666,34 +636,8 @@
 	g_return_if_fail (n_cols > 0 && n_rows > 0);
 	g_return_if_fail (old_nrows == n_rows - count);
 
-	cell_data = GET_PRIVATE(table_item)->cell_data;
-	GET_PRIVATE(table_item)->cell_data = g_realloc (cell_data, (n_rows*n_cols) * sizeof(gpointer));
-	cell_data = GET_PRIVATE(table_item)->cell_data;
-
 	GET_PRIVATE(table_item)->rows = n_rows; 
 
-	/* If rows are insert in the middle of a table. */
-	if (row + count < n_rows ) {
-		memmove(&cell_data[(row+count)*n_cols], &cell_data[row*n_cols],
-			(old_nrows-row)*n_cols*sizeof(gpointer));
-
-		/* Update cell's index. */
-		for (i = row + count; i < n_rows; i ++) {
-			for (j = 0; j < n_cols; j ++)
-				if (cell_data[i*n_cols + j] != NULL) {
-					AtkObject * a11y;
-
-					a11y = ATK_OBJECT(cell_data[i*n_cols + j]);
-                                        GAL_A11Y_E_CELL(a11y)->row = i;
-				}
-		}
-	}
-
-	/* Clear cache for the new added rows. */
-	for (i = row ; i < row+count; i ++)
-		for (j = 0 ;  j < n_cols; j ++)
-			cell_data [i*n_cols + j] = NULL;
-
 	g_signal_emit_by_name (table_item, "row-inserted", row,
 			       count, NULL);
 
@@ -708,132 +652,21 @@
 	g_signal_emit_by_name (table_item, "visible-data-changed");
 }
 
-/* 
- * reinit the eti's private data
- * make sure it is synchronized with the gal-e-table-item
- */
-static gpointer *
-eti_reinit_data (AtkTable *table, ETableItem *item)
-{
-	gpointer * cell_data;
-
-	int oldsize, newsize;
-	cell_data = GET_PRIVATE (table)->cell_data;
-	if (GET_PRIVATE (table)->rows != item->rows 
-		|| GET_PRIVATE (table)->cols != item->cols ) { /* reinit cell_data */
-		oldsize = GET_PRIVATE (table)->cols * GET_PRIVATE (table)->rows;
-		newsize = item->cols*item->rows;
-		GET_PRIVATE (table)->cols = item->cols;
-		GET_PRIVATE (table)->rows = item->rows;
-
-		cell_data = g_realloc(cell_data, newsize*sizeof(gpointer));
-		if (newsize > oldsize)
-			memset(&cell_data[oldsize], 0, (newsize-oldsize)*sizeof(gpointer));
-		
-		GET_PRIVATE (table)->cell_data = cell_data;
-	}
-	return cell_data;
-}
-
-/* 
- * clear all the AtkObjects stored in the cell_data
- * doesn't free the cell_data or resize it.
- */
-static void
-eti_clear_rows (ETableModel * model, AtkObject * table_item, int row, int count)
-{
-	gint i,j, n_rows, n_cols;
-	gpointer *cell_data;
-
-	g_return_if_fail (model && table_item);
-
-	cell_data = GET_PRIVATE (table_item)->cell_data;
-	g_return_if_fail (cell_data);
-
-	n_rows = GET_PRIVATE (table_item)->rows;
-	n_cols = GET_PRIVATE (table_item)->cols;
-
-	g_return_if_fail( row >= 0 && count > 0 && row+count <= n_rows);
-
-	/* DEFUNCT the deleted cells. */
-	for (i = row; i < row+count; i ++) {
-		for (j = 0; j < n_cols; j ++) {
-			if (cell_data[i*n_cols + j] != NULL) {
-				AtkObject * a11y;
-
-				a11y = ATK_OBJECT(cell_data[i*n_cols + j]);
-				gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL(a11y), ATK_STATE_DEFUNCT, TRUE);
-				cell_data[i*n_cols + j] = NULL;
-			}
-		}
-	}
-
-	g_signal_emit_by_name (table_item, "row-deleted", row,
-			       count, NULL);
-
-	for (i = row; i < row+count; i ++) {
-		for (j = 0; j < n_cols; j ++) {
-			g_signal_emit_by_name (table_item,
-				"children_changed::remove",
-				( (i*n_cols) + j), NULL, NULL);
-		}
-        }
-	g_signal_emit_by_name (table_item, "visible-data-changed");
-}
-
 static void
 eti_rows_deleted (ETableModel * model, int row, int count, 
 		  AtkObject * table_item)
 {
 	gint i,j, n_rows, n_cols, old_nrows;
-	gpointer *cell_data;
 	
 	n_rows = atk_table_get_n_rows (ATK_TABLE(table_item));
         n_cols = atk_table_get_n_columns (ATK_TABLE(table_item));
 
-	cell_data = GET_PRIVATE(table_item)->cell_data;
 	old_nrows = GET_PRIVATE(table_item)->rows;
 
 	g_return_if_fail ( row+count <= old_nrows);
 	g_return_if_fail (old_nrows == n_rows + count);
 	GET_PRIVATE(table_item)->rows = n_rows;
 
-	/* DEFUNCT the deleted cells. */
-	for (i = row; i < row+count; i ++) {
-		for (j = 0; j < n_cols; j ++) {
-			if (cell_data[i*n_cols + j] != NULL) {
-				AtkObject * a11y;
-
-				a11y = ATK_OBJECT(cell_data[i*n_cols + j]);
-				gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL(a11y), ATK_STATE_DEFUNCT, TRUE);
-				cell_data[i*n_cols + j] = NULL;
-			}
-		}
-	}
-
-	/* If more rows left, update the a11y object. */
-	if (old_nrows > row + count) {
-
-		/* Remove the defunct cells in cache. */
-		memmove (&cell_data[row*n_cols], &cell_data[(row+count)*n_cols],
-			( old_nrows-row-count)*n_cols*sizeof(gpointer));
-
-		GET_PRIVATE(table_item)->cell_data = g_realloc (cell_data, n_rows*n_cols*sizeof(gpointer));
-		cell_data = GET_PRIVATE(table_item)->cell_data;
-
-		/* Update index of cells below the deleted rows. */
-		for (i = row; i < n_rows; i ++) {
-			for (j = 0; j < n_cols; j ++) {
-				if (cell_data[i*n_cols + j] != NULL) {
-					AtkObject * a11y;
-
-					a11y = ATK_OBJECT(cell_data[i*n_cols + j]);
-					GAL_A11Y_E_CELL(a11y)->row = i;
-				}
-			}
-		}
-	}
-
 	g_signal_emit_by_name (table_item, "row-deleted", row,
 			       count, NULL);
 
@@ -858,9 +691,9 @@
 	atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti));
 	a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj);
 
-	/* we can't figure out which rows are changed, so just clear all of them ... */
+	/* we can't figure out which rows are changed, so just send out a signal ... */
 	if  (GET_PRIVATE (a11y)->rows > 0)
-		eti_clear_rows (eti->table_model, atk_obj, 0, GET_PRIVATE (a11y)->rows);
+		g_signal_emit_by_name (a11y, "visible-data-changed");
 }
 
 enum {
@@ -885,14 +718,10 @@
         GalA11yETableItemPrivate *priv;
         gint *state = NULL, *prev_state = NULL, *reorder = NULL;
         gint i,j,n_rows,n_cols, prev_n_cols;
-        gpointer * cell_data, * tmp;
                                                                                 
         a11y_item = GAL_A11Y_E_TABLE_ITEM (a11y);
         priv = GET_PRIVATE (a11y_item);
                                                                                 
-	g_return_if_fail (priv && priv->cell_data);
-	cell_data = priv->cell_data ;
-
 	/* Assume rows do not changed. */
         n_rows = priv->rows;
 
@@ -949,26 +778,6 @@
 	if (!reorder_found && !added_found && !removed_found)
 		return;
 
-	/* Now update our cache. */
-	tmp = g_malloc0 (n_rows*n_cols*sizeof(gpointer));
-	g_return_if_fail (tmp);
-
-	for (i = 0 ; i < n_rows; i ++) {
-		for ( j = 0 ; j < n_cols; j ++ ) {
-			if ( state[j] == ETI_HEADER_REORDERED ) {
-				tmp [i*n_cols+j] = cell_data[i*prev_n_cols+reorder[j]];
-				if (tmp[i*n_cols+j] &&  ATK_IS_OBJECT(tmp[i*n_cols+j])) {
-					GAL_A11Y_E_CELL(tmp[i*n_cols+j])->view_col = j;
-				}
-			} else if (state[j] == ETI_HEADER_UNCHANGED) {
-				tmp [i*n_cols+j] = cell_data[i*prev_n_cols+j];
-			} /* else: new added, keep NULL. */
-		}
-	}
-
-	g_free (cell_data);
-	priv->cell_data = tmp;
-
 	/* Emit signals */
 	if (reorder_found)
         	g_signal_emit_by_name (G_OBJECT(a11y_item), "column_reordered");
@@ -1040,11 +849,10 @@
 
 	object_class->dispose                 = eti_dispose;
 
-	atk_object_class->get_parent          = eti_get_parent;
 	atk_object_class->get_n_children      = eti_get_n_children;
 	atk_object_class->ref_child           = eti_ref_child;
-	atk_object_class->get_index_in_parent = eti_get_index_in_parent;
 	atk_object_class->initialize	      = eti_real_initialize;
+	atk_object_class->ref_state_set       = eti_ref_state_set;
 }
 
 static void
@@ -1054,8 +862,6 @@
 
 	priv = GET_PRIVATE (a11y);
 
-	priv->parent = NULL;
-	priv->index_in_parent = -1;
 	priv->selection_change_id = 0;
 	priv->cursor_change_id = 0;
 	priv->selection = NULL;
@@ -1149,37 +955,36 @@
 }
 
 AtkObject *
-gal_a11y_e_table_item_new (AtkObject *parent,
-			   ETableItem *item,
-			   int index_in_parent)
+gal_a11y_e_table_item_new (ETableItem *item)
 {
 	GalA11yETableItem *a11y;
 	AtkObject *accessible;
 	int n;
+	ESelectionModel * esm;
+	AtkObject * cell;
+	AtkObject *parent;
+	const char *name;
 
 	g_return_val_if_fail (item && item->cols >= 0 && item->rows >= 0, NULL);
 	a11y = g_object_new (gal_a11y_e_table_item_get_type (), NULL);
 
 	atk_object_initialize (ATK_OBJECT (a11y), item);
 
-	GET_PRIVATE (a11y)->parent = parent;
-	GET_PRIVATE (a11y)->index_in_parent = index_in_parent;
+	GET_PRIVATE (a11y)->state_set = atk_state_set_new ();
+
+	atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_TRANSIENT);
+	atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_ENABLED);
+	atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SENSITIVE);
+	atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SHOWING);
+	atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_VISIBLE);
+
 
 	accessible  = ATK_OBJECT(a11y);
-	accessible->role = ATK_ROLE_TREE_TABLE;
 
 	/* Initialize cell data. */
 	n = item->cols * item->rows;
 	GET_PRIVATE (a11y)->cols = item->cols;
 	GET_PRIVATE (a11y)->rows = item->rows;
-	if (n > 0) {
-		GET_PRIVATE (a11y)->cell_data = g_malloc0(n*sizeof(gpointer));
-		/* memory error. */
-		if ( GET_PRIVATE (a11y)->cell_data == NULL)
-			return NULL;
-	} else
-		GET_PRIVATE (a11y)->cell_data = NULL;
-		
 
         GET_PRIVATE (a11y)->columns = e_table_header_get_columns (item->header);                                                                                
         if ( GET_PRIVATE (a11y)->columns == NULL)
@@ -1196,22 +1001,49 @@
 
 		/* find the TableItem's parent: table or tree */
 		GET_PRIVATE (a11y)->widget = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas));
+		parent = gtk_widget_get_accessible (GET_PRIVATE (a11y)->widget);
+		name = atk_object_get_name (parent);
+		if (name)
+			atk_object_set_name (accessible, name);
+		atk_object_set_parent (accessible, parent);
+
 		if (E_IS_TREE (GET_PRIVATE (a11y)->widget)) {
 			ETreeModel *model;
 			model = e_tree_get_model (E_TREE (GET_PRIVATE (a11y)->widget));
 			g_signal_connect (G_OBJECT(model), "node_changed",
 					G_CALLBACK (eti_tree_model_node_changed_cb), item);
+			accessible->role = ATK_ROLE_TREE_TABLE;
+		} else if (E_IS_TABLE (GET_PRIVATE (a11y)->widget)) {
+			accessible->role = ATK_ROLE_TABLE;
 		} 
 	}
-	if (parent)
-		g_object_ref (parent);
 
-#if 0
 	if (item)
-		g_object_weak_ref (G_OBJECT (item),
-				   unref_accessible,
+		g_signal_connect (G_OBJECT (item), "destroy",
+				   G_CALLBACK (item_destroyed),
 				   a11y);
-#endif
+	esm = item->selection;
+
+	if (esm != NULL) {
+		int cursor_row, cursor_col, view_row, view_col;
+
+        	cursor_row = e_selection_model_cursor_row(esm);
+        	cursor_col = e_selection_model_cursor_col(esm);
+
+		view_row = model_to_view_row (item, cursor_row);
+		view_col = model_to_view_col (item, cursor_col);
+
+		if (view_row == -1)
+			view_row = 0;
+		if (view_col == -1)
+			view_col = 0;
+
+		cell = eti_ref_at (ATK_TABLE (a11y), view_row, view_col);
+		if (cell != NULL) {
+        		g_object_set_data (G_OBJECT(a11y), "gail-focus-object", cell);
+			gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (cell), ATK_STATE_FOCUSED, FALSE);
+		}
+	}
 
 	return ATK_OBJECT (a11y);
 }
@@ -1304,6 +1136,11 @@
 static void
 eti_a11y_selection_changed_cb (ESelectionModel *selection, GalA11yETableItem *a11y)
 {
+	GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y);
+
+	if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT))
+		return;
+
 	g_return_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (a11y));
 
 	g_signal_emit_by_name (a11y, "selection_changed");
@@ -1316,27 +1153,39 @@
 	AtkObject * cell;
 	int view_row, view_col;
 	ETableItem *item;
+	GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y);
 
 	g_return_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (a11y));
 
-	g_signal_emit_by_name (a11y, "selection_changed");
+	if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) 
+		return;
 
 	item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (a11y)));
 
 	g_return_if_fail (item);
 
+	if (row == -1 && col == -1)
+		return;
+
 	view_row = model_to_view_row (item, row);
 	view_col = model_to_view_col (item, col);
 
-	cell = atk_table_ref_at (ATK_TABLE (a11y), view_row, view_col);
+	if (view_col == -1)
+		view_col = 0;
+	cell = eti_ref_at (ATK_TABLE (a11y), view_row, view_col);
 	if (cell != NULL) {
-		gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (cell), ATK_STATE_FOCUSED, FALSE);
+		AtkObject *old_cell = (AtkObject *)g_object_get_data (G_OBJECT(a11y), "gail-focus-object");
+		if (old_cell && GAL_A11Y_IS_E_CELL (old_cell))
+			gal_a11y_e_cell_remove_state (GAL_A11Y_E_CELL (old_cell), ATK_STATE_FOCUSED, FALSE);
+		if (old_cell)
+			g_object_unref (old_cell);
+
+        	g_object_set_data (G_OBJECT(a11y), "gail-focus-object", cell);
 
         	if (ATK_IS_OBJECT (cell))
                 	g_signal_emit_by_name  (a11y,
                                         "active-descendant-changed",
                                         cell);
-		atk_focus_tracker_notify (cell);
 	}
 
 }
@@ -1357,7 +1206,7 @@
 selection_add_selection (AtkSelection *selection, gint index)
 {
 	AtkTable *table;
-	gint row, col;
+	gint row, col, cursor_row, cursor_col, model_row, model_col;
 	ETableItem *item;
 
 	item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (selection)));
@@ -1367,18 +1216,36 @@
 	table = ATK_TABLE (selection);
 
 	row = atk_table_get_row_at_index (table, index);
-	atk_table_add_row_selection (table, row);
-
 	col = atk_table_get_column_at_index (table, index);
+
+	model_row = view_to_model_row (item, row);
+	model_col = view_to_model_col (item, col);
+
+	cursor_row = e_selection_model_cursor_row (item->selection);
+	cursor_col = e_selection_model_cursor_col (item->selection);
+
+	/* check whether is selected already */
+	if (model_row == cursor_row && model_col == cursor_col)
+		return TRUE;
+
+	if (model_row != cursor_row) {
+		/* we need to make the item get focus */
+		e_canvas_item_grab_focus (GNOME_CANVAS_ITEM (item), TRUE);
+
+		/* FIXME, currently we only support single row selection */
+		atk_selection_clear_selection (selection);
+		atk_table_add_row_selection (table, row);
+	}
+
 	e_selection_model_change_cursor (item->selection,
-					 view_to_model_row (item, row),
-					 view_to_model_col (item, col));
+					 model_row,
+					 model_col);
 	e_selection_model_cursor_changed (item->selection,
-					  view_to_model_row (item, row),
-					  view_to_model_col (item, col));
+					  model_row,
+					  model_col);
 	e_selection_model_cursor_activated (item->selection,
-					    view_to_model_row (item, row),
-					    view_to_model_col (item, col));
+					    model_row,
+					    model_col);
 	return TRUE;
 }
 
@@ -1407,7 +1274,7 @@
 	if (!atk_table_is_row_selected (table, row))
 		return NULL;
 
-	return atk_table_ref_at (table, row, col);
+	return eti_ref_at (table, row, col);
 }
 
 static gint
@@ -1430,4 +1297,12 @@
 
 	row = atk_table_get_row_at_index (ATK_TABLE (selection), i);
 	return atk_table_is_row_selected (ATK_TABLE (selection), row);
+}
+
+void
+gal_a11y_e_table_item_init (void)
+{
+        atk_registry_set_factory_type (atk_get_default_registry (),
+                                       E_TABLE_ITEM_TYPE,
+                                       gal_a11y_e_table_item_factory_get_type ());
 }
Index: gal/a11y/e-table/gal-a11y-e-table-item.h
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-table-item.h,v
retrieving revision 1.2
diff -u -r1.2 gal-a11y-e-table-item.h
--- gal/a11y/e-table/gal-a11y-e-table-item.h	3 Nov 2003 06:40:50 -0000	1.2
+++ gal/a11y/e-table/gal-a11y-e-table-item.h	27 Jan 2005 03:27:43 -0000
@@ -37,8 +37,8 @@
 
 /* Standard Glib function */
 GType      gal_a11y_e_table_item_get_type  (void);
-AtkObject *gal_a11y_e_table_item_new       (AtkObject  *parent,
-					    ETableItem *item,
-					    int         index_in_parent);
+AtkObject *gal_a11y_e_table_item_new       (ETableItem *item);
+
+void gal_a11y_e_table_item_init (void);
 
 #endif /* ! __GAL_A11Y_E_TABLE_ITEM_H__ */
Index: gal/a11y/e-table/gal-a11y-e-table.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-table.c,v
retrieving revision 1.3
diff -u -r1.3 gal-a11y-e-table.c
--- gal/a11y/e-table/gal-a11y-e-table.c	17 Dec 2003 02:35:20 -0000	1.3
+++ gal/a11y/e-table/gal-a11y-e-table.c	27 Jan 2005 03:27:43 -0000
@@ -12,6 +12,7 @@
 #include "gal-a11y-util.h"
 #include <gal/e-table/e-table.h>
 #include <gal/e-table/e-table-group.h>
+#include <gal/e-table/e-table-group-container.h>
 #include <gal/e-table/e-table-group-leaf.h>
 #include <gal/e-table/e-table-click-to-add.h>
 
@@ -27,16 +28,80 @@
 };
 
 /* Static functions */
+static ETableItem *
+find_first_table_item (ETableGroup *group)
+{
+	GnomeCanvasGroup *cgroup;
+	GList *l;
 
-static void
+	cgroup = GNOME_CANVAS_GROUP (group);
+
+	for (l = cgroup->item_list; l; l = l->next) {
+		GnomeCanvasItem *i;
+
+		i = GNOME_CANVAS_ITEM (l->data);
+
+		if (E_IS_TABLE_GROUP (i))
+			return find_first_table_item (E_TABLE_GROUP (i));
+		else if (E_IS_TABLE_ITEM (i)) {
+			return E_TABLE_ITEM (i);
+		}
+	}
+
+	return NULL;
+}
+
+static AtkObject*
+eti_get_accessible (ETableItem *eti, AtkObject *parent)
+{
+	AtkObject *a11y = NULL;
+
+	g_return_val_if_fail (eti, NULL);
+
+	a11y = atk_gobject_accessible_for_object (G_OBJECT (eti));
+	g_return_val_if_fail (a11y, NULL);
+
+	return a11y;
+}
+
+static ETableItem *
+find_table_item (ETable *table)
+{
+	if (e_table_model_row_count(table->model) < 1)
+		return NULL;
+	else {
+		if (table->group)
+			return find_first_table_item (table->group);
+	}
+
+	return NULL;
+}
+
+static gboolean 
 init_child_item (GalA11yETable *a11y)
 {
-	GalA11yETablePrivate *priv = GET_PRIVATE (a11y);
-	ETable *table = E_TABLE (GTK_ACCESSIBLE (a11y)->widget);
-	if (priv->child_item == NULL) {
-		priv->child_item = atk_gobject_accessible_for_object (G_OBJECT(E_TABLE_GROUP_LEAF (table->group)->item));
-		priv->child_item->role = ATK_ROLE_TABLE;
+	ETable *table;
+
+	if (!a11y || !GTK_IS_ACCESSIBLE (a11y))
+		return FALSE;
+
+	table = E_TABLE (GTK_ACCESSIBLE (a11y)->widget);
+	if (table && GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && table->group && E_IS_TABLE_GROUP_CONTAINER(table->group)) {
+		ETableGroupContainer *etgc =  (ETableGroupContainer *)table->group;
+		GList *list;
+
+		for (list = etgc->children; list; list = g_list_next (list)) {
+			ETableGroupContainerChildNode *child_node = list->data;
+			ETableGroup *child = child_node->child;
+			ETableItem *eti = find_first_table_item (child);
+
+			eti_get_accessible (eti, ATK_OBJECT (a11y));
+		}
 	}
+	g_object_unref (a11y);
+	g_object_unref (table);
+
+	return FALSE;
 }
 
 static AtkObject*
@@ -46,7 +111,8 @@
 			     AtkCoordType coord_type)
 {
 	GalA11yETable *a11y = GAL_A11Y_E_TABLE (component);
-	init_child_item (a11y);
+	if (GET_PRIVATE (a11y)->child_item)
+		g_object_ref (GET_PRIVATE (a11y)->child_item);
 	return GET_PRIVATE (a11y)->child_item;
 }
 
@@ -55,13 +121,23 @@
 {
 	GalA11yETable *a11y = GAL_A11Y_E_TABLE (accessible);
 	ETable * et;
+	int n = 0;
 
 	et = E_TABLE(GTK_ACCESSIBLE (a11y)->widget);
-	if (et && et->use_click_to_add) {
-		return 2;
-	}
 
-	return 1;
+	if (et->group) {
+		if (E_IS_TABLE_GROUP_LEAF (et->group))
+			n = 1;
+		else if (E_IS_TABLE_GROUP_CONTAINER (et->group)) {
+			ETableGroupContainer *etgc = (ETableGroupContainer *)et->group;
+			n = g_list_length (etgc->children);
+		}
+	}
+	
+	if (et && et->use_click_to_add && et->click_to_add) {
+		n++;
+	}
+	return n;
 }
 
 static AtkObject*
@@ -70,24 +146,40 @@
 {
 	GalA11yETable *a11y = GAL_A11Y_E_TABLE (accessible);
 	ETable * et;
+	gint child_no;
 
 	et = E_TABLE(GTK_ACCESSIBLE (a11y)->widget);
 
-	if (i == 0) {
-		init_child_item (a11y);
-		g_object_ref (GET_PRIVATE (a11y)->child_item);
-		return GET_PRIVATE (a11y)->child_item;
-	} else if (i == 1) {
+	child_no = et_get_n_children (accessible);
+	if (i == 0 || i < child_no - 1) {
+		if (E_IS_TABLE_GROUP_LEAF (et->group)) {
+			ETableItem *eti = find_first_table_item (et->group);
+			AtkObject *aeti = eti_get_accessible (eti, accessible);
+			if (aeti)
+				g_object_ref (aeti);
+			return aeti;
+
+		} else if (E_IS_TABLE_GROUP_CONTAINER (et->group)) {
+			ETableGroupContainer *etgc =  (ETableGroupContainer *) et->group;
+			ETableGroupContainerChildNode *child_node = g_list_nth_data (etgc->children, i);
+			if (child_node) {
+				ETableGroup *child = child_node->child;
+				ETableItem * eti = find_first_table_item (child);
+				AtkObject *aeti =  eti_get_accessible (eti, accessible);
+				if (aeti)
+					g_object_ref (aeti);
+				return aeti;
+			}
+		}
+	} else if (i == child_no -1) {
         	AtkObject * accessible;
 		ETableClickToAdd * etcta;
 
 		if (et && et->use_click_to_add && et->click_to_add) {
 			etcta = E_TABLE_CLICK_TO_ADD(et->click_to_add);
-			if (etcta->rect) {
-				accessible = atk_gobject_accessible_for_object (G_OBJECT(etcta));
-			} else {
-				accessible = atk_gobject_accessible_for_object (G_OBJECT(etcta->row));
-			}
+			accessible = atk_gobject_accessible_for_object (G_OBJECT(etcta));
+			if (accessible)
+				g_object_ref (accessible);
 			return accessible;
 		}
 	}
@@ -95,6 +187,12 @@
 	return NULL;
 }
 
+static AtkLayer
+et_get_layer (AtkComponent *component)
+{
+	return ATK_LAYER_WIDGET;
+}
+
 static void
 et_class_init (GalA11yETableClass *klass)
 {
@@ -110,6 +208,7 @@
 et_atk_component_iface_init (AtkComponentIface *iface)
 {
 	iface->ref_accessible_at_point = et_ref_accessible_at_point;
+	iface->get_layer = et_get_layer;
 }
 
 static void
@@ -180,6 +279,16 @@
 	a11y = g_object_new (gal_a11y_e_table_get_type (), NULL);
 
 	GTK_ACCESSIBLE (a11y)->widget = GTK_WIDGET (widget);
+
+	/* we need to init all the children for multiple table items */
+	if (table && GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && table->group && E_IS_TABLE_GROUP_CONTAINER (table->group)) {
+		/* Ref it here so that it is still valid in the idle function */
+		/* It will be unrefed in the idle function */
+		g_object_ref (a11y);
+		g_object_ref (widget);
+
+		g_idle_add ((GSourceFunc)init_child_item, a11y);
+	}
 
 	return ATK_OBJECT (a11y);
 }
Index: gal/a11y/e-table/gal-a11y-e-tree.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-tree.c,v
retrieving revision 1.4
diff -u -r1.4 gal-a11y-e-tree.c
--- gal/a11y/e-table/gal-a11y-e-tree.c	10 Jun 2004 17:00:45 -0000	1.4
+++ gal/a11y/e-table/gal-a11y-e-tree.c	27 Jan 2005 03:27:44 -0000
@@ -35,11 +35,6 @@
 	eti = e_tree_get_item (tree);
 	if (priv->child_item == NULL) {
 		priv->child_item = atk_gobject_accessible_for_object (G_OBJECT (eti));
-		if (!priv->child_item)
-			priv->child_item = gal_a11y_e_table_item_new (ATK_OBJECT (a11y),eti, 0);
-
-		g_return_if_fail (priv->child_item);
-		priv->child_item->role = ATK_ROLE_TREE_TABLE;
 	}
 }
 
@@ -72,6 +67,12 @@
 	return GET_PRIVATE (a11y)->child_item;
 }
 
+static AtkLayer
+et_get_layer (AtkComponent *component)
+{
+	return ATK_LAYER_WIDGET;
+}
+
 static void
 et_class_init (GalA11yETreeClass *klass)
 {
@@ -87,6 +88,7 @@
 et_atk_component_iface_init (AtkComponentIface *iface)
 {
 	iface->ref_accessible_at_point = et_ref_accessible_at_point;
+	iface->get_layer = et_get_layer;
 }
 
 static void

--- End Message ---


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]