1 /*
2  * gog-smoothed-curve.c :
3  *
4  * Copyright (C) 2006 Jean Brefort (jean.brefort@normalesup.org)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) version 3.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
19  * USA
20  */
21 
22 #include <goffice/goffice-config.h>
23 #include <goffice/goffice.h>
24 
25 #include <gsf/gsf-impl-utils.h>
26 #include <glib/gi18n-lib.h>
27 
28 static GType gog_smoothed_curve_view_get_type (void);
29 
30 static GObjectClass *smoothed_curve_parent_klass;
31 
32 /**
33  * GogSmoothedCurveClass:
34  * @base: base class.
35  * @max_dim: number of #GOData parameters.
36  *
37  * Base class for smoothed curves.
38  **/
39 #ifdef GOFFICE_WITH_GTK
40 static void
gog_smoothed_curve_populate_editor(GogObject * gobj,GOEditor * editor,GogDataAllocator * dalloc,GOCmdContext * cc)41 gog_smoothed_curve_populate_editor (GogObject	*gobj,
42 			       GOEditor	*editor,
43 			       GogDataAllocator	*dalloc,
44 			       GOCmdContext	*cc)
45 {
46 	GtkWidget *w, *child;
47 	GtkGrid *grid;
48 	GogDataset *set = GOG_DATASET (gobj);
49 
50 	w = gtk_grid_new ();
51 	grid = GTK_GRID (w);
52 	g_object_set (G_OBJECT (grid), "margin", 12, "column-spacing", 12,
53 	              "orientation", GTK_ORIENTATION_VERTICAL, NULL);
54 	child = gtk_label_new (_("(Name):"));
55 	gtk_grid_attach (grid, child, 0, 0, 1, 1);
56 	child = GTK_WIDGET (gog_data_allocator_editor (dalloc, set, -1, GOG_DATA_SCALAR));
57 	g_object_set (G_OBJECT (child), "hexpand", TRUE, NULL);
58 	gtk_grid_attach (grid, child, 1, 0, 1, 1);
59 	gtk_widget_show_all (w);
60 	go_editor_add_page (editor, w, _("Details"));
61 
62 	(GOG_OBJECT_CLASS (smoothed_curve_parent_klass)->populate_editor) (gobj, editor, dalloc, cc);
63 }
64 #endif
65 
66 static void
gog_smoothed_curve_init_style(GogStyledObject * gso,GOStyle * style)67 gog_smoothed_curve_init_style (GogStyledObject *gso, GOStyle *style)
68 {
69 	style->interesting_fields = GO_STYLE_LINE;
70 	gog_theme_fillin_style (gog_object_get_theme (GOG_OBJECT (gso)),
71 		style, GOG_OBJECT (gso), 0, GO_STYLE_LINE);
72 }
73 
74 static void
gog_smoothed_curve_finalize(GObject * obj)75 gog_smoothed_curve_finalize (GObject *obj)
76 {
77 	GogSmoothedCurve *curve = GOG_SMOOTHED_CURVE (obj);
78 	g_free (curve->x);
79 	g_free (curve->y);
80 	if (curve->name != NULL) {
81 		gog_dataset_finalize (GOG_DATASET (obj));
82 		g_free (curve->name); /* aliased pointer */
83 		curve->name = NULL;
84 	}
85 	(*smoothed_curve_parent_klass->finalize) (obj);
86 }
87 
88 static char const *
gog_smoothed_curve_type_name(GogObject const * gobj)89 gog_smoothed_curve_type_name (GogObject const *gobj)
90 {
91 	return N_("Smoothed Curve");
92 }
93 
94 static void
gog_smoothed_curve_parent_changed(GogObject * obj,G_GNUC_UNUSED gboolean was_set)95 gog_smoothed_curve_parent_changed (GogObject *obj, G_GNUC_UNUSED gboolean was_set)
96 {
97 	GogSmoothedCurve *sc = GOG_SMOOTHED_CURVE (obj);
98 	if (sc->name == NULL) {
99 		GogSmoothedCurveClass *klass = (GogSmoothedCurveClass *) G_OBJECT_GET_CLASS (obj);
100 		sc->name = g_new0 (GogDatasetElement, klass->max_dim + 2);
101 	}
102 	GOG_OBJECT_CLASS (smoothed_curve_parent_klass)->parent_changed (obj, was_set);
103 }
104 
105 static void
gog_smoothed_curve_class_init(GogObjectClass * gog_klass)106 gog_smoothed_curve_class_init (GogObjectClass *gog_klass)
107 {
108 	GObjectClass *gobject_klass = (GObjectClass *) gog_klass;
109 	GogStyledObjectClass *style_klass = (GogStyledObjectClass *) gog_klass;
110 	GogSmoothedCurveClass *curve_klass = (GogSmoothedCurveClass *) gog_klass;
111 	smoothed_curve_parent_klass = g_type_class_peek_parent (gog_klass);
112 
113 	gobject_klass->finalize = gog_smoothed_curve_finalize;
114 
115 	curve_klass->max_dim = -1;
116 	style_klass->init_style = gog_smoothed_curve_init_style;
117 	gog_klass->type_name	= gog_smoothed_curve_type_name;
118 	gog_klass->parent_changed = gog_smoothed_curve_parent_changed;
119 	gog_klass->view_type	= gog_smoothed_curve_view_get_type ();
120 
121 #ifdef GOFFICE_WITH_GTK
122 	gog_klass->populate_editor  = gog_smoothed_curve_populate_editor;
123 #endif
124 }
125 
126 static void
gog_smoothed_curve_init(GogSmoothedCurve * curve)127 gog_smoothed_curve_init (GogSmoothedCurve *curve)
128 {
129 	curve->nb = 0;
130 	curve->x = curve->y = NULL;
131 }
132 
133 static void
gog_smoothed_curve_dataset_dims(GogDataset const * set,int * first,int * last)134 gog_smoothed_curve_dataset_dims (GogDataset const *set, int *first, int *last)
135 {
136 	GogSmoothedCurveClass *klass = (GogSmoothedCurveClass *) G_OBJECT_GET_CLASS (set);
137 
138 	*first = -1;
139 	*last = klass->max_dim;
140 }
141 
142 static GogDatasetElement *
gog_smoothed_curve_dataset_get_elem(GogDataset const * set,int dim_i)143 gog_smoothed_curve_dataset_get_elem (GogDataset const *set, int dim_i)
144 {
145 	GogSmoothedCurve const *sc = GOG_SMOOTHED_CURVE (set);
146 	GogSmoothedCurveClass *klass = (GogSmoothedCurveClass *) G_OBJECT_GET_CLASS (set);
147 	g_return_val_if_fail (dim_i >= -1 && dim_i <= klass->max_dim, NULL);
148 	dim_i++;
149 	return sc->name + dim_i;
150 }
151 
152 static void
gog_smoothed_curve_dataset_dim_changed(GogDataset * set,int dim_i)153 gog_smoothed_curve_dataset_dim_changed (GogDataset *set, int dim_i)
154 {
155 	GogSmoothedCurveClass *klass = (GogSmoothedCurveClass *) G_OBJECT_GET_CLASS (set);
156 	g_return_if_fail (dim_i >= -1 && dim_i <= klass->max_dim);
157 	{
158 		GogSmoothedCurve const *sc = GOG_SMOOTHED_CURVE (set);
159 		if (dim_i == -1) {
160 			GOData *name_src = sc->name->data;
161 			char *name = (name_src != NULL)
162 				? go_data_get_scalar_string (name_src) : NULL;
163 			gog_object_set_name (GOG_OBJECT (set), name, NULL);
164 		} else
165 			gog_object_request_update (GOG_OBJECT (set));
166 	}
167 }
168 
169 static void
gog_smoothed_curve_dataset_init(GogDatasetClass * iface)170 gog_smoothed_curve_dataset_init (GogDatasetClass *iface)
171 {
172 	iface->get_elem	   = gog_smoothed_curve_dataset_get_elem;
173 	iface->dims	   = gog_smoothed_curve_dataset_dims;
174 	iface->dim_changed	   = gog_smoothed_curve_dataset_dim_changed;
175 }
176 
177 GSF_CLASS_FULL (GogSmoothedCurve, gog_smoothed_curve,
178 	   NULL, NULL, gog_smoothed_curve_class_init, NULL,
179            gog_smoothed_curve_init, GOG_TYPE_TREND_LINE, G_TYPE_FLAG_ABSTRACT,
180 	   GSF_INTERFACE (gog_smoothed_curve_dataset_init, GOG_TYPE_DATASET))
181 
182 /****************************************************************************/
183 
184 typedef GogView		GogSmoothedCurveView;
185 typedef GogViewClass	GogSmoothedCurveViewClass;
186 
187 #define GOG_TYPE_SMOOTHED_CURVE_VIEW	(gog_smoothed_curve_view_get_type ())
188 #define GOG_SMOOTHED_CURVE_VIEW(o)	(G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_TYPE_SMOOTHED_CURVE_VIEW, GogSmoothedCurveView))
189 #define GOG_IS_SMOOTHED_CURVE_VIEW(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_TYPE_SMOOTHED_CURVE_VIEW))
190 
191 /*static GogViewClass *smoothed_curve_view_parent_klass; */
192 
193 static void
gog_smoothed_curve_view_render(GogView * view,GogViewAllocation const * bbox)194 gog_smoothed_curve_view_render (GogView *view, GogViewAllocation const *bbox)
195 {
196 	GogSmoothedCurve *curve = GOG_SMOOTHED_CURVE (view->model);
197 	GogSeries *series = GOG_SERIES ((GOG_OBJECT (curve))->parent);
198 	GogPlot *plot = series->plot;
199 	GogChart *chart = GOG_CHART (GOG_OBJECT (plot)->parent);
200 	GogChartMap *chart_map;
201 	GOStyle *style;
202 	GOPath *path;
203 
204 	if (curve->nb == 0 || curve->x == NULL || curve->y == NULL)
205 		return;
206 
207 	chart_map = gog_chart_map_new (chart, &view->residual,
208 				       plot->axis[GOG_AXIS_X],
209 				       plot->axis[GOG_AXIS_Y],
210 				       NULL, FALSE);
211 	if (!gog_chart_map_is_valid (chart_map)) {
212 		gog_chart_map_free (chart_map);
213 		return;
214 	}
215 
216 	gog_renderer_push_clip_rectangle (view->renderer, view->residual.x, view->residual.y,
217 					  view->residual.w, view->residual.h);
218 
219 	path = gog_chart_map_make_path (chart_map, curve->x, curve->y, curve->nb, GO_LINE_INTERPOLATION_LINEAR, FALSE, NULL);
220 	style = GOG_STYLED_OBJECT (curve)->style;
221 	gog_renderer_push_style (view->renderer, style);
222 	gog_renderer_stroke_serie (view->renderer, path);
223 	gog_renderer_pop_style (view->renderer);
224 	go_path_free (path);
225 	gog_renderer_pop_clip (view->renderer);
226 
227 	gog_chart_map_free (chart_map);
228 }
229 
230 static void
gog_smoothed_curve_view_class_init(GogSmoothedCurveViewClass * gview_klass)231 gog_smoothed_curve_view_class_init (GogSmoothedCurveViewClass *gview_klass)
232 {
233 	GogViewClass *view_klass    = (GogViewClass *) gview_klass;
234 
235 	view_klass->render	  = gog_smoothed_curve_view_render;
236 }
237 
238 static GSF_CLASS (GogSmoothedCurveView, gog_smoothed_curve_view,
239 		  gog_smoothed_curve_view_class_init, NULL,
240 		  GOG_TYPE_VIEW)
241