]> Dogcows Code - chaz/homebank/blob - src/gtk-chart.c
import homebank-4.6.3
[chaz/homebank] / src / gtk-chart.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2014 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <math.h>
21 #include <string.h>
22
23 #include <gtk/gtk.h>
24
25 #include "homebank.h"
26 #include "gtk-chart-colors.h"
27 #include "gtk-chart.h"
28
29
30 #define HELPDRAW 0
31
32 #define MYDEBUG 0
33
34 #if MYDEBUG
35 #define DB(x) (x);
36 #else
37 #define DB(x);
38 #endif
39
40
41 static void gtk_chart_class_intern_init (gpointer);
42 static void gtk_chart_class_init (GtkChartClass *klass);
43 static void gtk_chart_init (GtkChart *chart);
44 static void gtk_chart_destroy (GtkObject *chart);
45
46 static gboolean
47 drawarea_configure_event (GtkWidget *widget,
48 GdkEventConfigure *event,
49 gpointer user_data);
50 static void drawarea_sizeallocate_callback(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data);
51 static void drawarea_realize_callback(GtkWidget *widget, gpointer user_data);
52 static gboolean drawarea_draw_callback( GtkWidget *widget, GdkEventExpose *event, gpointer user_data);
53 static gboolean drawarea_motionnotifyevent_callback(GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
54 static gboolean drawarea_querytooltip_callback(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, gpointer user_data);
55
56 static gboolean drawarea_full_redraw(GtkWidget *widget, gpointer user_data);
57
58 static void chart_calculation(GtkChart *chart);
59 static void chart_clear(GtkChart *chart, gboolean store);
60
61 static void colchart_first_changed( GtkAdjustment *adj, gpointer user_data);
62 static void colchart_compute_range(GtkChart *chart);
63 static void colchart_calculation(GtkChart *chart);
64 static void colchart_scrollbar_setvalues(GtkChart *chart);
65
66 static void piechart_calculation(GtkChart *chart);
67
68 static GdkPixbuf *create_color_pixbuf (GdkColor *col);
69 static GtkWidget *legend_list_new(GtkChart *chart);
70
71
72 static GtkHBoxClass *gtk_chart_parent_class = NULL;
73
74
75 GType
76 gtk_chart_get_type ()
77 {
78 static GType chart_type = 0;
79
80 if (!chart_type)
81 {
82 static const GTypeInfo chart_info =
83 {
84 sizeof (GtkChartClass),
85 NULL, /* base_init */
86 NULL, /* base_finalize */
87 (GClassInitFunc) gtk_chart_class_intern_init,
88 NULL, /* class_finalize */
89 NULL, /* class_data */
90 sizeof (GtkChart),
91 0, /* n_preallocs */
92 (GInstanceInitFunc) gtk_chart_init,
93 NULL
94 };
95
96 chart_type = g_type_register_static (GTK_TYPE_HBOX, "GtkChart",
97 &chart_info, 0);
98
99 }
100 return chart_type;
101 }
102
103 static void
104 gtk_chart_class_intern_init (gpointer klass)
105 {
106 gtk_chart_parent_class = g_type_class_peek_parent (klass);
107 gtk_chart_class_init ((GtkChartClass *) klass);
108 }
109
110 static void
111 gtk_chart_class_init (GtkChartClass * klass)
112 {
113 //GObjectClass *gobject_class;
114 GtkObjectClass *object_class;
115 //GtkWidgetClass *widget_class;
116
117 //gobject_class = (GObjectClass*) klass;
118 object_class = (GtkObjectClass*) klass;
119 //widget_class = (GtkWidgetClass*) klass;
120
121 gtk_chart_parent_class = g_type_class_peek_parent (klass);
122
123 DB( g_print("\n[gtkchart] class_init\n") );
124
125 object_class->destroy = gtk_chart_destroy;
126
127 }
128
129 static void
130 gtk_chart_init (GtkChart * chart)
131 {
132 GtkWidget *widget, *vbox, *frame;
133 GtkWidget *scrollwin, *treeview;
134
135 chart->surface = NULL;
136 chart->nb_items = 0;
137 chart->items = NULL;
138 chart->title = NULL;
139 chart->abs = FALSE;
140 chart->dual = FALSE;
141 chart->barw = GTK_CHART_BARW;
142
143 chart->active = -1;
144 chart->lastactive = -1;
145
146 chart->minor_rate = 1.0;
147 chart->timer_tag = 0;
148
149 gtk_chart_set_color_scheme(chart, CHART_COLMAP_HOMEBANK);
150
151 widget=GTK_WIDGET(chart);
152
153 gtk_box_set_homogeneous(GTK_BOX(widget), FALSE);
154
155 vbox = gtk_vbox_new (FALSE, 0);
156 gtk_box_pack_start (GTK_BOX (widget), vbox, TRUE, TRUE, 0);
157
158 /* drawing area */
159 frame = gtk_frame_new(NULL);
160 gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
161 gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
162
163 chart->drawarea = gtk_drawing_area_new();
164 //gtk_widget_set_double_buffered (GTK_WIDGET(widget), FALSE);
165
166 gtk_container_add( GTK_CONTAINER(frame), chart->drawarea );
167 gtk_widget_set_size_request(chart->drawarea, 150, 150 );
168 gtk_widget_set_has_tooltip(chart->drawarea, TRUE);
169 gtk_widget_show(chart->drawarea);
170
171 #if MYDEBUG == 1
172 GtkStyle *style;
173 PangoFontDescription *font_desc;
174
175 g_print("draw_area font\n");
176
177 style = gtk_widget_get_style(GTK_WIDGET(chart->drawarea));
178 font_desc = style->font_desc;
179
180 g_print("family: %s\n", pango_font_description_get_family(font_desc) );
181 g_print("size: %d (%d)\n", pango_font_description_get_size (font_desc), pango_font_description_get_size (font_desc )/PANGO_SCALE );
182
183 #endif
184
185 /* scrollbar */
186 chart->adjustment = GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 1.0, 1.0, 1.0, 1.0));
187 chart->scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (chart->adjustment));
188 gtk_box_pack_start (GTK_BOX (vbox), chart->scrollbar, FALSE, TRUE, 0);
189
190
191 /* legend treeview */
192 scrollwin = gtk_scrolled_window_new(NULL,NULL);
193 chart->scrollwin = scrollwin;
194 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
195 //gtk_container_set_border_width (GTK_CONTAINER(scrollwin), 5);
196 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
197 treeview = legend_list_new(chart);
198 chart->treeview = treeview;
199 chart->legend = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
200 gtk_container_add(GTK_CONTAINER(scrollwin), treeview);
201 gtk_box_pack_start (GTK_BOX (widget), scrollwin, FALSE, FALSE, 0);
202
203 gtk_widget_add_events(GTK_WIDGET(chart->drawarea),
204 GDK_EXPOSURE_MASK |
205 //GDK_POINTER_MOTION_MASK |
206 GDK_POINTER_MOTION_HINT_MASK
207 //GDK_BUTTON_PRESS_MASK |
208 //GDK_BUTTON_RELEASE_MASK
209 );
210
211 g_signal_connect( G_OBJECT(chart->drawarea),"configure-event", G_CALLBACK (drawarea_configure_event), chart);
212 g_signal_connect( G_OBJECT(chart->drawarea), "size-allocate", G_CALLBACK(drawarea_sizeallocate_callback), chart ) ;
213 g_signal_connect( G_OBJECT(chart->drawarea), "realize", G_CALLBACK(drawarea_realize_callback), chart ) ;
214 g_signal_connect( G_OBJECT(chart->drawarea), "expose-event", G_CALLBACK(drawarea_draw_callback), chart ) ;
215 g_signal_connect( G_OBJECT(chart->drawarea), "query-tooltip", G_CALLBACK(drawarea_querytooltip_callback), chart );
216 g_signal_connect( G_OBJECT(chart->drawarea), "motion-notify-event", G_CALLBACK(drawarea_motionnotifyevent_callback), chart );
217
218 g_signal_connect (G_OBJECT(chart->adjustment), "value_changed", G_CALLBACK (colchart_first_changed), chart);
219
220 //g_signal_connect( G_OBJECT(chart->drawarea), "map-event", G_CALLBACK(chart_map), chart ) ;
221 //g_signal_connect( G_OBJECT(chart->drawarea), "button-press-event", G_CALLBACK(chart_button_press), chart );
222 //g_signal_connect( G_OBJECT(chart->drawarea), "button-release-event", G_CALLBACK(chart_button_release), chart );
223 }
224
225
226 /* --- */
227
228 GtkWidget *
229 gtk_chart_new (gint type)
230 {
231 GtkChart *chart;
232
233 DB( g_print("\n[gtkchart] new\n") );
234
235 chart = g_object_new (GTK_TYPE_CHART, NULL);
236 chart->type = type;
237
238 return GTK_WIDGET(chart);
239 }
240
241
242 static void
243 gtk_chart_destroy (GtkObject * object)
244 {
245 GtkChart *chart;
246
247 DB( g_print("\n[gtkchart] destroy\n") );
248
249 g_return_if_fail (GTK_IS_CHART (object));
250
251 chart = GTK_CHART (object);
252
253 chart_clear(chart, FALSE);
254
255 if (chart->surface)
256 {
257 cairo_surface_destroy (chart->surface);
258 chart->surface = NULL;
259 }
260 GTK_OBJECT_CLASS (gtk_chart_parent_class)->destroy (object);
261 }
262
263
264
265
266 /*
267 ** print a integer number
268 */
269 static gchar *chart_print_int(GtkChart *chart, gint value)
270 {
271
272 //mystrfmon(chart->buffer, CHART_BUFFER_LENGTH-1, (gdouble)value, chart->minor);
273 mystrfmon_int(chart->buffer1, CHART_BUFFER_LENGTH-1, (gdouble)value, chart->minor);
274
275 /*
276 if(chart->minor)
277 {
278 value *= chart->minor_rate;
279 strfmon(chart->buffer, CHART_BUFFER_LENGTH-1, "%!.0n ", (gdouble)value);
280 strcat(chart->buffer, chart->minor_symbol);
281 }
282 else
283 strfmon(chart->buffer, CHART_BUFFER_LENGTH-1, "%.0n", (gdouble)value);
284 */
285
286 return chart->buffer1;
287 }
288
289 /*
290 ** print a double number
291 */
292 static gchar *chart_print_double(GtkChart *chart, gchar *buffer, gdouble value)
293 {
294
295 mystrfmon(buffer, CHART_BUFFER_LENGTH-1, value, chart->minor);
296
297 /*
298 if(chart->minor)
299 {
300 value *= chart->minor_rate;
301 strfmon(chart->buffer, CHART_BUFFER_LENGTH-1, "%!n ", (gdouble)value);
302 strcat(chart->buffer, chart->minor_symbol);
303 }
304 else
305 strfmon(chart->buffer, CHART_BUFFER_LENGTH-1, "%n", (gdouble)value);
306 */
307
308 return buffer;
309 }
310
311
312 /*
313 ** clear any allocated memory
314 */
315 static void chart_clear(GtkChart *chart, gboolean store)
316 {
317 gint i;
318
319 DB( g_print("\n[gtkchart] clear\n") );
320
321 //free & clear any previous allocated datas
322 if(chart->title != NULL)
323 {
324 g_free(chart->title);
325 chart->title = NULL;
326 }
327
328 if(chart->items != NULL)
329 {
330 for(i=0;i<chart->nb_items;i++)
331 {
332 ChartItem *item = &g_array_index(chart->items, ChartItem, i);
333
334 g_free(item->legend);
335 }
336 g_array_free(chart->items, TRUE);
337 chart->items = NULL;
338 }
339
340 if(store == TRUE)
341 {
342 gtk_list_store_clear (GTK_LIST_STORE(chart->legend));
343 }
344
345 chart->nb_items = 0;
346
347 chart->total = 0;
348 chart->range = 0;
349 chart->rawmin = 0;
350 chart->rawmax = 0;
351 chart->every_xval = 7;
352
353 chart->active = -1;
354 chart->lastactive = -1;
355
356 }
357
358
359 /*
360 ** setup our chart with a model and column
361 */
362 static void chart_setup_with_model(GtkChart *chart, GtkTreeModel *list_store, guint column1, guint column2)
363 {
364 gint i;
365 gboolean valid;
366 GtkTreeIter iter, l_iter;
367 gint color;
368 GdkColor colour;
369
370 DB( g_print("\n[gtkchart] setup with model\n") );
371
372 chart_clear(chart, TRUE);
373 chart->nb_items = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list_store), NULL);
374
375 chart->items = g_array_sized_new(FALSE, FALSE, sizeof(ChartItem), chart->nb_items);
376
377 DB( g_print(" nb=%d, struct=%d\n", chart->nb_items, sizeof(ChartItem)) );
378
379 chart->dual = (column1 == column2) ? FALSE : TRUE;
380
381 /* Get the first iter in the list */
382 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(list_store), &iter);
383 i = 0;
384 while (valid)
385 {
386 gint id;
387 gchar *label;
388 gdouble value1, value2;
389 ChartItem item;
390
391 /* column 0: pos (gint) */
392 /* column 1: key (gint) */
393 /* column 2: label (gchar) */
394 /* column x: values (double) */
395
396 gtk_tree_model_get (GTK_TREE_MODEL(list_store), &iter,
397 0, &id,
398 2, &label,
399 column1, &value1,
400 column2, &value2,
401 -1);
402
403 if(chart->dual || chart->abs)
404 {
405 value1 = ABS(value1);
406 value2 = ABS(value2);
407 }
408
409 DB( g_print("%d: '%s' %.2f %2f\n", i, label, value1, value2) );
410
411 /* data1 value storage & min, max compute */
412 chart->rawmin = MIN(chart->rawmin, value1);
413 chart->rawmax = MAX(chart->rawmax, value1);
414
415 if( chart->dual )
416 {
417 /* data2 value storage & min, max compute */
418 chart->rawmin = MIN(chart->rawmin, value2);
419 chart->rawmax = MAX(chart->rawmax, value2);
420 }
421
422 item.label = label;
423 item.serie1 = value1;
424 item.serie2 = value2;
425 g_array_append_vals(chart->items, &item, 1);
426
427 /* populate our legend list */
428
429 color = i % chart->nb_cols;
430 //color = id % chart->nb_cols;
431
432 //DB( g_print ("Row %d: (%s, %2.f) color %d\n", id, title, value, color) );
433
434 colour.red = COLTO16(chart->colors[color].r);
435 colour.green = COLTO16(chart->colors[color].g);
436 colour.blue = COLTO16(chart->colors[color].b);
437
438 gtk_list_store_append (GTK_LIST_STORE(chart->legend), &l_iter);
439 gtk_list_store_set (GTK_LIST_STORE(chart->legend), &l_iter,
440 LST_LEGEND_COLOR, create_color_pixbuf (&colour),
441 LST_LEGEND_TITLE, label,
442 LST_LEGEND_AMOUNT, value1,
443 -1);
444
445
446 /* pie chart total sum */
447 chart->total += ABS(value1);
448
449 valid = gtk_tree_model_iter_next (list_store, &iter);
450 i++;
451 }
452
453 // compute rate for legend for bar/pie
454 for(i=0;i<chart->nb_items;i++)
455 {
456 ChartItem *item = &g_array_index(chart->items, ChartItem, i);
457
458 item->rate = ABS(item->serie1*100/chart->total);
459 item->legend = g_markup_printf_escaped("%s (%.2f%%)", item->label, item->rate);
460 }
461
462 if( chart->type != CHART_TYPE_LINE )
463 {
464
465 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(chart->legend), &iter);
466 while (valid)
467 {
468 gdouble amount, rate;
469
470 gtk_tree_model_get(GTK_TREE_MODEL(chart->legend), &iter,
471 LST_LEGEND_AMOUNT, &amount,
472 -1);
473
474 rate = ABS( amount*100/chart->total);
475
476 gtk_list_store_set(GTK_LIST_STORE(chart->legend), &iter,
477 LST_LEGEND_RATE, rate,
478 -1);
479
480 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(chart->legend), &iter);
481 }
482
483 }
484
485
486 //g_print("total is %.2f\n", total);
487 //ensure the widget is mapped
488 //gtk_widget_map(chart);
489
490 }
491
492
493
494 /*
495 ** recompute according to type
496 */
497 static void chart_recompute(GtkChart *chart)
498 {
499
500 DB( g_print("\n[gtkchart] recompute\n") );
501
502 chart_calculation (chart);
503
504 switch(chart->type)
505 {
506 case CHART_TYPE_LINE:
507 case CHART_TYPE_COL:
508 colchart_compute_range(chart);
509
510 colchart_calculation(chart);
511 gtk_adjustment_set_value(chart->adjustment, 0);
512 colchart_scrollbar_setvalues(chart);
513 gtk_widget_show(chart->scrollbar);
514 break;
515 case CHART_TYPE_PIE:
516 piechart_calculation(chart);
517 gtk_widget_hide(chart->scrollbar);
518 break;
519 }
520
521 }
522
523
524
525
526 /* bar section */
527
528
529 static float CalculateStepSize(float range, float targetSteps)
530 {
531 // calculate an initial guess at step size
532 float tempStep = range/targetSteps;
533
534 // get the magnitude of the step size
535 float mag = (float)floor(log10(tempStep));
536 float magPow = (float)pow(10, mag);
537
538 // calculate most significant digit of the new step size
539 float magMsd = (int)(tempStep/magPow + 0.5);
540
541 // promote the MSD to either 1, 2, or 5
542 if (magMsd > 5.0)
543 magMsd = 10.0f;
544 else if (magMsd > 2.0)
545 magMsd = 5.0f;
546 else if (magMsd >= 1.0)
547 magMsd = 2.0f;
548
549 return magMsd*magPow;
550 }
551
552
553 static void colchart_compute_range(GtkChart *chart)
554 {
555 double lobound=chart->rawmin, hibound=chart->rawmax;
556
557 DB( g_print("\n[gtkchart] bar compute range\n") );
558
559 /* comptute max ticks */
560 chart->range = chart->rawmax - chart->rawmin;
561 gint maxticks = MIN(10,floor(chart->graph_height / (chart->font_h * 2)));
562
563 DB( g_print(" raw :: [%.2f - %.2f] range=%.2f\n", chart->rawmin, chart->rawmax, chart->range) );
564 DB( g_print(" raw :: maxticks=%d (%g / (%g*2))\n", maxticks, chart->graph_height, chart->font_h) );
565
566 DB( g_print("\n") );
567 chart->unit = CalculateStepSize((hibound-lobound), maxticks);
568 chart->min = -chart->unit * ceil(-lobound/chart->unit);
569 chart->max = chart->unit * ceil(hibound/chart->unit);
570 chart->range = chart->max - chart->min;
571 chart->div = chart->range / chart->unit;
572
573 DB( g_print(" end :: interval=%.2f, ticks=%d\n", chart->unit, chart->div) );
574 DB( g_print(" end :: [%.2f - %.2f], range=%.2f\n", chart->min, chart->max, chart->range) );
575
576 }
577
578
579 static void chart_calculation(GtkChart *chart)
580 {
581 GtkWidget *drawarea = chart->drawarea;
582 GdkWindow *gdkwindow;
583 cairo_surface_t *surf = NULL;
584 cairo_t *cr;
585 cairo_text_extents_t te;
586 cairo_font_extents_t fe;
587 GtkAllocation allocation;
588 gchar *valstr;
589
590
591 DB( g_print("\n[gtkchart] calculation\n") );
592
593 gtk_widget_get_allocation(drawarea, &allocation);
594
595 chart->l = CHART_MARGIN;
596 chart->t = CHART_MARGIN;
597 chart->r = allocation.width - CHART_MARGIN;
598 chart->b = allocation.height - CHART_MARGIN;
599 chart->w = allocation.width - (CHART_MARGIN*2);
600 chart->h = allocation.height - (CHART_MARGIN*2);
601
602
603 gdkwindow = gtk_widget_get_window(chart->drawarea);
604 if(!gdkwindow)
605 {
606 surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height);
607 cr = cairo_create (surf);
608 }
609 else
610 cr = gdk_cairo_create (gdkwindow);
611
612 // compute title
613 chart->title_zh = 0;
614 if(chart->title != NULL)
615 {
616 cairo_set_font_size(cr, CHART_FONT_SIZE_TITLE);
617 cairo_font_extents(cr, &fe);
618 chart->title_zh = fe.height;
619 }
620
621 // compute subtitle
622 chart->subtitle_zh = 0;
623 if(chart->subtitle != NULL)
624 {
625 cairo_set_font_size(cr, CHART_FONT_SIZE_PERIOD);
626 cairo_font_extents(cr, &fe);
627 chart->subtitle_zh = fe.height;
628 }
629
630 chart->subtitle_y = chart->t + chart->title_zh;
631
632 cairo_set_font_size(cr, CHART_FONT_SIZE_NORMAL);
633
634 // compute amount scale
635 valstr = chart_print_int(chart, (gint)chart->min);
636 cairo_text_extents(cr, valstr, &te);
637 chart->scale_w = te.width;
638 valstr = chart_print_int(chart, (gint)chart->max);
639 cairo_text_extents(cr, valstr, &te);
640 chart->scale_w = MAX(chart->scale_w, te.width);
641 DB( g_print(" - scale: %g,%g %g,%g\n", chart->l, 0.0, chart->scale_w, 0.0) );
642
643 // compute font height
644 cairo_font_extents(cr, &fe);
645 chart->font_h = fe.height;
646
647 // compute graph region
648 switch(chart->type)
649 {
650 case CHART_TYPE_LINE:
651 case CHART_TYPE_COL:
652 chart->graph_x = chart->l + chart->scale_w + 2;
653 chart->graph_y = chart->t + chart->title_zh + chart->subtitle_zh;
654 chart->graph_width = chart->w - chart->scale_w - 2;
655 chart->graph_height = chart->h - chart->title_zh - chart->subtitle_zh;
656 break;
657 case CHART_TYPE_PIE:
658 chart->graph_x = chart->l;
659 chart->graph_y = chart->t + chart->title_zh + chart->subtitle_zh;
660 chart->graph_width = chart->w;
661 chart->graph_height = chart->h - chart->title_zh - chart->subtitle_zh;
662 break;
663 }
664
665 if(chart->title_zh > 0 || chart->subtitle_zh > 0)
666 {
667 chart->graph_y += CHART_MARGIN;
668 chart->graph_height -= CHART_MARGIN;
669 }
670
671 if(chart->type != CHART_TYPE_PIE && chart->show_xval)
672 chart->graph_height -= (chart->font_h + CHART_SPACING);
673
674 cairo_destroy(cr);
675 cairo_surface_destroy(surf);
676
677 }
678
679
680 static void colchart_calculation(GtkChart *chart)
681 {
682 gint blkw;
683
684 DB( g_print("\n[gtkchart] bar calculation\n") );
685
686
687 //if expand : we compute available space
688 //chart->barw = MAX(32, (chart->graph_width)/chart->nb_items);
689 //chart->barw = 32; // usr setted or defaut to BARW
690
691 // if fixed
692 blkw = chart->barw + 3;
693 if( chart->dual )
694 blkw = (chart->barw * 2) + 3;
695
696 chart->blkw = blkw;
697 chart->visible = chart->graph_width / blkw;
698 chart->visible = MIN(chart->visible, chart->nb_items);
699
700 chart->ox = chart->l;
701 chart->oy = floor(chart->graph_y + (chart->max/chart->range) * chart->graph_height);
702
703 DB( g_print(" + ox=%f oy=%f\n", chart->ox, chart->oy) );
704
705 }
706
707
708 /*
709 ** draw the scale
710 */
711 static void colchart_draw_scale(GtkWidget *widget, gpointer user_data)
712 {
713 GtkChart *chart = GTK_CHART(user_data);
714 double x, y;
715 gdouble curxval;
716 gint i, first;
717
718 DB( g_print("\n(gtkline) draw scale\n") );
719
720 cairo_t *cr;
721 //static const double dashed3[] = {2.0};
722
723 //gdkwindow = gtk_widget_get_window(widget);
724 //cr = gdk_cairo_create (gdkwindow);
725 //cr = gdk_cairo_create (widget->window);
726 cr = cairo_create (chart->surface);
727
728 cairo_set_line_width(cr, 1);
729
730 /* clip */
731 //cairo_rectangle(cr, CHART_MARGIN, 0, chart->w, chart->h + CHART_MARGIN);
732 //cairo_clip(cr);
733
734 /* draw vertical lines + legend */
735 if(chart->show_xval)
736 {
737 x = chart->graph_x + 1.5 + (chart->barw/2);
738 y = chart->oy;
739 first = gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
740
741 for(i=first; i<(first+chart->visible) ;i++)
742 {
743 if( !(i % chart->every_xval) )
744 {
745 //cairo_user_set_rgbcol(cr, &global_colors[GREY1]);
746 cairo_user_set_rgbacol(cr, &global_colors[THTEXT], 0.05);
747
748 cairo_move_to(cr, x, chart->graph_y);
749 cairo_line_to(cr, x, chart->b);
750 cairo_stroke(cr);
751 }
752
753 x += chart->blkw;
754 }
755 }
756
757 /* horizontal lines */
758
759 curxval = chart->max;
760 for(i=0;i<=chart->div;i++)
761 {
762
763 //if(i == 0 || i == chart->div) /* top/bottom line */
764 //{
765 //cairo_set_dash(cr, 0, 0, 0);
766 //cairo_user_set_rgbcol(cr, &global_colors[GREY1]);
767 cairo_user_set_rgbacol(cr, &global_colors[THTEXT], 0.1);
768 //}
769 //else /* intermediate line (dotted) */
770 //{
771 //cairo_set_dash(cr, dashed3, 1, 0);
772 //cairo_user_set_rgbcol(cr, &global_colors[GREY1]);
773 //}
774
775 /* x axis ? */
776 if( curxval == 0.0 )
777 {
778 //cairo_set_dash(cr, 0, 0, 0);
779 cairo_user_set_rgbacol(cr, &global_colors[THTEXT], 0.8);
780 }
781
782 y = 0.5 + floor(chart->graph_y + ((i * chart->unit) / chart->range) * chart->graph_height);
783
784 DB( g_print(" + i=%d :: y=%f (%f / %f) * %f\n", i, y, i*chart->unit, chart->range, chart->graph_height) );
785
786 cairo_move_to(cr, chart->graph_x, y);
787 cairo_line_to(cr, chart->graph_x + chart->graph_width, y);
788 cairo_stroke(cr);
789
790 curxval -= chart->unit;
791 }
792
793 cairo_destroy(cr);
794
795 }
796
797
798 static void colchart_draw_scale_text(GtkWidget *widget, gpointer user_data)
799 {
800 GtkChart *chart = GTK_CHART(user_data);
801 double x, y;
802 gdouble curxval;
803 gchar *valstr;
804 gint i, first;
805
806 DB( g_print("----------------------\n(gtkline) draw scale text\n") );
807
808 cairo_t *cr;
809 cairo_text_extents_t te;
810
811 //GdkWindow *gdkwindow;
812 //gdkwindow = gtk_widget_get_window(widget);
813
814 //cr = gdk_cairo_create (gdkwindow);
815 //cr = gdk_cairo_create (widget->window);
816 cr = cairo_create (chart->surface);
817
818 cairo_set_line_width(cr, 1);
819
820 /* clip */
821 //cairo_rectangle(cr, CHART_MARGIN, 0, chart->w, chart->h + CHART_MARGIN);
822 //cairo_clip(cr);
823
824 //cairo_set_operator(cr, CAIRO_OPERATOR_SATURATE);
825
826 /* draw x-legend (items) */
827 if(chart->show_xval)
828 {
829 x = chart->graph_x + 1.5 + (chart->barw/2);
830 y = chart->b - chart->font_h;
831 first = (gint)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
832
833 for(i=first; i<(first+chart->visible) ;i++)
834 {
835 ChartItem *item = &g_array_index(chart->items, ChartItem, i);
836
837 if( !(i % chart->every_xval) )
838 {
839 valstr = item->label;
840 cairo_text_extents(cr, valstr, &te);
841
842 DB( g_print("%s w=%f h=%f\n", valstr, te.width, te.height) );
843
844 cairo_user_set_rgbacol(cr, &global_colors[THTEXT], 0.78);
845 //cairo_move_to(cr, x - (te.width/2), y - te.y_bearing);
846 cairo_move_to(cr, x, y - te.y_bearing);
847 cairo_show_text(cr, valstr);
848
849 /*cairo_user_set_rgbcol(cr, &global_colors[TEXT]);
850 cairo_move_to(cr, x, y);
851 cairo_line_to(cr, x, y + te.height);
852 cairo_stroke(cr);*/
853 }
854
855 x += chart->blkw;
856 }
857 }
858
859 /* draw y-legend (amount) */
860
861 curxval = chart->max;
862 for(i=0;i<=chart->div;i++)
863 {
864 y = 0.5 + floor(chart->graph_y + ((i * chart->unit) / chart->range) * chart->graph_height);
865
866 DB( g_print(" + i=%d :: y=%f (%f / %f) * %f\n", i, y, i*chart->unit, chart->range, chart->graph_height) );
867
868 if( curxval != 0.0 )
869 {
870 valstr = chart_print_int(chart, (gint)curxval);
871 cairo_text_extents(cr, valstr, &te);
872
873 //DB( g_print("'%s', %f %f %f %f %f %f\n", valstr, te.x_bearing, te.y_bearing, te.width, te.height, te.x_advance, te.y_advance) );
874
875 // draw texts
876 cairo_move_to(cr, chart->graph_x - te.x_bearing - te.width - 2, y + (( te.height)/2));
877 cairo_user_set_rgbacol (cr, &global_colors[THTEXT], 0.78);
878 cairo_show_text(cr, valstr);
879
880 }
881
882 curxval -= chart->unit;
883 }
884
885 cairo_destroy(cr);
886 }
887
888 /*
889 ** draw all visible bars
890 */
891 static void colchart_draw_bars(GtkWidget *widget, gpointer user_data)
892 {
893 GtkChart *chart = GTK_CHART(user_data);
894 cairo_t *cr;
895 double x, x2, y2, h;
896 gint i, first;
897
898 DB( g_print("\n[gtkchart] bar draw bars\n") );
899
900 x = chart->graph_x;
901 first = (gint)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
902
903 cr = gdk_cairo_create (gtk_widget_get_window(widget));
904 //cr = cairo_create (chart->surface);
905
906 #if HELPDRAW == 1
907 x2 = x + 0.5;
908 cairo_set_line_width(cr, 1.0);
909 cairo_set_source_rgb(cr, 1.0, 0.0, 1.0); // violet
910 for(i=first; i<=(first+chart->visible) ;i++)
911 {
912 cairo_move_to(cr, x2, chart->graph_y);
913 cairo_line_to(cr, x2, chart->graph_x + chart->graph_height);
914
915 x2 += chart->blkw;
916 }
917 cairo_stroke(cr);
918 #endif
919
920 for(i=first; i<(first+chart->visible) ;i++)
921 {
922 ChartItem *item = &g_array_index(chart->items, ChartItem, i);
923 gint color;
924 gint barw = chart->barw;
925
926 //if(!chart->datas1[i]) goto nextbar;
927
928 color = i % chart->nb_cols;
929
930 cairo_user_set_rgbcol_over(cr, &chart->colors[color], i == chart->active);
931
932 if(item->serie1)
933 {
934 x2 = x;
935 h = floor((item->serie1 / chart->range) * chart->graph_height);
936 y2 = chart->oy - h;
937 if(item->serie1 < 0.0)
938 y2 += 1;
939
940 //DB( g_print(" + i=%d :: y2=%f h=%f (%f / %f) * %f\n", i, y2, h, chart->datas1[i], chart->range, chart->graph_height ) );
941
942
943 cairo_rectangle(cr, x2+2, y2, barw, h);
944 cairo_fill(cr);
945
946 }
947
948 if( chart->dual && item->serie2)
949 {
950
951 x2 = x + barw + 1;
952 h = floor((item->serie2 / chart->range) * chart->graph_height);
953 y2 = chart->oy - h;
954
955 cairo_rectangle(cr, x2+2, y2, barw, h);
956 cairo_fill(cr);
957
958 }
959
960 x += chart->blkw;
961
962 //debug
963 //gdk_draw_line (widget->window, widget->style->fg_gc[widget->state], x, chart->oy-chart->posbarh, x, chart->oy+chart->negbarh);
964
965 }
966
967 cairo_destroy(cr);
968
969 }
970
971 /*
972 ** get the bar under the mouse pointer
973 */
974 static gint colchart_get_active(GtkWidget *widget, gint x, gint y, gpointer user_data)
975 {
976 GtkChart *chart = GTK_CHART(user_data);
977 gint retval;
978 gint index, first, px;
979
980 retval = -1;
981
982 if( x <= chart->r && x >= chart->graph_x && y >= chart->graph_y && y <= chart->b )
983 {
984 px = (x - chart->graph_x);
985 //py = (y - chart->oy);
986 first = gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
987 index = first + (px / chart->blkw);
988
989 if(index < chart->nb_items)
990 retval = index;
991 }
992
993 return(retval);
994 }
995
996 static void colchart_first_changed( GtkAdjustment *adj, gpointer user_data)
997 {
998 GtkChart *chart = GTK_CHART(user_data);
999 //gint first;
1000
1001 DB( g_print("\n[gtkchart] bar first changed\n") );
1002
1003 //first = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj));
1004
1005 //DB( g_print(" first=%d\n", first) );
1006
1007 /*
1008 DB( g_print("scrollbar\n adj=%8x, low=%.2f upp=%.2f val=%.2f step=%.2f page=%.2f size=%.2f\n", adj,
1009 adj->lower, adj->upper, adj->value, adj->step_increment, adj->page_increment, adj->page_size) );
1010 */
1011 /* Set the number of decimal places to which adj->value is rounded */
1012 //gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
1013 //gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
1014
1015 drawarea_full_redraw (chart->drawarea, chart);
1016 gtk_widget_queue_draw(chart->drawarea);
1017
1018 }
1019
1020 /*
1021 ** scrollbar set values for upper, page size, and also show/hide
1022 */
1023 static void colchart_scrollbar_setvalues(GtkChart *chart)
1024 {
1025 GtkAdjustment *adj = chart->adjustment;
1026 gint first;
1027
1028 g_return_if_fail (GTK_IS_ADJUSTMENT (adj));
1029
1030 DB( g_print("\n[gtkchart] sb_set_values\n") );
1031
1032 first = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj));
1033
1034 DB( g_print(" entries=%d, visible=%d\n", chart->nb_items, chart->visible) );
1035 DB( g_print(" first=%d, upper=%d, pagesize=%d\n", first, chart->nb_items, chart->visible) );
1036
1037 gtk_adjustment_set_upper(adj, (gdouble)chart->nb_items);
1038 gtk_adjustment_set_page_size(adj, (gdouble)chart->visible);
1039 gtk_adjustment_set_page_increment(adj, (gdouble)chart->visible);
1040
1041 if(first+chart->visible > chart->nb_items)
1042 {
1043 gtk_adjustment_set_value(adj, (gdouble)chart->nb_items - chart->visible);
1044 }
1045 gtk_adjustment_changed (adj);
1046
1047 if( chart->visible < chart->nb_items )
1048 gtk_widget_hide(GTK_WIDGET(chart->scrollbar));
1049 else
1050 gtk_widget_show(GTK_WIDGET(chart->scrollbar));
1051
1052 }
1053
1054 /* line section */
1055
1056 /*
1057 ** draw all visible lines
1058 */
1059 static void linechart_draw_plot(cairo_t *cr, double x, double y, double r, GtkChart *chart)
1060 {
1061 cairo_set_line_width(cr, r / 2);
1062
1063 cairo_user_set_rgbcol(cr, &global_colors[THBASE]);
1064 cairo_arc(cr, x, y, r, 0, 2*M_PI);
1065 cairo_stroke_preserve(cr);
1066
1067 //cairo_set_source_rgb(cr, COLTOCAIRO(0), COLTOCAIRO(119), COLTOCAIRO(204));
1068 cairo_user_set_rgbcol(cr, &chart->colors[chart->cs_blue]);
1069 cairo_fill(cr);
1070 }
1071
1072
1073 static void linechart_draw_lines(GtkWidget *widget, gpointer user_data)
1074 {
1075 GtkChart *chart = GTK_CHART(user_data);
1076 cairo_t *cr;
1077 double x, y, x2, y2, firstx, lastx, linew;
1078 gint first, i;
1079
1080
1081 DB( g_print("\n(gtkline) line draw lines\n") );
1082
1083 x = chart->graph_x;
1084 y = chart->oy;
1085 first = (gint)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
1086
1087 cr = gdk_cairo_create (gtk_widget_get_window(widget));
1088 //cr = cairo_create (chart->surface);
1089
1090 /* clip */
1091 //cairo_rectangle(cr, CHART_MARGIN, 0, chart->w, chart->h + CHART_MARGIN);
1092 //cairo_clip(cr);
1093
1094
1095 #if HELPDRAW == 1
1096 x2 = x + 0.5;
1097 cairo_set_line_width(cr, 1.0);
1098 cairo_set_source_rgb(cr, 1.0, 0.0, 1.0); // violet
1099 for(i=first; i<=(first+chart->visible) ;i++)
1100 {
1101 cairo_move_to(cr, x2, chart->graph_y);
1102 cairo_line_to(cr, x2, chart->graph_x + chart->graph_height);
1103 cairo_stroke(cr);
1104 x2 += chart->blkw;
1105 }
1106 #endif
1107
1108 //todo: it should be possible to draw line & plot together using surface and composite fill, or sub path ??
1109 lastx = x;
1110 firstx = x;
1111 linew = 4.0;
1112 if(chart->barw < 24)
1113 {
1114 linew = 1 + (chart->barw / 8.0);
1115 }
1116
1117 cairo_set_line_join(cr, CAIRO_LINE_JOIN_BEVEL);
1118 cairo_set_line_width(cr, linew);
1119
1120 for(i=first; i<(first+chart->visible) ;i++)
1121 {
1122 ChartItem *item = &g_array_index(chart->items, ChartItem, i);
1123
1124 x2 = x + (chart->blkw)/2;
1125 y2 = chart->oy - (item->serie1 / chart->range) * chart->graph_height;
1126 if( i == first)
1127 {
1128 firstx = x2;
1129 cairo_move_to(cr, x2, y2);
1130 }
1131 else
1132 {
1133 if( i < (chart->nb_items) )
1134 {
1135 cairo_line_to(cr, x2, y2);
1136 lastx = x2;
1137 }
1138 else
1139 lastx = x2 - chart->barw;
1140 }
1141
1142 x += chart->blkw;
1143 }
1144
1145 cairo_user_set_rgbcol(cr, &chart->colors[chart->cs_blue]);
1146 cairo_stroke_preserve(cr);
1147
1148 cairo_line_to(cr, lastx, y);
1149 cairo_line_to(cr, firstx, y);
1150 cairo_close_path(cr);
1151
1152 cairo_user_set_rgbacol(cr, &chart->colors[chart->cs_blue], 0.15);
1153 cairo_fill(cr);
1154
1155 x = chart->graph_x;
1156 y = chart->oy;
1157 first = (gint)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
1158
1159 // draw plots
1160 for(i=first; i<(first+chart->visible) ;i++)
1161 {
1162 ChartItem *item = &g_array_index(chart->items, ChartItem, i);
1163
1164 x2 = x + (chart->blkw)/2;
1165 y2 = chart->oy - (item->serie1 / chart->range) * chart->graph_height;
1166 linechart_draw_plot(cr, x2, y2, i == chart->active ? linew+1 : linew, chart);
1167 x += chart->blkw;
1168 }
1169
1170 /* overdrawn */
1171 if( chart->show_over )
1172 {
1173 if(chart->minimum != 0 && chart->minimum >= chart->min)
1174 {
1175 y = chart->oy - (chart->minimum/chart->range) * chart->graph_height;
1176 cairo_set_source_rgba(cr, COLTOCAIRO(255), COLTOCAIRO(0), COLTOCAIRO(0), .15);
1177
1178 DB( g_print(" draw over: %f, %f, %f, %f\n", chart->l, y, chart->w, chart->b - y) );
1179
1180 cairo_rectangle(cr, chart->graph_x, y, chart->graph_width, chart->b - y);
1181 cairo_fill(cr);
1182 }
1183 }
1184
1185 cairo_destroy(cr);
1186
1187
1188 }
1189
1190
1191
1192
1193 /*
1194 ** get the point under the mouse pointer
1195 */
1196 static gint linechart_get_active(GtkWidget *widget, gint x, gint y, gpointer user_data)
1197 {
1198 GtkChart *chart = GTK_CHART(user_data);
1199 gint retval;
1200 gint first, index, px;
1201
1202 retval = -1;
1203
1204 if( x <= chart->r && x >= chart->l )
1205 {
1206 px = (x - chart->graph_x);
1207 //py = (y - chart->oy);
1208 first = gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
1209 index = first + (px / (chart->blkw));
1210
1211 if(index < chart->nb_items)
1212 retval = index;
1213 }
1214
1215 return(retval);
1216 }
1217
1218
1219
1220 /* pie section */
1221
1222 static void piechart_calculation(GtkChart *chart)
1223 {
1224 GtkWidget *drawarea = chart->drawarea;
1225 GtkAllocation allocation;
1226 gint w, h;
1227
1228 w = chart->graph_width;
1229 h = chart->graph_height;
1230
1231 chart->rayon = MIN(w, h);
1232
1233 gtk_widget_get_allocation(drawarea, &allocation);
1234
1235 chart->ox = chart->graph_x + (chart->graph_width / 2);
1236 chart->oy = chart->graph_y + (chart->rayon / 2);
1237
1238 }
1239
1240
1241 static void piechart_draw_slices(GtkWidget *widget, gpointer user_data)
1242 {
1243 GtkChart *chart = GTK_CHART(user_data);
1244 cairo_t *cr;
1245
1246 if(chart->nb_items <= 0)
1247 return;
1248
1249
1250 //cairo drawing
1251
1252 double a1 = 0 * (M_PI / 180);
1253 double a2 = 360 * (M_PI / 180);
1254
1255 //g_print("angle1=%.2f angle2=%.2f\n", a1, a2);
1256
1257 double cx = chart->ox;
1258 double cy = chart->oy;
1259 double radius = chart->rayon/2;
1260 gint i;
1261 double dx, dy;
1262 double sum = 0.0;
1263 gint color;
1264
1265 cr = gdk_cairo_create (gtk_widget_get_window(widget));
1266 //cr = cairo_create (chart->surface);
1267
1268 for(i=0; i< chart->nb_items ;i++)
1269 {
1270 ChartItem *item = &g_array_index(chart->items, ChartItem, i);
1271
1272 a1 = ((360 * (sum / chart->total)) - 90) * (M_PI / 180);
1273 sum += ABS(item->serie1);
1274 a2 = ((360 * (sum / chart->total)) - 90) * (M_PI / 180);
1275 if(i < chart->nb_items-1) a2 += 0.0175;
1276
1277 dx = cx;
1278 dy = cy;
1279
1280 cairo_move_to(cr, dx, dy);
1281 cairo_arc(cr, dx, dy, radius, a1, a2);
1282
1283 #if PIE_LINE_SLICE == 1
1284 cairo_set_line_width(cr, 1.0);
1285 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1286 cairo_line_to(cr, cx, cy);
1287 cairo_stroke_preserve(cr);
1288 #endif
1289
1290 DB( g_print("%d: %.2f%% %.2f %.2f\n", i, sum / chart->total, a1, a2) );
1291
1292 //g_print("color : %f %f %f\n", COLTOCAIRO(colors[i].r), COLTOCAIRO(colors[i].g), COLTOCAIRO(colors[i].b));
1293
1294 color = i % chart->nb_cols;
1295 cairo_user_set_rgbcol_over(cr, &chart->colors[color], i == chart->active);
1296 cairo_fill(cr);
1297 }
1298
1299 #if SOFT_LIGHT == 1
1300 cairo_pattern_t *pat1;
1301
1302 a1 = 0;
1303 a2 = 2 * M_PI;
1304
1305 pat1 = cairo_pattern_create_radial( cx, cy, 0, cx, cy, radius);
1306 cairo_pattern_add_color_stop_rgba(pat1, 0.0, 1.0, 1.0, 1.0, .50);
1307 cairo_pattern_add_color_stop_rgba(pat1, 0.9, 1.0, 1.0, 1.0, 0.1);
1308
1309 cairo_arc(cr, cx, cy, radius, a1, a2);
1310 cairo_set_source(cr, pat1);
1311 cairo_fill(cr);
1312 #endif
1313
1314 #if GRADIENT == 1
1315 cairo_pattern_t *pat1;
1316
1317 a1 = 0;
1318 a2 = 2 * M_PI;
1319 double gradius = radius - 8;
1320
1321 // start point, end point
1322 pat1 = cairo_pattern_create_linear(cx, cy-gradius, cx, cy+gradius);
1323
1324 cairo_pattern_add_color_stop_rgba(pat1, 0.0, 1.0, 1.0, 1.0, .15);
1325 cairo_pattern_add_color_stop_rgba(pat1, 1.0, 1.0, 1.0, 1.0, 0.0);
1326
1327 //debug
1328 //cairo_rectangle(cr, cx-radius, cy-radius, radius*2, radius*2);
1329
1330 cairo_arc(cr, cx, cy, gradius, a1, a2);
1331 cairo_set_source(cr, pat1);
1332 cairo_fill(cr);
1333
1334 #endif
1335
1336 #if CHART_PIE_DONUT == 1
1337 a1 = 0;
1338 a2 = 2 * M_PI;
1339 radius = (gint)((chart->rayon/3) * (1 / PHI));
1340
1341 cairo_arc(cr, cx, cy, radius, a1, a2);
1342 cairo_user_set_rgbcol(cr, &global_colors[THBASE]);
1343 cairo_fill(cr);
1344
1345
1346
1347 #endif
1348
1349
1350
1351 cairo_destroy(cr);
1352
1353
1354 }
1355
1356
1357 static gint piechart_get_active(GtkWidget *widget, gint x, gint y, gpointer user_data)
1358 {
1359 GtkChart *chart = GTK_CHART(user_data);
1360 gint retval, px, py;
1361 gint index;
1362 double h;
1363
1364 px = x - chart->ox;
1365 py = y - chart->oy;
1366 h = sqrt( pow(px,2) + pow(py,2) );
1367 retval = -1;
1368
1369 if(h < (chart->rayon/2))
1370 {
1371 double angle, b;
1372
1373 b = (acos(px / h) * 180) / M_PI;
1374 angle = py > 0 ? b : 360 - b;
1375 angle += 90;
1376 if(angle > 360) angle -= 360;
1377 //angle = 360 - angle;
1378
1379 //todo optimize
1380 gdouble cumul = 0;
1381 for(index=0; index< chart->nb_items ;index++)
1382 {
1383 ChartItem *item = &g_array_index(chart->items, ChartItem, index);
1384
1385 cumul += ABS(item->serie1/chart->total)*360;
1386 if( cumul > angle )
1387 {
1388 retval = index;
1389 break;
1390 }
1391 }
1392
1393 //DB( g_print(" inside: x=%d, y=%d\n", x, y) );
1394 //DB( g_print(" inside: b=%f angle=%f, slice is %d\n", b, angle, index) );
1395 }
1396 return(retval);
1397 }
1398
1399
1400 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1401 static gboolean drawarea_full_redraw(GtkWidget *widget, gpointer user_data)
1402 {
1403 GtkChart *chart = GTK_CHART(user_data);
1404 cairo_text_extents_t te;
1405 cairo_font_extents_t fe;
1406 cairo_t *cr;
1407
1408 DB( g_print("\n[gtkchart] drawarea full redraw\n") );
1409
1410
1411
1412 cr = cairo_create (chart->surface);
1413
1414 #if MYDEBUG == 1
1415 cairo_font_face_t *ff;
1416 cairo_scaled_font_t *sf;
1417
1418 ff = cairo_get_font_face(cr);
1419 sf = cairo_get_scaled_font(cr);
1420
1421 g_print("cairo ff = '%s'\n", cairo_toy_font_face_get_family(ff) );
1422
1423 ff = cairo_scaled_font_get_font_face(sf);
1424 g_print("cairo sf = '%s'\n", cairo_toy_font_face_get_family(ff) );
1425
1426
1427 //cairo_set_font_face(cr, ff);
1428
1429
1430
1431 #endif
1432
1433
1434
1435
1436 /* fillin the back in white */
1437 //cairo_user_set_rgbcol(cr, &global_colors[WHITE]);
1438 cairo_user_set_rgbcol(cr, &global_colors[THBASE]);
1439
1440 cairo_paint(cr);
1441
1442 /* taken from scrolled window
1443 gtk_paint_shadow (widget->style, widget->window,
1444 GTK_STATE_NORMAL, scrolled_window->shadow_type,
1445 area, widget, "scrolled_window",
1446 widget->allocation.x + relative_allocation.x,
1447 widget->allocation.y + relative_allocation.y,
1448 relative_allocation.width,
1449 relative_allocation.height);
1450 */
1451
1452
1453 /*debug help draws */
1454 #if HELPDRAW == 1
1455 cairo_set_line_width(cr, 1.0);
1456 cairo_set_source_rgb(cr, 0.0, 1.0, 0.0); //green
1457 cairo_rectangle(cr, chart->l+0.5, chart->t+0.5, chart->w, chart->h);
1458 cairo_stroke(cr);
1459
1460 cairo_set_source_rgb(cr, 1.0, 0.5, 0.0); //orange
1461 cairo_rectangle(cr, chart->graph_x+0.5, chart->graph_y+0.5, chart->graph_width, chart->graph_height);
1462 cairo_stroke(cr);
1463 #endif
1464
1465 // draw title
1466 cairo_set_font_size(cr, CHART_FONT_SIZE_TITLE);
1467 cairo_font_extents(cr, &fe);
1468 cairo_text_extents(cr, chart->title, &te);
1469
1470 #if HELPDRAW == 1
1471 double dashlength;
1472 cairo_set_source_rgb(cr, 0.0, 0.0, 1.0); //blue
1473 dashlength = 3;
1474 cairo_set_dash (cr, &dashlength, 1, 0);
1475 cairo_move_to(cr, chart->l, chart->t);
1476 cairo_rectangle(cr, chart->l + te.x_bearing, chart->t, te.width, fe.height);
1477 cairo_stroke(cr);
1478 #endif
1479
1480 //center title
1481 //cairo_move_to(cr, chart->l + (chart->w/2) - ((te.width - te.x_bearing) / 2), chart->t - te.y_bearing);
1482 cairo_move_to(cr, chart->l, chart->t - te.y_bearing);
1483 //cairo_user_set_rgbcol(cr, &global_colors[BLACK]);
1484 cairo_user_set_rgbcol(cr, &global_colors[THTEXT]);
1485 cairo_show_text(cr, chart->title);
1486
1487 cairo_destroy(cr);
1488
1489 if(chart->nb_items == 0)
1490 return FALSE;
1491
1492 switch(chart->type)
1493 {
1494 case CHART_TYPE_COL:
1495 colchart_draw_scale(widget, chart);
1496 //colchart_draw_bars(widget, chart);
1497 colchart_draw_scale_text(widget, chart);
1498 break;
1499 case CHART_TYPE_LINE:
1500 colchart_draw_scale(widget, chart);
1501 //linechart_draw_lines(widget, chart);
1502 colchart_draw_scale_text(widget, chart);
1503 break;
1504 case CHART_TYPE_PIE:
1505 //piechart_draw_slices(widget, chart);
1506 break;
1507 }
1508
1509 return TRUE;
1510 }
1511
1512
1513 static gboolean
1514 drawarea_configure_event (GtkWidget *widget,
1515 GdkEventConfigure *event,
1516 gpointer user_data)
1517 {
1518 GtkChart *chart = GTK_CHART(user_data);
1519 GtkAllocation allocation;
1520 GtkStyle *style;
1521 GdkColor *color;
1522
1523 DB( g_print("\n[gtkchart] drawarea configure \n") );
1524
1525 DB( g_print("w=%d h=%d\n", allocation.width, allocation.height) );
1526
1527 gtk_widget_get_allocation (widget, &allocation);
1528
1529 chart_recompute(chart);
1530
1531 if (chart->surface)
1532 cairo_surface_destroy (chart->surface);
1533
1534 chart->surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
1535 CAIRO_CONTENT_COLOR,
1536 allocation.width,
1537 allocation.height);
1538
1539
1540 // get theme color
1541 style = gtk_widget_get_style (widget);
1542 //style = gtk_widget_get_style (chart->treeview);
1543 //style = gtk_widget_get_default_style();
1544
1545 //get text color
1546 color = &style->text[GTK_STATE_NORMAL];
1547 struct rgbcol *tcol = &global_colors[THTEXT];
1548 tcol->r = color->red;
1549 tcol->g = color->green;
1550 tcol->b = color->blue;
1551 DB( g_print(" - theme text col: %x %x %x\n", tcol->r, tcol->g, tcol->b) );
1552
1553 // get base color
1554 color = &style->base[GTK_STATE_NORMAL];
1555 tcol = &global_colors[THBASE];
1556 tcol->r = color->red;
1557 tcol->g = color->green;
1558 tcol->b = color->blue;
1559 DB( g_print(" - theme base col: %x %x %x\n", tcol->r, tcol->g, tcol->b) );
1560
1561
1562 drawarea_full_redraw(widget, user_data);
1563
1564
1565 /* We've handled the configure event, no need for further processing. */
1566 return TRUE;
1567 }
1568
1569
1570 static void drawarea_sizeallocate_callback(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data)
1571 {
1572 GtkChart *chart = GTK_CHART(user_data);
1573
1574 DB( g_print("\n[gtkchart] drawarea sizeallocate\n") );
1575 DB( g_print("w=%d h=%d\n", allocation->width, allocation->height) );
1576
1577 //g_print("\n[gtkchart] drawarea sizeallocate\n") ;
1578 //g_print("w=%d h=%d\n", allocation->width, allocation->height) ;
1579
1580
1581 if( gtk_widget_get_realized(widget))
1582 {
1583 chart_recompute(chart);
1584 }
1585
1586 }
1587
1588
1589 static void drawarea_realize_callback(GtkWidget *widget, gpointer user_data)
1590 {
1591 //GtkChart *chart = GTK_CHART(user_data);
1592
1593 DB( g_print("\n[gtkchart] drawarea realize\n") );
1594
1595 //chart_recompute(chart);
1596
1597 }
1598
1599
1600
1601 static gboolean drawarea_draw_callback( GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
1602 {
1603 GtkChart *chart = GTK_CHART(user_data);
1604 cairo_t *cr;
1605
1606 DB( g_print("\n[gtkchart] drawarea expose\n") );
1607
1608 DB( g_print(" type=%d regionempty=%d\n", event->type, cairo_region_is_empty(event->region)) );
1609
1610
1611
1612 cr = gdk_cairo_create (gtk_widget_get_window (widget));
1613
1614 cairo_set_source_surface (cr, chart->surface, 0, 0);
1615 //gdk_cairo_rectangle (cr, &event->area);
1616 cairo_paint (cr);
1617
1618 /* here draw only line, bar, slices */
1619 if(chart->nb_items == 0)
1620 return FALSE;
1621
1622 switch(chart->type)
1623 {
1624 case CHART_TYPE_COL:
1625 colchart_draw_bars(widget, chart);
1626 break;
1627 case CHART_TYPE_LINE:
1628 linechart_draw_lines(widget, chart);
1629 break;
1630 case CHART_TYPE_PIE:
1631 piechart_draw_slices(widget, chart);
1632 break;
1633 }
1634
1635
1636
1637 cairo_destroy (cr);
1638
1639 return FALSE;
1640 }
1641
1642
1643 static gboolean drawarea_querytooltip_callback(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, gpointer user_data)
1644 {
1645 GtkChart *chart = GTK_CHART(user_data);
1646 gchar *strval, *strval2, *buffer;
1647 gboolean retval = FALSE;
1648
1649 DB( g_print("\n[gtkchart] drawarea querytooltip\n") );
1650
1651 DB( g_print(" x=%d, y=%d kbm=%d\n", x, y, keyboard_mode) );
1652 if(chart->lastactive != chart->active)
1653 {
1654 goto end;
1655 }
1656
1657 if(chart->active >= 0)
1658 {
1659 ChartItem *item = &g_array_index(chart->items, ChartItem, chart->active);
1660
1661 strval = chart_print_double(chart, chart->buffer1, item->serie1);
1662 if( !chart->dual )
1663 {
1664
1665 if( chart->type == CHART_TYPE_PIE )
1666 buffer = g_markup_printf_escaped("%s\n%s\n%.2f%%", item->label, strval, item->rate);
1667 else
1668 buffer = g_markup_printf_escaped("%s\n%s", item->label, strval);
1669
1670 }
1671 else
1672 {
1673 strval2 = chart_print_double(chart, chart->buffer2, item->serie2);
1674 buffer = g_markup_printf_escaped("%s\n+%s\n%s", item->label, strval2, strval);
1675 }
1676
1677 gtk_tooltip_set_text(tooltip, buffer);
1678 //gtk_label_set_markup(GTK_LABEL(chart->ttlabel), buffer);
1679 g_free(buffer);
1680 retval = TRUE;
1681 }
1682 end:
1683 chart->lastactive = chart->active;
1684
1685 return retval;
1686 }
1687
1688
1689 static gboolean drawarea_motionnotifyevent_callback(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
1690 {
1691 GtkChart *chart = GTK_CHART(user_data);
1692 gboolean retval = TRUE;
1693 gint x, y;
1694
1695 if(chart->nb_items == 0)
1696 return FALSE;
1697
1698 DB( g_print("\n[gtkchart] drawarea motion\n") );
1699 x = event->x;
1700 y = event->y;
1701
1702 //todo see this
1703 if(event->is_hint)
1704 {
1705 DB( g_print(" is hint\n") );
1706
1707 //gdk_window_get_device_position(event->window, event->device, &x, &y, NULL);
1708 gdk_window_get_pointer(event->window, &x, &y, NULL);
1709 //return FALSE;
1710 }
1711
1712 switch(chart->type)
1713 {
1714 case CHART_TYPE_COL:
1715 chart->active = colchart_get_active(widget, x, y, chart);
1716 break;
1717 case CHART_TYPE_LINE:
1718 chart->active = linechart_get_active(widget, x, y, chart);
1719 break;
1720 case CHART_TYPE_PIE:
1721 chart->active = piechart_get_active(widget, x, y, chart);
1722 break;
1723 }
1724
1725 // rollover redraw ?
1726 DB( g_print(" active: last=%d, curr=%d\n", chart->lastactive, chart->active) );
1727
1728 if(chart->lastactive != chart->active)
1729 {
1730 DB( g_print(" rollover redraw :: active=%d\n", chart->active) );
1731 //chart->drawmode = CHART_DRAW_OVERCHANGE;
1732 //gtk_widget_queue_draw_area(widget, chart->graph_x, chart->graph_y, chart->graph_width, chart->graph_height);
1733
1734 gtk_widget_queue_draw( widget );
1735 //retval = FALSE;
1736 }
1737
1738 DB( g_print(" x=%d, y=%d, time=%d\n", x, y, event->time) );
1739 DB( g_print(" trigger tooltip query\n") );
1740
1741 gtk_tooltip_trigger_tooltip_query(gtk_widget_get_display(chart->drawarea));
1742
1743 return retval;
1744 }
1745
1746
1747 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1748 /* public functions */
1749 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1750
1751 void gtk_chart_queue_redraw(GtkChart *chart)
1752 {
1753 chart_recompute(chart);
1754 drawarea_full_redraw(chart->drawarea, chart);
1755 gtk_widget_queue_draw( chart->drawarea );
1756 }
1757
1758
1759 /*
1760 ** change the model and/or column
1761 */
1762 void gtk_chart_set_datas(GtkChart *chart, GtkTreeModel *model, guint column, gchar *title)
1763 {
1764 g_return_if_fail (GTK_IS_CHART (chart));
1765
1766 if( GTK_IS_TREE_MODEL(model) )
1767 {
1768 chart_setup_with_model(chart, model, column, column);
1769 if(title != NULL)
1770 chart->title = g_strdup(title);
1771
1772
1773
1774 gtk_chart_queue_redraw(chart);
1775 }
1776 else
1777 {
1778 chart_clear(chart, TRUE);
1779 }
1780 }
1781
1782 /*
1783 ** change the model and/or column
1784 */
1785 void gtk_chart_set_dualdatas(GtkChart *chart, GtkTreeModel *model, guint column1, guint column2, gchar *title)
1786 {
1787 g_return_if_fail (GTK_IS_CHART (chart));
1788
1789 if( GTK_IS_TREE_MODEL(model) )
1790 {
1791 chart_setup_with_model(chart, model, column1, column2 );
1792 if(title != NULL)
1793 chart->title = g_strdup(title);
1794
1795
1796
1797 gtk_chart_queue_redraw(chart);
1798 }
1799 else
1800 {
1801 chart_clear(chart, TRUE);
1802 }
1803 }
1804
1805
1806 /*
1807 ** change the type dynamically
1808 */
1809 void gtk_chart_set_type(GtkChart * chart, gint type)
1810 {
1811 g_return_if_fail (GTK_IS_CHART (chart));
1812 //g_return_if_fail (type < CHART_TYPE_MAX);
1813
1814 DB( g_print("\n[gtkchart] set type %d\n", type) );
1815
1816 chart->type = type;
1817 chart->dual = FALSE;
1818
1819 gtk_chart_queue_redraw(chart);
1820 }
1821
1822 /* = = = = = = = = = = parameters = = = = = = = = = = */
1823
1824 void gtk_chart_set_color_scheme(GtkChart * chart, gint colorscheme)
1825 {
1826 chart->cs_blue = 0;
1827
1828 switch(colorscheme)
1829 {
1830 default:
1831 case CHART_COLMAP_HOMEBANK:
1832 chart->colors = homebank_colors;
1833 chart->nb_cols = homebank_nbcolors;
1834 break;
1835 case CHART_COLMAP_MSMONEY:
1836 chart->colors = money_colors;
1837 chart->nb_cols = money_nbcolors;
1838 chart->cs_blue = 1;
1839 break;
1840 case CHART_COLMAP_SAP:
1841 chart->colors = sap_colors;
1842 chart->nb_cols = sap_nbcolors;
1843 break;
1844 case CHART_COLMAP_QUICKEN:
1845 chart->colors = quicken_colors;
1846 chart->nb_cols = quicken_nbcolors;
1847 chart->cs_blue = 3;
1848 break;
1849 case CHART_COLMAP_OFFICE2010:
1850 chart->colors = office2010_colors;
1851 chart->nb_cols = office2010_nbcolors;
1852 break;
1853 case CHART_COLMAP_OFFICE2013:
1854 chart->colors = office2013_colors;
1855 chart->nb_cols = office2013_nbcolors;
1856 break;
1857 case CHART_COLMAP_ANALYTICS:
1858 chart->colors = analytics_colors;
1859 chart->nb_cols = analytics_nbcolors;
1860 break;
1861 }
1862 }
1863
1864
1865
1866 /*
1867 ** set the minor parameters
1868 */
1869 void gtk_chart_set_minor_prefs(GtkChart * chart, gdouble rate, gchar *symbol)
1870 {
1871 g_return_if_fail (GTK_IS_CHART (chart));
1872
1873 chart->minor_rate = rate;
1874 chart->minor_symbol = symbol;
1875 }
1876
1877
1878 void gtk_chart_set_absolute(GtkChart * chart, gboolean abs)
1879 {
1880 g_return_if_fail (GTK_IS_CHART (chart));
1881
1882 chart->abs = abs;
1883 }
1884
1885 /*
1886 void gtk_chart_set_currency(GtkChart * chart, guint32 kcur)
1887 {
1888 g_return_if_fail (GTK_IS_CHART (chart));
1889
1890 chart->kcur = kcur;
1891 }
1892 */
1893
1894 /*
1895 ** set the overdrawn minimum
1896 */
1897 void gtk_chart_set_overdrawn(GtkChart * chart, gdouble minimum)
1898 {
1899 g_return_if_fail (GTK_IS_CHART (chart));
1900
1901 chart->minimum = minimum;
1902
1903 //if(chart->type == CHART_TYPE_LINE)
1904 // chart_recompute(chart);
1905 }
1906
1907 /*
1908 ** set the every_xval
1909 */
1910 void gtk_chart_set_every_xval(GtkChart * chart, gint gap)
1911 {
1912 g_return_if_fail (GTK_IS_CHART (chart));
1913
1914 chart->every_xval = gap;
1915
1916 //if(chart->type != CHART_TYPE_PIE)
1917 // chart_recompute(chart);
1918 }
1919
1920
1921 /*
1922 ** set the barw
1923 */
1924 void gtk_chart_set_barw(GtkChart * chart, gdouble barw)
1925 {
1926 g_return_if_fail (GTK_IS_CHART (chart));
1927
1928 chart->barw = barw;
1929
1930 if(chart->type != CHART_TYPE_PIE)
1931 gtk_chart_queue_redraw(chart);
1932 }
1933
1934
1935 /* = = = = = = = = = = visibility = = = = = = = = = = */
1936
1937 /*
1938 ** change the legend visibility
1939 */
1940 void gtk_chart_show_legend(GtkChart * chart, gboolean visible, gboolean showextracol)
1941 {
1942 GtkTreeViewColumn *column;
1943
1944 g_return_if_fail (GTK_IS_CHART (chart));
1945
1946 if(visible == TRUE)
1947 gtk_widget_show(chart->scrollwin);
1948 else
1949 gtk_widget_hide(chart->scrollwin);
1950
1951 /* manage column visibility */
1952 column = gtk_tree_view_get_column (GTK_TREE_VIEW(chart->treeview), 1); //amount
1953 gtk_tree_view_column_set_visible (column, showextracol);
1954
1955 column = gtk_tree_view_get_column (GTK_TREE_VIEW(chart->treeview), 2); //percent
1956 gtk_tree_view_column_set_visible (column, showextracol);
1957
1958 }
1959
1960 /*
1961 ** change the x-value visibility
1962 */
1963 void gtk_chart_show_xval(GtkChart * chart, gboolean visible)
1964 {
1965 g_return_if_fail (GTK_IS_CHART (chart));
1966
1967 chart->show_xval = visible;
1968
1969 //if(chart->type != CHART_TYPE_PIE)
1970 // chart_recompute(chart);
1971 }
1972
1973 /*
1974 ** chnage the overdrawn visibility
1975 */
1976 void gtk_chart_show_overdrawn(GtkChart * chart, gboolean visible)
1977 {
1978 g_return_if_fail (GTK_IS_CHART (chart));
1979
1980 chart->show_over = visible;
1981
1982 //if(chart->type == CHART_TYPE_LINE)
1983 // chart_recompute(chart);
1984 }
1985
1986
1987 /*
1988 ** change the minor visibility
1989 */
1990 void gtk_chart_show_minor(GtkChart * chart, gboolean minor)
1991 {
1992 g_return_if_fail (GTK_IS_CHART (chart));
1993
1994 chart->minor = minor;
1995
1996 if(chart->type != CHART_TYPE_PIE)
1997 gtk_chart_queue_redraw(chart);
1998
1999 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(chart->treeview));
2000 }
2001
2002
2003
2004
2005 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2006
2007 /* legend list */
2008
2009 static GdkPixbuf *
2010 //create_color_pixbuf (const char *color)
2011 create_color_pixbuf (GdkColor *col)
2012 {
2013 GdkPixbuf *pixbuf;
2014 //GdkColor col = color;
2015
2016 int x;
2017 int num;
2018 guchar *p;
2019
2020 /*
2021 if (!gdk_color_parse (color, &col))
2022 return NULL;
2023 */
2024
2025 #define squaredim 12
2026
2027 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
2028 FALSE, 8, //bits
2029 squaredim, squaredim); //width,height
2030
2031 //rowstride = gdk_pixbuf_get_rowstride (pixbuf);
2032 p = gdk_pixbuf_get_pixels (pixbuf);
2033
2034 num = gdk_pixbuf_get_width (pixbuf) *
2035 gdk_pixbuf_get_height (pixbuf);
2036
2037 for (x = 0; x < num; x++) {
2038
2039 p[0] = col->red;
2040 p[1] = col->green;
2041 p[2] = col->blue;
2042
2043 /*
2044 p[0] = col->red / 65535 * 255;
2045 p[1] = col->green / 65535 * 255;
2046 p[2] = col->blue / 65535 * 255;
2047 */
2048 p += 3;
2049 }
2050
2051 return pixbuf;
2052 }
2053
2054 static void legend_list_cell_data_function(GtkTreeViewColumn *col,
2055 GtkCellRenderer *renderer,
2056 GtkTreeModel *model,
2057 GtkTreeIter *iter,
2058 gpointer user_data)
2059 {
2060 GdkPixbuf *pixbuf;
2061 gchar *title;
2062
2063 gtk_tree_model_get(model, iter,
2064 LST_LEGEND_COLOR, &pixbuf,
2065 LST_LEGEND_TITLE, &title,
2066 -1);
2067
2068 switch(GPOINTER_TO_INT(user_data))
2069 {
2070 case LST_LEGEND_COLOR:
2071 g_object_set(renderer, "pixbuf", pixbuf, NULL);
2072 break;
2073 case LST_LEGEND_TITLE:
2074 g_object_set(renderer, "text", title, NULL);
2075 break;
2076 }
2077
2078 }
2079
2080 static void
2081 legend_list_float_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
2082 {
2083 GtkChart *chart = user_data;
2084 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
2085 gdouble amount;
2086
2087 gtk_tree_model_get(model, iter,
2088 LST_LEGEND_AMOUNT, &amount,
2089 -1);
2090
2091 //hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, value, kcur);
2092 //todo: manage GLOBALS->minor eq
2093 mystrfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, amount, chart->minor);
2094
2095 g_object_set(renderer,
2096 "text", buf,
2097 NULL);
2098
2099 }
2100
2101 static void legend_list_rate_cell_data_function (GtkTreeViewColumn *col,
2102 GtkCellRenderer *renderer,
2103 GtkTreeModel *model,
2104 GtkTreeIter *iter,
2105 gpointer user_data)
2106 {
2107 gdouble rate;
2108 gchar buf[8];
2109
2110 gtk_tree_model_get(model, iter,
2111 LST_LEGEND_RATE, &rate,
2112 -1);
2113
2114 g_snprintf(buf, sizeof(buf), "%.02f %%", rate);
2115 g_object_set(renderer, "text", buf, NULL);
2116
2117 }
2118
2119
2120 static GtkWidget *legend_list_new(GtkChart *chart)
2121 {
2122 GtkListStore *store;
2123 GtkWidget *view;
2124 GtkCellRenderer *renderer;
2125 GtkTreeViewColumn *column;
2126
2127 store = gtk_list_store_new(NUM_LST_LEGEND,
2128 G_TYPE_POINTER,
2129 GDK_TYPE_PIXBUF,
2130 G_TYPE_STRING,
2131 G_TYPE_DOUBLE,
2132 G_TYPE_DOUBLE
2133 );
2134
2135 //treeview
2136 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
2137 g_object_unref(store);
2138
2139 #if MYDEBUG == 1
2140 /* GtkStyle *style;
2141 PangoFontDescription *font_desc;
2142
2143 g_print("legend_list_new font\n");
2144
2145 style = gtk_widget_get_style(GTK_WIDGET(view));
2146 font_desc = style->font_desc;
2147
2148 g_print("family: %s\n", pango_font_description_get_family(font_desc) );
2149 g_print("size: %d (%d)\n", pango_font_description_get_size (font_desc), pango_font_description_get_size (font_desc )/PANGO_SCALE );
2150 */
2151 #endif
2152
2153 // change the font size to a smaller one
2154 PangoFontDescription *font = pango_font_description_new();
2155 pango_font_description_set_size (font, 8 * PANGO_SCALE);
2156 gtk_widget_modify_font(GTK_WIDGET(view), font);
2157 pango_font_description_free( font );
2158
2159 // column 1
2160 column = gtk_tree_view_column_new();
2161 renderer = gtk_cell_renderer_pixbuf_new ();
2162 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2163 gtk_tree_view_column_set_cell_data_func(column, renderer, legend_list_cell_data_function, GINT_TO_POINTER(LST_LEGEND_COLOR), NULL);
2164
2165 renderer = gtk_cell_renderer_text_new ();
2166 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2167 gtk_tree_view_column_set_cell_data_func(column, renderer, legend_list_cell_data_function, GINT_TO_POINTER(LST_LEGEND_TITLE), NULL);
2168 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
2169
2170 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2171
2172 // column 2
2173 column = gtk_tree_view_column_new();
2174 //gtk_tree_view_column_set_title(column, name);
2175
2176 renderer = gtk_cell_renderer_text_new ();
2177 g_object_set(renderer, "xalign", 1.0, NULL);
2178 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2179 gtk_tree_view_column_set_cell_data_func(column, renderer, legend_list_float_cell_data_function, chart, NULL);
2180 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
2181 //gtk_tree_view_column_set_resizable(column, TRUE);
2182 //gtk_tree_view_column_set_alignment (column, 0.5);
2183 //gtk_tree_view_column_set_spacing( column, 16 );
2184
2185 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2186 gtk_tree_view_column_set_visible (column, FALSE);
2187
2188 // column 3
2189 column = gtk_tree_view_column_new();
2190 //gtk_tree_view_column_set_title(column, "%");
2191 renderer = gtk_cell_renderer_text_new ();
2192 g_object_set(renderer, "xalign", 1.0, NULL);
2193 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2194 //gtk_tree_view_column_add_attribute(column, renderer, "text", id);
2195 gtk_tree_view_column_set_cell_data_func(column, renderer, legend_list_rate_cell_data_function, GINT_TO_POINTER(3), NULL);
2196 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
2197 //gtk_tree_view_column_set_alignment (column, 0.5);
2198 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2199 gtk_tree_view_column_set_visible (column, FALSE);
2200
2201
2202 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), GTK_SELECTION_NONE);
2203 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
2204 //gtk_tree_view_set_reorderable (GTK_TREE_VIEW(view), TRUE);
2205
2206 /*
2207 GValue value = { 0, };
2208 g_value_init (&value, G_TYPE_INT);
2209 g_value_set_int (&value, 20);
2210 g_object_set_property(view, "vertical-separator", &value);
2211 g_value_unset (&value);
2212 */
2213
2214 return(view);
2215 }
2216
This page took 0.131072 seconds and 4 git commands to generate.