[goffice] Canvas: avoid invalidation of invisible items.



commit 829ceff56420bf663614a3872cd1da7d46d40de4
Author: Morten Welinder <terra gnome org>
Date:   Fri Apr 8 14:01:13 2011 -0400

    Canvas: avoid invalidation of invisible items.

 ChangeLog                  |   11 ++++++++
 goffice/canvas/goc-group.c |   58 ++++++++++++++++++++-----------------------
 goffice/canvas/goc-item.c  |   56 ++++++++++++++++++++++++++++++------------
 goffice/canvas/goc-item.h  |    1 +
 4 files changed, 79 insertions(+), 47 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index f5c3835..d422cae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2011-04-08  Morten Welinder  <terra gnome org>
+
+	* goffice/canvas/goc-group.c: Cleanup list traversal.
+
+	* goffice/canvas/goc-item.c (goc_item_maybe_invalidate): New
+	function, extracted from goc_item_invalidate.  Avoid invalidating
+	invisible items.
+	(goc_item_set_visible): New function.
+	(goc_item_show, goc_item_hide): Base on goc_item_set_visible.
+	This avoids invalidation when nothing changes.
+
 2011-04-06  Jean Brefort  <jean brefort normalesup org>
 
 	* plugins/plot_xy/gog-xy-dropbar-prefs.ui: implement dropbar plots with
diff --git a/goffice/canvas/goc-group.c b/goffice/canvas/goc-group.c
index f2349bd..3c38739 100644
--- a/goffice/canvas/goc-group.c
+++ b/goffice/canvas/goc-group.c
@@ -45,7 +45,7 @@ enum {
  **/
 static void
 goc_group_set_property (GObject *gobject, guint param_id,
-				    GValue const *value, GParamSpec *pspec)
+			GValue const *value, GParamSpec *pspec)
 {
 	GocGroup *group = GOC_GROUP (gobject);
 
@@ -66,7 +66,7 @@ goc_group_set_property (GObject *gobject, guint param_id,
 
 static void
 goc_group_get_property (GObject *gobject, guint param_id,
-				    GValue *value, GParamSpec *pspec)
+			GValue *value, GParamSpec *pspec)
 {
 	GocGroup *group = GOC_GROUP (gobject);
 
@@ -92,21 +92,18 @@ goc_group_update_bounds (GocItem *item)
 	item->x0 = item->y0 = G_MAXDOUBLE;
 	item->x1 = item->y1 = -G_MAXDOUBLE;
 	if (group->children != NULL) {
-		GList *l = g_list_first (group->children);
-		while (l) {
-			if (l->data) {
-				goc_item_get_bounds (GOC_ITEM (l->data),
-						     &x0, &y0, &x1, &y1);
-				if (x0 < item->x0)
-					item->x0 = x0;
-				if (y0 < item->y0)
-					item->y0 = y0;
-				if (x1 > item->x1)
-					item->x1 = x1;
-				if (y1 > item->y1)
-					item->y1 = y1;
-			}
-			l = g_list_next (l);
+		GList *l;
+		for (l = group->children; l; l = l->next) {
+			GocItem *child = GOC_ITEM (l->data);
+			goc_item_get_bounds (child, &x0, &y0, &x1, &y1);
+			if (x0 < item->x0)
+				item->x0 = x0;
+			if (y0 < item->y0)
+				item->y0 = y0;
+			if (x1 > item->x1)
+				item->x1 = x1;
+			if (y1 > item->y1)
+				item->y1 = y1;
 		}
 		item->x0 += group->x;
 		item->y0 += group->y;
@@ -121,7 +118,7 @@ goc_group_draw_region (GocItem const *item, cairo_t *cr,
 		      double x1, double y1)
 {
 	GocGroup *group = GOC_GROUP (item);
-	GList *l = g_list_first (group->children);
+	GList *l = group->children;
 	if (!l)
 		return TRUE;
 	cairo_save (cr);
@@ -129,19 +126,17 @@ goc_group_draw_region (GocItem const *item, cairo_t *cr,
 	y0 -= group->y;
 	x1 -= group->x;
 	y1 -= group->y;
-	while (l) {
+	for (; l; l = l->next) {
 		double x, y, x_, y_;
 		GocItem *item = GOC_ITEM (l->data);
-		if (!goc_item_is_visible (item)) {
-			l = l->next;
+		if (!goc_item_is_visible (item))
 			continue;
-		}
+
 		goc_item_get_bounds (item, &x, &y, &x_, &y_);
 		if (x <= x1 && x_ >= x0 && y <= y1 && y_ >= y0) {
 			if (!goc_item_draw_region (item, cr, x0, y0, x1, y1))
 				goc_item_draw (item, cr);
 		}
-		l = g_list_next (l);
 	}
 	cairo_restore (cr);
 	return TRUE;
@@ -164,12 +159,12 @@ goc_group_distance (GocItem *item, double x, double y, GocItem **near_item)
 	double th = GOC_THRESHOLD / item->canvas->pixels_per_unit;
 	x -= group->x;
 	y -= group->y;
-	for (l = g_list_last (group->children); l; l = g_list_previous (l)) {
+	for (l = g_list_last (group->children); l; l = l->prev) {
 		GocItem *it = GOC_ITEM (l->data);
 		if (!it->visible || it->x0 > x + th || it->x1 < x - th
 		    || it->y0 > y + th || it->y1 < y - th)
 			continue;
-		dist = goc_item_distance (GOC_ITEM (l->data), x, y, &cur_item);
+		dist = goc_item_distance (it, x, y, &cur_item);
 		if (dist < result) {
 			*near_item = cur_item;
 			result = dist;
@@ -186,7 +181,7 @@ goc_group_realize (GocItem *item)
 	GocGroup *group = GOC_GROUP (item);
 	GList *l;
 
-	for (l = g_list_first (group->children); l; l = g_list_next (l)) {
+	for (l = group->children; l; l = l->next) {
 		GocItem *child = GOC_ITEM (l->data);
 		_goc_item_realize (child);
 	}
@@ -202,7 +197,7 @@ goc_group_unrealize (GocItem *item)
 
 	parent_klass->unrealize (item);
 
-	for (l = g_list_first (group->children); l; l = g_list_next (l)) {
+	for (l = group->children; l; l = l->next) {
 		GocItem *child = GOC_ITEM (l->data);
 		_goc_item_unrealize (child);
 	}
@@ -214,10 +209,11 @@ goc_group_notify_scrolled (GocItem *item)
 	GocGroup *group = GOC_GROUP (item);
 	GList *l;
 	GocItemClass *klass;
-	for (l = g_list_first (group->children); l; l = g_list_next (l)) {
-		klass = GOC_ITEM_GET_CLASS (l->data);
+	for (l = group->children; l; l = l->next) {
+		GocItem *child = GOC_ITEM (l->data);
+		klass = GOC_ITEM_GET_CLASS (child);
 		if (klass->notify_scrolled)
-			klass->notify_scrolled (GOC_ITEM (l->data));
+			klass->notify_scrolled (child);
 	}
 }
 
@@ -278,7 +274,7 @@ goc_group_new (GocGroup *parent)
 	g_return_val_if_fail (GOC_IS_GROUP (parent), NULL);
 
 	group = GOC_GROUP (g_object_new (GOC_TYPE_GROUP, NULL));
-	g_return_val_if_fail ((group != NULL), NULL);
+	g_return_val_if_fail (group != NULL, NULL);
 
 	goc_group_add_child (parent, GOC_ITEM (group));
 
diff --git a/goffice/canvas/goc-item.c b/goffice/canvas/goc-item.c
index 567cc59..3957016 100644
--- a/goffice/canvas/goc-item.c
+++ b/goffice/canvas/goc-item.c
@@ -433,20 +433,12 @@ goc_item_draw_region (GocItem const *item, cairo_t *cr,
 		klass->draw_region (item, cr, x0, y0, x1, y1): FALSE;
 }
 
-/**
- * goc_item_invalidate :
- * @item: #GocItem
- *
- * Force a redraw of @item bounding region.
- **/
-void
-goc_item_invalidate (GocItem *item)
+static void
+goc_item_maybe_invalidate (GocItem *item, gboolean ignore_visibility)
 {
 	GocGroup const *parent;
 	double x0, y0, x1, y1;
 
-	g_return_if_fail (GOC_IS_ITEM (item));
-
 	parent = item->parent;
 	if (!parent)
 		return;
@@ -454,6 +446,9 @@ goc_item_invalidate (GocItem *item)
 	if (!gtk_widget_get_realized (GTK_WIDGET (item->canvas)))
 		return;
 
+	if (!ignore_visibility && !item->visible)
+		return;
+
 	if (!item->cached_bounds)
 		_goc_item_update_bounds (GOC_ITEM (item)); /* don't care about const */
 	x0 = item->x0;
@@ -465,6 +460,39 @@ goc_item_invalidate (GocItem *item)
 }
 
 /**
+ * goc_item_invalidate :
+ * @item: #GocItem
+ *
+ * Force a redraw of @item bounding region.
+ **/
+void
+goc_item_invalidate (GocItem *item)
+{
+	g_return_if_fail (GOC_IS_ITEM (item));
+
+	goc_item_maybe_invalidate (item, FALSE);
+}
+
+/**
+ * goc_item_set_visible :
+ * @item: #GocItem
+ * @visible: whether the item should be visible
+ *
+ * Either hides or shows @item as appropriate..
+ **/
+void
+goc_item_set_visible (GocItem *item, gboolean visible)
+{
+	g_return_if_fail (GOC_IS_ITEM (item));
+
+	visible = (visible != FALSE);
+	if (visible != item->visible) {
+		item->visible = visible;
+		goc_item_maybe_invalidate (item, TRUE);
+	}
+}
+
+/**
  * goc_item_show :
  * @item: #GocItem
  *
@@ -473,9 +501,7 @@ goc_item_invalidate (GocItem *item)
 void
 goc_item_show (GocItem *item)
 {
-	g_return_if_fail (GOC_IS_ITEM (item));
-	item->visible = TRUE;
-	goc_item_invalidate (item);
+	goc_item_set_visible (item, TRUE);
 }
 
 /**
@@ -487,9 +513,7 @@ goc_item_show (GocItem *item)
 void
 goc_item_hide (GocItem *item)
 {
-	g_return_if_fail (GOC_IS_ITEM (item));
-	item->visible = FALSE;
-	goc_item_invalidate (item);
+	goc_item_set_visible (item, FALSE);
 }
 
 /**
diff --git a/goffice/canvas/goc-item.h b/goffice/canvas/goc-item.h
index 61ecafa..e8e0f6b 100644
--- a/goffice/canvas/goc-item.h
+++ b/goffice/canvas/goc-item.h
@@ -80,6 +80,7 @@ gboolean	 goc_item_draw_region	(GocItem const *item, cairo_t *cr,
 void		 goc_item_invalidate	(GocItem *item);
 void		 goc_item_show		(GocItem *item);
 void		 goc_item_hide		(GocItem *item);
+void		 goc_item_set_visible   (GocItem *item, gboolean visible);
 gboolean	 goc_item_is_visible	(GocItem *item);
 void		 goc_item_get_bounds	(GocItem const *item,
 					 double *x0, double *y0,



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