[gnumeric] Dependents: move changed actions into klass method.



commit 53732722f65f3e1ef125db64f74d79fe54b2164e
Author: Morten Welinder <terra gnome org>
Date:   Sat Jul 28 22:54:34 2012 -0400

    Dependents: move changed actions into klass method.

 ChangeLog       |    8 +++++
 NEWS            |    2 +-
 src/dependent.c |   80 ++++++++++++++++++++++++++++++++++++------------------
 src/dependent.h |    1 +
 4 files changed, 63 insertions(+), 28 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 729205c..f94392b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2012-07-28  Morten Welinder  <terra gnome org>
+
+	* src/dependent.h (GnmDependentClass): Add new "changed" method
+	for propagating changes.
+
+	* src/dependent.c (dependent_queue_recalc_main): Use new
+	->changed.
+
 2012-07-27  Morten Welinder  <terra gnome org>
 
 	* src/dependent.c (cell_dep_eval): Don't complain if we're not
diff --git a/NEWS b/NEWS
index 49ae6f2..c011c10 100644
--- a/NEWS
+++ b/NEWS
@@ -12,7 +12,7 @@ Jean:
 
 Morten:
 	* Fix xls read crash.  [#679992]
-	* Reduce code duplication for dependents.
+	* Dependents code cleanups.
 	* Make cells regular dependents.
 	* Fix non-linear solver crash.  [#680719]
 
diff --git a/src/dependent.c b/src/dependent.c
index 32e2f66..8028b02 100644
--- a/src/dependent.c
+++ b/src/dependent.c
@@ -233,8 +233,10 @@ gnm_dep_unlink_undo_new (GSList *deps)
 
 static void cell_dep_eval	   (GnmDependent *dep);
 static void cell_dep_set_expr	   (GnmDependent *dep, GnmExprTop const *new_texpr);
+static GSList *cell_dep_changed	   (GnmDependent *dep);
 static void cell_dep_debug_name    (GnmDependent const *dep, GString *target);
 static void dynamic_dep_eval	   (GnmDependent *dep);
+static GSList *dynamic_dep_changed (GnmDependent *dep);
 static void dynamic_dep_debug_name (GnmDependent const *dep, GString *target);
 static void name_dep_eval	   (GnmDependent *dep);
 static void name_dep_debug_name	   (GnmDependent const *dep, GString *target);
@@ -245,21 +247,25 @@ static GPtrArray *dep_classes = NULL;
 static GnmDependentClass cell_dep_class = {
 	cell_dep_eval,
 	cell_dep_set_expr,
+	cell_dep_changed,
 	cell_dep_debug_name,
 };
 static GnmDependentClass dynamic_dep_class = {
 	dynamic_dep_eval,
 	NULL,
+	dynamic_dep_changed,
 	dynamic_dep_debug_name,
 };
 static GnmDependentClass name_dep_class = {
 	name_dep_eval,
 	NULL,
+	NULL,
 	name_dep_debug_name,
 };
 static GnmDependentClass managed_dep_class = {
 	managed_dep_eval,
 	NULL,
+	NULL,
 	managed_dep_debug_name,
 };
 typedef struct {
@@ -447,34 +453,16 @@ dependent_queue_recalc_main (GSList *work)
 	while (work) {
 		GnmDependent *dep = work->data;
 		int const t = dependent_type (dep);
+		GnmDependentClass *klass = g_ptr_array_index (dep_classes, t);
+
 		/* Pop the top element.  */
-		GSList *list = work;
-		work = work->next;
-
-		g_slist_free_1 (list);
-
-		if (t == DEPENDENT_CELL) {
-			GSList *deps = cell_list_deps (GNM_DEP_TO_CELL (dep));
-			GSList *waste = NULL;
-			GSList *next;
-			for (list = deps; list != NULL ; list = next) {
-				GnmDependent *dep = list->data;
-				next = list->next;
-				if (dependent_needs_recalc (dep)) {
-					list->next = waste;
-					waste = list;
-				} else {
-					dependent_flag_recalc (dep);
-					list->next = work;
-					work = list;
-				}
-			}
-			g_slist_free (waste);
-		} else if (t == DEPENDENT_DYNAMIC_DEP) {
-			DynamicDep const *dyn = (DynamicDep *)dep;
-			if (!dependent_needs_recalc (dyn->container)) {
-				dependent_flag_recalc (dyn->container);
-				work = g_slist_prepend (work, dyn->container);
+		work = g_slist_delete_link (work, work);
+
+		if (klass->changed) {
+			GSList *extra = klass->changed (dep);
+			if (extra) {
+				g_slist_last (extra)->next = work;
+				work = extra;
 			}
 		}
 	}
@@ -1171,6 +1159,30 @@ cell_dep_set_expr (GnmDependent *dep, GnmExprTop const *new_texpr)
 	gnm_cell_set_expr_unsafe (GNM_DEP_TO_CELL (dep), new_texpr);
 }
 
+static GSList *
+cell_dep_changed (GnmDependent *dep)
+{
+	/* When a cell changes, so do its dependents.  */
+
+	GSList *deps = cell_list_deps (GNM_DEP_TO_CELL (dep));
+	GSList *waste = NULL, *work = NULL;
+	GSList *next, *list;
+	for (list = deps; list != NULL ; list = next) {
+		GnmDependent *dep = list->data;
+		next = list->next;
+		if (dependent_needs_recalc (dep)) {
+			list->next = waste;
+			waste = list;
+		} else {
+			dependent_flag_recalc (dep);
+			list->next = work;
+			work = list;
+		}
+	}
+	g_slist_free (waste);
+	return work;
+}
+
 static void
 cell_dep_debug_name (GnmDependent const *dep, GString *target)
 {
@@ -1264,6 +1276,20 @@ dynamic_dep_eval (G_GNUC_UNUSED GnmDependent *dep)
 {
 }
 
+static GSList *
+dynamic_dep_changed (GnmDependent *dep)
+{
+	DynamicDep const *dyn = (DynamicDep *)dep;
+
+	/* When a dynamic dependent changes, we mark its container.  */
+
+	if (dependent_needs_recalc (dyn->container))
+		return NULL;
+
+	dependent_flag_recalc (dyn->container);
+	return g_slist_prepend (NULL, dyn->container);
+}
+
 static void
 dynamic_dep_debug_name (GnmDependent const *dep, GString *target)
 {
diff --git a/src/dependent.h b/src/dependent.h
index b72b28b..9b15e39 100644
--- a/src/dependent.h
+++ b/src/dependent.h
@@ -19,6 +19,7 @@ struct _GnmDependent {
 typedef struct {
 	void (*eval)	   (GnmDependent *dep);
 	void (*set_expr)   (GnmDependent *dep, GnmExprTop const *new_texpr);
+	GSList* (*changed) (GnmDependent *dep);
 	void (*debug_name) (GnmDependent const *dep, GString *target);
 } GnmDependentClass;
 



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