1 /* $Id: gtkdatabox_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_graph.h>
21 #include <gtk/gtk.h>
22 
23 G_DEFINE_TYPE(GtkDataboxGraph, gtk_databox_graph,
24 	G_TYPE_OBJECT)
25 
26 static void gtk_databox_graph_real_draw (GtkDataboxGraph * graph,
27     GtkDatabox * draw);
28 static gint gtk_databox_graph_real_calculate_extrema (GtkDataboxGraph * graph,
29     gfloat * min_x,
30     gfloat * max_x,
31     gfloat * min_y,
32     gfloat * max_y);
33 
34 /* IDs of properties */
35 enum
36 {
37   GRAPH_COLOR = 1,
38   GRAPH_SIZE,
39   GRAPH_HIDE,
40 };
41 
42 /**
43  * GtkDataboxGraphPrivate
44  *
45  * A private data structure used by the #GtkDataboxGraph. It shields all internal things
46  * from developers who are just using the object.
47  *
48  **/
49 typedef struct _GtkDataboxGraphPrivate GtkDataboxGraphPrivate;
50 
51 struct _GtkDataboxGraphPrivate
52 {
53   GdkRGBA color;
54   gint size;
55   gboolean hide;
56   GdkRGBA rgba;
57 };
58 
59 static void
gtk_databox_graph_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)60 gtk_databox_graph_set_property (GObject * object,
61                                 guint property_id,
62                                 const GValue * value, GParamSpec * pspec)
63 {
64   GtkDataboxGraph *graph = GTK_DATABOX_GRAPH (object);
65 
66   switch (property_id)
67     {
68     case GRAPH_COLOR:
69     {
70       gtk_databox_graph_set_color (graph,
71                                    (GdkRGBA *)
72                                    g_value_get_pointer (value));
73     }
74     break;
75     case GRAPH_SIZE:
76     {
77       gtk_databox_graph_set_size (graph, g_value_get_int (value));
78     }
79     break;
80     case GRAPH_HIDE:
81     {
82       gtk_databox_graph_set_hide (graph, g_value_get_boolean (value));
83     }
84     break;
85     default:
86       /* We don't have any other property... */
87       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
88       break;
89     }
90 }
91 
92 static void
gtk_databox_graph_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)93 gtk_databox_graph_get_property (GObject * object,
94                                 guint property_id,
95                                 GValue * value, GParamSpec * pspec)
96 {
97   GtkDataboxGraph *graph = GTK_DATABOX_GRAPH (object);
98 
99   switch (property_id)
100     {
101     case GRAPH_COLOR:
102     {
103       g_value_set_pointer (value, gtk_databox_graph_get_color (graph));
104     }
105     break;
106     case GRAPH_SIZE:
107     {
108       g_value_set_int (value, gtk_databox_graph_get_size (graph));
109     }
110     break;
111     case GRAPH_HIDE:
112     {
113       g_value_set_boolean (value, gtk_databox_graph_get_hide (graph));
114     }
115     break;
116     default:
117       /* We don't have any other property... */
118       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
119       break;
120     }
121 }
122 
123 /**
124  * gtk_databox_graph_create_gc:
125  * @graph: A #GtkDataboxGraph object
126  * @box: A #GtkDatabox object
127  *
128  * Virtual function which creates a graphics context for the @graph.
129  *
130  * Typically called by derived graph objects when the graphics context is needed for the first time.
131  *
132  * Return value: The new graphics context.
133  */
134 cairo_t*
gtk_databox_graph_create_gc(GtkDataboxGraph * graph,GtkDatabox * box)135 gtk_databox_graph_create_gc (GtkDataboxGraph * graph,
136                              GtkDatabox* box)
137 {
138   return GTK_DATABOX_GRAPH_GET_CLASS (graph)->create_gc (graph, box);
139 }
140 
141 static cairo_t *
gtk_databox_graph_real_create_gc(GtkDataboxGraph * graph,GtkDatabox * box)142 gtk_databox_graph_real_create_gc (GtkDataboxGraph * graph,
143                                   GtkDatabox* box)
144 {
145   GtkDataboxGraphPrivate *priv = GTK_DATABOX_GRAPH_GET_PRIVATE(graph);
146   cairo_t *cr;
147 
148   g_return_val_if_fail (GTK_DATABOX_IS_GRAPH (graph), NULL);
149 
150    cr = cairo_create (gtk_databox_get_backing_surface (box));
151    gdk_cairo_set_source_rgba (cr, &priv->color);
152    cairo_set_line_width (cr,  (priv->size > 1) ? priv->size : 1);
153 
154    return cr;
155 }
156 
157 static void
gtk_databox_graph_class_init(GtkDataboxGraphClass * klass)158 gtk_databox_graph_class_init (GtkDataboxGraphClass *klass)
159 {
160   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
161   GParamSpec *graph_param_spec;
162 
163   gobject_class->set_property = gtk_databox_graph_set_property;
164   gobject_class->get_property = gtk_databox_graph_get_property;
165 
166   graph_param_spec = g_param_spec_pointer ("color",
167                      "Graph color",
168                      "Color of graph",
169                      G_PARAM_READWRITE);
170 
171   g_object_class_install_property (gobject_class,
172                                    GRAPH_COLOR, graph_param_spec);
173 
174   graph_param_spec = g_param_spec_int ("size", "Graph size", "Size of displayed items", G_MININT, G_MAXINT, 0,	/* default value */
175                                        G_PARAM_READWRITE);
176 
177   g_object_class_install_property (gobject_class,
178                                    GRAPH_SIZE, graph_param_spec);
179 
180   graph_param_spec = g_param_spec_boolean ("hide", "Graph hidden", "Determine if graph is hidden or not", FALSE,	/* default value */
181                      G_PARAM_READWRITE);
182 
183   g_object_class_install_property (gobject_class,
184                                    GRAPH_HIDE, graph_param_spec);
185 
186   klass->draw = gtk_databox_graph_real_draw;
187   klass->calculate_extrema = gtk_databox_graph_real_calculate_extrema;
188   klass->create_gc = gtk_databox_graph_real_create_gc;
189 
190   g_type_class_add_private (klass, sizeof (GtkDataboxGraphPrivate));
191 }
192 
gtk_databox_graph_init(GtkDataboxGraph * graph)193 static void gtk_databox_graph_init (GtkDataboxGraph *graph) { graph = graph;}
194 
195 /**
196  * gtk_databox_graph_draw:
197  * @graph: A #GtkDataboxGraph object
198  * @box: A #GtkDatabox object
199  *
200  * Virtual function which draws the #GtkDataboxGraph on the drawing area of the GtkDatabox object.
201  *
202  * Typically this function is called by #GtkDatabox objects.
203  *
204  */
205 void
gtk_databox_graph_draw(GtkDataboxGraph * graph,GtkDatabox * box)206 gtk_databox_graph_draw (GtkDataboxGraph * graph, GtkDatabox* box)
207 {
208   if (!GTK_DATABOX_GRAPH_GET_PRIVATE(graph)->hide)
209     GTK_DATABOX_GRAPH_GET_CLASS (graph)->draw (graph, box);
210 }
211 
212 /**
213  * gtk_databox_graph_calculate_extrema:
214  * @graph: A #GtkDataboxGraph object
215  * @min_x: Will be filled with the lowest x value of the dataset
216  * @max_x: Will be filled with the highest x value of the dataset
217  * @min_y: Will be filled with the lowest y value of the dataset
218  * @max_y: Will be filled with the highest y value of the dataset
219  *
220  * Virtual function which determines the minimum and maximum x and y values of the values of this
221  * #GtkDataboxGraph object if applicable (there are graphs which do
222  * not contain data).
223  *
224  * Return value: 0 on success,
225  *          -1 if no data is available,
226  *
227  */
228 gint
gtk_databox_graph_calculate_extrema(GtkDataboxGraph * graph,gfloat * min_x,gfloat * max_x,gfloat * min_y,gfloat * max_y)229 gtk_databox_graph_calculate_extrema (GtkDataboxGraph * graph,
230                                      gfloat * min_x, gfloat * max_x,
231                                      gfloat * min_y, gfloat * max_y)
232 {
233   return
234     GTK_DATABOX_GRAPH_GET_CLASS (graph)->calculate_extrema (graph, min_x,
235         max_x, min_y,
236         max_y);
237 }
238 
239 static void
gtk_databox_graph_real_draw(GtkDataboxGraph * graph,GtkDatabox * box)240 gtk_databox_graph_real_draw (GtkDataboxGraph * graph,
241                              GtkDatabox* box)
242 {
243   g_return_if_fail (graph);
244   g_return_if_fail (box);
245 
246   /* We have no data... */
247   return;
248 }
249 
250 
251 static gint
gtk_databox_graph_real_calculate_extrema(GtkDataboxGraph * graph,gfloat * min_x,gfloat * max_x,gfloat * min_y,gfloat * max_y)252 gtk_databox_graph_real_calculate_extrema (GtkDataboxGraph * graph,
253     gfloat * min_x, gfloat * max_x,
254     gfloat * min_y, gfloat * max_y)
255 {
256   g_return_val_if_fail (graph, -1);
257   g_return_val_if_fail (min_x, -1);
258   g_return_val_if_fail (max_x, -1);
259   g_return_val_if_fail (min_y, -1);
260   g_return_val_if_fail (max_y, -1);
261 
262   /* We have no data... */
263   return -1;
264 }
265 
266 /**
267  * gtk_databox_graph_set_color:
268  * @graph: A #GtkDataboxGraph object
269  * @color: Color which is to be used by the graph object
270  *
271  * Sets the color which the #GtkDataboxGraph object is supposed to be using when drawing itself.
272  *
273  */
274 void
gtk_databox_graph_set_color(GtkDataboxGraph * graph,GdkRGBA * color)275 gtk_databox_graph_set_color (GtkDataboxGraph * graph, GdkRGBA * color)
276 {
277   GtkDataboxGraphPrivate *priv = GTK_DATABOX_GRAPH_GET_PRIVATE(graph);
278 
279   g_return_if_fail (GTK_DATABOX_IS_GRAPH (graph));
280 
281   priv->color = *color;
282 
283   g_object_notify (G_OBJECT (graph), "color");
284 }
285 
286 /**
287  * gtk_databox_graph_get_color:
288  * @graph: A #GtkDataboxGraph object
289  *
290  * Gets the current color of the graph elements (e.g. points).
291  *
292  * Return value: The color of the graph.
293  *
294  */
295 GdkRGBA *
gtk_databox_graph_get_color(GtkDataboxGraph * graph)296 gtk_databox_graph_get_color (GtkDataboxGraph * graph)
297 {
298   return &GTK_DATABOX_GRAPH_GET_PRIVATE(graph)->color;
299 }
300 
301 /**
302  * gtk_databox_graph_set_size:
303  * @graph: A #GtkDataboxGraph object
304  * @size: Size of graph elements for the graph object
305  *
306  * Sets the size (e.g. line width) which the #GtkDataboxGraph object is supposed to be using when drawing itself.
307  *
308  */
309 void
gtk_databox_graph_set_size(GtkDataboxGraph * graph,gint size)310 gtk_databox_graph_set_size (GtkDataboxGraph * graph, gint size)
311 {
312   g_return_if_fail (GTK_DATABOX_IS_GRAPH (graph));
313 
314   GTK_DATABOX_GRAPH_GET_PRIVATE(graph)->size = MAX (1, size);;
315 
316   g_object_notify (G_OBJECT (graph), "size");
317 }
318 
319 /**
320  * gtk_databox_graph_get_size:
321  * @graph: A #GtkDataboxGraph object
322  *
323  * Gets the size of the graph elements (e.g. the line width).
324  *
325  * Return value: size of the graph elements
326  *
327  */
328 gint
gtk_databox_graph_get_size(GtkDataboxGraph * graph)329 gtk_databox_graph_get_size (GtkDataboxGraph * graph)
330 {
331   g_return_val_if_fail (GTK_DATABOX_IS_GRAPH (graph), -1);
332 
333   return GTK_DATABOX_GRAPH_GET_PRIVATE(graph)->size;
334 }
335 
336 /**
337  * gtk_databox_graph_set_hide:
338  * @graph: A #GtkDataboxGraph object
339  * @hide: Declares whether should be hidden (true) or not (false).
340  *
341  * Hidden graphs are not shown, when the #GtkDatabox containing them is redrawn.
342  *
343  */
344 void
gtk_databox_graph_set_hide(GtkDataboxGraph * graph,gboolean hide)345 gtk_databox_graph_set_hide (GtkDataboxGraph * graph, gboolean hide)
346 {
347   g_return_if_fail (GTK_DATABOX_IS_GRAPH (graph));
348 
349   GTK_DATABOX_GRAPH_GET_PRIVATE(graph)->hide = hide;
350 
351   g_object_notify (G_OBJECT (graph), "hide");
352 }
353 
354 /**
355  * gtk_databox_graph_get_hide:
356  * @graph: A #GtkDataboxGraph object
357  *
358  * Gets the current "hide" status.
359  *
360  * Return value: Whether the graph is hidden (true) or not (false).
361  *
362  */
363 gboolean
gtk_databox_graph_get_hide(GtkDataboxGraph * graph)364 gtk_databox_graph_get_hide (GtkDataboxGraph * graph)
365 {
366   g_return_val_if_fail (GTK_DATABOX_IS_GRAPH (graph), -1);
367 
368   return GTK_DATABOX_GRAPH_GET_PRIVATE(graph)->hide;
369 }
370