[goffice] Make data labels work in bar/column charts.



commit 51e2f91818c9af7bf65dd1633ad711447d23429b
Author: Jean Brefort <jean brefort normalesup org>
Date:   Sat Aug 20 16:28:49 2011 +0200

    Make data labels work in bar/column charts.

 ChangeLog                         |   13 ++++
 goffice/graph/goffice-graph.h     |    2 +-
 goffice/graph/gog-renderer.c      |  145 +++++++++++++++++++++++++++++++++++++
 goffice/graph/gog-renderer.h      |    4 +
 goffice/graph/gog-series-labels.c |   18 +----
 goffice/graph/gog-series-labels.h |    2 +-
 goffice/graph/gog-view.c          |    6 ++
 goffice/graph/gog-view.h          |    2 +
 plugins/plot_barcol/gog-barcol.c  |    6 ++-
 9 files changed, 181 insertions(+), 17 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 9c66037..92de6cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2011-08-20  Jean Brefort  <jean brefort normalesup org>
+	* goffice/graph/goffice-graph.h: fix include order.
+	* goffice/graph/gog-renderer.c (gog_renderer_draw_data_label): new function.
+	* goffice/graph/gog-renderer.h: ditto.
+	* goffice/graph/gog-series-labels.c (gog_series_labels_update): make legend
+	entry in label work.
+	* goffice/graph/gog-series-labels.h: ditto.
+	* goffice/graph/gog-view.c (gog_view_get_natural_size): new function
+	(see #629794)
+	* goffice/graph/gog-view.h: ditto.
+	* plugins/plot_barcol/gog-barcol.c (gog_barcol_view_render): use 
+	gog_renderer_draw_data_label.
+
 2011-08-18  Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* goffice/app/go-cmd-context-impl.h (go_cmd_context_progress_set):
diff --git a/goffice/graph/goffice-graph.h b/goffice/graph/goffice-graph.h
index 9ad07fb..3cf1849 100644
--- a/goffice/graph/goffice-graph.h
+++ b/goffice/graph/goffice-graph.h
@@ -266,9 +266,9 @@ G_END_DECLS
 #include <goffice/graph/gog-plot.h>
 #include <goffice/graph/gog-plot-impl.h>
 #include <goffice/graph/gog-reg-curve.h>
+#include <goffice/graph/gog-series-labels.h>
 #include <goffice/graph/gog-renderer.h>
 #include <goffice/graph/gog-series-lines.h>
-#include <goffice/graph/gog-series-labels.h>
 #include <goffice/graph/gog-smoothed-curve.h>
 #include <goffice/graph/gog-theme.h>
 
diff --git a/goffice/graph/gog-renderer.c b/goffice/graph/gog-renderer.c
index 7ea33d9..066e30c 100644
--- a/goffice/graph/gog-renderer.c
+++ b/goffice/graph/gog-renderer.c
@@ -1090,6 +1090,151 @@ gog_renderer_get_gostring_AABR (GogRenderer *rend, GOString *str,
 	go_geometry_OBR_to_AABR (&obr, aabr);
 }
 
+void
+gog_renderer_draw_data_label (GogRenderer *rend, GogSeriesLabelElt const *elt,
+                              GogViewAllocation const *pos, GOAnchorType anchor,
+                              GOStyle *legend_style)
+{
+	/* things are a bit different from gog_renderer_draw_gostring, so the
+	 * code must be copied */
+	PangoLayout *layout;
+	PangoContext *context;
+	cairo_t *cairo;
+	GOGeometryOBR obr;
+	GOGeometryAABR aabr;
+	GOStyle const *style;
+	int iw, ih;
+	PangoAttrList *attrs;
+	PangoRectangle rect;
+
+	g_return_if_fail (elt != NULL && elt->str != NULL);
+	g_return_if_fail (GOG_IS_RENDERER (rend));
+	g_return_if_fail (rend->cur_style != NULL);
+
+	cairo = rend->cairo;
+	style = rend->cur_style;
+
+	/* Note: orig layout may not have been created using cairo! */
+	layout = pango_cairo_create_layout (cairo);
+	context = pango_layout_get_context (layout);
+	pango_layout_set_text (layout, elt->str->str, -1);
+	attrs = pango_attr_list_copy (go_string_get_markup (elt->str));
+	pango_layout_set_font_description (layout, style->font.font->desc);
+	if (attrs)
+		pango_layout_set_attributes (layout, attrs);
+	pango_cairo_context_set_resolution (context, 72.0);
+	/*now get the real size */
+	pango_layout_get_size (layout, &iw, &ih);
+	if (elt->legend_pos >= 0) {
+		/* we need to add enough room to draw the legend entry */
+		PangoRectangle rect;
+		PangoAttribute *attr;
+		rect.x = rect.y = 0;
+		pango_layout_get_size (layout, &iw, &ih);
+		rect.height = 1; /* only the width is important */
+		rect.width = (legend_style->interesting_fields & GO_STYLE_LINE)? 2 * ih: ih; 
+		attr = pango_attr_shape_new (&rect, &rect);
+		attr->start_index = elt->legend_pos;
+		attr->end_index = elt->legend_pos + 1;
+		pango_attr_list_insert (attrs, attr);
+		pango_layout_set_attributes (layout, attrs);
+		pango_layout_get_size (layout, &iw, &ih);
+	}
+	pango_attr_list_unref (attrs);
+
+	obr.w = rend->scale * ((double) iw + (double) PANGO_SCALE / 2.0)
+		/ (double) PANGO_SCALE;
+	obr.h = rend->scale * ((double) ih + (double) PANGO_SCALE / 2.0)
+		/(double) PANGO_SCALE;
+	obr.alpha = -style->text_layout.angle * M_PI / 180.0;
+	obr.x = pos->x;
+	obr.y = pos->y;
+	go_geometry_OBR_to_AABR (&obr, &aabr);
+
+	switch (anchor) {
+		case GO_ANCHOR_NW: case GO_ANCHOR_W: case GO_ANCHOR_SW:
+			obr.x += aabr.w / 2.0;
+			break;
+		case GO_ANCHOR_NE : case GO_ANCHOR_SE : case GO_ANCHOR_E :
+			obr.x -= aabr.w / 2.0;
+			break;
+		default : break;
+	}
+
+	switch (anchor) {
+		case GO_ANCHOR_NW: case GO_ANCHOR_N: case GO_ANCHOR_NE:
+			obr.y += aabr.h / 2.0;
+			break;
+		case GO_ANCHOR_SE : case GO_ANCHOR_S : case GO_ANCHOR_SW :
+			obr.y -= aabr.h / 2.0;
+			break;
+		default : break;
+	}
+
+	cairo_save (cairo);
+	cairo_set_source_rgba (cairo, GO_COLOR_TO_CAIRO (style->font.color));
+	cairo_translate (cairo, obr.x - (obr.w / 2.0) * cos (obr.alpha) +
+		       (obr.h / 2.0) * sin (obr.alpha),
+		       obr.y - (obr.w / 2.0) * sin (obr.alpha) -
+		       (obr.h / 2.0) * cos (obr.alpha));
+	cairo_rotate (cairo, obr.alpha);
+	cairo_scale (cairo, rend->scale, rend->scale);
+	pango_cairo_show_layout (cairo, layout);
+	/* now draw the legen entry if needed */
+	if (elt->legend_pos >= 0 && legend_style != NULL) {
+		GOStyle *style = go_style_dup (legend_style);
+		GogViewAllocation rectangle;
+		double x, y,w, h;
+		pango_layout_index_to_pos (layout, elt->legend_pos, &rect);
+		x = (double) rect.x / PANGO_SCALE;
+		y = (double) rect.y / PANGO_SCALE;
+		w = (double) rect.width / PANGO_SCALE;
+		h = (double) rect.height / PANGO_SCALE;
+		if (style->interesting_fields & GO_STYLE_LINE) { /* line and marker */
+			GOPath *line_path;
+			if (style->line.width > h / 3.)
+				style->line.width = h / 3.;
+			if (go_marker_get_size (style->marker.mark) > h)
+				go_marker_set_size (style->marker.mark, h);
+			gog_renderer_push_style (rend, style);
+			line_path = go_path_new ();
+			y += h / 2.;
+			go_path_move_to (line_path, x, y);
+			go_path_line_to (line_path, x + w, y);
+			if (style->interesting_fields & GO_STYLE_FILL) {
+				rectangle.x = x;
+				rectangle.y = y;
+				rectangle.w = w;
+				rectangle.h = h / 2.0;
+				gog_renderer_fill_rectangle (rend, &rectangle);
+			}
+			gog_renderer_stroke_serie (rend, line_path);
+			go_path_free (line_path);
+			gog_renderer_draw_marker (rend, x + w / 2., y);
+		} else if (style->interesting_fields & GO_STYLE_FILL) {/* area */
+			if (style->line.width > h / 3.)
+				style->line.width = h / 3.;
+
+			rectangle.x = x;
+			rectangle.y = y;
+			rectangle.w = w;
+			rectangle.h = h;
+
+			gog_renderer_push_style (rend, style);
+			gog_renderer_draw_rectangle (rend, &rectangle);
+		} else if (style->interesting_fields & GO_STYLE_MARKER) {					/* markers only */
+			if (go_marker_get_size (style->marker.mark) > h)
+				go_marker_set_size (style->marker.mark, h);
+			gog_renderer_push_style (rend, style);
+			gog_renderer_draw_marker (rend, x + w / 2., y + h / 2.);
+		}
+		gog_renderer_pop_style (rend);
+		g_object_unref (style);
+	}
+	cairo_restore (cairo);
+	g_object_unref (layout);
+}
+
 static void
 _free_marker_data (GogRenderer *rend)
 {
diff --git a/goffice/graph/gog-renderer.h b/goffice/graph/gog-renderer.h
index 2e31e6b..c0821b2 100644
--- a/goffice/graph/gog-renderer.h
+++ b/goffice/graph/gog-renderer.h
@@ -91,6 +91,10 @@ void  gog_renderer_draw_text	  (GogRenderer *rend, char const *text,
 				   GOAnchorType anchor,
 				   gboolean use_markup);
 
+void  gog_renderer_draw_data_label (GogRenderer *rend, GogSeriesLabelElt const *elt,
+                                    GogViewAllocation const *pos, GOAnchorType anchor,
+                                    GOStyle *legend_style);
+
 void  gog_renderer_draw_gostring  (GogRenderer *rend,
 				   GOString *str,
 				   GogViewAllocation const *pos,
diff --git a/goffice/graph/gog-series-labels.c b/goffice/graph/gog-series-labels.c
index 7c32c5f..72ca1ff 100644
--- a/goffice/graph/gog-series-labels.c
+++ b/goffice/graph/gog-series-labels.c
@@ -21,7 +21,7 @@
  */
 
 #include <goffice/goffice-config.h>
-#include <goffice/graph/gog-series-labels.h>
+#include <goffice/goffice.h>
 
 #include <gsf/gsf-impl-utils.h>
 #include <glib/gi18n-lib.h>
@@ -599,8 +599,6 @@ gog_series_labels_update (GogObject *obj)
 {
 	GogSeriesLabels *labels = GOG_SERIES_LABELS (obj);
 	GogObject *parent = gog_object_get_parent (GOG_OBJECT (obj));
-	GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (obj));
-	int height = pango_font_description_get_size (style->font.font->desc);
 	unsigned i, n;
 	if (labels->elements) {
 		n = labels->n_elts;
@@ -618,6 +616,7 @@ gog_series_labels_update (GogObject *obj)
 			PangoAttrList *markup = pango_attr_list_new (), *l;
 			char const *format = labels->format;
 			char *next;
+			labels->elements[i].legend_pos = -1;
 			while (*format) {
 				if (*format == '%') {
 					format++;
@@ -641,17 +640,8 @@ gog_series_labels_update (GogObject *obj)
 						}
 						break;
 					case 'l': {
-						/* add room for the legend entry */
-						PangoRectangle rect;
-						PangoAttribute *attr;
-						rect.x = rect.y = 0;
-						rect.height = 1; /* only the width is important */
-						rect.width = 2 * height; /* FIXME, should not always be 2 */
-						attr = pango_attr_shape_new (&rect, &rect);
-						attr->start_index = str->len;
-						g_string_append_c (str, 'o');
-						attr->end_index = str->len;
-						pango_attr_list_insert (markup, attr);
+						labels->elements[i].legend_pos = str->len;
+						g_string_append_c (str, ' '); /* this one will be replaced by the legend entry */
 						break;
 					}
 					case '0':
diff --git a/goffice/graph/gog-series-labels.h b/goffice/graph/gog-series-labels.h
index caf2cd7..deed348 100644
--- a/goffice/graph/gog-series-labels.h
+++ b/goffice/graph/gog-series-labels.h
@@ -29,7 +29,7 @@ G_BEGIN_DECLS
 
 typedef struct  {
 	GOString *str;
-	double legend_offset, legend_width, width, height;
+	int legend_pos;
 } GogSeriesLabelElt;
 
 struct _GogSeriesLabels {
diff --git a/goffice/graph/gog-view.c b/goffice/graph/gog-view.c
index dd2ae99..7af8d3b 100644
--- a/goffice/graph/gog-view.c
+++ b/goffice/graph/gog-view.c
@@ -1024,3 +1024,9 @@ gog_view_get_tip_at_point (GogView *view, double x, double y)
 	GogViewClass *klass = GOG_VIEW_GET_CLASS (view);
 	return (klass->get_tip_at_point != NULL)? (klass->get_tip_at_point) (view, x, y): NULL;
 }
+
+void
+gog_view_get_natural_size (GogView *view, GogViewRequisition *requisition)
+{
+	requisition->w = requisition->h = 0.; /*FIXME!!!*/
+}
diff --git a/goffice/graph/gog-view.h b/goffice/graph/gog-view.h
index 0ab1a69..1a9b31d 100644
--- a/goffice/graph/gog-view.h
+++ b/goffice/graph/gog-view.h
@@ -92,6 +92,7 @@ typedef struct {
 
 	void	 (*build_toolkit)		(GogView *view);
 	char    *(*get_tip_at_point)		(GogView *view, double x, double y);
+	void	 (*natural_size)    		(GogView *view, GogViewRequisition *req);
 } GogViewClass;
 
 #define GOG_TYPE_VIEW		(gog_view_get_type ())
@@ -114,6 +115,7 @@ void       gog_view_size_allocate    (GogView *view, GogViewAllocation const *al
 gboolean   gog_view_update_sizes     (GogView *view);
 GogView   *gog_view_find_child_view  (GogView const *container,
 				      GogObject const *target_model);
+void       gog_view_get_natural_size (GogView *view, GogViewRequisition *requisition);
 
 GSList const	*gog_view_get_toolkit		(GogView *view);
 void 		 gog_view_render_toolkit 	(GogView *view);
diff --git a/plugins/plot_barcol/gog-barcol.c b/plugins/plot_barcol/gog-barcol.c
index 3113c5d..a07b055 100644
--- a/plugins/plot_barcol/gog-barcol.c
+++ b/plugins/plot_barcol/gog-barcol.c
@@ -862,7 +862,11 @@ 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_gostring (view->renderer, label_pos[i][j].elt->str, &alloc, label_pos[i][j].anchor);
+				gog_renderer_draw_data_label (view->renderer,
+				                              label_pos[i][j].elt,
+				                              &alloc,
+				                              label_pos[i][j].anchor,
+				                              styles[i]);
 			}
 			gog_renderer_pop_style (view->renderer);
 		}



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