[goffice] Implement error bars in radar and polar plots. [#572720]



commit 1191c1332ceff0f173b0c5386a8cbb1306f9d216
Author: Jean Brefort <jean brefort normalesup org>
Date:   Wed Nov 4 19:42:53 2009 +0100

    Implement error bars in radar and polar plots. [#572720]

 ChangeLog                            |   23 +++
 NEWS                                 |    1 +
 goffice/graph/gog-error-bar-prefs.ui |    3 +-
 goffice/graph/gog-error-bar.c        |  126 ++++++++++++++--
 goffice/graph/gog-error-bar.h        |   13 ++-
 plugins/plot_barcol/gog-barcol.c     |    4 +-
 plugins/plot_barcol/gog-line.c       |    4 +-
 plugins/plot_radar/gog-radar.c       |  274 +++++++++++++++++++++++++++++++++-
 plugins/plot_xy/gog-xy.c             |   10 +-
 9 files changed, 425 insertions(+), 33 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 2c6c44e..6afa86a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
 2009-11-04  Jean Brefort  <jean brefort normalesup org>
 
+	* goffice/graph/gog-error-bar-prefs.ui: implement error bars in
+	radar and polar plots. [#572720]
+	* goffice/graph/gog-error-bar.c (gog_error_bar_prefs),
+	(gog_error_bar_render): ditto.
+	* goffice/graph/gog-error-bar.h: ditto.
+	* plugins/plot_barcol/gog-barcol.c (gog_barcol_view_render): fixed after
+	error bars API changes.
+	* plugins/plot_barcol/gog-line.c (gog_line_view_render): ditto.
+	* plugins/plot_radar/gog-radar.c (gog_rt_plot_update),
+	(gog_radar_plot_class_init), (gog_polar_plot_class_init),
+	(gog_color_polar_plot_class_init), (gog_rt_view_render),
+	(gog_rt_series_set_property), (gog_rt_series_get_property),
+	(gog_rt_series_finalize), (gog_rt_series_populate_editor),
+	(gog_rt_series_class_init), (gog_polar_series_set_property),
+	(gog_polar_series_get_property),
+	(gog_polar_series_populate_editor), (gog_polar_series_finalize),
+	(gog_polar_series_class_init):  implement error bars in
+	radar and polar plots. [#572720]
+	* plugins/plot_xy/gog-xy.c (gog_xy_view_render): fixed after
+	error bars API changes.
+
+2009-11-04  Jean Brefort  <jean brefort normalesup org>
+
 	* goffice/app/go-conf-keyfile.c (go_conf_get_real_key): do not add a '/'
 	when subkey is NULL. [#600654]
 
diff --git a/NEWS b/NEWS
index bed17a8..83bb208 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ goffice 0.7.16:
 Jean:
 	* Add parent name for new objects in the graph guru "Add" menu.
 	* Fix configuratioin loading when using .gnumericrc. [#600654]
+	* Implement error bars in radar and polar plots. [#572720]
 
 --------------------------------------------------------------------------
 goffice 0.7.15:
diff --git a/goffice/graph/gog-error-bar-prefs.ui b/goffice/graph/gog-error-bar-prefs.ui
index c180be9..e0d66fd 100644
--- a/goffice/graph/gog-error-bar-prefs.ui
+++ b/goffice/graph/gog-error-bar-prefs.ui
@@ -1,5 +1,6 @@
 <?xml version="1.0"?>
 <interface>
+  <!-- interface-requires gtk+ 2.12 -->
   <!-- interface-naming-policy toplevel-contextual -->
   <object class="GtkAdjustment" id="adjustment1">
     <property name="value">1</property>
@@ -218,7 +219,7 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkLabel" id="label1">
+                      <object class="GtkLabel" id="width-label">
                         <property name="visible">True</property>
                         <property name="xalign">0</property>
                         <property name="label" translatable="yes">pts</property>
diff --git a/goffice/graph/gog-error-bar.c b/goffice/graph/gog-error-bar.c
index 401dbbe..d678e23 100644
--- a/goffice/graph/gog-error-bar.c
+++ b/goffice/graph/gog-error-bar.c
@@ -198,7 +198,7 @@ cb_type_changed (GtkWidget *w, GogErrorBarEditor *editor)
 gpointer
 gog_error_bar_prefs (GogSeries *series,
 		     char const *property,
-		     gboolean horizontal,
+		     GogErrorBarDirection direction,
 		     GogDataAllocator *dalloc,
 		     GOCmdContext *cc)
 {
@@ -276,7 +276,7 @@ gog_error_bar_prefs (GogSeries *series,
 	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell, "text", 1, NULL);
 
 	for (i = 0; i < G_N_ELEMENTS (display_combo_desc); i++) {
-		pixbuf = go_pixbuf_new_from_file (horizontal ?
+		pixbuf = go_pixbuf_new_from_file (direction == GOG_ERROR_BAR_DIRECTION_HORIZONTAL ?
 						  display_combo_desc[i].h_pixbuf :
 						  display_combo_desc[i].v_pixbuf);
 		gtk_list_store_append (list, &iter);
@@ -293,6 +293,13 @@ gog_error_bar_prefs (GogSeries *series,
 	gtk_table_attach (GTK_TABLE (style_table), GTK_WIDGET(combo), 1, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
 	g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (cb_display_changed), editor);
 
+	/* if radial, change the width unit */
+	if (direction == GOG_ERROR_BAR_DIRECTION_RADIAL) {
+		w = go_gtk_builder_get_widget (gui, "width-label");
+		/* Note for translator: the angle unit */
+		gtk_label_set_text (GTK_LABEL (w), _("°"));
+	}
+
 	/* Category property*/
 	w = go_gtk_builder_get_widget (gui, "category_combo");
 	gtk_combo_box_set_active (GTK_COMBO_BOX (w), (editor->bar)? (int) editor->bar->type: 0);
@@ -615,13 +622,12 @@ gog_error_bar_dup		(GogErrorBar const *bar)
  * gog_error_bar_render :
  * @bar : A GogErrorBar
  * @rend : A GogRenderer
- * @x_map :  A GogAxisMap for the x axis
- * @y_map :  A GogAxisMap for the y axis
+ * @map :  A GogChartMap for the chart
  * @x : x coordinate of the origin of the bar
  * @y : y coordinate of the origin of the bar
  * @plus : distance from the origin to the positive end of the bar
  * @minus : distance from the origin to the negative end of the bar
- * @horizontal : whether the bar is horizontal or not.
+ * @direction : the #GogErrorBarDirection for the bar.
  *
  * Displays the error bar. If @plus is negative, the positive side of the bar is not displayed,
  * and if @minus is negative, the negative side of the bar is not displayed.
@@ -630,21 +636,25 @@ gog_error_bar_dup		(GogErrorBar const *bar)
  **/
 void gog_error_bar_render (const GogErrorBar *bar,
 			   GogRenderer *rend,
-			   GogAxisMap *x_map, GogAxisMap *y_map,
+			   GogChartMap *map,
 			   double x, double y,
 			   double minus,
 			   double plus,
-			   gboolean horizontal)
+			   GogErrorBarDirection direction)
 {
 	GOPath *path;
 	double x_start, y_start, x_end, y_end;
 	double line_width, width;
-	gboolean start = plus > .0 && bar ->display & GOG_ERROR_BAR_DISPLAY_POSITIVE,
-		 end = minus > 0. && bar ->display & GOG_ERROR_BAR_DISPLAY_NEGATIVE;
+	gboolean start = plus > .0 && bar->display & GOG_ERROR_BAR_DISPLAY_POSITIVE,
+		 end = minus > 0. && bar->display & GOG_ERROR_BAR_DISPLAY_NEGATIVE;
+	GogAxisMap *x_map = gog_chart_map_get_axis_map (map, 0),
+		   *y_map = gog_chart_map_get_axis_map (map, 1);
 
-	if (!start && !end) return;
+	if (!start && !end)
+		return;
 
-	if (horizontal) {
+	switch (direction) {
+	case GOG_ERROR_BAR_DIRECTION_HORIZONTAL:
 		if (!gog_axis_map_finite (x_map, x) ||
 		    !gog_axis_map_finite (y_map, y) ||
 		    (start && !gog_axis_map_finite (x_map, x + plus)) ||
@@ -658,7 +668,8 @@ void gog_error_bar_render (const GogErrorBar *bar,
 			gog_axis_map_to_view (x_map , x - minus) :
 			gog_axis_map_to_view (x_map , x);
 		y_start = y_end = gog_axis_map_to_view (y_map, y);
-	} else {
+		break;
+	case GOG_ERROR_BAR_DIRECTION_VERTICAL:
 		if (!gog_axis_map_finite (x_map, x) ||
 		    !gog_axis_map_finite (y_map, y) ||
 		    (start && !gog_axis_map_finite (y_map, y + plus)) ||
@@ -672,6 +683,93 @@ void gog_error_bar_render (const GogErrorBar *bar,
 		y_end =  end ?
 			gog_axis_map_to_view (y_map, y - minus) :
 			gog_axis_map_to_view (y_map, y);
+		break;
+	case GOG_ERROR_BAR_DIRECTION_RADIAL: {
+		GogChartMapPolarData *polar_parms;
+		double cx, cy;
+		double a, rr, xx, yy, y_min, y_max;
+		gboolean cap_min, cap_max;
+		/* x = angle, y = radius */
+		polar_parms = gog_chart_map_get_polar_parms (map);
+		cx = polar_parms->cx;
+		cy = polar_parms->cy;
+		gog_axis_map_get_bounds (y_map, &y_min, &y_max);
+		width = gog_renderer_pt2r (rend, bar->width) / 2.;
+		if (start && y + plus > y_max) {
+			plus = y_max - y;
+			cap_max = FALSE;
+		} else
+			cap_max = TRUE;
+		if (end && y - minus < y_min) {
+			minus = y -y_min;
+			cap_min = FALSE;
+		} else
+			cap_min = TRUE;
+			
+		gog_chart_map_2D_to_view (map, x, (start ? y + plus : y),
+							  &xx, &yy);
+		path = go_path_new ();
+		if (start && cap_max) {
+			rr = hypot (xx - cx, yy - cy);
+			a = atan2 (yy - cy, xx - cx);
+			go_path_arc (path, cx, cy, rr, rr, a - width * M_PI / 180., a + width * M_PI / 180.);
+		}
+		go_path_move_to (path, xx, yy);
+		gog_chart_map_2D_to_view (map, x, (end ? y - minus : y),
+							  &xx, &yy);
+		go_path_line_to (path, xx, yy);
+		if (end && cap_min) {
+			rr = hypot (xx - cx, yy - cy);
+			a = atan2 (yy - cy, xx - cx);
+			go_path_arc (path, cx, cy, rr, rr, a - width * M_PI / 180., a + width * M_PI / 180.);
+		}
+		gog_renderer_push_style (rend, bar->style);
+		gog_renderer_stroke_serie (rend, path);
+		gog_renderer_pop_style (rend);
+		go_path_free (path);
+		return;
+	}
+	case GOG_ERROR_BAR_DIRECTION_ANGULAR: {
+		GogChartMapPolarData *polar_parms;
+		double cx, cy, a0, x0, y0, a1, x1, y1, rr, y_min, y_max;
+		polar_parms = gog_chart_map_get_polar_parms (map);
+		cx = polar_parms->cx;
+		cy = polar_parms->cy;
+		gog_axis_map_get_bounds (y_map, &y_min, &y_max);
+		if (y < y_min || y > y_max)
+			return;
+		width = gog_renderer_pt2r (rend, bar->width) / 2.;
+		line_width = gog_renderer_pt2r (rend, bar->style->line.width);
+		gog_chart_map_2D_to_view (map, (start ? x + plus : x), y,
+							  &x0, &y0);
+		rr = hypot (x0 - cx, y0 - cy);
+		if (rr == 0.)
+			return;
+		a0 = atan2 (y0 - cy, x0 - cx);
+		path = go_path_new ();
+		gog_chart_map_2D_to_view (map, (end ? x - minus : x), y,
+							  &x1, &y1);
+		a1 = atan2 (y1 - cy, x1 - cx);
+		go_path_arc (path, cx, cy, rr, rr, a1, a0);
+		if ((2. * width) > line_width) {
+			double dx, dy;
+			dx = width * cos (a0);
+			dy = width * sin (a0);
+			go_path_move_to (path, x0 - dx, y0 - dy);
+			go_path_line_to (path, x0 + dx, y0 + dy);
+			dx = width * cos (a1);
+			dy = width * sin (a1);
+			go_path_move_to (path, x1 - dx, y1 - dy);
+			go_path_line_to (path, x1 + dx, y1 + dy);
+		}
+		gog_renderer_push_style (rend, bar->style);
+		gog_renderer_stroke_serie (rend, path);
+		gog_renderer_pop_style (rend);
+		go_path_free (path);
+		return;
+	}
+	default:
+		return; /* should not occur */
 	}
 	x = gog_axis_map_to_view (x_map, x);
 	y = gog_axis_map_to_view (y_map, y);
@@ -680,7 +778,7 @@ void gog_error_bar_render (const GogErrorBar *bar,
 	go_path_move_to (path, x_start, y_start);
 	go_path_line_to (path, x_end, y_end);
 
-	if (horizontal) {
+	if (direction == GOG_ERROR_BAR_DIRECTION_HORIZONTAL) {
 		width = gog_renderer_pt2r_y (rend, bar->width) / 2.;
 		line_width = gog_renderer_pt2r_x (rend, bar->style->line.width);
 	} else {
@@ -689,7 +787,7 @@ void gog_error_bar_render (const GogErrorBar *bar,
 	}
 
 	if ((2. * width) > line_width) {
-		if (horizontal) {
+		if (direction == GOG_ERROR_BAR_DIRECTION_HORIZONTAL) {
 			if (start) {
 				go_path_move_to (path, x_start, y - width);
 				go_path_line_to (path, x_start, y + width);
diff --git a/goffice/graph/gog-error-bar.h b/goffice/graph/gog-error-bar.h
index e0689bb..a7fe992 100644
--- a/goffice/graph/gog-error-bar.h
+++ b/goffice/graph/gog-error-bar.h
@@ -34,6 +34,13 @@ typedef enum {
 } GogErrorBarType;
 
 typedef enum {
+	GOG_ERROR_BAR_DIRECTION_HORIZONTAL,
+	GOG_ERROR_BAR_DIRECTION_VERTICAL,
+	GOG_ERROR_BAR_DIRECTION_ANGULAR,
+	GOG_ERROR_BAR_DIRECTION_RADIAL
+} GogErrorBarDirection;
+
+typedef enum {
 	GOG_ERROR_BAR_DISPLAY_NONE,
 	GOG_ERROR_BAR_DISPLAY_POSITIVE,
 	GOG_ERROR_BAR_DISPLAY_NEGATIVE,
@@ -61,7 +68,7 @@ GogErrorBar  	*gog_error_bar_dup		(GogErrorBar const *bar);
 
 #ifdef GOFFICE_WITH_GTK
 gpointer 	 gog_error_bar_prefs (GogSeries *series, char const *property,
-				      gboolean horizontal, GogDataAllocator *dalloc,
+				      GogErrorBarDirection direction, GogDataAllocator *dalloc,
 				      GOCmdContext *cc);
 #endif
 
@@ -70,11 +77,11 @@ gboolean 	 gog_error_bar_get_bounds (const GogErrorBar *bar, int index,
 void 		 gog_error_bar_get_minmax (const GogErrorBar *bar,
 					   double *min, double *max);
 void 		 gog_error_bar_render (const GogErrorBar *bar, GogRenderer *rend,
-				       GogAxisMap *x_map, GogAxisMap *y_map,
+				       GogChartMap *map,
 				       double x, double y,
 				       double minus,
 				       double plus,
-				       gboolean horizontal);
+				       GogErrorBarDirection direction);
 gboolean 	 gog_error_bar_is_visible (GogErrorBar *bar);
 
 G_END_DECLS
diff --git a/plugins/plot_barcol/gog-barcol.c b/plugins/plot_barcol/gog-barcol.c
index 2dfc3b2..f9b3732 100644
--- a/plugins/plot_barcol/gog-barcol.c
+++ b/plugins/plot_barcol/gog-barcol.c
@@ -547,10 +547,10 @@ gog_barcol_view_render (GogView *view, GogViewAllocation const *bbox)
 		if (gog_error_bar_is_visible (errors[i])) {
 			for (j = 0; j < lengths[i]; j++)
 				gog_error_bar_render (errors[i], view->renderer,
-						      x_map, y_map,
+						      chart_map,
 						      error_data[i][j].x , error_data[i][j].y,
 						      error_data[i][j].minus, error_data[i][j].plus,
-						      model->horizontal);
+						      model->horizontal? GOG_ERROR_BAR_DIRECTION_HORIZONTAL: GOG_ERROR_BAR_DIRECTION_VERTICAL);
 			g_free (error_data[i]);
 		}
 
diff --git a/plugins/plot_barcol/gog-line.c b/plugins/plot_barcol/gog-line.c
index de830c6..eb9a591 100644
--- a/plugins/plot_barcol/gog-line.c
+++ b/plugins/plot_barcol/gog-line.c
@@ -677,10 +677,10 @@ gog_line_view_render (GogView *view, GogViewAllocation const *bbox)
 	for (i = 0; i < num_series; i++)
 		if (gog_error_bar_is_visible (errors[i]))
 			for (j = 0; j < lengths[i]; j++)
-				gog_error_bar_render (errors[i], view->renderer, x_map, y_map,
+				gog_error_bar_render (errors[i], view->renderer, chart_map,
 						      error_data[i][j].x, error_data[i][j].y,
 						      error_data[i][j].minus, error_data[i][j].plus,
-						      FALSE);
+						      GOG_ERROR_BAR_DIRECTION_VERTICAL);
 
 	gog_renderer_pop_clip (view->renderer);
 
diff --git a/plugins/plot_radar/gog-radar.c b/plugins/plot_radar/gog-radar.c
index 9b1a53e..ee1a674 100644
--- a/plugins/plot_radar/gog-radar.c
+++ b/plugins/plot_radar/gog-radar.c
@@ -25,6 +25,7 @@
 #include <goffice/graph/gog-axis.h>
 #include <goffice/graph/gog-chart.h>
 #include <goffice/graph/gog-chart-map.h>
+#include <goffice/graph/gog-error-bar.h>
 #include <goffice/graph/gog-grid-line.h>
 #include <goffice/graph/gog-view.h>
 #include <goffice/graph/gog-renderer.h>
@@ -63,10 +64,14 @@ GOFFICE_PLUGIN_MODULE_HEADER;
 typedef struct {
 	GogSeries 	   base;
 	GogObject 	  *radial_drop_lines;
+	GogErrorBar 	  *r_errors;
 } GogRTSeries;
 
-typedef GogRTSeries GogPolarSeries;
-typedef GogRTSeries GogColorPolarSeries;
+typedef struct {
+	GogRTSeries        base;
+	GogErrorBar 	  *a_errors;
+} GogPolarSeries;
+typedef GogPolarSeries GogColorPolarSeries;
 
 typedef GogSeriesClass GogRTSeriesClass;
 typedef GogRTSeriesClass GogPolarSeriesClass;
@@ -82,6 +87,11 @@ enum {
 #define GOG_IS_RT_SERIES(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_TYPE_RT_SERIES))
 
 static GType gog_rt_series_get_type (void);
+
+#define GOG_TYPE_POLAR_SERIES	(gog_polar_series_get_type ())
+#define GOG_POLAR_SERIES(o)	(G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_TYPE_POLAR_SERIES, GogPolarSeries))
+#define GOG_IS_POLAR_SERIES(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_TYPE_POLAR_SERIES))
+
 static GType gog_polar_series_get_type (void);
 static GType gog_color_polar_series_get_type (void);
 static GType gog_rt_view_get_type (void);
@@ -146,6 +156,7 @@ gog_rt_plot_update (GogObject *obj)
 	unsigned num_elements = 0;
 	double val_min, val_max, tmp_min, tmp_max;
 	GSList *ptr;
+	GogErrorBar *errors;
 
 	val_min =  DBL_MAX;
 	val_max = -DBL_MAX;
@@ -159,6 +170,15 @@ gog_rt_plot_update (GogObject *obj)
 		go_data_get_bounds (series->base.values[1].data, &tmp_min, &tmp_max);
 		if (val_min > tmp_min) val_min = tmp_min;
 		if (val_max < tmp_max) val_max = tmp_max;
+
+		errors = series->r_errors;
+		if (gog_error_bar_is_visible (errors)) {
+			gog_error_bar_get_minmax (errors, &tmp_min, &tmp_max);
+			if (val_min > tmp_min)
+				val_min = tmp_min;
+			if (val_max < tmp_max)
+				val_max = tmp_max;
+		}
 	}
 	model->num_elements = num_elements;
 
@@ -299,7 +319,11 @@ gog_radar_plot_class_init (GogPlotClass *gog_plot_klass)
 			{ N_("Labels"), GOG_SERIES_SUGGESTED, TRUE,
 			  GOG_DIM_LABEL, GOG_MS_DIM_CATEGORIES },
 			{ N_("Values"), GOG_SERIES_REQUIRED, FALSE,
-			  GOG_DIM_VALUE, GOG_MS_DIM_VALUES }
+			  GOG_DIM_VALUE, GOG_MS_DIM_VALUES },
+			{ "Magnitude+err", GOG_SERIES_ERRORS, FALSE,
+			  GOG_DIM_VALUE, GOG_MS_DIM_ERR_plus1 },
+			{ "Magnitude-err", GOG_SERIES_ERRORS, FALSE,
+			  GOG_DIM_VALUE, GOG_MS_DIM_ERR_minus1 }
 		};
 		gog_plot_klass->desc.series.dim = dimensions;
 		gog_plot_klass->desc.series.num_dim = G_N_ELEMENTS (dimensions);
@@ -406,7 +430,16 @@ gog_polar_plot_class_init (GogPlotClass *gog_plot_klass)
 			{ N_("Angle"), GOG_SERIES_SUGGESTED, FALSE,
 			  GOG_DIM_INDEX, GOG_MS_DIM_CATEGORIES },
 			{ N_("Magnitude"), GOG_SERIES_REQUIRED, FALSE,
-			  GOG_DIM_VALUE, GOG_MS_DIM_VALUES }
+			  GOG_DIM_VALUE, GOG_MS_DIM_VALUES },
+/* Names of the error data are not translated since they are not used */
+			{ "Angle+err", GOG_SERIES_ERRORS, FALSE,
+			  GOG_DIM_VALUE, GOG_MS_DIM_ERR_plus2 },
+			{ "Angle-err", GOG_SERIES_ERRORS, FALSE,
+			  GOG_DIM_VALUE, GOG_MS_DIM_ERR_minus2 },
+			{ "Magnitude+err", GOG_SERIES_ERRORS, FALSE,
+			  GOG_DIM_VALUE, GOG_MS_DIM_ERR_plus1 },
+			{ "Magnitude-err", GOG_SERIES_ERRORS, FALSE,
+			  GOG_DIM_VALUE, GOG_MS_DIM_ERR_minus1 }
 		};
 		gog_plot_klass->desc.series.dim = dimensions;
 		gog_plot_klass->desc.series.num_dim = G_N_ELEMENTS (dimensions);
@@ -607,7 +640,15 @@ gog_color_polar_plot_class_init (GogPlotClass *gog_plot_klass)
 			{ N_("Magnitude"), GOG_SERIES_REQUIRED, FALSE,
 			  GOG_DIM_VALUE, GOG_MS_DIM_VALUES },
 			{ N_("Z"), GOG_SERIES_REQUIRED, FALSE,
-			  GOG_DIM_VALUE, GOG_MS_DIM_EXTRA1 }
+			  GOG_DIM_VALUE, GOG_MS_DIM_EXTRA1 },
+			{ "Angle+err", GOG_SERIES_ERRORS, FALSE,
+			  GOG_DIM_VALUE, GOG_MS_DIM_ERR_plus2 },
+			{ "Angle-err", GOG_SERIES_ERRORS, FALSE,
+			  GOG_DIM_VALUE, GOG_MS_DIM_ERR_minus2 },
+			{ "Magnitude+err", GOG_SERIES_ERRORS, FALSE,
+			  GOG_DIM_VALUE, GOG_MS_DIM_ERR_plus1 },
+			{ "Magnitude-err", GOG_SERIES_ERRORS, FALSE,
+			  GOG_DIM_VALUE, GOG_MS_DIM_ERR_minus1 }
 		};
 		gog_plot_klass->desc.series.dim = dimensions;
 		gog_plot_klass->desc.series.num_dim = G_N_ELEMENTS (dimensions);
@@ -671,6 +712,7 @@ gog_rt_view_render (GogView *view, GogViewAllocation const *bbox)
 	double rho_min, rho_max, rho;
 	gboolean const is_polar = GOG_IS_PLOT_POLAR (model);
 	gboolean is_map = GOG_IS_PLOT_COLOR_POLAR (model), hide_outliers = TRUE;
+	double errmin, errmax;
 
 	r_axis = GOG_PLOT (model)->axis[GOG_AXIS_RADIAL];
 	c_axis = GOG_PLOT (model)->axis[GOG_AXIS_CIRCULAR];
@@ -803,7 +845,8 @@ gog_rt_view_render (GogView *view, GogViewAllocation const *bbox)
 							  r_vals[i], &theta, &rho);
 				if (   go_finite (theta)
 				    && go_finite (rho)
-				    && rho > rho_min) {
+				    && r_vals[i] > rho_min
+				    && r_vals[i] <= rho_max) {
 					go_path_move_to (drop_path, parms->cx, parms->cy);
 					go_path_line_to (drop_path, theta, rho);
 				}
@@ -818,6 +861,33 @@ gog_rt_view_render (GogView *view, GogViewAllocation const *bbox)
 			go_path_free (path);
 		}
 
+		/* draw error bars before markers and after anything else */
+		for (count = 0; count < series->base.num_elements; count++)
+			if (gog_error_bar_is_visible (series->r_errors)) {
+				GogErrorBar const *bar = series->r_errors;
+				if (gog_error_bar_get_bounds (bar, count, &errmin, &errmax)) {
+					gog_error_bar_render (bar, view->renderer,
+							      chart_map,
+							      ((c_vals != NULL) ? c_vals[count] : count + 1), r_vals[count],
+							      errmin, errmax,
+							      GOG_ERROR_BAR_DIRECTION_RADIAL);
+					 }
+				}
+		if (GOG_IS_POLAR_SERIES (series)) {
+			GogPolarSeries *polar_series = GOG_POLAR_SERIES (series);
+			for (count = 0; count < series->base.num_elements; count++)
+				if (gog_error_bar_is_visible (polar_series->a_errors)) {
+					GogErrorBar const *bar = polar_series->a_errors;
+					if (gog_error_bar_get_bounds (bar, count, &errmin, &errmax)) {
+						gog_error_bar_render (bar, view->renderer, 
+								      chart_map,
+								      c_vals[count], r_vals[count],
+								      errmin, errmax,
+								      GOG_ERROR_BAR_DIRECTION_ANGULAR);
+					 }
+				}
+		}
+
 		if (is_polar)
 			gog_renderer_pop_clip (view->renderer);
 
@@ -910,6 +980,11 @@ radial_drop_lines_pre_remove (GogObject *parent, GogObject *child)
 
 static GogStyledObjectClass *series_parent_klass;
 
+enum {
+	RT_SERIES_PROP_0,
+	RT_SERIES_PROP_RERRORS,
+};
+
 static void
 gog_rt_series_update (GogObject *obj)
 {
@@ -966,6 +1041,81 @@ gog_rt_series_init_style (GogStyledObject *gso, GOStyle *style)
 }
 
 static void
+gog_rt_series_set_property (GObject *obj, guint param_id,
+			    GValue const *value, GParamSpec *pspec)
+{
+	GogRTSeries *series=  GOG_RT_SERIES (obj);
+	GogErrorBar* bar;
+
+	switch (param_id) {
+	case RT_SERIES_PROP_RERRORS :
+		bar = g_value_get_object (value);
+		if (series->r_errors == bar)
+			return;
+		if (bar) {
+			bar = gog_error_bar_dup (bar);
+			bar->series = GOG_SERIES (series);
+			bar->dim_i = 1;
+			bar->error_i = series->base.plot->desc.series.num_dim - 2;
+		}
+		if (!series->base.needs_recalc) {
+			series->base.needs_recalc = TRUE;
+			gog_object_emit_changed (GOG_OBJECT (series), FALSE);
+		}
+		if (series->r_errors != NULL)
+			g_object_unref (series->r_errors);
+		series->r_errors = bar;
+		break;
+	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+		 break;
+	}
+}
+
+static void
+gog_rt_series_get_property (GObject *obj, guint param_id,
+			  GValue *value, GParamSpec *pspec)
+{
+	GogRTSeries *series=  GOG_RT_SERIES (obj);
+
+	switch (param_id) {
+	case RT_SERIES_PROP_RERRORS :
+		g_value_set_object (value, series->r_errors);
+		break;
+		break;
+	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+		 break;
+	}
+}
+
+static void
+gog_rt_series_finalize (GObject *obj)
+{
+	GogRTSeries *series = GOG_RT_SERIES (obj);
+
+	if (series->r_errors != NULL) {
+		g_object_unref (series->r_errors); 
+		series->r_errors = NULL;
+	}
+
+	G_OBJECT_CLASS (series_parent_klass)->finalize (obj);
+}
+
+#ifdef GOFFICE_WITH_GTK
+static void
+gog_rt_series_populate_editor (GogObject *obj,
+			       GOEditor *editor,
+			       GogDataAllocator *dalloc,
+			       GOCmdContext *cc)
+{
+	GtkWidget *w;
+	(GOG_OBJECT_CLASS(series_parent_klass)->populate_editor) (obj, editor, dalloc, cc);
+
+	w = gog_error_bar_prefs (GOG_SERIES (obj), "r-errors", GOG_ERROR_BAR_DIRECTION_RADIAL, dalloc, cc);
+	go_editor_add_page (editor, w, _("Radial error bars"));
+}
+#endif
+
+static void
 gog_rt_series_class_init (GogStyledObjectClass *gso_klass)
 {
 	static GogObjectRole const roles[] = {
@@ -979,12 +1129,25 @@ gog_rt_series_class_init (GogStyledObjectClass *gso_klass)
 			NULL }
 	};
 
+	GObjectClass *gobject_klass = G_OBJECT_CLASS (gso_klass);
 	GogObjectClass *obj_klass = GOG_OBJECT_CLASS (gso_klass);
 	GogSeriesClass *series_klass = GOG_SERIES_CLASS (gso_klass);
 
 	series_parent_klass = 	g_type_class_peek_parent (gso_klass);
 	gso_klass->init_style =	gog_rt_series_init_style;
+	gobject_klass->finalize		= gog_rt_series_finalize;
+	gobject_klass->set_property = gog_rt_series_set_property;
+	gobject_klass->get_property = gog_rt_series_get_property;
 	obj_klass->update = gog_rt_series_update;
+#ifdef GOFFICE_WITH_GTK
+	obj_klass->populate_editor = gog_rt_series_populate_editor;
+#endif
+	g_object_class_install_property (gobject_klass, RT_SERIES_PROP_RERRORS,
+		g_param_spec_object ("r-errors", 
+			_("Radial error bars"),
+			_("GogErrorBar *"),
+			GOG_TYPE_ERROR_BAR, 
+			GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
 
 	series_klass->has_interpolation = 	TRUE;
 
@@ -997,6 +1160,89 @@ GSF_DYNAMIC_CLASS (GogRTSeries, gog_rt_series,
 
 /*****************************************************************************/
 
+static GObjectClass *polar_series_parent_klass;
+
+enum {
+	POLAR_SERIES_PROP_0,
+	POLAR_SERIES_PROP_AERRORS,
+};
+
+/*****************************************************************************/
+
+static void
+gog_polar_series_set_property (GObject *obj, guint param_id,
+			    GValue const *value, GParamSpec *pspec)
+{
+	GogPolarSeries *series=  GOG_POLAR_SERIES (obj);
+	GogErrorBar* bar;
+
+	switch (param_id) {
+	case POLAR_SERIES_PROP_AERRORS :
+		bar = g_value_get_object (value);
+		if (series->a_errors == bar)
+			return;
+		if (bar) {
+			bar = gog_error_bar_dup (bar);
+			bar->series = GOG_SERIES (series);
+			bar->dim_i = 0;
+			bar->error_i = series->base.base.plot->desc.series.num_dim - 4;
+		}
+		if (!series->base.base.needs_recalc) {
+			series->base.base.needs_recalc = TRUE;
+			gog_object_emit_changed (GOG_OBJECT (series), FALSE);
+		}
+		if (series->a_errors != NULL)
+			g_object_unref (series->a_errors);
+		series->a_errors = bar;
+		break;
+	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+		 break;
+	}
+}
+
+static void
+gog_polar_series_get_property (GObject *obj, guint param_id,
+			  GValue *value, GParamSpec *pspec)
+{
+	GogPolarSeries *series=  GOG_POLAR_SERIES (obj);
+
+	switch (param_id) {
+	case POLAR_SERIES_PROP_AERRORS :
+		g_value_set_object (value, series->a_errors);
+		break;
+	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+		 break;
+	}
+}
+
+#ifdef GOFFICE_WITH_GTK
+static void
+gog_polar_series_populate_editor (GogObject *obj,
+			       GOEditor *editor,
+			       GogDataAllocator *dalloc,
+			       GOCmdContext *cc)
+{
+	GtkWidget *w;
+	(GOG_OBJECT_CLASS(polar_series_parent_klass)->populate_editor) (obj, editor, dalloc, cc);
+
+	w = gog_error_bar_prefs (GOG_SERIES (obj), "a-errors", GOG_ERROR_BAR_DIRECTION_ANGULAR, dalloc, cc);
+	go_editor_add_page (editor, w, _("Angular error bars"));
+}
+#endif
+
+static void
+gog_polar_series_finalize (GObject *obj)
+{
+	GogPolarSeries *series = GOG_POLAR_SERIES (obj);
+
+	if (series->a_errors != NULL) {
+		g_object_unref (series->a_errors); 
+		series->a_errors = NULL;
+	}
+
+	G_OBJECT_CLASS (polar_series_parent_klass)->finalize (obj);
+}
+
 static void
 gog_polar_series_class_init (GogObjectClass *gog_klass)
 {
@@ -1009,10 +1255,24 @@ gog_polar_series_class_init (GogObjectClass *gog_klass)
 		GOG_SERIES_FILL_TYPE_INVALID
 	};
 
+	GObjectClass *gobject_klass = G_OBJECT_CLASS (gog_klass);
 	GogSeriesClass *series_klass = GOG_SERIES_CLASS (gog_klass);
 
+	polar_series_parent_klass = 	g_type_class_peek_parent (gog_klass);
 	series_klass->has_fill_type =		TRUE;
 	series_klass->valid_fill_type_list = 	valid_fill_type_list;
+	gobject_klass->finalize		= gog_polar_series_finalize;
+	gobject_klass->set_property = gog_polar_series_set_property;
+	gobject_klass->get_property = gog_polar_series_get_property;
+#ifdef GOFFICE_WITH_GTK
+	gog_klass->populate_editor = gog_polar_series_populate_editor;
+#endif
+	g_object_class_install_property (gobject_klass, POLAR_SERIES_PROP_AERRORS,
+		g_param_spec_object ("a-errors", 
+			_("Angular error bars"),
+			_("GogErrorBar *"),
+			GOG_TYPE_ERROR_BAR, 
+			GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
 }
 
 GSF_DYNAMIC_CLASS (GogPolarSeries, gog_polar_series,
@@ -1060,7 +1320,7 @@ gog_color_polar_series_class_init (GogObjectClass *gog_klass)
 
 GSF_DYNAMIC_CLASS (GogColorPolarSeries, gog_color_polar_series,
 	gog_color_polar_series_class_init, NULL,
-	GOG_TYPE_RT_SERIES)
+	GOG_TYPE_POLAR_SERIES)
 
 G_MODULE_EXPORT void
 go_plugin_init (GOPlugin *plugin, GOCmdContext *cc)
diff --git a/plugins/plot_xy/gog-xy.c b/plugins/plot_xy/gog-xy.c
index aa2b5c9..66ed780 100644
--- a/plugins/plot_xy/gog-xy.c
+++ b/plugins/plot_xy/gog-xy.c
@@ -1192,9 +1192,10 @@ gog_xy_view_render (GogView *view, GogViewAllocation const *bbox)
 					GogErrorBar const *bar = series->x_errors;
 				 if (gog_error_bar_get_bounds (bar, i - 1, &xerrmin, &xerrmax)) {
 					 gog_error_bar_render (bar, view->renderer,
-								   x_map, y_map,
+								   chart_map,
 								   x, y,
-								   xerrmin, xerrmax, TRUE);
+								   xerrmin, xerrmax,
+								   GOG_ERROR_BAR_DIRECTION_HORIZONTAL);
 				 }
 			}
 
@@ -1202,8 +1203,9 @@ gog_xy_view_render (GogView *view, GogViewAllocation const *bbox)
 				GogErrorBar const *bar = series->y_errors;
 				 if (gog_error_bar_get_bounds (bar, i - 1, &yerrmin, &yerrmax)) {
 					 gog_error_bar_render (bar, view->renderer,
-								   x_map, y_map, x, y,
-								   yerrmin, yerrmax, FALSE);
+								   chart_map, x, y,
+								   yerrmin, yerrmax,
+								   GOG_ERROR_BAR_DIRECTION_VERTICAL);
 				 }
 			}
 



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