[goffice] Data labels work.



commit 0b59d6e0ef831d1e62aebb6bf701fee9eb85aa91
Author: Jean Brefort <jean brefort normalesup org>
Date:   Sun Aug 14 15:25:23 2011 +0200

    Data labels work.

 ChangeLog                         |   13 ++++
 goffice/data/go-data-impl.h       |    1 +
 goffice/data/go-data.c            |    8 ++
 goffice/data/go-data.h            |    1 +
 goffice/graph/gog-label.c         |    1 -
 goffice/graph/gog-series-labels.c |  135 ++++++++++++++++++++++++++++++++++++-
 goffice/graph/gog-series-labels.h |    9 +++
 goffice/graph/gog-series.c        |    7 ++-
 plugins/plot_barcol/gog-barcol.c  |    9 +--
 9 files changed, 175 insertions(+), 9 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index d3fcb32..4378dab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2011-08-14  Jean Brefort  <jean brefort normalesup org>
+
+	* goffice/data/go-data-impl.h: add new is_valid method.
+	* goffice/data/go-data.c (go_data_is_valid): ditto.
+	* goffice/data/go-data.h: ditto.
+	* goffice/graph/gog-label.c (gog_text_view_size_request): don't unref a
+	GOString twice.
+	* goffice/graph/gog-series-labels.c: more work on data labels.
+	* goffice/graph/gog-series-labels.h: ditto.
+	* goffice/graph/gog-series.c (role_series_labels_can_add),
+	(gog_series_update): ditto.
+	* plugins/plot_barcol/gog-barcol.c (gog_barcol_view_render): ditto.
+
 2011-08-12  Morten Welinder  <terra gnome org>
 
 	* goffice/utils/go-format.c (go_format_value_gstring): Avoid
diff --git a/goffice/data/go-data-impl.h b/goffice/data/go-data-impl.h
index f6b6a90..d4b6a9b 100644
--- a/goffice/data/go-data-impl.h
+++ b/goffice/data/go-data-impl.h
@@ -58,6 +58,7 @@ typedef struct {
 	double		(*get_value)		(GOData *data, unsigned int *coordinates);
 	char *		(*get_string)		(GOData *data, unsigned int *coordinates);
 	PangoAttrList * (*get_markup)		(GOData *data, unsigned int *coordinates);
+	gboolean	(*is_valid)		(GOData const *data);
 
 	/* signals */
 	void (*changed)	(GOData *dat);
diff --git a/goffice/data/go-data.c b/goffice/data/go-data.c
index 2596096..dcb76c9 100644
--- a/goffice/data/go-data.c
+++ b/goffice/data/go-data.c
@@ -209,6 +209,14 @@ go_data_unserialize (GOData *dat, char const *str, gpointer user)
 	return (*klass->unserialize) (dat, str, user);
 }
 
+gboolean
+go_data_is_valid (GOData const *data)
+{
+	GODataClass const *klass = GO_DATA_GET_CLASS (data);
+	g_return_val_if_fail (klass != NULL, FALSE);
+	return (klass->is_valid != NULL)? (*klass->is_valid) (data): FALSE;
+}
+
 /**
  * go_data_emit_changed :
  * @dat : #GOData
diff --git a/goffice/data/go-data.h b/goffice/data/go-data.h
index 4b77f2c..1451cff 100644
--- a/goffice/data/go-data.h
+++ b/goffice/data/go-data.h
@@ -37,6 +37,7 @@ GOData *	go_data_dup			(GOData const *src);
 gboolean  	go_data_eq			(GOData const *a, GOData const *b);
 GOFormat const *go_data_preferred_fmt 		(GOData const *dat);
 GODateConventions const *go_data_date_conv	(GOData const *dat);
+gboolean	go_data_is_valid		(GOData const *dat);
 
 char *		go_data_serialize		(GOData const *dat, gpointer user);
 gboolean  	go_data_unserialize		(GOData *dat, char const *str, gpointer user);
diff --git a/goffice/graph/gog-label.c b/goffice/graph/gog-label.c
index 07ea47a..41089c0 100644
--- a/goffice/graph/gog-label.c
+++ b/goffice/graph/gog-label.c
@@ -560,7 +560,6 @@ gog_text_view_size_request (GogView *v,
 			req->w = aabr.w;
 			req->h = aabr.h;
 		}
-		go_string_unref (gostr);
 		g_free (str);
 	}
 	text_view_parent_klass->size_request (v, available, req);
diff --git a/goffice/graph/gog-series-labels.c b/goffice/graph/gog-series-labels.c
index b027566..33d396e 100644
--- a/goffice/graph/gog-series-labels.c
+++ b/goffice/graph/gog-series-labels.c
@@ -560,7 +560,7 @@ gog_series_labels_parent_changed (GogObject *obj, gboolean was_set)
 		switch (plot->desc.series.dim[j].ms_type) {
 		case GOG_MS_DIM_VALUES:
 			labels->format = g_strdup_printf ("%%%u", j);
-				j = plot->desc.series.num_dim; /* ensure we exit the loop */
+			j = plot->desc.series.num_dim; /* ensure we exit the loop */
 			break;
 		default:
 			break;
@@ -570,11 +570,121 @@ gog_series_labels_parent_changed (GogObject *obj, gboolean was_set)
 }
 
 static void
+gog_series_labels_changed (GogObject *obj, gboolean size)
+{
+	gog_object_emit_changed (gog_object_get_parent (obj), size);
+}
+
+struct attr_closure {
+	PangoAttrList *l;
+	unsigned offset;
+};
+
+static gboolean
+attr_position (PangoAttribute *attr, gpointer data)
+{
+	struct attr_closure *c = (struct attr_closure *) data;
+	PangoAttribute *new_attr = pango_attribute_copy (attr);
+	new_attr->start_index += c->offset;
+	new_attr->end_index += c->offset;
+	pango_attr_list_change (c->l, new_attr);
+	return FALSE;
+}
+
+static void
+gog_series_labels_update (GogObject *obj)
+{
+	GogSeriesLabels *labels = GOG_SERIES_LABELS (obj);
+	GogObject *parent = gog_object_get_parent (GOG_OBJECT (obj));
+	unsigned i, n;
+	if (labels->elements) {
+		n = labels->n_elts;
+		for (i = 0; i < n; i++)
+			go_string_unref (labels->elements[i].str);
+		g_free (labels->elements);
+	}
+	if (GOG_IS_SERIES (parent)) {
+		GogSeries *series = GOG_SERIES (parent);
+		labels->n_elts = n = gog_series_num_elements (series);
+		labels->elements = g_new0 (GogSeriesLabelElt, n);
+		for (i = 0; i < n; i++) {
+			GString *str = g_string_new ("");
+			unsigned index;
+			PangoAttrList *markup = pango_attr_list_new (), *l;
+			char const *format = labels->format;
+			char *next;
+			while (*format) {
+				if (*format == '%') {
+					format++;
+					switch (*format) {
+					case 0: /* protect from an unexpected string end */
+						break;
+					case 'c':
+						next = go_data_get_vector_string (labels->custom_labels.data, i);
+						if (next) {
+							index = str->len;
+							g_string_append (str, next);
+							g_free (next);
+							l = go_data_get_vector_markup (labels->custom_labels.data, i);
+							if (l) {
+								struct attr_closure c;
+								c.l = markup;
+								c.offset = index;
+								pango_attr_list_filter (l, attr_position, &c);
+								pango_attr_list_unref (l);
+							}
+						}
+						break;
+					case 'l':
+						break;
+					case '0':
+					case '1':
+					case '2':
+					case '3':
+					case '4':
+					case '5':
+					case '6':
+					case '7':
+					case '8':
+					case '9':
+						index = *format - '0';
+						next = go_data_get_vector_string (series->values[index].data, i);
+						if (next) {
+							g_string_append (str, next);
+							g_free (next);
+						}
+						break;
+					case '%':
+						g_string_append_c (str, '%');
+						break;
+					default:
+						continue;
+					}
+					format++;
+				} else {
+					next = g_utf8_next_char (format);
+					g_string_append_len (str, format, next - format);
+					format = next;
+				}
+			}
+			labels->elements[i].str = go_string_new_rich (g_string_free (str, FALSE), -1, FALSE, markup, NULL);
+		}
+	} else
+		labels->elements = NULL; /* FIXME: might be a SeriesElement */
+}
+
+static void
 gog_series_labels_finalize (GObject *obj)
 {
 	GogSeriesLabels *labels = GOG_SERIES_LABELS (obj);
 	gog_dataset_finalize (GOG_DATASET (obj));
 	g_free (labels->format);
+	if (labels->elements) {
+		unsigned i, n = labels->n_elts;
+		for (i = 0; i < n; i++)
+			go_string_unref (labels->elements[i].str);
+		g_free (labels->elements);
+	}
 	series_labels_parent_klass->finalize (obj);
 }
 
@@ -611,6 +721,8 @@ gog_series_labels_class_init (GObjectClass *obj_klass)
 	gog_klass->populate_editor = gog_series_labels_populate_editor;
 #endif
 	gog_klass->parent_changed = gog_series_labels_parent_changed;
+	gog_klass->changed = gog_series_labels_changed;
+	gog_klass->update = gog_series_labels_update;
 	style_klass->init_style = gog_series_labels_init_style;
 }
 
@@ -632,7 +744,7 @@ gog_series_labels_dataset_get_elem (GogDataset const *set, int dim_i)
 static void
 gog_series_labels_dataset_dim_changed (GogDataset *set, int dim_i)
 {
-	gog_object_request_update (GOG_OBJECT (set));
+	gog_object_request_update (gog_object_get_parent (GOG_OBJECT (set)));
 }
 
 static void
@@ -718,3 +830,22 @@ gog_series_labels_get_position (GogSeriesLabels const *lbls)
 	return (lbls->position == GOG_SERIES_LABELS_DEFAULT_POS)?
 		lbls->default_pos: lbls->position;
 }
+
+GogSeriesLabelElt const *gog_series_labels_scalar_get_element (GogSeriesLabels const *lbls)
+{
+	g_return_val_if_fail (GOG_IS_SERIES_LABELS (lbls), NULL);
+	return lbls->elements;
+}
+
+GogSeriesLabelElt const *gog_series_labels_vector_get_element (GogSeriesLabels const *lbls, unsigned n)
+{
+	GogObject *obj;
+	g_return_val_if_fail (GOG_IS_SERIES_LABELS (lbls) && lbls->elements != NULL, NULL);
+	obj= gog_object_get_parent (GOG_OBJECT (lbls));
+	if (GOG_IS_SERIES (obj)) {
+		GogSeries *series = GOG_SERIES (obj);
+		g_return_val_if_fail (n < gog_series_num_elements (series), NULL);
+		return lbls->elements + n;
+	}
+	return NULL;
+}
diff --git a/goffice/graph/gog-series-labels.h b/goffice/graph/gog-series-labels.h
index 5fa7585..caf2cd7 100644
--- a/goffice/graph/gog-series-labels.h
+++ b/goffice/graph/gog-series-labels.h
@@ -27,6 +27,11 @@
 
 G_BEGIN_DECLS
 
+typedef struct  {
+	GOString *str;
+	double legend_offset, legend_width, width, height;
+} GogSeriesLabelElt;
+
 struct _GogSeriesLabels {
 	GogOutlinedObject base;
 
@@ -37,6 +42,8 @@ struct _GogSeriesLabels {
 	unsigned offset; /* position offset in pixels */
 	char *format;
 	GogDatasetElement custom_labels;
+	unsigned n_elts;
+	GogSeriesLabelElt *elements;
 };
 
 #define GOG_TYPE_SERIES_LABELS		(gog_series_labels_get_type ())
@@ -49,6 +56,8 @@ void gog_series_labels_set_allowed_position (GogSeriesLabels *lbls, unsigned all
 void gog_series_labels_set_position (GogSeriesLabels *lbls, GogSeriesLabelsPos pos);
 void gog_series_labels_set_default_position (GogSeriesLabels *lbls, GogSeriesLabelsPos pos);
 GogSeriesLabelsPos gog_series_labels_get_position (GogSeriesLabels const *lbls);
+GogSeriesLabelElt const *gog_series_labels_scalar_get_element (GogSeriesLabels const *lbls);
+GogSeriesLabelElt const *gog_series_labels_vector_get_element (GogSeriesLabels const *lbls, unsigned n);
 
 G_END_DECLS
 
diff --git a/goffice/graph/gog-series.c b/goffice/graph/gog-series.c
index e954ada..f770478 100644
--- a/goffice/graph/gog-series.c
+++ b/goffice/graph/gog-series.c
@@ -305,7 +305,7 @@ role_series_labels_can_add (GogObject const *parent)
 {
 	GogSeries *series = GOG_SERIES (parent);
 
-	return (series->allowed_pos != 0);
+	return (series->allowed_pos != 0 && gog_object_get_child_by_name (parent, "Data labels") == NULL);
 }
 
 static void
@@ -628,7 +628,12 @@ static void
 gog_series_update (GogObject *obj)
 {
 	GogSeries *series = GOG_SERIES (obj);
+	GogObjectRole const *role = gog_object_find_role_by_name (obj, "Data labels");
+	GSList *l = gog_object_get_children (obj, role), *ptr;
 	series->needs_recalc = FALSE;
+	for (ptr = l; ptr; ptr = ptr->next)
+		gog_object_request_update (ptr->data);
+	g_slist_free (l);
 }
 
 static void
diff --git a/plugins/plot_barcol/gog-barcol.c b/plugins/plot_barcol/gog-barcol.c
index 684cd6d..3113c5d 100644
--- a/plugins/plot_barcol/gog-barcol.c
+++ b/plugins/plot_barcol/gog-barcol.c
@@ -378,8 +378,8 @@ typedef struct {
 typedef struct {
 	double		 x;
 	double 		 y;
-	char		*str;
-	GOAnchorType    anchor;
+	GogSeriesLabelElt const	*elt;
+	GOAnchorType     anchor;
 } LabelData;
 
 static int
@@ -642,7 +642,7 @@ gog_barcol_view_render (GogView *view, GogViewAllocation const *bbox)
 		if (labels[i]) {
 			label_pos[i] = g_malloc (sizeof (LabelData) * lengths[i]);
 			for (j = 0; j < lengths[i]; j++)
-				label_pos[i][j].str = go_data_get_vector_string (base_series->values[1].data, j);
+				label_pos[i][j].elt = gog_series_labels_vector_get_element (labels[i] , j);
 		} else
 			label_pos[i] = NULL;
 	}
@@ -862,8 +862,7 @@ gog_barcol_view_render (GogView *view, GogViewAllocation const *bbox)
 			for (j = 0; j < lengths[i]; j++) {
 				alloc.x = label_pos[i][j].x;
 				alloc.y = label_pos[i][j].y;
-				gog_renderer_draw_text (view->renderer, label_pos[i][j].str, &alloc, label_pos[i][j].anchor, FALSE);
-				g_free (label_pos[i][j].str);
+				gog_renderer_draw_gostring (view->renderer, label_pos[i][j].elt->str, &alloc, label_pos[i][j].anchor);
 			}
 			gog_renderer_pop_style (view->renderer);
 		}



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