1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
4 * This file is part of HomeBank.
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.
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.
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/>.
27 #include "gtk-chart-colors.h"
28 #include "gtk-chart.h"
43 #define DBGDRAW_RECT 0
44 #define DBGDRAW_TEXT 0
45 #define DBGDRAW_ITEM 0
48 static void gtk_chart_class_intern_init (gpointer
);
49 static void gtk_chart_class_init (GtkChartClass
*klass
);
50 static void gtk_chart_init (GtkChart
*chart
);
51 static void gtk_chart_dispose (GObject
* object
);
52 static void gtk_chart_finalize (GObject
* object
);
54 static gboolean
drawarea_configure_event_callback(GtkWidget
*widget
, GdkEventConfigure
*event
, gpointer user_data
);
55 static void drawarea_realize_callback(GtkWidget
*widget
, gpointer user_data
);
56 static gboolean
drawarea_draw_callback(GtkWidget
*widget
, cairo_t
*wcr
, gpointer user_data
);
57 static gboolean
drawarea_motionnotifyevent_callback(GtkWidget
*widget
, GdkEventMotion
*event
, gpointer user_data
);
58 static gboolean
drawarea_querytooltip_callback(GtkWidget
*widget
, gint x
, gint y
, gboolean keyboard_mode
, GtkTooltip
*tooltip
, gpointer user_data
);
60 static gboolean
drawarea_full_redraw(GtkWidget
*widget
, gpointer user_data
);
62 static void chart_calculation(GtkChart
*chart
);
63 static void chart_clear(GtkChart
*chart
);
65 static void colchart_first_changed( GtkAdjustment
*adj
, gpointer user_data
);
66 static void colchart_compute_range(GtkChart
*chart
);
67 static void colchart_calculation(GtkChart
*chart
);
68 static void colchart_scrollbar_setvalues(GtkChart
*chart
);
70 static void piechart_calculation(GtkChart
*chart
);
75 static GtkBoxClass
*gtk_chart_parent_class
= NULL
;
77 static const double dashed3
[] = {3.0};
82 static GType chart_type
= 0;
86 static const GTypeInfo chart_info
=
88 sizeof (GtkChartClass
),
90 NULL
, /* base_finalize */
91 (GClassInitFunc
) gtk_chart_class_intern_init
,
92 NULL
, /* class_finalize */
93 NULL
, /* class_data */
96 (GInstanceInitFunc
) gtk_chart_init
,
100 chart_type
= g_type_register_static (GTK_TYPE_BOX
, "GtkChart",
108 gtk_chart_class_intern_init (gpointer klass
)
110 gtk_chart_parent_class
= g_type_class_peek_parent (klass
);
111 gtk_chart_class_init ((GtkChartClass
*) klass
);
115 gtk_chart_class_init (GtkChartClass
* class)
117 GObjectClass
*gobject_class
= G_OBJECT_CLASS (class);
118 //GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
120 DB( g_print("\n[gtkchart] class init\n") );
122 //gobject_class->get_property = gtk_chart_get_property;
123 //gobject_class->set_property = gtk_chart_set_property;
124 gobject_class
->dispose
= gtk_chart_dispose
;
125 gobject_class
->finalize
= gtk_chart_finalize
;
127 //widget_class->size_allocate = gtk_chart_size_allocate;
133 gtk_chart_init (GtkChart
* chart
)
135 GtkWidget
*widget
, *vbox
, *frame
;
137 DB( g_print("\n[gtkchart] init\n") );
140 chart
->surface
= NULL
;
148 chart
->usrbarw
= 0.0;
149 chart
->barw
= GTK_CHART_BARW
;
151 chart
->show_legend
= TRUE
;
152 chart
->show_legend_wide
= FALSE
;
153 chart
->show_mono
= FALSE
;
155 chart
->lastactive
= -1;
157 chart
->minor_rate
= 1.0;
158 chart
->timer_tag
= 0;
160 gtk_chart_set_color_scheme(chart
, CHART_COLMAP_HOMEBANK
);
162 widget
=GTK_WIDGET(chart
);
164 gtk_box_set_homogeneous(GTK_BOX(widget
), FALSE
);
166 vbox
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 0);
167 gtk_box_pack_start (GTK_BOX (widget
), vbox
, TRUE
, TRUE
, 0);
170 frame
= gtk_frame_new(NULL
);
171 gtk_frame_set_shadow_type (GTK_FRAME(frame
), GTK_SHADOW_ETCHED_IN
);
172 gtk_box_pack_start (GTK_BOX (vbox
), frame
, TRUE
, TRUE
, 0);
174 chart
->drawarea
= gtk_drawing_area_new();
175 //gtk_widget_set_double_buffered (GTK_WIDGET(widget), FALSE);
177 gtk_container_add( GTK_CONTAINER(frame
), chart
->drawarea
);
178 gtk_widget_set_size_request(chart
->drawarea
, 100, 100 );
180 gtk_widget_set_has_tooltip(chart
->drawarea
, TRUE
);
182 gtk_widget_show(chart
->drawarea
);
186 PangoFontDescription *font_desc;
188 g_print("draw_area font\n");
190 style = gtk_widget_get_style(GTK_WIDGET(chart->drawarea));
191 font_desc = style->font_desc;
193 g_print("family: %s\n", pango_font_description_get_family(font_desc) );
194 g_print("size: %d (%d)\n", pango_font_description_get_size (font_desc), pango_font_description_get_size (font_desc )/PANGO_SCALE );
199 chart
->adjustment
= GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 1.0, 1.0, 1.0, 1.0));
200 chart
->scrollbar
= gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL
, GTK_ADJUSTMENT (chart
->adjustment
));
201 gtk_box_pack_start (GTK_BOX (vbox
), chart
->scrollbar
, FALSE
, TRUE
, 0);
202 gtk_widget_show(chart
->scrollbar
);
204 g_signal_connect( G_OBJECT(chart
->drawarea
), "configure-event", G_CALLBACK (drawarea_configure_event_callback
), chart
);
205 g_signal_connect( G_OBJECT(chart
->drawarea
), "realize", G_CALLBACK(drawarea_realize_callback
), chart
) ;
206 g_signal_connect( G_OBJECT(chart
->drawarea
), "draw", G_CALLBACK(drawarea_draw_callback
), chart
) ;
209 gtk_widget_add_events(GTK_WIDGET(chart
->drawarea
),
211 //GDK_POINTER_MOTION_MASK |
212 GDK_POINTER_MOTION_HINT_MASK
213 //GDK_BUTTON_PRESS_MASK |
214 //GDK_BUTTON_RELEASE_MASK
217 g_signal_connect( G_OBJECT(chart
->drawarea
), "query-tooltip", G_CALLBACK(drawarea_querytooltip_callback
), chart
);
218 g_signal_connect( G_OBJECT(chart
->drawarea
), "motion-notify-event", G_CALLBACK(drawarea_motionnotifyevent_callback
), chart
);
220 g_signal_connect (G_OBJECT(chart
->adjustment
), "value-changed", G_CALLBACK (colchart_first_changed
), chart
);
222 //g_signal_connect( G_OBJECT(chart->drawarea), "map-event", G_CALLBACK(chart_map), chart ) ;
223 //g_signal_connect( G_OBJECT(chart->drawarea), "button-press-event", G_CALLBACK(chart_button_press), chart );
224 //g_signal_connect( G_OBJECT(chart->drawarea), "button-release-event", G_CALLBACK(chart_button_release), chart );
231 gtk_chart_new (gint type
)
235 DB( g_print("\n======================================================\n") );
236 DB( g_print("\n[gtkchart] new\n") );
238 chart
= g_object_new (GTK_TYPE_CHART
, NULL
);
241 return GTK_WIDGET(chart
);
246 gtk_chart_dispose (GObject
*gobject
)
248 //GtkChart *chart = GTK_CHART (object);
250 DB( g_print("\n[gtkchart] dispose\n") );
252 /* In dispose(), you are supposed to free all types referenced from this
253 * object which might themselves hold a reference to self. Generally,
254 * the most simple solution is to unref all members on which you own a
258 /* dispose() might be called multiple times, so we must guard against
259 * calling g_object_unref() on an invalid GObject by setting the member
260 * NULL; g_clear_object() does this for us, atomically.
262 //g_clear_object (&self->priv->an_object);
264 /* Always chain up to the parent class; there is no need to check if
265 * the parent class implements the dispose() virtual function: it is
266 * always guaranteed to do so
268 G_OBJECT_CLASS (gtk_chart_parent_class
)->dispose (gobject
);
273 gtk_chart_finalize (GObject
* object
)
275 GtkChart
*chart
= GTK_CHART (object
);
277 DB( g_print("\n[gtkchart] finalize\n") );
283 pango_font_description_free (chart
->pfd
);
289 cairo_surface_destroy (chart
->surface
);
290 chart
->surface
= NULL
;
293 G_OBJECT_CLASS (gtk_chart_parent_class
)->finalize (object
);
298 ** print a integer number
300 static gchar
*chart_print_int(GtkChart
*chart
, gint value
)
302 hb_strfmon_int(chart
->buffer1
, CHART_BUFFER_LENGTH
-1, (gdouble
)value
, chart
->kcur
, chart
->minor
);
303 return chart
->buffer1
;
308 ** print a rate number
310 static gchar
*chart_print_rate(GtkChart
*chart
, gdouble value
)
312 g_snprintf (chart
->buffer1
, CHART_BUFFER_LENGTH
-1, "%.2f%%", value
);
313 return chart
->buffer1
;
318 ** print a double number
320 static gchar
*chart_print_double(GtkChart
*chart
, gchar
*buffer
, gdouble value
)
322 hb_strfmon(buffer
, CHART_BUFFER_LENGTH
-1, value
, chart
->kcur
, chart
->minor
);
328 ** clear any allocated memory
330 static void chart_clear(GtkChart
*chart
)
334 DB( g_print("\n[gtkchart] clear\n") );
336 //free & clear any previous allocated datas
337 if(chart
->title
!= NULL
)
339 g_free(chart
->title
);
343 if(chart
->subtitle
!= NULL
)
345 g_free(chart
->subtitle
);
346 chart
->subtitle
= NULL
;
349 if(chart
->items
!= NULL
)
351 for(i
=0;i
<chart
->nb_items
;i
++)
353 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, i
);
355 g_free(item
->label
); //we free label as it comes from a model_get into setup_with_model
356 g_free(item
->legend
);
358 g_array_free(chart
->items
, TRUE
);
368 chart
->every_xval
= 7;
371 chart
->lastactive
= -1;
377 ** setup our chart with a model and column
379 static void chart_setup_with_model(GtkChart
*chart
, GtkTreeModel
*list_store
, guint column1
, guint column2
)
385 DB( g_print("\n[chart] setup with model\n") );
389 chart
->nb_items
= gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list_store
), NULL
);
391 chart
->items
= g_array_sized_new(FALSE
, FALSE
, sizeof(ChartItem
), chart
->nb_items
);
393 DB( g_print(" nb=%d, struct=%d\n", chart
->nb_items
, sizeof(ChartItem
)) );
395 chart
->dual
= (column1
== column2
) ? FALSE
: TRUE
;
397 /* Get the first iter in the list */
398 valid
= gtk_tree_model_get_iter_first (GTK_TREE_MODEL(list_store
), &iter
);
404 gdouble value1
, value2
;
407 /* column 0: pos (gint) */
408 /* column 1: key (gint) */
409 /* column 2: label (gchar) */
410 /* column x: values (double) */
412 gtk_tree_model_get (GTK_TREE_MODEL(list_store
), &iter
,
419 if(chart
->dual
|| chart
->abs
)
421 value1
= ABS(value1
);
422 value2
= ABS(value2
);
425 DB( g_print("%d: '%s' %.2f %2f\n", i
, label
, value1
, value2
) );
427 /* data1 value storage & min, max compute */
428 chart
->rawmin
= MIN(chart
->rawmin
, value1
);
429 chart
->rawmax
= MAX(chart
->rawmax
, value1
);
433 /* data2 value storage & min, max compute */
434 chart
->rawmin
= MIN(chart
->rawmin
, value2
);
435 chart
->rawmax
= MAX(chart
->rawmax
, value2
);
439 item
.serie1
= value1
;
440 item
.serie2
= value2
;
441 g_array_append_vals(chart
->items
, &item
, 1);
443 /* ensure rawmin rawmax not equal */
444 if(chart
->rawmin
== chart
->rawmax
)
450 /* pie chart total sum */
451 chart
->total
+= ABS(value1
);
454 //don't g_free(label); here done into chart_clear
456 valid
= gtk_tree_model_iter_next (list_store
, &iter
);
460 // compute rate for legend for bar/pie
461 for(i
=0;i
<chart
->nb_items
;i
++)
463 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, i
);
466 strval
= chart_print_double(chart
, chart
->buffer1
, item
->serie1
);
467 item
->rate
= ABS(item
->serie1
*100/chart
->total
);
468 item
->legend
= g_markup_printf_escaped("%s\n%s (%.f%%)", item
->label
, strval
, item
->rate
);
471 //g_print("total is %.2f\n", total);
472 //ensure the widget is mapped
473 //gtk_widget_map(chart);
478 static void chart_set_font_size(GtkChart
*chart
, PangoLayout
*layout
, gint font_size
)
482 //TODO: use PANGO_SCALE INSTEAD
484 //DB( g_print("\n[chart] set font size\n") );
488 case CHART_FONT_SIZE_TITLE
:
489 size
= chart
->pfd_size
+ 3;
491 case CHART_FONT_SIZE_SUBTITLE
:
492 size
= chart
->pfd_size
+ 1;
494 case CHART_FONT_SIZE_NORMAL
:
495 size
= chart
->pfd_size
- 1;
497 case CHART_FONT_SIZE_SMALL
:
498 size
= chart
->pfd_size
- 2;
502 //DB( g_print(" size=%d\n", size) );
504 pango_font_description_set_size(chart
->pfd
, size
* PANGO_SCALE
);
506 pango_layout_set_font_description (layout
, chart
->pfd
);
512 ** recompute according to type
514 static void chart_recompute(GtkChart
*chart
)
517 DB( g_print("\n[gtkchart] recompute\n") );
520 if( !gtk_widget_get_realized(chart
->drawarea
) || chart
->surface
== NULL
)
523 chart_calculation (chart
);
527 case CHART_TYPE_LINE
:
529 colchart_calculation(chart
);
530 gtk_adjustment_set_value(chart
->adjustment
, 0);
531 colchart_scrollbar_setvalues(chart
);
532 gtk_widget_show(chart
->scrollbar
);
535 piechart_calculation(chart
);
536 gtk_widget_hide(chart
->scrollbar
);
547 static float CalculateStepSize(float range
, float targetSteps
)
549 // calculate an initial guess at step size
550 float tempStep
= range
/targetSteps
;
552 // get the magnitude of the step size
553 float mag
= (float)floor(log10(tempStep
));
554 float magPow
= (float)pow(10, mag
);
556 // calculate most significant digit of the new step size
557 float magMsd
= (int)(tempStep
/magPow
+ 0.5);
559 // promote the MSD to either 1, 2, or 5
562 else if (magMsd
> 2.0)
564 else if (magMsd
>= 1.0)
567 return magMsd
*magPow
;
571 static void colchart_compute_range(GtkChart
*chart
)
573 double lobound
=chart
->rawmin
, hibound
=chart
->rawmax
;
575 DB( g_print("\n[column] compute range\n") );
577 /* comptute max ticks */
578 chart
->range
= chart
->rawmax
- chart
->rawmin
;
579 gint maxticks
= MIN(10,floor(chart
->graph
.height
/ (chart
->font_h
* 2)));
581 DB( g_print(" raw :: [%.2f - %.2f] range=%.2f\n", chart
->rawmin
, chart
->rawmax
, chart
->range
) );
582 DB( g_print(" raw :: maxticks=%d (%g / (%g*2))\n", maxticks
, chart
->graph
.height
, chart
->font_h
) );
585 chart
->unit
= CalculateStepSize((hibound
-lobound
), maxticks
);
586 chart
->min
= -chart
->unit
* ceil(-lobound
/chart
->unit
);
587 chart
->max
= chart
->unit
* ceil(hibound
/chart
->unit
);
588 chart
->range
= chart
->max
- chart
->min
;
589 chart
->div
= chart
->range
/ chart
->unit
;
591 DB( g_print(" end :: interval=%.2f, ticks=%d\n", chart
->unit
, chart
->div
) );
592 DB( g_print(" end :: [%.2f - %.2f], range=%.2f\n", chart
->min
, chart
->max
, chart
->range
) );
597 static void chart_calculation(GtkChart
*chart
)
599 GtkWidget
*drawarea
= chart
->drawarea
;
600 GdkWindow
*gdkwindow
;
601 cairo_surface_t
*surf
= NULL
;
604 GtkAllocation allocation
;
610 DB( g_print("\n[gtkchart] calculation\n") );
612 gtk_widget_get_allocation(drawarea
, &allocation
);
614 chart
->l
= CHART_MARGIN
;
615 chart
->t
= CHART_MARGIN
;
616 chart
->r
= allocation
.width
- CHART_MARGIN
;
617 chart
->b
= allocation
.height
- CHART_MARGIN
;
618 chart
->w
= allocation
.width
- (CHART_MARGIN
*2);
619 chart
->h
= allocation
.height
- (CHART_MARGIN
*2);
621 gdkwindow
= gtk_widget_get_window(chart
->drawarea
);
624 surf
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
, allocation
.width
, allocation
.height
);
625 cr
= cairo_create (surf
);
628 cr
= gdk_cairo_create (gdkwindow
);
630 /* Create a PangoLayout, set the font and text */
631 layout
= pango_cairo_create_layout (cr
);
636 if(chart
->title
!= NULL
)
638 chart_set_font_size(chart
, layout
, CHART_FONT_SIZE_TITLE
);
639 pango_layout_set_text (layout
, chart
->title
, -1);
640 pango_layout_get_size (layout
, &tw
, &th
);
641 chart
->title_zh
= (th
/ PANGO_SCALE
);
642 DB( g_print(" - title: %s w=%d h=%d\n", chart
->title
, tw
, th
) );
646 chart
->subtitle_zh
= 0;
647 if(chart
->subtitle
!= NULL
)
649 chart_set_font_size(chart
, layout
, CHART_FONT_SIZE_SUBTITLE
);
650 pango_layout_set_text (layout
, chart
->subtitle
, -1);
651 pango_layout_get_size (layout
, &tw
, &th
);
652 chart
->subtitle_zh
= (th
/ PANGO_SCALE
);
653 DB( g_print(" - title: %s w=%d h=%d\n", chart
->subtitle
, tw
, th
) );
655 chart
->subtitle_y
= chart
->t
+ chart
->title_zh
;
658 chart
->graph
.y
= chart
->t
+ chart
->title_zh
+ chart
->subtitle_zh
;
659 chart
->graph
.height
= chart
->h
- chart
->title_zh
- chart
->subtitle_zh
;
661 if(chart
->title_zh
> 0 || chart
->subtitle_zh
> 0)
663 chart
->graph
.y
+= CHART_MARGIN
;
664 chart
->graph
.height
-= CHART_MARGIN
;
668 // compute other text
669 chart_set_font_size(chart
, layout
, CHART_FONT_SIZE_NORMAL
);
671 // y-axis labels (amounts)
673 colchart_compute_range(chart
);
675 valstr
= chart_print_int(chart
, (gint
)chart
->min
);
676 pango_layout_set_text (layout
, valstr
, -1);
677 pango_layout_get_size (layout
, &tw
, &th
);
678 chart
->scale_w
= (tw
/ PANGO_SCALE
);
680 valstr
= chart_print_int(chart
, (gint
)chart
->max
);
681 pango_layout_set_text (layout
, valstr
, -1);
682 pango_layout_get_size (layout
, &tw
, &th
);
683 chart
->scale_w
= MAX(chart
->scale_w
, (tw
/ PANGO_SCALE
));
685 DB( g_print(" - scale: %d,%d %g,%g\n", chart
->l
, 0, chart
->scale_w
, 0.0) );
687 // todo: compute maxwidth of item labels
689 for(i
=0;i
<chart
->nb_items
;i
++)
691 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, i
);
694 pango_layout_set_text (layout
, item
->label
, -1);
695 pango_layout_get_size (layout
, &tw
, &th
);
696 label_w
= MAX(label_w
, (tw
/ PANGO_SCALE
));
698 chart
->label_w
= label_w
;
700 // compute font height
701 chart
->font_h
= (th
/ PANGO_SCALE
);
703 // compute graph region
706 case CHART_TYPE_LINE
:
708 chart
->graph
.x
= chart
->l
+ chart
->scale_w
+ 2;
709 chart
->graph
.width
= chart
->w
- chart
->scale_w
- 2;
712 chart
->graph
.x
= chart
->l
;
713 chart
->graph
.width
= chart
->w
;
717 DB( g_print(" - graph : %g,%g %g,%g\n", chart
->graph
.x
, chart
->graph
.y
, chart
->graph
.width
, chart
->graph
.height
) );
720 if( ((chart
->type
== CHART_TYPE_LINE
) || (chart
->type
== CHART_TYPE_COL
)) && chart
->show_xval
)
721 chart
->graph
.height
-= (chart
->font_h
+ CHART_SPACING
);
723 // compute: each legend column width, and legend width
724 if(chart
->show_legend
)
726 chart_set_font_size(chart
, layout
, CHART_FONT_SIZE_SMALL
);
728 //we compute the rate text here to get the font height
729 pango_layout_set_text (layout
, "00.00 %", -1);
730 pango_layout_get_size (layout
, &tw
, &th
);
732 chart
->legend_font_h
= (th
/ PANGO_SCALE
);
734 // labels not much than 1/4 of graph
735 gdouble lw
= floor(chart
->graph
.width
/ 4);
736 chart
->legend_label_w
= MIN(chart
->label_w
, lw
);
738 chart
->legend
.width
= chart
->legend_font_h
+ CHART_SPACING
+ chart
->legend_label_w
;
739 chart
->legend
.height
= MIN(floor(chart
->nb_items
* chart
->legend_font_h
* CHART_LINE_SPACING
), chart
->graph
.height
);
741 if(chart
->show_legend_wide
)
743 chart
->legend_value_w
= chart
->scale_w
;
744 chart
->legend_rate_w
= (tw
/ PANGO_SCALE
);
745 chart
->legend
.width
+= CHART_SPACING
+ chart
->legend_value_w
+ CHART_SPACING
+ chart
->legend_rate_w
;
748 //if legend visible, substract
749 chart
->graph
.width
-= (chart
->legend
.width
+ CHART_MARGIN
);
751 chart
->legend
.x
= chart
->graph
.x
+ chart
->graph
.width
+ CHART_MARGIN
;
752 chart
->legend
.y
= chart
->graph
.y
;
754 DB( g_print(" - graph : %g %g %g %g\n", chart
->graph
.x
, chart
->graph
.y
, chart
->graph
.width
, chart
->graph
.height
) );
755 DB( g_print(" - legend: %g %g %g %g\n", chart
->legend
.x
, chart
->legend
.y
, chart
->legend
.width
, chart
->legend
.height
) );
758 g_object_unref (layout
);
761 cairo_surface_destroy(surf
);
765 static void colchart_calculation(GtkChart
*chart
)
769 DB( g_print("\n[column] calculation\n") );
772 the bar has a default width of 41
773 min space is 3 and min barw is 8
777 if( chart
->usrbarw
> 0.0 )
779 blkw
= chart
->usrbarw
;
780 chart
->barw
= blkw
- 3;
784 //minvisi = floor(chart->graph.width / (GTK_CHART_MINBARW+3) );
785 maxvisi
= floor(chart
->graph
.width
/ (GTK_CHART_MAXBARW
+3) );
787 DB( g_print(" width=%.2f, nb=%d, minvisi=%d, maxvisi=%d\n", chart
->graph
.width
, chart
->nb_items
, minvisi
, maxvisi
) );
789 if( chart
->nb_items
<= maxvisi
)
791 chart
->barw
= GTK_CHART_MAXBARW
;
792 blkw
= GTK_CHART_MAXBARW
+ ( chart
->graph
.width
- (chart
->nb_items
*GTK_CHART_MAXBARW
) ) / chart
->nb_items
;
796 blkw
= MAX(GTK_CHART_MINBARW
, floor(chart
->graph
.width
/ chart
->nb_items
));
797 chart
->barw
= blkw
- 3;
802 chart
->barw
= chart
->barw
/ 2;
804 DB( g_print(" blkw=%d, barw=%2.f\n", blkw
, chart
->barw
) );
808 chart
->visible
= chart
->graph
.width
/ blkw
;
809 chart
->visible
= MIN(chart
->visible
, chart
->nb_items
);
811 chart
->ox
= chart
->l
;
812 chart
->oy
= chart
->b
;
814 chart
->oy
= floor(chart
->graph
.y
+ (chart
->max
/chart
->range
) * chart
->graph
.height
);
816 DB( g_print(" + ox=%f oy=%f\n", chart
->ox
, chart
->oy
) );
818 /* todo: hack on every xval */
819 if(chart
->label_w
> 0 && chart
->visible
> 0)
821 if( chart
->label_w
<= chart
->blkw
)
822 chart
->every_xval
= 1;
824 chart
->every_xval
= floor( 0.5 + (chart
->label_w
+ CHART_SPACING
) / chart
->blkw
);
826 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
) );
834 static void colchart_draw_scale(GtkWidget
*widget
, gpointer user_data
)
836 GtkChart
*chart
= GTK_CHART(user_data
);
846 DB( g_print("\n[column] draw scale\n") );
848 cr
= cairo_create (chart
->surface
);
849 layout
= pango_cairo_create_layout (cr
);
850 chart_set_font_size(chart
, layout
, CHART_FONT_SIZE_NORMAL
);
851 cairo_set_line_width (cr
, 1);
854 //cairo_rectangle(cr, CHART_MARGIN, 0, chart->w, chart->h + CHART_MARGIN);
857 // Y-scale lines + labels (amounts)
858 curxval
= chart
->max
;
859 cairo_set_dash(cr
, 0, 0, 0);
860 for(i
=0 ; i
<=chart
->div
; i
++)
862 y
= 0.5 + floor (chart
->graph
.y
+ ((i
* chart
->unit
) / chart
->range
) * chart
->graph
.height
);
863 //DB( g_print(" + i=%d :: y=%f (%f / %f) * %f\n", i, y, i*chart->unit, chart->range, chart->graph.height) );
865 // curxval = 0.0 is x-axis
866 cairo_user_set_rgbacol (cr
, &global_colors
[THTEXT
], ( curxval
== 0.0 ) ? 0.8 : 0.1);
867 cairo_move_to (cr
, chart
->graph
.x
, y
);
868 cairo_line_to (cr
, chart
->graph
.x
+ chart
->graph
.width
, y
);
871 cairo_user_set_rgbacol (cr
, &global_colors
[THTEXT
], 0.78);
872 valstr
= chart_print_int(chart
, (gint
)curxval
);
873 pango_layout_set_text (layout
, valstr
, -1);
874 pango_layout_get_size (layout
, &tw
, &th
);
875 cairo_move_to (cr
, chart
->graph
.x
- (tw
/ PANGO_SCALE
) - 2, y
- ((th
/ PANGO_SCALE
)*0.8) );
876 pango_cairo_show_layout (cr
, layout
);
878 curxval
-= chart
->unit
;
881 // X-scale lines + labels (items)
882 if(chart
->show_xval
&& chart
->every_xval
> 0 )
884 x
= chart
->graph
.x
+ (chart
->blkw
/2);
885 y
= chart
->b
- chart
->font_h
;
886 first
= gtk_adjustment_get_value(GTK_ADJUSTMENT(chart
->adjustment
));
888 cairo_set_dash(cr
, dashed3
, 1, 0);
890 for(i
=first
; i
<(first
+chart
->visible
) ; i
++)
892 if( !(i
% chart
->every_xval
) )
894 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, i
);
896 cairo_user_set_rgbacol(cr
, &global_colors
[THTEXT
], 0.1);
897 cairo_move_to(cr
, x
, chart
->graph
.y
);
898 cairo_line_to(cr
, x
, chart
->b
- chart
->font_h
);
901 valstr
= item
->label
;
902 pango_layout_set_text (layout
, valstr
, -1);
903 pango_layout_get_size (layout
, &tw
, &th
);
904 cairo_user_set_rgbacol(cr
, &global_colors
[THTEXT
], 0.78);
905 cairo_move_to(cr
, x
- ((tw
/ PANGO_SCALE
)/2), y
);
906 pango_cairo_show_layout (cr
, layout
);
913 if( chart
->show_average
)
915 if( chart
->average
< 0 )
917 y
= 0.5 + chart
->oy
+ (ABS(chart
->average
)/chart
->range
) * chart
->graph
.height
;
921 y
= 0.5 + chart
->oy
- (ABS(chart
->average
)/chart
->range
) * chart
->graph
.height
;
924 DB( g_print(" draw average: x%d, y%f, w%d\n", chart
->l
, y
, chart
->w
) );
926 cairo_user_set_rgbacol(cr
, &global_colors
[THTEXT
], 1.0);
927 cairo_set_line_width(cr
, 1.0);
928 cairo_set_dash (cr
, dashed3
, 1, 0);
929 cairo_move_to(cr
, chart
->graph
.x
, y
);
930 cairo_line_to (cr
, chart
->graph
.x
+ chart
->graph
.width
, y
);
934 g_object_unref (layout
);
940 ** draw all visible bars
942 static void colchart_draw_bars(GtkWidget
*widget
, gpointer user_data
)
944 GtkChart
*chart
= GTK_CHART(user_data
);
949 DB( g_print("\n[column] draw bars\n") );
952 first
= (gint
)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart
->adjustment
));
954 cr
= gdk_cairo_create (gtk_widget_get_window(widget
));
955 //cr = cairo_create (chart->surface);
957 DB( g_print(" x=%.2f first=%d, blkw=%.2f, barw=%.2f\n", x
, first
, chart
->blkw
, chart
->barw
) );
959 #if DBGDRAW_ITEM == 1
961 cairo_set_line_width(cr
, 1.0);
964 cairo_set_dash (cr
, &dashlength
, 1, 0);
965 cairo_set_source_rgb(cr
, 1.0, 0.0, 1.0); // violet
966 for(i
=first
; i
<=(first
+chart
->visible
) ;i
++)
968 cairo_move_to(cr
, x2
, chart
->graph
.y
);
969 cairo_line_to(cr
, x2
, chart
->graph
.x
+ chart
->graph
.height
);
973 cairo_set_dash (cr
, &dashlength
, 0, 0);
976 for(i
=first
; i
<(first
+chart
->visible
) ;i
++)
978 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, i
);
980 gint barw
= chart
->barw
;
982 //if(!chart->datas1[i]) goto nextbar;
984 if(!chart
->show_mono
)
985 color
= i
% chart
->color_scheme
.nb_cols
;
987 color
= chart
->color_scheme
.cs_green
;
989 cairo_user_set_rgbcol_over(cr
, &chart
->color_scheme
.colors
[color
], i
== chart
->active
);
991 x2
= x
+ (chart
->blkw
/2) - 1;
992 x2
= !chart
->dual
? x2
- (barw
/2) : x2
- barw
- 1;
996 h
= floor((item
->serie1
/ chart
->range
) * chart
->graph
.height
);
998 if(item
->serie1
< 0.0)
1001 if(chart
->show_mono
)
1003 color
= chart
->color_scheme
.cs_red
;
1004 cairo_user_set_rgbcol_over(cr
, &chart
->color_scheme
.colors
[color
], i
== chart
->active
);
1007 //DB( g_print(" + i=%d :: y2=%f h=%f (%f / %f) * %f\n", i, y2, h, chart->datas1[i], chart->range, chart->graph.height ) );
1009 cairo_rectangle(cr
, x2
+2, y2
, barw
, h
);
1014 if( chart
->dual
&& item
->serie2
)
1017 h
= floor((item
->serie2
/ chart
->range
) * chart
->graph
.height
);
1020 cairo_rectangle(cr
, x2
+2, y2
, barw
, h
);
1028 //gdk_draw_line (widget->window, widget->style->fg_gc[widget->state], x, chart->oy-chart->posbarh, x, chart->oy+chart->negbarh);
1037 ** get the bar under the mouse pointer
1039 static gint
colchart_get_active(GtkWidget
*widget
, gint x
, gint y
, gpointer user_data
)
1041 GtkChart
*chart
= GTK_CHART(user_data
);
1043 gint index
, first
, px
;
1047 if( x
<= chart
->r
&& x
>= chart
->graph
.x
&& y
>= chart
->graph
.y
&& y
<= chart
->b
)
1049 px
= (x
- chart
->graph
.x
);
1050 //py = (y - chart->oy);
1051 first
= gtk_adjustment_get_value(GTK_ADJUSTMENT(chart
->adjustment
));
1052 index
= first
+ (px
/ chart
->blkw
);
1054 if(index
< chart
->nb_items
)
1061 static void colchart_first_changed( GtkAdjustment
*adj
, gpointer user_data
)
1063 GtkChart
*chart
= GTK_CHART(user_data
);
1066 DB( g_print("\n[column] first changed\n") );
1068 //first = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj));
1070 //DB( g_print(" first=%d\n", first) );
1073 DB( g_print("scrollbar\n adj=%8x, low=%.2f upp=%.2f val=%.2f step=%.2f page=%.2f size=%.2f\n", adj,
1074 adj->lower, adj->upper, adj->value, adj->step_increment, adj->page_increment, adj->page_size) );
1076 /* Set the number of decimal places to which adj->value is rounded */
1077 //gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
1078 //gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
1080 drawarea_full_redraw (chart
->drawarea
, chart
);
1082 DB( g_print("gtk_widget_queue_draw\n") );
1083 gtk_widget_queue_draw(chart
->drawarea
);
1088 ** scrollbar set values for upper, page size, and also show/hide
1090 static void colchart_scrollbar_setvalues(GtkChart
*chart
)
1092 GtkAdjustment
*adj
= chart
->adjustment
;
1095 g_return_if_fail (GTK_IS_ADJUSTMENT (adj
));
1097 DB( g_print("\n[column] sb_set_values\n") );
1099 first
= gtk_adjustment_get_value(GTK_ADJUSTMENT(adj
));
1101 DB( g_print(" entries=%d, visible=%d\n", chart
->nb_items
, chart
->visible
) );
1102 DB( g_print(" first=%d, upper=%d, pagesize=%d\n", first
, chart
->nb_items
, chart
->visible
) );
1104 gtk_adjustment_set_upper(adj
, (gdouble
)chart
->nb_items
);
1105 gtk_adjustment_set_page_size(adj
, (gdouble
)chart
->visible
);
1106 gtk_adjustment_set_page_increment(adj
, (gdouble
)chart
->visible
);
1108 if(first
+chart
->visible
> chart
->nb_items
)
1110 gtk_adjustment_set_value(adj
, (gdouble
)chart
->nb_items
- chart
->visible
);
1112 gtk_adjustment_changed (adj
);
1114 if( chart
->visible
< chart
->nb_items
)
1115 gtk_widget_hide(GTK_WIDGET(chart
->scrollbar
));
1117 gtk_widget_show(GTK_WIDGET(chart
->scrollbar
));
1124 ** draw all visible lines
1126 static void linechart_draw_plot(cairo_t
*cr
, double x
, double y
, double r
, GtkChart
*chart
)
1128 cairo_set_line_width(cr
, r
/ 2);
1130 cairo_user_set_rgbcol(cr
, &global_colors
[THBASE
]);
1131 cairo_arc(cr
, x
, y
, r
, 0, 2*M_PI
);
1132 cairo_stroke_preserve(cr
);
1134 //cairo_set_source_rgb(cr, COLTOCAIRO(0), COLTOCAIRO(119), COLTOCAIRO(204));
1135 cairo_user_set_rgbcol(cr
, &chart
->color_scheme
.colors
[chart
->color_scheme
.cs_blue
]);
1140 static void linechart_draw_lines(GtkWidget
*widget
, gpointer user_data
)
1142 GtkChart
*chart
= GTK_CHART(user_data
);
1144 double x
, y
, x2
, y2
, firstx
, lastx
, linew
;
1148 DB( g_print("\n[line] draw lines\n") );
1152 first
= (gint
)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart
->adjustment
));
1154 cr
= gdk_cairo_create (gtk_widget_get_window(widget
));
1155 //cr = cairo_create (chart->surface);
1158 //cairo_rectangle(cr, CHART_MARGIN, 0, chart->w, chart->h + CHART_MARGIN);
1162 #if DBGDRAW_ITEM == 1
1164 cairo_set_line_width(cr
, 1.0);
1165 double dashlength
= 4;
1166 cairo_set_dash (cr
, &dashlength
, 1, 0);
1167 cairo_set_source_rgb(cr
, 1.0, 0.0, 1.0); // violet
1168 for(i
=first
; i
<=(first
+chart
->visible
) ;i
++)
1170 cairo_move_to(cr
, x2
, chart
->graph
.y
);
1171 cairo_line_to(cr
, x2
, chart
->graph
.x
+ chart
->graph
.height
);
1176 cairo_set_dash (cr
, &dashlength
, 0, 0);
1179 //todo: it should be possible to draw line & plot together using surface and composite fill, or sub path ??
1183 if(chart
->barw
< 24)
1185 linew
= 1 + (chart
->barw
/ 8.0);
1188 cairo_set_line_join(cr
, CAIRO_LINE_JOIN_BEVEL
);
1189 cairo_set_line_width(cr
, linew
);
1191 for(i
=first
; i
<(first
+chart
->visible
) ;i
++)
1193 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, i
);
1195 x2
= x
+ (chart
->blkw
)/2;
1196 y2
= chart
->oy
- (item
->serie1
/ chart
->range
) * chart
->graph
.height
;
1200 cairo_move_to(cr
, x2
, y2
);
1204 if( i
< (chart
->nb_items
) )
1206 cairo_line_to(cr
, x2
, y2
);
1210 lastx
= x2
- chart
->barw
;
1216 cairo_user_set_rgbcol(cr
, &chart
->color_scheme
.colors
[chart
->color_scheme
.cs_blue
]);
1217 cairo_stroke_preserve(cr
);
1219 cairo_line_to(cr
, lastx
, y
);
1220 cairo_line_to(cr
, firstx
, y
);
1221 cairo_close_path(cr
);
1223 cairo_user_set_rgbacol(cr
, &chart
->color_scheme
.colors
[chart
->color_scheme
.cs_blue
], AREA_ALPHA
);
1228 first
= (gint
)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart
->adjustment
));
1231 for(i
=first
; i
<(first
+chart
->visible
) ;i
++)
1233 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, i
);
1235 x2
= x
+ (chart
->blkw
)/2;
1236 y2
= chart
->oy
- (item
->serie1
/ chart
->range
) * chart
->graph
.height
;
1238 //test draw vertical selection line
1239 if( i
== chart
->active
)
1241 cairo_user_set_rgbacol(cr
, &global_colors
[THTEXT
], 0.1);
1243 //cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); //blue
1244 cairo_set_line_width(cr
, 1.0);
1245 cairo_move_to(cr
, x2
, chart
->graph
.y
);
1246 cairo_line_to(cr
, x2
, chart
->b
- chart
->font_h
);
1251 linechart_draw_plot(cr
, x2
, y2
, i
== chart
->active
? linew
+1 : linew
, chart
);
1259 if( chart
->show_average
)
1261 if( chart
->average
< 0 )
1263 y
= 0.5 + chart
->oy
+ (ABS(chart
->average
)/chart
->range
) * chart
->graph
.height
;
1267 y
= 0.5 + chart
->oy
- (ABS(chart
->average
)/chart
->range
) * chart
->graph
.height
;
1270 y2
= (ABS(chart
->min
)/chart
->range
) * chart
->graph
.height
- (y
- chart
->oy
) + 1;
1272 DB( g_print(" draw average: x%d, y%f, w%d, h%f\n", chart
->l
, y
, chart
->w
, y2
) );
1274 cairo_user_set_rgbacol(cr
, &global_colors
[THTEXT
], 1.0);
1275 cairo_set_line_width(cr
, 1.0);
1276 cairo_set_dash (cr
, dashed3
, 1, 0);
1277 cairo_move_to(cr
, chart
->graph
.x
, y
);
1278 cairo_line_to (cr
, chart
->graph
.x
+ chart
->graph
.width
, y
);
1285 DB( g_print(" min=%.2f range=%.2f\n", chart
->min
, chart
->range
) );
1287 if( chart
->show_over
)
1289 //if(chart->minimum != 0 && chart->minimum >= chart->min)
1290 if(chart
->minimum
>= chart
->min
)
1292 if( chart
->minimum
< 0 )
1294 y
= 0.5 + chart
->oy
+ (ABS(chart
->minimum
)/chart
->range
) * chart
->graph
.height
;
1298 y
= 0.5 + chart
->oy
- (ABS(chart
->minimum
)/chart
->range
) * chart
->graph
.height
;
1301 y2
= (ABS(chart
->min
)/chart
->range
) * chart
->graph
.height
- (y
- chart
->oy
) + 1;
1303 cairo_set_source_rgba(cr
, COLTOCAIRO(255), COLTOCAIRO(0), COLTOCAIRO(0), AREA_ALPHA
/ 2);
1305 DB( g_print(" draw over: x%d, y%f, w%d, h%f\n", chart
->l
, y
, chart
->w
, y2
) );
1307 cairo_rectangle(cr
, chart
->graph
.x
, y
, chart
->graph
.width
, y2
);
1310 cairo_set_line_width(cr
, 1.0);
1311 cairo_set_source_rgb(cr
, COLTOCAIRO(255), COLTOCAIRO(0), COLTOCAIRO(0));
1313 cairo_set_dash (cr
, dashed3
, 1, 0);
1314 cairo_move_to(cr
, chart
->graph
.x
, y
);
1315 cairo_line_to (cr
, chart
->graph
.x
+ chart
->graph
.width
, y
);
1329 ** get the point under the mouse pointer
1331 static gint
linechart_get_active(GtkWidget
*widget
, gint x
, gint y
, gpointer user_data
)
1333 GtkChart
*chart
= GTK_CHART(user_data
);
1335 gint first
, index
, px
;
1337 DB( g_print("\n[line] get active\n") );
1341 if( x
<= chart
->r
&& x
>= chart
->graph
.x
&& y
>= chart
->graph
.y
&& y
<= chart
->b
)
1343 px
= (x
- chart
->graph
.x
);
1344 //py = (y - chart->oy);
1345 first
= gtk_adjustment_get_value(GTK_ADJUSTMENT(chart
->adjustment
));
1346 index
= first
+ (px
/ (chart
->blkw
));
1348 if(index
< chart
->nb_items
)
1358 static void piechart_calculation(GtkChart
*chart
)
1360 //GtkWidget *drawarea = chart->drawarea;
1363 DB( g_print("\n[pie] calculation\n") );
1365 w
= chart
->graph
.width
;
1366 h
= chart
->graph
.height
;
1368 chart
->rayon
= MIN(w
, h
);
1371 #if CHART_PARAM_PIE_MARK == TRUE
1372 gint m
= floor(chart
->rayon
/ 100);
1374 chart
->rayon
-= (m
* 2);
1378 chart
->ox
= chart
->graph
.x
+ (w
/ 2);
1379 chart
->oy
= chart
->graph
.y
+ (chart
->rayon
/ 2);
1381 DB( g_print(" center: %g, %g - R=%d, mark=%d\n", chart
->ox
, chart
->oy
, chart
->rayon
, chart
->mark
) );
1386 static void piechart_draw_slices(GtkWidget
*widget
, gpointer user_data
)
1388 GtkChart
*chart
= GTK_CHART(user_data
);
1391 if(chart
->nb_items
<= 0 || chart
->total
== 0.0)
1394 DB( g_print("\n[pie] draw slices\n") );
1399 double a1
= 0 * (M_PI
/ 180);
1400 double a2
= 360 * (M_PI
/ 180);
1402 //g_print("angle1=%.2f angle2=%.2f\n", a1, a2);
1404 double cx
= chart
->ox
;
1405 double cy
= chart
->oy
;
1406 double radius
= chart
->rayon
/2;
1412 cr
= gdk_cairo_create (gtk_widget_get_window(widget
));
1413 //cr = cairo_create (chart->surface);
1415 DB( g_print("rayon=%d\n", chart
->rayon
) );
1416 DB( g_print("total=%.f\n", chart
->total
) );
1418 for(i
=0; i
< chart
->nb_items
;i
++)
1420 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, i
);
1422 a1
= ((360 * (sum
/ chart
->total
)) - 90) * (M_PI
/ 180);
1423 sum
+= ABS(item
->serie1
);
1424 a2
= ((360 * (sum
/ chart
->total
)) - 90) * (M_PI
/ 180);
1425 //if(i < chart->nb_items-1) a2 += 0.0175;
1430 DB( g_print("- s%2d: %.2f%% a1=%.2f a2=%.2f | %s %.f\n", i
, sum
/ chart
->total
, a1
, a2
, item
->label
, item
->serie1
) );
1433 cairo_move_to(cr
, dx
, dy
);
1434 cairo_arc(cr
, dx
, dy
, radius
, a1
, a2
);
1436 #if CHART_PARAM_PIE_LINE == TRUE
1437 cairo_set_line_width(cr
, 2.0);
1438 cairo_set_source_rgb(cr
, 1.0, 1.0, 1.0);
1439 cairo_line_to(cr
, cx
, cy
);
1440 cairo_stroke_preserve(cr
);
1443 //g_print("color : %f %f %f\n", COLTOCAIRO(colors[i].r), COLTOCAIRO(colors[i].g), COLTOCAIRO(colors[i].b));
1445 color
= i
% chart
->color_scheme
.nb_cols
;
1446 cairo_user_set_rgbcol_over(cr
, &chart
->color_scheme
.colors
[color
], i
== chart
->active
);
1452 #if CHART_PARAM_PIE_DONUT == TRUE
1457 //radius = (gint)((chart->rayon/3) * (1 / PHI));
1459 //radius = (gint)((chart->rayon/2) * 2 / 3);
1461 //piehole value from 0.4 to 0.6 will look best on most charts
1462 radius
= (gint
)(chart
->rayon
/2) * CHART_PARAM_PIE_HOLEVALUE
;
1464 cairo_arc(cr
, cx
, cy
, radius
, a1
, a2
);
1465 cairo_user_set_rgbcol(cr
, &global_colors
[THBASE
]);
1474 static gint
piechart_get_active(GtkWidget
*widget
, gint x
, gint y
, gpointer user_data
)
1476 GtkChart
*chart
= GTK_CHART(user_data
);
1477 gint retval
, px
, py
;
1481 DB( g_print("\n[pie] get active\n") );
1487 h
= sqrt( pow(px
,2) + pow(py
,2) );
1488 radius
= chart
->rayon
/ 2;
1490 if(h
<= radius
&& h
>= (radius
* CHART_PARAM_PIE_HOLEVALUE
) )
1494 b
= (acos(px
/ h
) * 180) / M_PI
;
1495 angle
= py
> 0 ? b
: 360 - b
;
1497 if(angle
> 360) angle
-= 360;
1498 //angle = 360 - angle;
1502 for(index
=0; index
< chart
->nb_items
;index
++)
1504 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, index
);
1506 cumul
+= ABS(item
->serie1
/chart
->total
)*360;
1514 //DB( g_print(" inside: x=%d, y=%d\n", x, y) );
1515 //DB( g_print(" inside: b=%f angle=%f, slice is %d\n", b, angle, index) );
1521 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1522 static gboolean
drawarea_full_redraw(GtkWidget
*widget
, gpointer user_data
)
1524 GtkChart
*chart
= GTK_CHART(user_data
);
1526 PangoLayout
*layout
;
1529 DB( g_print("------\n[gtkchart] drawarea full redraw\n") );
1531 cr
= cairo_create (chart
->surface
);
1534 cairo_font_face_t
*ff
;
1535 cairo_scaled_font_t
*sf
;
1537 ff
= cairo_get_font_face(cr
);
1538 sf
= cairo_get_scaled_font(cr
);
1540 g_print("cairo ff = '%s'\n", cairo_toy_font_face_get_family(ff
) );
1542 ff
= cairo_scaled_font_get_font_face(sf
);
1543 g_print("cairo sf = '%s'\n", cairo_toy_font_face_get_family(ff
) );
1545 //cairo_set_font_face(cr, ff);
1548 /* fillin the back in white */
1549 //cairo_user_set_rgbcol(cr, &global_colors[WHITE]);
1550 cairo_user_set_rgbcol(cr
, &global_colors
[THBASE
]);
1554 if(chart
->nb_items
== 0)
1560 /*debug help draws */
1561 #if DBGDRAW_RECT == 1
1563 cairo_set_line_width(cr
, 1.0);
1564 cairo_set_source_rgb(cr
, 0.0, 1.0, 0.0); //green
1565 cairo_rectangle(cr
, chart
->l
+0.5, chart
->t
+0.5, chart
->w
, chart
->h
);
1569 cairo_set_source_rgb(cr
, 1.0, 0.5, 0.0); //orange
1570 cairo_rectangle(cr
, chart
->graph
.x
+0.5, chart
->graph
.y
+0.5, chart
->graph
.width
, chart
->graph
.height
);
1577 layout
= pango_cairo_create_layout (cr
);
1579 chart_set_font_size(chart
, layout
, CHART_FONT_SIZE_TITLE
);
1580 pango_layout_set_text (layout
, chart
->title
, -1);
1581 pango_layout_get_size (layout
, &tw
, &th
);
1583 cairo_user_set_rgbcol(cr
, &global_colors
[THTEXT
]);
1584 cairo_move_to(cr
, chart
->l
, chart
->t
);
1585 pango_cairo_show_layout (cr
, layout
);
1587 #if DBGDRAW_TEXT == 1
1589 cairo_set_source_rgb(cr
, 0.0, 0.0, 1.0); //blue
1591 cairo_set_dash (cr
, &dashlength
, 1, 0);
1592 //cairo_move_to(cr, chart->l, chart->t);
1593 cairo_rectangle(cr
, chart
->l
+0.5, chart
->t
+0.5, (tw
/ PANGO_SCALE
), (th
/ PANGO_SCALE
));
1597 g_object_unref (layout
);
1602 case CHART_TYPE_COL
:
1603 colchart_draw_scale(widget
, chart
);
1604 //colchart_draw_bars(widget, chart);
1606 case CHART_TYPE_LINE
:
1607 colchart_draw_scale(widget
, chart
);
1608 //linechart_draw_lines(widget, chart);
1610 case CHART_TYPE_PIE
:
1611 //piechart_draw_slices(widget, chart);
1617 if(chart
->show_legend
)
1625 DB( g_print("\n[chart] draw legend\n") );
1627 layout
= pango_cairo_create_layout (cr
);
1628 chart_set_font_size(chart
, layout
, CHART_FONT_SIZE_SMALL
);
1629 pango_layout_set_ellipsize(layout
, PANGO_ELLIPSIZE_END
);
1631 x
= chart
->legend
.x
;
1632 y
= chart
->legend
.y
;
1633 radius
= chart
->legend_font_h
;
1635 #if DBGDRAW_RECT == 1
1637 cairo_set_source_rgb(cr
, 1.0, 0.5, 0.0); //orange
1639 cairo_set_dash (cr
, &dashlength
, 1, 0);
1640 //cairo_move_to(cr, x, y);
1641 cairo_rectangle(cr
, chart
->legend
.x
+0.5, chart
->legend
.y
+0.5, chart
->legend
.width
, chart
->legend
.height
);
1645 for(i
=0; i
< chart
->nb_items
;i
++)
1647 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, i
);
1651 //DB( g_print(" draw %2d '%s' y=%g\n", i, item->label, y) );
1653 #if DBGDRAW_TEXT == 1
1655 cairo_set_source_rgb(cr
, 0.0, 0.0, 1.0); //blue
1657 cairo_set_dash (cr
, &dashlength
, 1, 0);
1658 //cairo_move_to(cr, x, y);
1659 cairo_rectangle(cr
, x
+0.5, y
+0.5, chart
->legend_font_h
+ CHART_SPACING
+ chart
->legend_label_w
, chart
->legend_font_h
);
1663 // check if enought height to draw
1664 if( chart
->nb_items
- i
> 1 )
1666 if( (y
+ floor(2 * radius
* CHART_LINE_SPACING
)) > chart
->b
)
1668 DB( g_print(" print ...\n\n") );
1669 pango_layout_set_text (layout
, "...", -1);
1670 cairo_move_to(cr
, x
+ radius
+ CHART_SPACING
, y
);
1671 pango_cairo_show_layout (cr
, layout
);
1677 cairo_arc(cr
, x
+ (radius
/2), y
+ (radius
/2), (radius
/2), 0, 2 * M_PI
);
1678 color
= i
% chart
->color_scheme
.nb_cols
;
1679 cairo_user_set_rgbcol(cr
, &chart
->color_scheme
.colors
[color
]);
1682 cairo_user_set_rgbacol(cr
, &global_colors
[THTEXT
], 0.78);
1685 valstr
= item
->label
;
1686 pango_layout_set_text (layout
, valstr
, -1);
1687 pango_layout_set_width(layout
, chart
->legend_label_w
* PANGO_SCALE
);
1688 cairo_move_to(cr
, x
+ chart
->legend_font_h
+ CHART_SPACING
, y
);
1689 pango_cairo_show_layout (cr
, layout
);
1691 if( chart
->show_legend_wide
)
1693 pango_layout_set_width(layout
, -1);
1696 valstr
= chart_print_double(chart
, chart
->buffer1
, item
->serie1
);
1697 pango_layout_set_text (layout
, valstr
, -1);
1698 pango_layout_get_size (layout
, &tw
, &th
);
1699 cairo_move_to(cr
, x
+ chart
->legend_font_h
+ chart
->legend_label_w
+ (CHART_SPACING
*3) + chart
->legend_value_w
- (tw
/PANGO_SCALE
), y
);
1700 pango_cairo_show_layout (cr
, layout
);
1703 valstr
= chart_print_rate(chart
, item
->rate
);
1704 pango_layout_set_text (layout
, valstr
, -1);
1705 pango_layout_get_size (layout
, &tw
, &th
);
1706 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
);
1707 pango_cairo_show_layout (cr
, layout
);
1710 //the radius contains the font height here
1711 //y += floor(chart->font_h * CHART_LINE_SPACING);
1712 y
+= floor(radius
* CHART_LINE_SPACING
);
1716 g_object_unref (layout
);
1727 drawarea_configure_event_callback (GtkWidget
*widget
,
1728 GdkEventConfigure
*event
,
1731 GtkChart
*chart
= GTK_CHART(user_data
);
1732 GtkAllocation allocation
;
1733 GtkStyleContext
*context
;
1734 PangoFontDescription
*desc
;
1738 DB( g_print("\n[gtkchart] drawarea configure \n") );
1740 gtk_widget_get_allocation (widget
, &allocation
);
1742 DB( g_print("w=%d h=%d\n", allocation
.width
, allocation
.height
) );
1746 cairo_surface_destroy (chart
->surface
);
1748 chart
->surface
= gdk_window_create_similar_surface (gtk_widget_get_window (widget
),
1749 CAIRO_CONTENT_COLOR
,
1753 context
= gtk_widget_get_style_context (widget
);
1755 chart_color_global_default();
1758 colfound
= gtk_style_context_lookup_color(context
, "theme_base_color", &color
);
1760 colfound
= gtk_style_context_lookup_color(context
, "base_color", &color
);
1764 struct rgbcol
*tcol
= &global_colors
[THBASE
];
1765 tcol
->r
= color
.red
* 255;
1766 tcol
->g
= color
.green
* 255;
1767 tcol
->b
= color
.blue
* 255;
1768 DB( g_print(" - theme base col: %x %x %x\n", tcol
->r
, tcol
->g
, tcol
->b
) );
1772 colfound
= gtk_style_context_lookup_color(context
, "theme_text_color", &color
);
1774 gtk_style_context_lookup_color(context
, "text_color", &color
);
1779 struct rgbcol
*tcol
= &global_colors
[THTEXT
];
1780 tcol
->r
= color
.red
* 255;
1781 tcol
->g
= color
.green
* 255;
1782 tcol
->b
= color
.blue
* 255;
1783 DB( g_print(" - theme text (bg) col: %x %x %x\n", tcol
->r
, tcol
->g
, tcol
->b
) );
1787 //drawarea_full_redraw(widget, user_data);
1789 /* get and copy the font */
1790 gtk_style_context_get(context
, GTK_STATE_FLAG_NORMAL
, "font", &desc
, NULL
);
1793 pango_font_description_free (chart
->pfd
);
1796 chart
->pfd
= pango_font_description_copy(desc
);
1797 chart
->pfd_size
= pango_font_description_get_size (desc
) / PANGO_SCALE
;
1798 //chart->barw = (6 + chart->pfd_size) * PHI;
1800 //leak: we should free desc here ?
1801 //or no need to copy above ?
1802 //pango_font_description_free(desc);
1804 DB( g_print("family: %s\n", pango_font_description_get_family(chart
->pfd
) ) );
1805 DB( g_print("size : %d (%d)\n", chart
->pfd_size
, chart
->pfd_size
/PANGO_SCALE
) );
1806 DB( g_print("isabs : %d\n", pango_font_description_get_size_is_absolute (chart
->pfd
) ) );
1809 if( gtk_widget_get_realized(widget
))
1811 chart_recompute(chart
);
1812 drawarea_full_redraw(widget
, chart
);
1815 /* We've handled the configure event, no need for further processing. */
1820 static void drawarea_realize_callback(GtkWidget
*widget
, gpointer user_data
)
1822 //GtkChart *chart = GTK_CHART(user_data);
1824 DB( g_print("\n[gtkchart] drawarea realize\n") );
1826 //chart_recompute(chart);
1831 static gboolean
drawarea_draw_callback(GtkWidget
*widget
, cairo_t
*cr
, gpointer user_data
)
1833 GtkChart
*chart
= GTK_CHART(user_data
);
1835 if( !gtk_widget_get_realized(widget
) || chart
->surface
== NULL
)
1838 DB( g_print("\n[gtkchart] drawarea draw callback\n") );
1840 cairo_set_source_surface (cr
, chart
->surface
, 0, 0);
1845 case CHART_TYPE_COL
:
1846 colchart_draw_bars(widget
, chart
);
1848 case CHART_TYPE_LINE
:
1849 linechart_draw_lines(widget
, chart
);
1851 case CHART_TYPE_PIE
:
1852 piechart_draw_slices(widget
, chart
);
1860 static gboolean
drawarea_querytooltip_callback(GtkWidget
*widget
, gint x
, gint y
, gboolean keyboard_mode
, GtkTooltip
*tooltip
, gpointer user_data
)
1862 GtkChart
*chart
= GTK_CHART(user_data
);
1863 gchar
*strval
, *strval2
, *buffer
;
1864 gboolean retval
= FALSE
;
1866 if(chart
->surface
== NULL
)
1869 DB( g_print("\n[gtkchart] drawarea querytooltip\n") );
1871 DB( g_print(" x=%d, y=%d kbm=%d\n", x
, y
, keyboard_mode
) );
1872 if(chart
->lastactive
!= chart
->active
)
1877 if(chart
->active
>= 0)
1879 ChartItem
*item
= &g_array_index(chart
->items
, ChartItem
, chart
->active
);
1881 strval
= chart_print_double(chart
, chart
->buffer1
, item
->serie1
);
1884 //#1420495 don't use g_markup_printf_escaped
1885 if( chart
->type
== CHART_TYPE_PIE
)
1886 buffer
= g_strdup_printf("%s\n%s\n%.2f%%", item
->label
, strval
, item
->rate
);
1888 buffer
= g_strdup_printf("%s\n%s", item
->label
, strval
);
1893 strval2
= chart_print_double(chart
, chart
->buffer2
, item
->serie2
);
1894 buffer
= g_strdup_printf("%s\n+%s\n%s", item
->label
, strval2
, strval
);
1897 gtk_tooltip_set_text(tooltip
, buffer
);
1898 //gtk_label_set_markup(GTK_LABEL(chart->ttlabel), buffer);
1903 chart
->lastactive
= chart
->active
;
1909 static gboolean
drawarea_motionnotifyevent_callback(GtkWidget
*widget
, GdkEventMotion
*event
, gpointer user_data
)
1911 GtkChart
*chart
= GTK_CHART(user_data
);
1912 gboolean retval
= TRUE
;
1915 if(chart
->surface
== NULL
|| chart
->nb_items
== 0)
1918 DB( g_print("\n[gtkchart] drawarea motion\n") );
1925 DB( g_print(" is hint\n") );
1927 gdk_window_get_device_position(event
->window
, event
->device
, &x
, &y
, NULL
);
1928 //gdk_window_get_pointer(event->window, &x, &y, NULL);
1934 case CHART_TYPE_COL
:
1935 chart
->active
= colchart_get_active(widget
, x
, y
, chart
);
1937 case CHART_TYPE_LINE
:
1938 chart
->active
= linechart_get_active(widget
, x
, y
, chart
);
1940 case CHART_TYPE_PIE
:
1941 chart
->active
= piechart_get_active(widget
, x
, y
, chart
);
1946 if( chart
->show_legend
&& chart
->active
== - 1)
1948 if( x
>= chart
->legend
.x
&& (x
<= (chart
->legend
.x
+chart
->legend
.width
))
1949 && y
>= chart
->legend
.y
&& (y
<= (chart
->legend
.y
+chart
->legend
.height
))
1952 //use the radius a font height here
1953 chart
->active
= (y
- chart
->legend
.y
) / floor(chart
->legend_font_h
* CHART_LINE_SPACING
);
1956 if( chart
->active
> chart
->nb_items
- 1)
1962 // rollover redraw ?
1963 DB( g_print(" active: last=%d, curr=%d\n", chart
->lastactive
, chart
->active
) );
1965 if(chart
->lastactive
!= chart
->active
)
1967 GdkRectangle update_rect
;
1970 DB( g_print(" motion rollover redraw :: active=%d\n", chart
->active
) );
1972 first
= (gint
)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart
->adjustment
));
1974 /* pie : always invalidate all graph area */
1975 if( chart
->type
== CHART_TYPE_PIE
)
1977 update_rect
.x
= chart
->graph
.x
;
1978 update_rect
.y
= chart
->graph
.y
;
1979 update_rect
.width
= chart
->graph
.width
;
1980 update_rect
.height
= chart
->graph
.height
;
1982 /* Now invalidate the affected region of the drawing area. */
1983 gdk_window_invalidate_rect (gtk_widget_get_window (widget
),
1988 if(chart
->lastactive
!= -1)
1990 /* column/line : invalidate rollover */
1991 if( chart
->type
== CHART_TYPE_COL
|| chart
->type
== CHART_TYPE_LINE
)
1993 update_rect
.x
= chart
->graph
.x
+ (chart
->lastactive
- first
) * chart
->blkw
;
1994 update_rect
.y
= chart
->graph
.y
- 6;
1995 update_rect
.width
= chart
->blkw
;
1996 update_rect
.height
= chart
->graph
.height
+ 12;
1999 /* Now invalidate the affected region of the drawing area. */
2000 gdk_window_invalidate_rect (gtk_widget_get_window (widget
),
2005 /* column/line : invalidate current item */
2006 if( chart
->type
== CHART_TYPE_COL
|| chart
->type
== CHART_TYPE_LINE
)
2008 update_rect
.x
= chart
->graph
.x
+ (chart
->active
- first
) * chart
->blkw
;
2009 update_rect
.y
= chart
->graph
.y
- 6;
2010 update_rect
.width
= chart
->blkw
;
2011 update_rect
.height
= chart
->graph
.height
+ 12;
2013 /* Now invalidate the affected region of the drawing area. */
2014 gdk_window_invalidate_rect (gtk_widget_get_window (widget
),
2019 //gtk_widget_queue_draw( widget );
2023 DB( g_print(" x=%d, y=%d, time=%d\n", x
, y
, event
->time
) );
2025 //if(inlegend != TRUE)
2026 // gtk_tooltip_trigger_tooltip_query(gtk_widget_get_display(chart->drawarea));
2032 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2033 /* public functions */
2034 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2036 void gtk_chart_queue_redraw(GtkChart
*chart
)
2038 DB( g_print("\n[gtkchart] queue redraw\n") );
2040 if( gtk_widget_get_realized(chart
->drawarea
) )
2042 chart_recompute(chart
);
2043 drawarea_full_redraw(chart
->drawarea
, chart
);
2044 DB( g_print("gtk_widget_queue_draw\n") );
2045 gtk_widget_queue_draw( chart
->drawarea
);
2051 ** change the model and/or column
2053 void gtk_chart_set_datas(GtkChart
*chart
, GtkTreeModel
*model
, guint column
, gchar
*title
, gchar
*subtitle
)
2055 g_return_if_fail (GTK_IS_CHART (chart
));
2057 DB( g_print("\n[gtkchart] set datas\n") );
2059 if( GTK_IS_TREE_MODEL(model
) )
2061 chart_setup_with_model(chart
, model
, column
, column
);
2063 chart
->title
= g_strdup(title
);
2064 if(subtitle
!= NULL
)
2065 chart
->subtitle
= g_strdup(subtitle
);
2067 gtk_chart_queue_redraw(chart
);
2072 if( GTK_IS_LIST_STORE(chart
->model
) )
2073 gtk_list_store_clear (GTK_LIST_STORE(chart
->model
));
2079 ** change the model and/or column
2081 void gtk_chart_set_dualdatas(GtkChart
*chart
, GtkTreeModel
*model
, guint column1
, guint column2
, gchar
*title
, gchar
*subtitle
)
2083 g_return_if_fail (GTK_IS_CHART (chart
));
2085 DB( g_print("\n[gtkchart] set dualdatas\n") );
2087 if( GTK_IS_TREE_MODEL(model
) )
2089 chart_setup_with_model(chart
, model
, column1
, column2
);
2091 chart
->title
= g_strdup(title
);
2092 if(subtitle
!= NULL
)
2093 chart
->subtitle
= g_strdup(subtitle
);
2095 gtk_chart_queue_redraw(chart
);
2100 if( GTK_IS_LIST_STORE(chart
->model
) )
2101 gtk_list_store_clear (GTK_LIST_STORE(chart
->model
));
2107 ** change the type dynamically
2109 void gtk_chart_set_type(GtkChart
* chart
, gint type
)
2111 g_return_if_fail (GTK_IS_CHART (chart
));
2112 //g_return_if_fail (type < CHART_TYPE_MAX);
2114 DB( g_print("\n[gtkchart] set type %d\n", type
) );
2117 chart
->dual
= FALSE
;
2119 gtk_chart_queue_redraw(chart
);
2122 /* = = = = = = = = = = parameters = = = = = = = = = = */
2124 void gtk_chart_set_color_scheme(GtkChart
* chart
, gint index
)
2126 colorscheme_init(&chart
->color_scheme
, index
);
2132 ** set the minor parameters
2134 void gtk_chart_set_minor_prefs(GtkChart
* chart
, gdouble rate
, gchar
*symbol
)
2136 g_return_if_fail (GTK_IS_CHART (chart
));
2138 DB( g_print("\n[gtkchart] set minor prefs\n") );
2140 chart
->minor_rate
= rate
;
2141 chart
->minor_symbol
= symbol
;
2145 void gtk_chart_set_absolute(GtkChart
* chart
, gboolean abs
)
2147 g_return_if_fail (GTK_IS_CHART (chart
));
2149 DB( g_print("\n[gtkchart] set absolute\n") );
2155 void gtk_chart_set_currency(GtkChart
* chart
, guint32 kcur
)
2157 g_return_if_fail (GTK_IS_CHART (chart
));
2164 ** set the overdrawn minimum
2166 void gtk_chart_set_overdrawn(GtkChart
* chart
, gdouble minimum
)
2168 g_return_if_fail (GTK_IS_CHART (chart
));
2170 DB( g_print("\n[gtkchart] set overdrawn\n") );
2172 chart
->minimum
= minimum
;
2174 //if(chart->type == CHART_TYPE_LINE)
2175 // chart_recompute(chart);
2180 ** obsolete: set the every_xval
2182 /*void gtk_chart_set_every_xval(GtkChart * chart, gint gap)
2184 g_return_if_fail (GTK_IS_CHART (chart));
2186 DB( g_print("\n[gtkchart] set every_xval\n") );
2188 chart->every_xval = gap;
2190 //if(chart->type != CHART_TYPE_PIE)
2191 // chart_recompute(chart);
2198 void gtk_chart_set_barw(GtkChart
* chart
, gdouble barw
)
2200 g_return_if_fail (GTK_IS_CHART (chart
));
2202 DB( g_print("\n[gtkchart] set barw\n") );
2204 if( barw
>= GTK_CHART_MINBARW
&& barw
<= GTK_CHART_MAXBARW
)
2205 chart
->usrbarw
= barw
;
2210 if(chart
->type
!= CHART_TYPE_PIE
)
2211 gtk_chart_queue_redraw(chart
);
2215 ** set the show mono (colors)
2217 void gtk_chart_set_showmono(GtkChart
* chart
, gboolean mono
)
2219 g_return_if_fail (GTK_IS_CHART (chart
));
2221 chart
->show_mono
= mono
;
2223 if(chart
->type
!= CHART_TYPE_PIE
)
2224 gtk_chart_queue_redraw(chart
);
2228 /* = = = = = = = = = = visibility = = = = = = = = = = */
2231 ** change the legend visibility
2233 void gtk_chart_show_legend(GtkChart
* chart
, gboolean visible
, gboolean showextracol
)
2235 g_return_if_fail (GTK_IS_CHART (chart
));
2237 chart
->show_legend
= visible
;
2238 chart
->show_legend_wide
= showextracol
;
2239 gtk_chart_queue_redraw(chart
);
2243 ** change the x-value visibility
2245 void gtk_chart_show_xval(GtkChart
* chart
, gboolean visible
)
2247 g_return_if_fail (GTK_IS_CHART (chart
));
2249 DB( g_print("\n[gtkchart] set show xval\n") );
2251 chart
->show_xval
= visible
;
2253 //if(chart->type != CHART_TYPE_PIE)
2254 // chart_recompute(chart);
2258 void gtk_chart_show_average(GtkChart
* chart
, gdouble value
, gboolean visible
)
2260 g_return_if_fail (GTK_IS_CHART (chart
));
2262 DB( g_print("\n[gtkchart] set show average %f\n", value
) );
2264 chart
->average
= value
;
2265 chart
->show_average
= visible
;
2267 //if(chart->type == CHART_TYPE_LINE)
2268 // chart_recompute(chart);
2274 ** chnage the overdrawn visibility
2276 void gtk_chart_show_overdrawn(GtkChart
* chart
, gboolean visible
)
2278 g_return_if_fail (GTK_IS_CHART (chart
));
2280 DB( g_print("\n[gtkchart] set show overdrawn\n") );
2282 chart
->show_over
= visible
;
2284 //if(chart->type == CHART_TYPE_LINE)
2285 // chart_recompute(chart);
2290 ** change the minor visibility
2292 void gtk_chart_show_minor(GtkChart
* chart
, gboolean minor
)
2294 g_return_if_fail (GTK_IS_CHART (chart
));
2296 DB( g_print("\n[gtkchart] set show minor\n") );
2298 chart
->minor
= minor
;
2300 if(chart
->type
!= CHART_TYPE_PIE
)
2301 gtk_chart_queue_redraw(chart
);