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