1 /* $Id: gtkdatabox_xyc_graph.c 4 2008-06-22 09:19:11Z rbock $ */
2 /* GtkDatabox - An extension to the gtk+ library
3 * Copyright (C) 1998 - 2008 Dr. Roland Bock
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 2.1
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include <gtkdatabox_xyc_graph.h>
21
22 G_DEFINE_TYPE(GtkDataboxXYCGraph, gtk_databox_xyc_graph,
23 GTK_DATABOX_TYPE_GRAPH)
24
25 static gint gtk_databox_xyc_graph_real_calculate_extrema (GtkDataboxGraph *
26 xyc_graph,
27 gfloat * min_x,
28 gfloat * max_x,
29 gfloat * min_y,
30 gfloat * max_y);
31
32 /* IDs of properties */
33 enum
34 {
35 PROP_X = 1,
36 PROP_Y,
37 PROP_LEN,
38 PROP_MAXLEN,
39 PROP_XSTART,
40 PROP_YSTART,
41 PROP_XSTRIDE,
42 PROP_YSTRIDE,
43 PROP_XTYPE,
44 PROP_YTYPE
45 };
46
47 /**
48 * GtkDataboxXYCGraphPrivate
49 *
50 * A private data structure used by the #GtkDataboxXYCGraph. It shields all internal things
51 * from developers who are just using the object.
52 *
53 **/
54 typedef struct _GtkDataboxXYCGraphPrivate GtkDataboxXYCGraphPrivate;
55
56 struct _GtkDataboxXYCGraphPrivate
57 {
58 gfloat *X;
59 gfloat *Y;
60 guint len;
61 guint maxlen;
62 guint xstart;
63 guint ystart;
64 guint xstride;
65 guint ystride;
66 GType xtype;
67 GType ytype;
68 };
69
70 //static gpointer parent_class = NULL;
71
72 void
gtk_databox_xyc_graph_set_X_Y_length(GtkDataboxXYCGraph * xyc_graph,gfloat * X,gfloat * Y,guint len)73 gtk_databox_xyc_graph_set_X_Y_length(GtkDataboxXYCGraph * xyc_graph, gfloat * X, gfloat * Y, guint len)
74 {
75 GtkDataboxXYCGraphPrivate *priv = GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph);
76 priv->Y = Y;
77 priv->X = X;
78 priv->len = len;
79 }
80
81 static void
gtk_databox_xyc_graph_set_X(GtkDataboxXYCGraph * xyc_graph,gfloat * X)82 gtk_databox_xyc_graph_set_X (GtkDataboxXYCGraph * xyc_graph, gfloat * X)
83 {
84 g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
85 g_return_if_fail (X);
86
87 GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->X = X;
88
89 g_object_notify (G_OBJECT (xyc_graph), "X-Values");
90 }
91
92 static void
gtk_databox_xyc_graph_set_Y(GtkDataboxXYCGraph * xyc_graph,gfloat * Y)93 gtk_databox_xyc_graph_set_Y (GtkDataboxXYCGraph * xyc_graph, gfloat * Y)
94 {
95 g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
96 g_return_if_fail (Y);
97
98 GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->Y = Y;
99
100 g_object_notify (G_OBJECT (xyc_graph), "Y-Values");
101 }
102
103 static void
gtk_databox_xyc_graph_set_length(GtkDataboxXYCGraph * xyc_graph,guint len)104 gtk_databox_xyc_graph_set_length (GtkDataboxXYCGraph * xyc_graph, guint len)
105 {
106 g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
107 g_return_if_fail (len > 0);
108
109 GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->len = len;
110
111 g_object_notify (G_OBJECT (xyc_graph), "length");
112 }
113
114 static void
gtk_databox_xyc_graph_set_maxlen(GtkDataboxXYCGraph * xyc_graph,guint maxlen)115 gtk_databox_xyc_graph_set_maxlen (GtkDataboxXYCGraph * xyc_graph, guint maxlen)
116 {
117 g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
118 g_return_if_fail (maxlen > 0);
119
120 GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->maxlen = maxlen;
121
122 g_object_notify (G_OBJECT (xyc_graph), "maxlen");
123 }
124
125 static void
gtk_databox_xyc_graph_set_xstart(GtkDataboxXYCGraph * xyc_graph,guint xstart)126 gtk_databox_xyc_graph_set_xstart (GtkDataboxXYCGraph * xyc_graph, guint xstart)
127 {
128 g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
129
130 GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->xstart = xstart;
131
132 g_object_notify (G_OBJECT (xyc_graph), "X-Values");
133 }
134
135 static void
gtk_databox_xyc_graph_set_ystart(GtkDataboxXYCGraph * xyc_graph,guint ystart)136 gtk_databox_xyc_graph_set_ystart (GtkDataboxXYCGraph * xyc_graph, guint ystart)
137 {
138 g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
139
140 GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->ystart = ystart;
141
142 g_object_notify (G_OBJECT (xyc_graph), "Y-Values");
143 }
144
145 static void
gtk_databox_xyc_graph_set_xstride(GtkDataboxXYCGraph * xyc_graph,guint xstride)146 gtk_databox_xyc_graph_set_xstride (GtkDataboxXYCGraph * xyc_graph, guint xstride)
147 {
148 g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
149
150 GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->xstride = xstride;
151
152 g_object_notify (G_OBJECT (xyc_graph), "X-Values");
153 }
154
155 static void
gtk_databox_xyc_graph_set_ystride(GtkDataboxXYCGraph * xyc_graph,guint ystride)156 gtk_databox_xyc_graph_set_ystride (GtkDataboxXYCGraph * xyc_graph, guint ystride)
157 {
158 g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
159
160 GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->ystride = ystride;
161
162 g_object_notify (G_OBJECT (xyc_graph), "Y-Values");
163 }
164
165 static void
gtk_databox_xyc_graph_set_xtype(GtkDataboxXYCGraph * xyc_graph,GType xtype)166 gtk_databox_xyc_graph_set_xtype (GtkDataboxXYCGraph * xyc_graph, GType xtype)
167 {
168 g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
169
170 GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->xtype = xtype;
171
172 g_object_notify (G_OBJECT (xyc_graph), "X-Values");
173 }
174
175 static void
gtk_databox_xyc_graph_set_ytype(GtkDataboxXYCGraph * xyc_graph,GType ytype)176 gtk_databox_xyc_graph_set_ytype (GtkDataboxXYCGraph * xyc_graph, GType ytype)
177 {
178 g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
179
180 GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->ytype = ytype;
181
182 g_object_notify (G_OBJECT (xyc_graph), "Y-Values");
183 }
184
185 static void
gtk_databox_xyc_graph_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)186 gtk_databox_xyc_graph_set_property (GObject * object,
187 guint property_id,
188 const GValue * value, GParamSpec * pspec)
189 {
190 GtkDataboxXYCGraph *xyc_graph = GTK_DATABOX_XYC_GRAPH (object);
191
192 switch (property_id)
193 {
194 case PROP_X:
195 gtk_databox_xyc_graph_set_X (xyc_graph, (gfloat *) g_value_get_pointer (value));
196 break;
197 case PROP_Y:
198 gtk_databox_xyc_graph_set_Y (xyc_graph, (gfloat *) g_value_get_pointer (value));
199 break;
200 case PROP_LEN:
201 gtk_databox_xyc_graph_set_length (xyc_graph, g_value_get_int (value));
202 break;
203 case PROP_MAXLEN:
204 gtk_databox_xyc_graph_set_maxlen (xyc_graph, g_value_get_int (value));
205 break;
206 case PROP_XSTART:
207 gtk_databox_xyc_graph_set_xstart (xyc_graph, g_value_get_int (value));
208 break;
209 case PROP_YSTART:
210 gtk_databox_xyc_graph_set_ystart (xyc_graph, g_value_get_int (value));
211 break;
212 case PROP_XSTRIDE:
213 gtk_databox_xyc_graph_set_xstride (xyc_graph, g_value_get_int (value));
214 break;
215 case PROP_YSTRIDE:
216 gtk_databox_xyc_graph_set_ystride (xyc_graph, g_value_get_int (value));
217 break;
218 case PROP_XTYPE:
219 gtk_databox_xyc_graph_set_xtype (xyc_graph, g_value_get_gtype (value));
220 break;
221 case PROP_YTYPE:
222 gtk_databox_xyc_graph_set_ytype (xyc_graph, g_value_get_gtype (value));
223 break;
224 default:
225 /* We don't have any other property... */
226 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
227 break;
228 }
229 }
230
231 /**
232 * gtk_databox_xyc_graph_get_X:
233 * @xyc_graph: A #GtkDataboxXYCGraph object
234 *
235 * Gets the X values of the @xzc_graph.
236 *
237 * Return value: Pointer to X values
238 */
239 gfloat *
gtk_databox_xyc_graph_get_X(GtkDataboxXYCGraph * xyc_graph)240 gtk_databox_xyc_graph_get_X (GtkDataboxXYCGraph * xyc_graph)
241 {
242 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), NULL);
243
244 return GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->X;
245 }
246
247 /**
248 * gtk_databox_xyc_graph_get_Y:
249 * @xyc_graph: A #GtkDataboxXYCGraph object
250 *
251 * Gets the Y values of the @xzc_graph.
252 *
253 * Return value: Pointer to Y values
254 */
255 gfloat *
gtk_databox_xyc_graph_get_Y(GtkDataboxXYCGraph * xyc_graph)256 gtk_databox_xyc_graph_get_Y (GtkDataboxXYCGraph * xyc_graph)
257 {
258 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), NULL);
259
260 return GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->Y;
261 }
262
263 /**
264 * gtk_databox_xyc_graph_get_length:
265 * @xyc_graph: A #GtkDataboxXYCGraph object
266 *
267 * Gets the the length of the X and Y values arrays.
268 *
269 * Return value: Length of X/Y arrays.
270 */
271 guint
gtk_databox_xyc_graph_get_length(GtkDataboxXYCGraph * xyc_graph)272 gtk_databox_xyc_graph_get_length (GtkDataboxXYCGraph * xyc_graph)
273 {
274 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
275 return GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->len;
276 }
277
278 /**
279 * gtk_databox_xyc_graph_get_maxlen:
280 * @xyc_graph: A #GtkDataboxXYCGraph object
281 *
282 * Gets the the maxlen of the X and Y values arrays.
283 *
284 * Return value: Size of X/Y arrays.
285 */
286 guint
gtk_databox_xyc_graph_get_maxlen(GtkDataboxXYCGraph * xyc_graph)287 gtk_databox_xyc_graph_get_maxlen (GtkDataboxXYCGraph * xyc_graph)
288 {
289 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
290 return GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->maxlen;
291 }
292
293 /**
294 * gtk_databox_xyc_graph_get_xstart:
295 * @xyc_graph: A #GtkDataboxXYCGraph object
296 *
297 * Gets the the start offset of the X values array. This is the element in the array pointed to by X that will be the first element plotted.
298 * If X is a pointer to a gfloat array, and xstart is 5, then x[5] will be the first data element. If Xstride is 1, then x[6] will be the
299 * second element. x[5 + len - 1] will be last element.
300 * Usually, xstart will be 0. It can be nonzero to allow for interleaved X/Y samples, or if the data is stored as a matrix, then X can point
301 * to the start of the matrix, xstart can be the column number, and xstride the number of columns.
302 *
303 * Return value: The xstart value.
304 */
305 guint
gtk_databox_xyc_graph_get_xstart(GtkDataboxXYCGraph * xyc_graph)306 gtk_databox_xyc_graph_get_xstart (GtkDataboxXYCGraph * xyc_graph)
307 {
308 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
309 return GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->xstart;
310 }
311
312 /**
313 * gtk_databox_xyc_graph_get_ystart:
314 * @xyc_graph: A #GtkDataboxXYCGraph object
315 *
316 * Gets the the start offset of the Y values array. This is the element in the array pointed to by Y that will be the first element plotted.
317 * If Y is a pointer to a gfloat array, and ystart is 5, then y[5] will be the first data element. If Ystride is 1, then y[6] will be the
318 * second element. y[5 + len - 1] will be last element.
319 * Usually, ystart will be 0. It can be nonzero to allow for interleaved X/Y samples, or if the data is stored as a matrix, then Y can point
320 * to the start of the matrix, ystart can be the column number, and ystride the number of columns.
321 *
322 * Return value: The ystart value.
323 */
324 guint
gtk_databox_xyc_graph_get_ystart(GtkDataboxXYCGraph * xyc_graph)325 gtk_databox_xyc_graph_get_ystart (GtkDataboxXYCGraph * xyc_graph)
326 {
327 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
328 return GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->ystart;
329 }
330
331 /**
332 * gtk_databox_xyc_graph_get_xstride:
333 * @xyc_graph: A #GtkDataboxXYCGraph object
334 *
335 * Gets the the stride offset of the X values array. This is the element in the array pointed to by X that will be the first element plotted.
336 * If X is a pointer to a gfloat array, and xstart is 5, then x[5] will be the first data element. If Xstride is 1, then x[6] will be the
337 * second element. x[5 + len - 1] will be last element.
338 * Usually, xstride will be 1. It can be nonzero to allow for interleaved X/Y samples, or if the data is stored as a matrix, then X can point
339 * to the start of the matrix, xstart can be the column number, and xstride the number of columns.
340 *
341 * Return value: The xstride value.
342 */
343 guint
gtk_databox_xyc_graph_get_xstride(GtkDataboxXYCGraph * xyc_graph)344 gtk_databox_xyc_graph_get_xstride (GtkDataboxXYCGraph * xyc_graph)
345 {
346 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
347 return GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->xstride;
348 }
349
350 /**
351 * gtk_databox_xyc_graph_get_ystride:
352 * @xyc_graph: A #GtkDataboxXYCGraph object
353 *
354 * Gets the the stride offset of the Y values array. This is the element in the array pointed to by Y that will be the first element plotted.
355 * If Y is a pointer to a gfloat array, and ystart is 5, then y[5] will be the first data element. If Ystride is 1, then y[6] will be the
356 * second element. y[5 + len - 1] will be last element.
357 * Usually, ystride will be 1. It can be nonzero to allow for interleaved X/Y samples, or if the data is stored as a matrix, then Y can point
358 * to the start of the matrix, ystart can be the column number, and ystride the number of columns.
359 *
360 * Return value: The ystride value.
361 */
362 guint
gtk_databox_xyc_graph_get_ystride(GtkDataboxXYCGraph * xyc_graph)363 gtk_databox_xyc_graph_get_ystride (GtkDataboxXYCGraph * xyc_graph)
364 {
365 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
366 return GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->ystride;
367 }
368
369 /**
370 * gtk_databox_xyc_graph_get_xtype:
371 * @xyc_graph: A #GtkDataboxXYCGraph object
372 *
373 * Gets the the GType of the X array elements. This may be G_TYPE_FLOAT, G_TYPE_DOUBLE, or similar.
374 *
375 * Return value: A GType, usually this is G_TYPE_FLOAT.
376 */
377 GType
gtk_databox_xyc_graph_get_xtype(GtkDataboxXYCGraph * xyc_graph)378 gtk_databox_xyc_graph_get_xtype (GtkDataboxXYCGraph * xyc_graph)
379 {
380 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
381 return GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->xtype;
382 }
383
384 /**
385 * gtk_databox_xyc_graph_get_ytype:
386 * @xyc_graph: A #GtkDataboxXYCGraph object
387 *
388 * Gets the the GType of the Y array elements. This may be G_TYPE_FLOAT, G_TYPE_DOUBLE, or similar.
389 *
390 * Return value: A GType, usually this is G_TYPE_FLOAT.
391 */
392 GType
gtk_databox_xyc_graph_get_ytype(GtkDataboxXYCGraph * xyc_graph)393 gtk_databox_xyc_graph_get_ytype (GtkDataboxXYCGraph * xyc_graph)
394 {
395 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
396 return GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph)->ytype;
397 }
398
399 static void
gtk_databox_xyc_graph_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)400 gtk_databox_xyc_graph_get_property (GObject * object,
401 guint property_id,
402 GValue * value, GParamSpec * pspec)
403 {
404 GtkDataboxXYCGraph *xyc_graph = GTK_DATABOX_XYC_GRAPH (object);
405
406 switch (property_id)
407 {
408 case PROP_X:
409 g_value_set_pointer (value, gtk_databox_xyc_graph_get_X (xyc_graph));
410 break;
411 case PROP_Y:
412 g_value_set_pointer (value, gtk_databox_xyc_graph_get_Y (xyc_graph));
413 break;
414 case PROP_LEN:
415 g_value_set_int (value, gtk_databox_xyc_graph_get_length (xyc_graph));
416 break;
417 case PROP_MAXLEN:
418 g_value_set_int (value, gtk_databox_xyc_graph_get_maxlen (xyc_graph));
419 break;
420 case PROP_XSTART:
421 g_value_set_int (value, gtk_databox_xyc_graph_get_xstart (xyc_graph));
422 break;
423 case PROP_YSTART:
424 g_value_set_int (value, gtk_databox_xyc_graph_get_ystart (xyc_graph));
425 break;
426 case PROP_XSTRIDE:
427 g_value_set_int (value, gtk_databox_xyc_graph_get_xstride (xyc_graph));
428 break;
429 case PROP_YSTRIDE:
430 g_value_set_int (value, gtk_databox_xyc_graph_get_ystride (xyc_graph));
431 break;
432 case PROP_XTYPE:
433 g_value_set_gtype (value, gtk_databox_xyc_graph_get_xtype (xyc_graph));
434 break;
435 case PROP_YTYPE:
436 g_value_set_gtype (value, gtk_databox_xyc_graph_get_ytype (xyc_graph));
437 break;
438 default:
439 /* We don't have any other property... */
440 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
441 break;
442 }
443 }
444
445 static void
gtk_databox_xyc_graph_class_init(GtkDataboxXYCGraphClass * klass)446 gtk_databox_xyc_graph_class_init (GtkDataboxXYCGraphClass *klass)
447 {
448 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
449 GtkDataboxGraphClass *graph_class = GTK_DATABOX_GRAPH_CLASS (klass);
450 GParamSpec *xyc_graph_param_spec;
451
452 gobject_class->set_property = gtk_databox_xyc_graph_set_property;
453 gobject_class->get_property = gtk_databox_xyc_graph_get_property;
454
455 xyc_graph_param_spec = g_param_spec_pointer ("X-Values",
456 "X coordinates",
457 "X values of data",
458 G_PARAM_CONSTRUCT_ONLY |
459 G_PARAM_READWRITE);
460
461 g_object_class_install_property (gobject_class,
462 PROP_X, xyc_graph_param_spec);
463
464 xyc_graph_param_spec = g_param_spec_pointer ("Y-Values",
465 "Y coordinates",
466 "Y values of data",
467 G_PARAM_CONSTRUCT_ONLY |
468 G_PARAM_READWRITE);
469
470 g_object_class_install_property (gobject_class,
471 PROP_Y, xyc_graph_param_spec);
472
473 xyc_graph_param_spec = g_param_spec_int ("length", "length of X and Y", "number of data points", G_MININT, G_MAXINT, 0, /* default value */
474 G_PARAM_CONSTRUCT_ONLY |
475 G_PARAM_READWRITE);
476
477 g_object_class_install_property (gobject_class,
478 PROP_LEN, xyc_graph_param_spec);
479
480 xyc_graph_param_spec = g_param_spec_int ("maxlen", "maxlen of X and Y", "maximal number of data points", G_MININT, G_MAXINT, 0, /* default value */
481 G_PARAM_CONSTRUCT_ONLY |
482 G_PARAM_READWRITE);
483 g_object_class_install_property (gobject_class,
484 PROP_MAXLEN, xyc_graph_param_spec);
485
486 xyc_graph_param_spec = g_param_spec_int ("xstart", "array index of first X", "array index of first X", G_MININT, G_MAXINT, 0, /* default value */
487 G_PARAM_CONSTRUCT_ONLY |
488 G_PARAM_READWRITE);
489 g_object_class_install_property (gobject_class,
490 PROP_XSTART, xyc_graph_param_spec);
491
492 xyc_graph_param_spec = g_param_spec_int ("ystart", "array index of first Y", "array index of first Y", G_MININT, G_MAXINT, 0, /* default value */
493 G_PARAM_CONSTRUCT_ONLY |
494 G_PARAM_READWRITE);
495 g_object_class_install_property (gobject_class,
496 PROP_YSTART, xyc_graph_param_spec);
497
498 xyc_graph_param_spec = g_param_spec_int ("xstride", "stride of X values", "stride of X values", G_MININT, G_MAXINT, 1, /* default value */
499 G_PARAM_CONSTRUCT_ONLY |
500 G_PARAM_READWRITE);
501 g_object_class_install_property (gobject_class,
502 PROP_XSTRIDE, xyc_graph_param_spec);
503
504 xyc_graph_param_spec = g_param_spec_int ("ystride", "stride of Y values", "stride of Y values", G_MININT, G_MAXINT, 1, /* default value */
505 G_PARAM_CONSTRUCT_ONLY |
506 G_PARAM_READWRITE);
507 g_object_class_install_property (gobject_class,
508 PROP_YSTRIDE, xyc_graph_param_spec);
509
510 xyc_graph_param_spec = g_param_spec_gtype ("xtype", "GType of X elements", "GType of X elements", G_TYPE_NONE,
511 G_PARAM_CONSTRUCT_ONLY |
512 G_PARAM_READWRITE);
513 g_object_class_install_property (gobject_class,
514 PROP_XTYPE, xyc_graph_param_spec);
515
516 xyc_graph_param_spec = g_param_spec_gtype ("ytype", "GType of Y elements", "GType of Y elements", G_TYPE_NONE,
517 G_PARAM_CONSTRUCT_ONLY |
518 G_PARAM_READWRITE);
519 g_object_class_install_property (gobject_class,
520 PROP_YTYPE, xyc_graph_param_spec);
521
522 graph_class->calculate_extrema =
523 gtk_databox_xyc_graph_real_calculate_extrema;
524
525 g_type_class_add_private (klass, sizeof (GtkDataboxXYCGraphPrivate));
526 }
527
gtk_databox_xyc_graph_init(GtkDataboxXYCGraph * xyc_graph)528 static void gtk_databox_xyc_graph_init (GtkDataboxXYCGraph *xyc_graph) {xyc_graph = xyc_graph;}
529
530 static gint
gtk_databox_xyc_graph_real_calculate_extrema(GtkDataboxGraph * graph,gfloat * min_x,gfloat * max_x,gfloat * min_y,gfloat * max_y)531 gtk_databox_xyc_graph_real_calculate_extrema (GtkDataboxGraph * graph,
532 gfloat * min_x, gfloat * max_x,
533 gfloat * min_y, gfloat * max_y)
534 {
535 GtkDataboxXYCGraph *xyc_graph = GTK_DATABOX_XYC_GRAPH (graph);
536 GtkDataboxXYCGraphPrivate *priv = GTK_DATABOX_XYC_GRAPH_GET_PRIVATE(xyc_graph);
537 guint i, indx, len, maxlen, start, stride;
538 void *values;
539 GType vtype;
540 gfloat fval = 0.0, minval = 0.0, maxval = 0.0;
541
542 g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (graph), -1);
543 g_return_val_if_fail (min_x, -1);
544 g_return_val_if_fail (max_x, -1);
545 g_return_val_if_fail (min_y, -1);
546 g_return_val_if_fail (max_y, -1);
547 g_return_val_if_fail (priv->len, -1);
548
549 len = priv->len;
550 maxlen = priv->maxlen;
551 values = priv->X;
552 vtype = priv->xtype;
553 start = priv->xstart;
554 stride = priv->xstride;
555
556 indx = start * stride;
557 i = 0;
558 do {
559 if (vtype == G_TYPE_FLOAT)
560 fval = ((gfloat *)values)[indx];
561 else if (vtype == G_TYPE_DOUBLE)
562 fval = ((gdouble *)values)[indx];
563 else if (vtype == G_TYPE_INT)
564 fval = ((gint *)values)[indx];
565 else if (vtype == G_TYPE_UINT)
566 fval = ((guint *)values)[indx];
567 else if (vtype == G_TYPE_LONG)
568 fval = ((glong *)values)[indx];
569 else if (vtype == G_TYPE_ULONG)
570 fval = ((gulong *)values)[indx];
571 else if (vtype == G_TYPE_INT64)
572 fval = ((gint64 *)values)[indx];
573 else if (vtype == G_TYPE_UINT64)
574 fval = ((guint64 *)values)[indx];
575 else if (vtype == G_TYPE_CHAR)
576 fval = ((gchar *)values)[indx];
577 else if (vtype == G_TYPE_UCHAR)
578 fval = ((guchar *)values)[indx];
579
580 if (i==0)
581 {
582 minval = maxval = fval;
583 }
584 else
585 {
586 if (fval < minval) minval = fval;
587 if (fval > maxval) maxval = fval;
588 }
589
590 /* handle the wrap-around (ring buffer) issue using modulus. for efficiency, don't do this for non-wraparound cases. */
591 /* note this allows multiple wrap-arounds. One could hold a single cycle of a sine wave, and plot a continuous wave */
592 /* This can be optimized using pointers later */
593 if (i + start > maxlen)
594 indx = ((i + start) % maxlen) * stride;
595 else
596 indx += stride;
597 } while (++i < len);
598
599 *min_x = minval;
600 *max_x = maxval;
601
602 values = priv->Y;
603 vtype = priv->ytype;
604 start = priv->ystart;
605 stride = priv->ystride;
606
607 indx = start * stride;
608 i = 0;
609 do {
610 if (vtype == G_TYPE_FLOAT)
611 fval = ((gfloat *)values)[indx];
612 else if (vtype == G_TYPE_DOUBLE)
613 fval = ((gdouble *)values)[indx];
614 else if (vtype == G_TYPE_INT)
615 fval = ((gint *)values)[indx];
616 else if (vtype == G_TYPE_UINT)
617 fval = ((guint *)values)[indx];
618 else if (vtype == G_TYPE_LONG)
619 fval = ((glong *)values)[indx];
620 else if (vtype == G_TYPE_ULONG)
621 fval = ((gulong *)values)[indx];
622 else if (vtype == G_TYPE_INT64)
623 fval = ((gint64 *)values)[indx];
624 else if (vtype == G_TYPE_UINT64)
625 fval = ((guint64 *)values)[indx];
626 else if (vtype == G_TYPE_CHAR)
627 fval = ((gchar *)values)[indx];
628 else if (vtype == G_TYPE_UCHAR)
629 fval = ((guchar *)values)[indx];
630
631 if (i==0) /* yes putting this check inside the loop is inefficient, but it makes the code simpler */
632 {
633 minval = maxval = fval;
634 }
635 else
636 {
637 if (fval < minval) minval = fval;
638 if (fval > maxval) maxval = fval;
639 }
640
641 /* handle the wrap-around (ring buffer) issue using modulus. for efficiency, don't do this for non-wraparound cases. */
642 /* note this allows multiple wrap-arounds. One could hold a single cycle of a sine wave, and plot a continuous wave */
643 /* This can be optimized using pointers later */
644 if (i + start > maxlen)
645 indx = ((i + start) % maxlen) * stride;
646 else
647 indx += stride;
648 } while (++i < len);
649
650 *min_y = minval;
651 *max_y = maxval;
652
653 return 0;
654 }
655