[gnumeric] Deps: implement style dependents -- not hooked up yet.



commit 0acb4c9e12521fb20b13c128bca96e3cf97fec89
Author: Morten Welinder <terra gnome org>
Date:   Thu Feb 7 09:11:46 2013 -0500

    Deps: implement style dependents -- not hooked up yet.
    
    This contains the basics for style dependents, i.e., dependents for
    conditional formatting to trigger rerendering and redrawing of cells.
    
    This isn't actually hooked up yet.

 ChangeLog            |   10 +++++
 src/dependent.c      |   99 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/dependent.h      |    5 ++
 src/gnm-style-impl.h |    2 +
 src/mstyle.c         |  102 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/mstyle.h         |    5 ++
 6 files changed, 223 insertions(+), 0 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 742f13d..9f5aa35 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2013-02-07  Morten Welinder  <terra gnome org>
+
+	* src/dependent.c (GnmStyleDependent): New type of dependent.
+	When triggered, the cells in which it resised will be rerendered
+	and redrawn.
+
+	* src/mstyle.c (gnm_style_link_dependents)
+	(gnm_style_unlink_dependents): New functions to manage style
+	dependents due to conditional formatting.
+
 2013-02-06  Morten Welinder  <terra gnome org>
 
 	* src/sheet-style.c (vector_apply_pstyle): Turn loop structure
diff --git a/src/dependent.c b/src/dependent.c
index a64dae9..65bc7fa 100644
--- a/src/dependent.c
+++ b/src/dependent.c
@@ -283,6 +283,22 @@ static const GnmDependentClass managed_dep_class = {
 	managed_dep_debug_name,
 };
 
+static GSList *style_dep_changed (GnmDependent *dep);
+static GnmCellPos const *style_dep_pos (GnmDependent const *dep);
+static void style_dep_debug_name (GnmDependent const *dep, GString *target);
+static const GnmDependentClass style_dep_class = {
+	dummy_dep_eval,
+	NULL,
+	style_dep_changed,
+	style_dep_pos,
+	style_dep_debug_name,
+};
+typedef struct {
+	GnmDependent base;
+	GnmCellPos pos;
+} GnmStyleDependent;
+
+
 static GPtrArray *dep_classes = NULL;
 
 void
@@ -297,6 +313,7 @@ dependent_types_init (void)
 	g_ptr_array_add	(dep_classes, (gpointer)&dynamic_dep_class);
 	g_ptr_array_add	(dep_classes, (gpointer)&name_dep_class);
 	g_ptr_array_add	(dep_classes, (gpointer)&managed_dep_class);
+	g_ptr_array_add	(dep_classes, (gpointer)&style_dep_class);
 
 #if USE_POOLS
 	micro_few_pool =
@@ -1152,6 +1169,39 @@ workbook_unlink_3d_dep (GnmDependent *dep)
 	g_hash_table_remove (wb->sheet_order_dependents, dep);
 }
 
+GSList *
+gnm_dep_style_dependency (Sheet *sheet,
+			  GnmExprTop const *texpr,
+			  GnmRange const *r)
+{
+	int row, col;
+	GSList *res = NULL;
+
+	/*
+	 * FIXME: Maybe do better for an expression that is just an
+	 * absolute ref.
+	 */
+
+	for (row = r->start.row; row <= r->end.row; row++) {
+		for (col = r->start.col; col <= r->end.col; col++) {
+			GnmStyleDependent *sd = g_new0 (GnmStyleDependent, 1);
+			GnmDependent *dep = &sd->base;
+
+			dep->sheet = sheet;
+			dep->flags = DEPENDENT_STYLE;
+			dep->texpr = NULL;
+			sd->pos.col = col;
+			sd->pos.row = row;
+
+			dependent_set_expr (dep, texpr);
+			dependent_link (dep);
+			res = g_slist_prepend (res, dep);
+		}
+	}
+
+	return res;
+}
+
 /*****************************************************************************/
 
 static void
@@ -1272,6 +1322,55 @@ managed_dep_debug_name (GnmDependent const *dep, GString *target)
 
 /*****************************************************************************/
 
+static gboolean
+debug_style_deps (void)
+{
+	static int debug = -1;
+	if (debug < 0)
+		debug = gnm_debug_flag ("style-deps");
+	return debug;
+}
+
+static GSList *
+style_dep_changed (GnmDependent *dep)
+{
+	GnmCellPos const *pos = dependent_pos (dep);
+	GnmCell *cell;
+	Sheet *sheet = dep->sheet;
+
+	if (debug_style_deps ())
+		g_printerr ("StyleDep %p at %s changed\n",
+			    dep, cellpos_as_string (pos));
+
+	/*
+	 * If the cell exists, unrender it so format changes can take
+	 * effect.
+	 */
+	cell = sheet_cell_get (sheet, pos->col, pos->row);
+	if (cell)
+		gnm_cell_unrender (cell);
+
+	sheet_redraw_region (sheet,
+			     pos->col, pos->row,
+			     pos->col, pos->row);
+
+	return NULL;
+}
+
+static GnmCellPos const *
+style_dep_pos (GnmDependent const *dep)
+{
+	return &((GnmStyleDependent*)dep)->pos;
+}
+
+static void
+style_dep_debug_name (GnmDependent const *dep, GString *target)
+{
+	g_string_append_printf (target, "StyleDep%p", (void *)dep);
+}
+
+/*****************************************************************************/
+
 static void
 name_dep_debug_name (GnmDependent const *dep, GString *target)
 {
diff --git a/src/dependent.h b/src/dependent.h
index aa150ff..82d2dbb 100644
--- a/src/dependent.h
+++ b/src/dependent.h
@@ -32,6 +32,7 @@ typedef enum {
 	DEPENDENT_DYNAMIC_DEP	   = 0x00000002,	/* builtin type */
 	DEPENDENT_NAME		   = 0x00000003,	/* builtin pseudo type */
 	DEPENDENT_MANAGED	   = 0x00000004,	/* builtin type */
+	DEPENDENT_STYLE		   = 0x00000005,	/* builtin type */
 	DEPENDENT_TYPE_MASK	   = 0x00000fff,
 
 	/* Linked into the workbook wide expression list */
@@ -110,6 +111,10 @@ void dependents_workbook_destroy  (Workbook *wb);
 void dependents_revive_sheet      (Sheet *sheet);
 void workbook_queue_all_recalc	  (Workbook *wb);
 
+GSList *gnm_dep_style_dependency (Sheet *sheet,
+				  GnmExprTop const *texpr,
+				  GnmRange const *r);
+
 GnmDepContainer *gnm_dep_container_new  (Sheet *sheet);
 void		 gnm_dep_container_dump	(GnmDepContainer const *deps,
 					 Sheet *sheet);
diff --git a/src/gnm-style-impl.h b/src/gnm-style-impl.h
index 1d3af77..7e58cb0 100644
--- a/src/gnm-style-impl.h
+++ b/src/gnm-style-impl.h
@@ -64,6 +64,8 @@ struct _GnmStyle {
 	GnmInputMsg		*input_msg;
 	GnmStyleConditions	*conditions;
 	GPtrArray		*cond_styles;
+
+	GSList *deps;
 };
 
 #define elem_changed(style, elem) do { (style)->changed |= (1u << (elem)); } while(0)
diff --git a/src/mstyle.c b/src/mstyle.c
index a134f9d..cd6fa3f 100644
--- a/src/mstyle.c
+++ b/src/mstyle.c
@@ -16,7 +16,10 @@
 #include "sheet-style.h"
 #include "style-conditions.h"
 #include "application.h"
+#include "parse-util.h"
+#include "expr.h"
 #include "gutils.h"
+#include "ranges.h"
 #include "gnumeric-conf.h"
 #include <goffice/goffice.h>
 
@@ -733,6 +736,9 @@ gnm_style_unref (GnmStyle const *style)
 		gnm_style_clear_pango (unconst);
 		gnm_style_clear_font (unconst);
 
+		if (style->deps)
+			g_warning ("Leftover style deps!");
+
 		CHUNK_FREE (gnm_style_pool, unconst);
 	}
 }
@@ -1748,6 +1754,102 @@ gnm_style_get_conditions (GnmStyle const *style)
 	return style->conditions;
 }
 
+static gboolean
+debug_style_deps (void)
+{
+	static int debug = -1;
+	if (debug < 0)
+		debug = gnm_debug_flag ("style-deps");
+	return debug;
+}
+
+void
+gnm_style_link_dependents (GnmStyle *style, GnmRange const *r)
+{
+	GnmStyleConditions *sc;
+	Sheet *sheet;
+	GSList *deps;
+
+	g_return_if_fail (style != NULL);
+	g_return_if_fail (r != NULL);
+
+	sheet = style->linked_sheet;
+	deps = style->deps;
+
+	/*
+	 * Conditional formatting.
+	 *
+	 * We need to trigger a reformatting of the cell if a cell referenced
+	 * by the condition changes.
+	 */
+	sc = elem_is_set (style, MSTYLE_CONDITIONS)
+		? gnm_style_get_conditions (style)
+		: NULL;
+	if (sc) {
+		GPtrArray const *conds = gnm_style_conditions_details (sc);
+		guint ui;
+		if (debug_style_deps ())
+			g_printerr ("Linking %s for %p\n",
+				    range_as_string (r), style);
+		for (ui = 0; ui < conds->len; ui++) {
+			GnmStyleCond const *c = g_ptr_array_index (conds, ui);
+			guint ei;
+
+			for (ei = 0; ei < 2; ei++) {
+				GnmExprTop const *texpr =
+					gnm_style_cond_get_expr (c, ei);
+				if (!texpr)
+					continue;
+				deps = g_slist_concat
+					(deps,
+					 gnm_dep_style_dependency
+					 (sheet, texpr, r));
+			}
+		}
+	}
+
+	/*
+	 * Validations.
+	 *
+	 * We can probably ignore those.  If a dependent cell changes such
+	 * that a validation condition is no longer satisfied, it is
+	 * grandfathered in a valid.
+	 */
+
+	/* The style owns the deps.  */
+	style->deps = deps;
+}
+
+void
+gnm_style_unlink_dependents (GnmStyle *style, GnmRange const *r)
+{
+	GSList *keep = NULL, *l, *next;
+
+	g_return_if_fail (style != NULL);
+	g_return_if_fail (r != NULL);
+
+	for (l = style->deps; l; l = next) {
+		GnmDependent *dep = l->data;
+		GnmCellPos const *pos = dependent_pos (dep);
+		next = l->next;
+
+		if (range_contains (r, pos->col, pos->row)) {
+			if (debug_style_deps ())
+				g_printerr ("Unlinking %s for %p\n",
+					    cellpos_as_string (pos), style);
+			dependent_set_expr (dep, NULL);
+			g_free (dep);
+			g_slist_free_1 (l);
+		} else {
+			l->next = keep;
+			keep = l;
+		}
+	}
+
+	style->deps = keep;
+}
+
+
 gboolean
 gnm_style_visible_in_blank (GnmStyle const *style)
 {
diff --git a/src/mstyle.h b/src/mstyle.h
index db1de9e..3a73eb2 100644
--- a/src/mstyle.h
+++ b/src/mstyle.h
@@ -158,6 +158,11 @@ GnmInputMsg	*gnm_style_get_input_msg	(GnmStyle const *style);
 void		 gnm_style_set_conditions	(GnmStyle *style, GnmStyleConditions *sc);
 GnmStyleConditions *gnm_style_get_conditions	(GnmStyle const *style);
 
+void             gnm_style_link_dependents      (GnmStyle *style,
+						 GnmRange const *r);
+void             gnm_style_unlink_dependents    (GnmStyle *style,
+						 GnmRange const *r);
+
 gboolean	 gnm_style_visible_in_blank (GnmStyle const *style);
 
 PangoAttrList	*gnm_style_generate_attrs_full (GnmStyle const *style);


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