"Fossies" - the Fresh Open Source Software Archive 
Member "gtkdatabox-1.0.0/gtk/gtkdatabox_grid.c" (31 Mar 2021, 17128 Bytes) of package /linux/privat/gtkdatabox-1.0.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* $Id: gtkdatabox_grid.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_grid.h>
21 #include <math.h>
22
23 static void gtk_databox_grid_real_draw (GtkDataboxGraph * grid,
24 GtkDatabox* box);
25 static cairo_t* gtk_databox_grid_real_create_gc (GtkDataboxGraph * graph,
26 GtkDatabox* box);
27
28 /* IDs of properties */
29 enum
30 {
31 GRID_HLINES = 1,
32 GRID_VLINES,
33 GRID_HLINE_VALS,
34 GRID_VLINE_VALS,
35 GRID_LINE_STYLE
36 };
37
38 /**
39 * GtkDataboxGridPrivate
40 *
41 * A private data structure used by the #GtkDataboxGrid. It shields all internal things
42 * from developers who are just using the object.
43 *
44 **/
45 typedef struct _GtkDataboxGridPrivate GtkDataboxGridPrivate;
46
47 struct _GtkDataboxGridPrivate
48 {
49 gint hlines;
50 gint vlines;
51 gfloat *hline_vals;
52 gfloat *vline_vals;
53 GtkDataboxGridLineStyle line_style;
54 };
55
56 G_DEFINE_TYPE_WITH_PRIVATE(GtkDataboxGrid, gtk_databox_grid,
57 GTK_DATABOX_TYPE_GRAPH)
58
59 static void
60 gtk_databox_grid_set_property (GObject * object,
61 guint property_id,
62 const GValue * value, GParamSpec * pspec)
63 {
64 GtkDataboxGrid *grid = GTK_DATABOX_GRID (object);
65
66 switch (property_id)
67 {
68 case GRID_HLINES:
69 {
70 gtk_databox_grid_set_hlines (grid, g_value_get_int (value));
71 }
72 break;
73 case GRID_VLINES:
74 {
75 gtk_databox_grid_set_vlines (grid, g_value_get_int (value));
76 }
77 break;
78 case GRID_HLINE_VALS:
79 {
80 gtk_databox_grid_set_hline_vals (grid, (gfloat *) g_value_get_pointer (value));
81 }
82 break;
83 case GRID_VLINE_VALS:
84 {
85 gtk_databox_grid_set_vline_vals (grid, (gfloat *) g_value_get_pointer (value));
86 }
87 break;
88 case GRID_LINE_STYLE:
89 {
90 gtk_databox_grid_set_line_style (grid, g_value_get_int (value));
91 }
92 break;
93 default:
94 /* We don't have any other property... */
95 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
96 break;
97 }
98 }
99
100 static void
101 gtk_databox_grid_get_property (GObject * object,
102 guint property_id,
103 GValue * value, GParamSpec * pspec)
104 {
105 GtkDataboxGrid *grid = GTK_DATABOX_GRID (object);
106
107 switch (property_id)
108 {
109 case GRID_HLINES:
110 {
111 g_value_set_int (value, gtk_databox_grid_get_hlines (grid));
112 }
113 break;
114 case GRID_VLINES:
115 {
116 g_value_set_int (value, gtk_databox_grid_get_vlines (grid));
117 }
118 break;
119 case GRID_HLINE_VALS:
120 {
121 g_value_set_pointer (value, gtk_databox_grid_get_hline_vals (grid));
122 }
123 break;
124 case GRID_VLINE_VALS:
125 {
126 g_value_set_pointer (value, gtk_databox_grid_get_vline_vals (grid));
127 }
128 break;
129 case GRID_LINE_STYLE:
130 {
131 g_value_set_int (value, gtk_databox_grid_get_line_style (grid));
132 }
133 break;
134 default:
135 /* We don't have any other property... */
136 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
137 break;
138 }
139 }
140
141
142
143 static cairo_t*
144 gtk_databox_grid_real_create_gc (GtkDataboxGraph * graph,
145 GtkDatabox* box)
146 {
147 cairo_t *cr;
148
149 g_return_val_if_fail (GTK_DATABOX_IS_GRID (graph), NULL);
150
151 cr = GTK_DATABOX_GRAPH_CLASS (gtk_databox_grid_parent_class)->create_gc (graph, box);
152
153 return cr;
154 }
155
156 static void
157 grid_finalize (GObject * object)
158 {
159 /* Chain up to the parent class */
160 G_OBJECT_CLASS (gtk_databox_grid_parent_class)->finalize (object);
161 }
162
163 static void
164 gtk_databox_grid_class_init (GtkDataboxGridClass *klass)
165 {
166 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
167 GtkDataboxGraphClass *graph_class = GTK_DATABOX_GRAPH_CLASS (klass);
168 GParamSpec *grid_param_spec;
169
170 gobject_class->set_property = gtk_databox_grid_set_property;
171 gobject_class->get_property = gtk_databox_grid_get_property;
172 gobject_class->finalize = grid_finalize;
173
174 grid_param_spec = g_param_spec_int ("grid-hlines", "grid-hlines", "Number of horizontal lines", G_MININT, G_MAXINT, 0, /* default value */
175 G_PARAM_READWRITE);
176
177 g_object_class_install_property (gobject_class,
178 GRID_HLINES, grid_param_spec);
179
180 grid_param_spec = g_param_spec_int ("grid-vlines", "grid-vlines", "Number of vertical lines", G_MININT, G_MAXINT, 0, /* default value */
181 G_PARAM_READWRITE);
182
183 g_object_class_install_property (gobject_class,
184 GRID_VLINES, grid_param_spec);
185
186 grid_param_spec = g_param_spec_pointer ("grid-hline-vals", "Grid Hline Vals", "The locations of each of the horizontal lines", G_PARAM_READWRITE);
187
188 g_object_class_install_property (gobject_class,
189 GRID_HLINE_VALS, grid_param_spec);
190
191 grid_param_spec = g_param_spec_pointer ("grid-vline-vals", "Grid Vline Vals", "The locations of each of the vertical lines", G_PARAM_READWRITE);
192
193 g_object_class_install_property (gobject_class,
194 GRID_VLINE_VALS, grid_param_spec);
195
196 grid_param_spec = g_param_spec_int ("line-style", "line-style", "Line style of grid lines",
197 GTK_DATABOX_GRID_DASHED_LINES, GTK_DATABOX_GRID_DOTTED_LINES,
198 GTK_DATABOX_GRID_DASHED_LINES,
199 G_PARAM_READWRITE);
200
201 g_object_class_install_property (gobject_class,
202 GRID_LINE_STYLE, grid_param_spec);
203
204
205 graph_class->draw = gtk_databox_grid_real_draw;
206 graph_class->create_gc = gtk_databox_grid_real_create_gc;
207 }
208
209 static void
210 gtk_databox_grid_init (GtkDataboxGrid *grid)
211 {
212 if (grid == NULL) g_warning ("grid_init with NULL");
213 }
214
215 /**
216 * gtk_databox_grid_new:
217 * @hlines: number of horizontal lines in the grid
218 * @vlines: number of vertical lines in the grid
219 * @color: color of the grid
220 * @size: line width of the grid
221 *
222 * Creates a new #GtkDataboxGrid object which can be added to a #GtkDatabox widget as nice decoration for other graphs.
223 *
224 * Return value: A new #GtkDataboxGrid object
225 **/
226 GtkDataboxGraph *
227 gtk_databox_grid_new (gint hlines, gint vlines, GdkRGBA * color, guint size)
228 {
229 GtkDataboxGrid *grid;
230 grid = g_object_new (GTK_DATABOX_TYPE_GRID,
231 "color", color,
232 "size", size,
233 "grid-hlines", hlines, "grid-vlines", vlines, "grid-hline-vals",NULL, "grid-vline-vals", NULL, NULL);
234
235 return GTK_DATABOX_GRAPH (grid);
236 }
237
238 /**
239 * gtk_databox_grid_array_new:
240 * @hlines: number of horizontal lines in the grid
241 * @vlines: number of vertical lines in the grid
242 * @hline_vals: a pointer to an array of gfloat horizontal grid coordinate
243 * @vline_vals: a pointer to an array of gfloat vertical grid coordinate
244 * @color: color of the grid
245 * @size: line width of the grid
246 *
247 * Creates a new #GtkDataboxGrid object which can be added to a #GtkDatabox widget as nice decoration for other graphs.
248 *
249 * Return value: A new #GtkDataboxGrid object
250 **/
251 GtkDataboxGraph *gtk_databox_grid_array_new (gint hlines, gint vlines, gfloat * local_hline_vals, gfloat * local_vline_vals,
252 GdkRGBA * color, guint size)
253 {
254 GtkDataboxGrid *grid;
255
256 grid = g_object_new (GTK_DATABOX_TYPE_GRID,
257 "color", color,
258 "size", size,
259 "grid-hlines", hlines, "grid-vlines", vlines, "grid-hline-vals", local_hline_vals, "grid-vline-vals", local_vline_vals, NULL);
260
261 return GTK_DATABOX_GRAPH (grid);
262 }
263
264 static void
265 gtk_databox_grid_real_draw (GtkDataboxGraph * graph,
266 GtkDatabox* box)
267 {
268 GtkWidget *widget;
269 GtkDataboxGrid *grid = GTK_DATABOX_GRID (graph);
270 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
271 gint i = 0;
272 gfloat x;
273 gfloat y;
274 gint16 width;
275 gint16 height;
276 gfloat offset_x;
277 gfloat offset_y;
278 gfloat factor_x;
279 gfloat factor_y;
280 gint16 pixel_x;
281 gint16 pixel_y;
282 gfloat left, right, top, bottom;
283 double pixel_right, pixel_left, pixel_top, pixel_bottom;
284 double target_spacing, grid_spacing;
285 double grid_dot[] = {0.0, 0.0};
286 cairo_t *cr;
287 GtkAllocation allocation;
288
289 g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
290 g_return_if_fail (GTK_IS_DATABOX (box));
291
292 widget = GTK_WIDGET(box);
293 gtk_widget_get_allocation(widget, &allocation);
294
295 gtk_databox_get_total_limits (box, &left, &right, &top, &bottom);
296
297 cr = gtk_databox_graph_create_gc (graph, box);
298
299 width = allocation.width;
300 height = allocation.height;
301
302 offset_x = left;
303 factor_x =
304 (right - left) / (priv->vlines + 1);
305
306 offset_y = top;
307 factor_y =
308 (bottom - top) / (priv->hlines + 1);
309
310 /* Cairo accepts spacing of dotted and dashed lines in user-space
311 * coordinates, in our case, pixels, but using floating point
312 * values, and we use this to our advantage!
313 *
314 * For normal size dotted lines, we target a dot every five pixels,
315 * but adjust this so that horizontal and vertical grid lines
316 * always meet at a dot.
317 *
318 * For normal size dashed lines, we target five pixel dashes with
319 * five pixel spaces between them, but adjust this so that grid
320 * crossings always occur in the middle of a dash.
321 *
322 * We widen the target spacing if the line size is wider.
323 *
324 * This doesn't work for custom hline_vals, but we'll always get
325 * something close to five pixels per dot or dash.
326 */
327
328 pixel_right = gtk_databox_value_to_pixel_x (box, right);
329 pixel_left = gtk_databox_value_to_pixel_x (box, left);
330 grid_spacing = (pixel_right - pixel_left)/(priv->vlines+1);
331 target_spacing = 4.0 + cairo_get_line_width(cr);
332
333 switch (priv->line_style) {
334 case GTK_DATABOX_GRID_DASHED_LINES:
335 grid_spacing /= 2*round(grid_spacing/target_spacing/2);
336 cairo_set_dash(cr, &grid_spacing, 1, grid_spacing/2);
337 break;
338
339 case GTK_DATABOX_GRID_DOTTED_LINES:
340 grid_spacing /= round(grid_spacing/target_spacing);
341 grid_dot[1] = grid_spacing;
342 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
343 cairo_set_dash(cr, grid_dot, 2, 0.0);
344 break;
345
346 case GTK_DATABOX_GRID_SOLID_LINES:
347 break;
348 }
349
350 if (priv->hline_vals == NULL)
351 for (i = 0; i < priv->hlines; i++)
352 {
353 y = offset_y + (i + 1) * factor_y;
354 pixel_y = gtk_databox_value_to_pixel_y (box, y);
355 cairo_move_to (cr, 0.0, pixel_y + 0.5);
356 cairo_line_to (cr, width, pixel_y + 0.5);
357 }
358 else
359 for (i = 0; i < priv->hlines; i++)
360 {
361 y = priv->hline_vals[i];
362 pixel_y = gtk_databox_value_to_pixel_y (box, y);
363 cairo_move_to (cr, 0.0, pixel_y + 0.5);
364 cairo_line_to (cr, width, pixel_y + 0.5);
365 }
366
367 cairo_stroke(cr);
368
369 pixel_bottom = gtk_databox_value_to_pixel_y (box, bottom);
370 pixel_top = gtk_databox_value_to_pixel_y (box, top);
371 grid_spacing = (pixel_bottom - pixel_top)/(priv->hlines+1);
372
373 switch (priv->line_style) {
374 case GTK_DATABOX_GRID_DASHED_LINES:
375 grid_spacing /= 2*round(grid_spacing/target_spacing/2);
376 cairo_set_dash(cr, &grid_spacing, 1, grid_spacing/2);
377 break;
378
379 case GTK_DATABOX_GRID_DOTTED_LINES:
380 grid_spacing /= round(grid_spacing/target_spacing);
381 grid_dot[1] = grid_spacing;
382 cairo_set_dash(cr, grid_dot, 2, 0.0);
383 break;
384
385 case GTK_DATABOX_GRID_SOLID_LINES:
386 break;
387 }
388
389 if (priv->vline_vals == NULL)
390 for (i = 0; i < priv->vlines; i++)
391 {
392 x = offset_x + (i + 1) * factor_x;
393 pixel_x = gtk_databox_value_to_pixel_x (box, x);
394 cairo_move_to (cr, pixel_x + 0.5, 0.0);
395 cairo_line_to (cr, pixel_x + 0.5, height);
396 }
397 else
398 for (i = 0; i < priv->vlines; i++)
399 {
400 x = priv->vline_vals[i];
401 pixel_x = gtk_databox_value_to_pixel_x (box, x);
402 cairo_move_to (cr, pixel_x + 0.5, 0);
403 cairo_line_to (cr, pixel_x + 0.5, height);
404 }
405 cairo_stroke(cr);
406 cairo_destroy(cr);
407
408 return;
409 }
410
411 /**
412 * gtk_databox_grid_set_hlines:
413 * @grid: a #GtkDataboxGrid graph object
414 * @hlines: number of vertical lines in the grid
415 *
416 * Sets the number of horizontal lines in the @grid.
417 **/
418 void
419 gtk_databox_grid_set_hlines (GtkDataboxGrid * grid, gint hlines)
420 {
421 g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
422 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
423 priv->hlines = MAX (1, hlines);
424
425 g_object_notify (G_OBJECT (grid), "grid-hlines");
426 }
427
428 /**
429 * gtk_databox_grid_get_hlines:
430 * @grid: a #GtkDataboxGrid graph object
431 *
432 * Gets the number of horizontal lines in the @grid.
433 *
434 * Return value: Number of horizontal lines in the @grid.
435 **/
436 gint
437 gtk_databox_grid_get_hlines (GtkDataboxGrid * grid)
438 {
439 g_return_val_if_fail (GTK_DATABOX_IS_GRID (grid), -1);
440 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
441 return priv->hlines;
442 }
443
444 /**
445 * gtk_databox_grid_set_vlines:
446 * @grid: a #GtkDataboxGrid graph object
447 * @vlines: number of vertical lines in the grid
448 *
449 * Sets the number of vertical lines in the @grid.
450 **/
451 void
452 gtk_databox_grid_set_vlines (GtkDataboxGrid * grid, gint vlines)
453 {
454 g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
455 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
456 priv->vlines = MAX (1, vlines);
457
458 g_object_notify (G_OBJECT (grid), "grid-vlines");
459 }
460
461 /**
462 * gtk_databox_grid_get_vlines:
463 * @grid: a #GtkDataboxGrid graph object
464 *
465 * Gets the number of vertical lines in the @grid.
466 *
467 * Return value: Number of vertical lines in the @grid.
468 **/
469 gint
470 gtk_databox_grid_get_vlines (GtkDataboxGrid * grid)
471 {
472 g_return_val_if_fail (GTK_DATABOX_IS_GRID (grid), -1);
473 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
474 return priv->vlines;
475 }
476
477 /**
478 * gtk_databox_grid_set_hline_vals:
479 * @grid: a #GtkDataboxGrid graph object
480 * @hline_vals: sets the pointer to the hline values for the grid
481 *
482 * Sets the pointer to the horizontal lines in the @grid.
483 **/
484 void
485 gtk_databox_grid_set_hline_vals (GtkDataboxGrid * grid, gfloat *hline_vals)
486 {
487 g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
488 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
489 priv->hline_vals = hline_vals;
490
491 g_object_notify (G_OBJECT (grid), "grid-hline-vals");
492 }
493
494 /**
495 * gtk_databox_grid_get_hline_vals:
496 * @grid: a #GtkDataboxGrid graph object
497 *
498 * Gets the pointer to the horizontal line values for the @grid.
499 *
500 * Return value: Pointer to the horizontal line values for the @grid. (or NULL if error)
501 **/
502 gfloat*
503 gtk_databox_grid_get_hline_vals (GtkDataboxGrid * grid)
504 {
505 g_return_val_if_fail (GTK_DATABOX_IS_GRID (grid), NULL);
506 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
507 return priv->hline_vals;
508 }
509
510 /**
511 * gtk_databox_grid_set_vline_vals:
512 * @grid: a #GtkDataboxGrid graph object
513 * @vline_vals: sets the pointer to the vline values for the grid
514 *
515 * Sets the pointer to the vertical lines in the @grid.
516 **/
517 void
518 gtk_databox_grid_set_vline_vals (GtkDataboxGrid * grid, gfloat *vline_vals)
519 {
520 g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
521 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
522 priv->vline_vals = vline_vals;
523
524 g_object_notify (G_OBJECT (grid), "grid-vline-vals");
525 }
526
527 /**
528 * gtk_databox_grid_get_vline_vals:
529 * @grid: a #GtkDataboxGrid graph object
530 *
531 * Gets the pointer to the vertical line values for the @grid.
532 *
533 * Return value: Pointer to the vertical line values for the @grid. (or NULL if error)
534 **/
535 gfloat*
536 gtk_databox_grid_get_vline_vals (GtkDataboxGrid * grid)
537 {
538 g_return_val_if_fail (GTK_DATABOX_IS_GRID (grid), NULL);
539 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
540 return priv->vline_vals;
541 }
542
543 /**
544 * gtk_databox_grid_set_line_style:
545 * @grid: a #GtkDataboxGrid graph object
546 * @line_style: GTK_DATABOX_GRID_DASHED_LINES,
547 * GTK_DATABOX_GRID_SOLID_LINES, or GTK_DATABOX_GRID_DOTTED_LINES
548 *
549 * Sets the line style to draw the lines in the @grid.
550 **/
551 void
552 gtk_databox_grid_set_line_style (GtkDataboxGrid *grid, gint line_style)
553 {
554 g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
555 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
556 priv->line_style = line_style;
557
558 g_object_notify (G_OBJECT (grid), "line-style");
559 }
560
561 /**
562 * gtk_databox_grid_get_line_style:
563 * @grid: a #GtkDataboxGrid graph object
564 *
565 * Retrieve the line style to draw the lines in the @grid.
566 *
567 * Return value: GTK_DATABOX_GRID_DASHED_LINES,
568 * GTK_DATABOX_GRID_SOLID_LINES, or GTK_DATABOX_GRID_DOTTED_LINES
569 **/
570 gint
571 gtk_databox_grid_get_line_style (GtkDataboxGrid *grid)
572 {
573 g_return_val_if_fail (GTK_DATABOX_IS_GRID (grid), -1);
574 GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
575 return priv->line_style;
576 }