[evolution-patches] gal, accessiblity, etable, handle the columns change (add/delete/reorder)



Hi Mike,

The patch fix bug 49594.
It work by listen to table header's  structure change signal.
By comparing table header with previously saved one, we know what actually happened.

column insert or delete or reorder. Then we manipulate the cache to reflect the new conditions.




Regards
York

Index: 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.2
diff -u -r1.2 gal-a11y-e-cell-toggle.c
--- gal-a11y-e-cell-toggle.c	21 Nov 2003 04:28:04 -0000	1.2
+++ gal-a11y-e-cell-toggle.c	24 Nov 2003 06:14:59 -0000
@@ -13,11 +13,6 @@
 {
 	GalA11yECellToggle *a11y = GAL_A11Y_E_CELL_TOGGLE (object);
 
-	ETableModel *e_table_model = GAL_A11Y_E_CELL (a11y)->cell_view->e_table_model;
-
-	if (e_table_model)
-		g_signal_handler_disconnect (e_table_model, a11y->model_id);
-
 	if (parent_class->dispose)
 		parent_class->dispose (object);
 }
Index: 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.5
diff -u -r1.5 gal-a11y-e-table-item.c
--- gal-a11y-e-table-item.c	21 Nov 2003 04:28:04 -0000	1.5
+++ gal-a11y-e-table-item.c	24 Nov 2003 06:15:00 -0000
@@ -38,6 +38,7 @@
 	gpointer *cell_data;
 	int selection_change_id;
 	int cursor_change_id;
+	ETableCol ** columns;
 };
 
 #if 0
@@ -91,6 +92,11 @@
 		priv->cell_data = NULL;
 	}
 
+	if (priv->columns) {
+		g_free(priv->columns);
+		priv->columns = NULL;
+	}
+
 	if (parent_class->dispose)
 		parent_class->dispose (object);
 }
@@ -706,6 +712,151 @@
 	g_signal_emit_by_name (table_item, "visible-data-changed");
 }
 
+enum {
+        ETI_HEADER_UNCHANGED = 0,
+        ETI_HEADER_REORDERED,
+        ETI_HEADER_NEW_ADDED,
+        ETI_HEADER_REMOVED,
+};
+                                                                                
+/*
+ * 1. Check what actually happened: column reorder, remove or add
+ * 2. Update cache
+ * 3. Emit signals
+ */
+static void
+eti_header_structure_changed (ETableHeader *eth, AtkObject *a11y)
+{
+                                                                                
+        gboolean reorder_found=FALSE, added_found=FALSE, removed_found=FALSE;
+        GalA11yETableItem * a11y_item;
+        ETableCol ** cols, **prev_cols;
+        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;
+
+        prev_n_cols = priv->cols;
+        prev_cols = priv->columns;
+
+        cols = e_table_header_get_columns (eth);
+	n_cols = eth->col_count;
+                                                                                
+        g_return_if_fail (cols && prev_cols && n_cols > 0);
+                                                                                
+        /* Init to ETI_HEADER_UNCHANGED. */
+        state = g_malloc0 (sizeof (gint) * n_cols);
+        prev_state = g_malloc0 (sizeof (gint) * prev_n_cols);
+        reorder = g_malloc0 (sizeof (gint) * n_cols);
+	g_return_if_fail (state && reorder && prev_state);
+
+        /* Compare with previously saved column headers. */
+        for ( i = 0 ; i < n_cols && cols[i]; i ++ ) {
+                for ( j = 0 ; j < prev_n_cols && prev_cols[j]; j ++ ) {
+                        if ( prev_cols [j] == cols[i] && i != j ) {
+
+                                reorder_found = TRUE;
+                                state [i] = ETI_HEADER_REORDERED;
+				reorder [i] = j;
+
+                                break;
+                        } else if (prev_cols[j] == cols[i]) {
+                                /* OK, this column is not changed. */
+                                break;
+                        }
+                }
+                                                                                
+                /* cols[i] is new added column. */
+                if ( j == prev_n_cols ) {
+			gint row;
+
+			added_found = TRUE;
+                        state[i] = ETI_HEADER_NEW_ADDED;
+                }
+        }
+
+        /* Now try to find if there are removed columns. */
+        for (i = 0 ; i < prev_n_cols && prev_cols[i]; i ++) {
+                for (j = 0 ; j < n_cols && cols[j]; j ++)
+                        if ( prev_cols [j] == cols[i] )
+				break;
+                                                                                
+                /* Removed columns found. */
+                if ( j == n_cols ) {
+			removed_found = TRUE;
+			prev_state[j] = ETI_HEADER_REMOVED;
+                }
+        }
+
+	/* If nothing interesting just return. */
+	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");
+
+
+	if (removed_found) {
+		for (i = 0; i < prev_n_cols; i ++ ) {
+			if (prev_state[i] == ETI_HEADER_REMOVED) {
+				g_signal_emit_by_name (G_OBJECT(a11y_item), "column-deleted", i, 1);
+				for (j = 0 ; j < n_rows; j ++)
+					g_signal_emit_by_name (G_OBJECT(a11y_item), "children_changed::remove", (j*prev_n_cols+i), NULL, NULL);
+			}
+		}
+	}
+
+	if (added_found) {
+		for ( i = 0; i < n_cols; i ++ ) {
+			if (state[i] == ETI_HEADER_NEW_ADDED) {
+				g_signal_emit_by_name (G_OBJECT(a11y_item), "column-inserted", i, 1);
+				for (j = 0 ; j < n_rows; j ++)
+					g_signal_emit_by_name (G_OBJECT(a11y_item), "children_changed::add", (j*n_cols+i), NULL, NULL);
+			}
+		}
+	}
+
+	priv->cols = n_cols;
+
+	g_free (state);
+	g_free (reorder);
+	g_free (prev_state);
+
+	g_free (priv->columns);
+	priv->columns = cols;
+}
+
+
 static void
 eti_real_initialize (AtkObject *obj, 
 		     gpointer data)
@@ -724,6 +875,9 @@
 	g_signal_connect (model, "model-rows-deleted",
 			  G_CALLBACK (eti_rows_deleted),
 			  obj);
+	g_signal_connect (G_OBJECT (eti->header), "structure_change",
+			  G_CALLBACK (eti_header_structure_changed), obj);
+
 }
 
 static void
@@ -868,6 +1022,10 @@
 	/* memory error. */
 	if ( GET_PRIVATE (a11y) == NULL)
 		return NULL;
+
+        GET_PRIVATE (a11y)->columns = e_table_header_get_columns (item->header);                                                                                
+        if ( GET_PRIVATE (a11y)->columns == NULL)
+                return NULL;
 
 	if (item) {
 		g_signal_connect (G_OBJECT(item), "selection_model_removed",


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