[goffice] introduce two new view methods.



commit 3ee36cce49e11f49a01820c2e1cd65862d4f24eb
Author: Jean Brefort <jean brefort normalesup org>
Date:   Mon Nov 9 17:30:45 2009 +0100

    introduce two new view methods.

 ChangeLog                     |   18 ++++++++
 goffice/canvas/goc-graph.c    |    1 +
 goffice/data/go-data.c        |    8 +++
 goffice/graph/goffice-graph.h |    1 +
 goffice/graph/gog-plot-impl.h |    7 ++-
 goffice/graph/gog-plot.c      |   20 +++++++++
 goffice/graph/gog-plot.h      |    3 +
 goffice/graph/gog-view.c      |   18 ++++++++
 goffice/graph/gog-view.h      |    6 ++-
 plugins/plot_pie/gog-pie.c    |   96 +++++++++++++++++++++++++++++++++++++++++
 10 files changed, 174 insertions(+), 4 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a163400..7737b03 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2009-11-09  Jean Brefort  <jean brefort normalesup org>
+
+	* goffice/canvas/goc-graph.c (goc_graph_do_tooltip): use
+	gog_view_get_tip_at_point when no XY map is available (pies and rings).
+	* goffice/data/go-data.c (go_data_vector_get_str),
+	(go_data_matrix_get_str): load data before returning a string.
+	* goffice/graph/goffice-graph.h: move GogPlotView there.
+	* goffice/graph/gog-plot-impl.h: new gog_plot_view_get_data_at_point.
+	* goffice/graph/gog-plot.c (gog_plot_view_get_data_at_point): new function
+	introduced to fix #580545.
+	* goffice/graph/gog-plot.h: ditto.
+	* goffice/graph/gog-view.c (gog_view_get_tip_at_point): new function.
+	* goffice/graph/gog-view.h: ditto.
+	* plugins/plot_pie/gog-pie.c (gog_pie_view_get_data_at_point),
+	(gog_pie_view_get_tip_at_point), (gog_pie_view_class_init): implement the
+	two new view methods (only partially for now, does not work properly for
+	split rings).
+
 2009-11-08  Jean Brefort  <jean brefort normalesup org>
 
 	* goffice/utils/go-color.c (go_color_from_str): call gdk_parse_color when
diff --git a/goffice/canvas/goc-graph.c b/goffice/canvas/goc-graph.c
index c93e04d..2fccfae 100644
--- a/goffice/canvas/goc-graph.c
+++ b/goffice/canvas/goc-graph.c
@@ -306,6 +306,7 @@ goc_graph_do_tooltip (GocGraph *graph)
 		g_slist_free (l);
 		break;
 	default:
+		buf = gog_view_get_tip_at_point (view, x, y);
 		goto tooltip;
 	}
 	map = gog_chart_map_new (chart, &alloc, x_axis, y_axis, NULL, FALSE);
diff --git a/goffice/data/go-data.c b/goffice/data/go-data.c
index 15f77c5..0d3b2ca 100644
--- a/goffice/data/go-data.c
+++ b/goffice/data/go-data.c
@@ -707,6 +707,10 @@ go_data_vector_get_str (GODataVector *vec, unsigned i)
 	char *res;
 
 	g_return_val_if_fail (klass != NULL, g_strdup (""));
+	if (! (vec->base.flags & GO_DATA_CACHE_IS_VALID)) {
+		(*klass->load_values) (vec);
+		g_return_val_if_fail (vec->base.flags & GO_DATA_CACHE_IS_VALID, g_strdup (""));
+	}
 	g_return_val_if_fail ((int)i < vec->len, g_strdup (""));
 
 	res = (*klass->get_str) (vec, i);
@@ -883,6 +887,10 @@ go_data_matrix_get_str (GODataMatrix *mat, unsigned i, unsigned j)
 	char *res;
 
 	g_return_val_if_fail (klass != NULL, NULL);
+	if (! (mat->base.flags & GO_DATA_CACHE_IS_VALID)) {
+		(*klass->load_values) (mat);
+		g_return_val_if_fail (mat->base.flags & GO_DATA_CACHE_IS_VALID, g_strdup (""));
+	}
 	g_return_val_if_fail (((int)i < mat->size.rows) && ((int)j < mat->size.columns), g_strdup (""));
 
 	res = (*klass->get_str) (mat, i, j);
diff --git a/goffice/graph/goffice-graph.h b/goffice/graph/goffice-graph.h
index 75eb85e..582a988 100644
--- a/goffice/graph/goffice-graph.h
+++ b/goffice/graph/goffice-graph.h
@@ -37,6 +37,7 @@ typedef struct _GogPlot		 GogPlot;	/* abstract base for plots */
 typedef struct _GogPlotType	 GogPlotType;	/* visible characterization */
 typedef struct _GogPlotFamily	 GogPlotFamily; /* a group of plot types */
 typedef struct _GogPlotDesc	 GogPlotDesc;	/* data/axis requirements */
+typedef struct _GogPlotView      GogPlotView;
 typedef struct _GogSeries	 GogSeries;	/* single plotable entity */
 typedef struct _GogSeriesDesc	 GogSeriesDesc; /* data requirements */
 typedef struct _GogSeriesDimDesc GogSeriesDimDesc; /* dimension of a series */
diff --git a/goffice/graph/gog-plot-impl.h b/goffice/graph/gog-plot-impl.h
index 640ba6f..4f17222 100644
--- a/goffice/graph/gog-plot-impl.h
+++ b/goffice/graph/gog-plot-impl.h
@@ -90,12 +90,15 @@ typedef struct {
 #define GOG_TYPE_PLOT_VIEW	(gog_plot_view_get_type ())
 #define GOG_PLOT_VIEW(o)	(G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_TYPE_PLOT_VIEW, GogPlotView))
 #define GOG_IS_PLOT_VIEW(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_TYPE_PLOT_VIEW))
+#define GOG_PLOT_VIEW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOG_TYPE_PLOT_VIEW, GogPlotViewClass))
 
-typedef struct _GogPlotView GogPlotView;
 struct _GogPlotView {
 	GogView base;
 };
-typedef GogViewClass	GogPlotViewClass;
+typedef struct {
+	GogViewClass base;
+	int     (*get_data_at_point)    (GogPlotView *view, double x, double y, GogSeries **series);
+} GogPlotViewClass;
 GType gog_plot_view_get_type (void);
 
 G_END_DECLS
diff --git a/goffice/graph/gog-plot.c b/goffice/graph/gog-plot.c
index 565dd8c..be1a9f0 100644
--- a/goffice/graph/gog-plot.c
+++ b/goffice/graph/gog-plot.c
@@ -1240,3 +1240,23 @@ gog_plot_view_class_init (GogPlotViewClass *pview_klass)
 GSF_CLASS_ABSTRACT (GogPlotView, gog_plot_view,
 		    gog_plot_view_class_init, NULL,
 		    GOG_TYPE_VIEW)
+
+
+/**
+ * gog_plot_view_get_data_at_point:
+ * @view : #GogPlotView
+ * @x : x position
+ * @y : y position
+ * @series: where to store the series
+ *
+ * Search a data represented at (@x,@y) in @view and set @series on success.
+ *
+ * return value: index of the found data in @series or -1.
+ **/
+int
+gog_plot_view_get_data_at_point (GogPlotView *view, double x, double y, GogSeries **series)
+{
+	GogPlotViewClass *klass = GOG_PLOT_VIEW_GET_CLASS (view);
+	g_return_val_if_fail (klass != NULL, -1);
+	return (klass->get_data_at_point)? klass->get_data_at_point (view, x, y, series): -1;
+}
diff --git a/goffice/graph/gog-plot.h b/goffice/graph/gog-plot.h
index 2144e2d..768f95e 100644
--- a/goffice/graph/gog-plot.h
+++ b/goffice/graph/gog-plot.h
@@ -71,6 +71,9 @@ void 	   gog_plot_update_3d 		(GogPlot *plot);
 void	   gog_plot_guru_helper		(GogPlot *plot);
 void	   gog_plot_clear_series	(GogPlot *plot);
 
+int        gog_plot_view_get_data_at_point (GogPlotView *view,
+					    double x, double y, GogSeries **series);
+
 G_END_DECLS
 
 #endif /* GOG_PLOT_H */
diff --git a/goffice/graph/gog-view.c b/goffice/graph/gog-view.c
index cfdc55c..e656114 100644
--- a/goffice/graph/gog-view.c
+++ b/goffice/graph/gog-view.c
@@ -1002,3 +1002,21 @@ gog_view_get_view_at_point (GogView *view, double x, double y, GogObject **obj,
 	*obj = NULL;
 	return NULL;
 }
+
+/**
+ * gog_view_get_tip_at_point:
+ * @view : #GogView
+ * @x : x position
+ * @y : y position
+ *
+ * Gets a tip string related to the position as defined by (@x,@y) in @view.
+ *
+ * return value: the newly allocated tip string if the view class supports
+ * that or NULL.
+ **/
+char*
+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;
+}
diff --git a/goffice/graph/gog-view.h b/goffice/graph/gog-view.h
index 18a1446..ab347cc 100644
--- a/goffice/graph/gog-view.h
+++ b/goffice/graph/gog-view.h
@@ -91,6 +91,7 @@ typedef struct {
 	void	 (*render)        		(GogView *view, GogViewAllocation const *bbox);
 
 	void	 (*build_toolkit)		(GogView *view);
+	char    *(*get_tip_at_point)		(GogView *view, double x, double y);
 } GogViewClass;
 
 #define GOG_TYPE_VIEW		(gog_view_get_type ())
@@ -120,8 +121,9 @@ GogTool		*gog_view_get_tool_at_point 	(GogView *view, double x, double y,
 						 GogObject **gobj);
 GogView 	*gog_view_get_view_at_point	(GogView *view, double x, double y,
 						 GogObject **obj, GogTool **tool);
-
-/* protected */
+char		*gog_view_get_tip_at_point      (GogView *view, double x, double y);
+    
+    /* protected */
 void gog_view_size_child_request (GogView *view,
 				  GogViewRequisition const *available,
 				  GogViewRequisition *req,
diff --git a/plugins/plot_pie/gog-pie.c b/plugins/plot_pie/gog-pie.c
index 677936c..fcfcfe0 100644
--- a/plugins/plot_pie/gog-pie.c
+++ b/plugins/plot_pie/gog-pie.c
@@ -631,6 +631,78 @@ typedef GogPlotViewClass	GogPieViewClass;
 
 static GogViewClass *pie_view_parent_klass;
 
+static int
+gog_pie_view_get_data_at_point (GogPlotView *view, double x, double y, GogSeries **series)
+{
+	GogPiePlot const *model = GOG_PIE_PLOT (view->base.model);
+	double r_max = view->base.allocation.h, cx, cy, r, h, theta, scale, *vals;
+	unsigned int index;
+	double center_size = 0.0;
+	unsigned num_series = 0;
+	double default_sep;
+	int ret = -1;
+	GSList *ptr;
+
+	/* compute number of valid series */
+	for (ptr = model->base.series ; ptr != NULL ; ptr = ptr->next) {
+		*series = ptr->data;
+		if (!gog_series_is_valid (GOG_SERIES (ptr->data)))
+			continue;
+		num_series++;
+	}
+
+	if (num_series <= 0)
+		return -1;
+
+	if (r_max > view->base.allocation.w)
+		r_max = view->base.allocation.w;
+	r_max /= 2.;
+	cx = view->base.allocation.x + view->base.allocation.w/2.;
+	cy = view->base.allocation.y + view->base.allocation.h/2.;
+	r = hypot (x - cx, y - cy);
+
+	if (r > r_max)
+		return -1;
+
+	if (GOG_IS_RING_PLOT (model))
+		center_size = GOG_RING_PLOT(model)->center_size;
+	/* FIXME: this is somewhat approximative, must be enhanced for ring plots with a slice separation */
+	center_size *= r_max;
+	if (r < center_size)
+		return -1;
+
+	default_sep = r_max * model->default_separation;
+	h = (r_max + default_sep - center_size) / num_series;
+	index = floor ((r - center_size) / h);
+	for (ptr = model->base.series ; ptr != NULL ; ptr = ptr->next) {
+		*series = ptr->data;
+		if (!gog_series_is_valid (GOG_SERIES (ptr->data)))
+			continue;
+		if (index-- == 0)
+			break;
+	}
+	theta = (atan2 (y - cy, x - cx)
+		 * 180 / M_PI - model->initial_angle + 90.) / model->span / 3.6;
+	if (theta < 0)
+		theta += 1.;
+
+	vals = go_data_get_values ((*series)->values[1].data);
+	scale = 1 / GOG_PIE_SERIES (*series)->total;
+	for (index = 0 ; index < (*series)->num_elements; index++) {
+		r = vals[index] * scale;
+		if (r < 0.)
+			r = model->show_negatives? -r: 0.;
+		if (go_finite (r) && r > 1e-3) {
+			theta -= r;
+			if (theta < 0)
+				break;
+		}
+	}
+	/* using r to store the value */
+	return (int) index;
+	return ret;
+}
+
 #define MAX_ARC_SEGMENTS 64
 
 static void
@@ -914,13 +986,37 @@ gog_pie_view_build_toolkit (GogView *view)
 #endif
 }
 
+static char*
+gog_pie_view_get_tip_at_point (GogView *view, double x, double y)
+{
+	GogPieSeries *series = NULL;
+	int index = gog_pie_view_get_data_at_point (GOG_PLOT_VIEW (view), x, y, (GogSeries** )&series);
+	char *label, *ret;
+	double *vals, value;
+
+	if (index < 0)
+		return NULL;
+	vals = go_data_get_values (series->base.values[1].data);
+	value = fabs (vals[index]);
+	label = series->base.values[0].data? go_data_get_vector_string (series->base.values[0].data, index): NULL;
+	if (label && *label)
+		ret = g_strdup_printf (_("%s: %g (%.2f%%)"), label, value, value * 100 / series->total);
+	else
+		ret = g_strdup_printf (_("%g (%.2f%%)"), value, value * 100 / series->total);
+	g_free (label);
+	return ret;
+}
+
 static void
 gog_pie_view_class_init (GogViewClass *view_klass)
 {
+	GogPlotViewClass *pv_klass = (GogPlotViewClass *) view_klass;
 	pie_view_parent_klass = g_type_class_peek_parent (view_klass);
 
 	view_klass->render 		= gog_pie_view_render;
 	view_klass->build_toolkit 	= gog_pie_view_build_toolkit;
+	view_klass->get_tip_at_point    = gog_pie_view_get_tip_at_point;
+	pv_klass->get_data_at_point     = gog_pie_view_get_data_at_point;
 }
 
 GSF_DYNAMIC_CLASS (GogPieView, gog_pie_view,



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