]> Dogcows Code - chaz/homebank/blob - src/gtk-chart-stack.c
import homebank-5.1.2
[chaz/homebank] / src / gtk-chart-stack.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2013 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 #include <gtk/gtk.h>
24
25 #include "homebank.h"
26 #include "gtk-chart-colors.h"
27 #include "gtk-chart-stack.h"
28
29 #define MYDEBUG 0
30
31 #if MYDEBUG
32 #define DB(x) (x);
33 #else
34 #define DB(x);
35 #endif
36
37
38 #define HELPDRAW 0
39
40
41
42 /* --- prototypes --- */
43 static void ui_chart_stack_class_init (ChartStackClass *klass);
44 static void ui_chart_stack_init (ChartStack *chart);
45 static void ui_chart_stack_destroy (GtkWidget *chart);
46 /*static void ui_chart_stack_set_property (GObject *object,
47 guint prop_id,
48 const GValue *value,
49 GParamSpec *pspec);*/
50
51 static gboolean drawarea_configure_event_callback (GtkWidget *widget, GdkEventConfigure *event, gpointer user_data);
52 static gboolean drawarea_draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data);
53 static gboolean drawarea_scroll_event_callback( GtkWidget *widget, GdkEventScroll *event, gpointer user_data);
54 static gboolean drawarea_motionnotifyevent_callback(GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
55 static void ui_chart_stack_first_changed( GtkAdjustment *adj, gpointer user_data);
56
57 static void ui_chart_stack_clear(ChartStack *chart, gboolean store);
58
59 static void ui_chart_stack_queue_redraw(ChartStack *chart);
60
61 /* --- variables --- */
62 static GtkBoxClass *parent_class = NULL;
63
64
65 /* --- functions --- */
66 GType ui_chart_stack_get_type ()
67 {
68 static GType ui_chart_stack_type = 0;
69
70 if (G_UNLIKELY(ui_chart_stack_type == 0))
71 {
72 const GTypeInfo ui_chart_stack_info =
73 {
74 sizeof (ChartStackClass),
75 NULL, /* base_init */
76 NULL, /* base_finalize */
77 (GClassInitFunc) ui_chart_stack_class_init,
78 NULL, /* class_finalize */
79 NULL, /* class_init */
80 sizeof (ChartStack),
81 0, /* n_preallocs */
82 (GInstanceInitFunc) ui_chart_stack_init,
83 NULL /* value_table */
84 };
85
86 ui_chart_stack_type = g_type_register_static (GTK_TYPE_BOX, "ChartStack",
87 &ui_chart_stack_info, 0);
88
89 }
90 return ui_chart_stack_type;
91 }
92
93
94 static void ui_chart_stack_class_init (ChartStackClass * class)
95 {
96 //GObjectClass *gobject_class;
97 GtkWidgetClass *widget_class;
98
99 DB( g_print("\n[chartstack] class_init\n") );
100
101 //gobject_class = (GObjectClass*) class;
102 widget_class = (GtkWidgetClass*) class;
103
104 parent_class = g_type_class_peek_parent (class);
105
106 //gobject_class->dispose = ui_chart_stack_dispose;
107 //gobject_class->finalize = ui_chart_stack_finalize;
108 //gobject_class->set_property = ui_chart_stack_set_property;
109 //gobject_class->get_property = ui_chart_stack_get_property;
110
111 widget_class->destroy = ui_chart_stack_destroy;
112
113
114 }
115
116 /* get/set properties goes here */
117
118
119 static void
120 ui_chart_stack_init (ChartStack * chart)
121 {
122 GtkWidget *widget, *hbox, *scrollwin;
123
124
125 DB( g_print("\n[chartstack] init\n") );
126
127 chart->surface = NULL;
128 chart->nb_items = 0;
129 chart->active = -1;
130 chart->title = NULL;
131 chart->subtitle = NULL;
132 chart->pfd = NULL;
133
134 chart->budget_title = "Budget";
135 chart->result_title = "Result";
136
137 chart->barw = GTK_CHARTSTACK_BARW;
138 ui_chart_stack_set_color_scheme(chart, CHART_COLMAP_HOMEBANK);
139
140 widget=GTK_WIDGET(chart);
141
142 gtk_box_set_homogeneous(GTK_BOX(widget), FALSE);
143
144 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
145 gtk_box_pack_start (GTK_BOX (widget), hbox, TRUE, TRUE, 0);
146
147 /* drawing area */
148 scrollwin = gtk_frame_new(NULL);
149 gtk_frame_set_shadow_type (GTK_FRAME(scrollwin), GTK_SHADOW_ETCHED_IN);
150 gtk_box_pack_start (GTK_BOX (hbox), scrollwin, TRUE, TRUE, 0);
151
152 //scrollwin = gtk_scrolled_window_new(NULL,NULL);
153 //gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
154 //gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
155 //gtk_box_pack_start (GTK_BOX (hbox), scrollwin, TRUE, TRUE, 0);
156
157 chart->drawarea = gtk_drawing_area_new();
158 //gtk_widget_set_double_buffered (GTK_WIDGET(widget), FALSE);
159
160 gtk_container_add( GTK_CONTAINER(scrollwin), chart->drawarea );
161 gtk_widget_set_size_request(chart->drawarea, 150, 150 );
162 gtk_widget_set_has_tooltip(chart->drawarea, FALSE);
163 gtk_widget_show(chart->drawarea);
164
165 /* scrollbar */
166 chart->adjustment = GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 1.0, 1.0, 1.0, 1.0));
167 chart->scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL,GTK_ADJUSTMENT (chart->adjustment));
168 gtk_box_pack_start (GTK_BOX (hbox), chart->scrollbar, FALSE, TRUE, 0);
169
170 gtk_widget_set_events(GTK_WIDGET(chart->drawarea),
171 GDK_EXPOSURE_MASK |
172 //GDK_POINTER_MOTION_MASK |
173 //GDK_POINTER_MOTION_HINT_MASK |
174 GDK_SCROLL_MASK
175 );
176
177 g_signal_connect( G_OBJECT(chart->drawarea), "configure-event", G_CALLBACK (drawarea_configure_event_callback), chart);
178 //g_signal_connect( G_OBJECT(chart->drawarea), "realize", G_CALLBACK(drawarea_realize_callback), chart ) ;
179 g_signal_connect( G_OBJECT(chart->drawarea), "draw", G_CALLBACK(drawarea_draw_callback), chart );
180 //g_signal_connect( G_OBJECT(chart->drawarea), "query-tooltip", G_CALLBACK(drawarea_querytooltip_callback), chart );
181 g_signal_connect( G_OBJECT(chart->drawarea), "scroll-event", G_CALLBACK(drawarea_scroll_event_callback), chart ) ;
182 g_signal_connect( G_OBJECT(chart->drawarea), "motion-notify-event", G_CALLBACK(drawarea_motionnotifyevent_callback), chart );
183
184 g_signal_connect (G_OBJECT(chart->adjustment), "value-changed", G_CALLBACK (ui_chart_stack_first_changed), chart);
185
186 /*
187 g_signal_connect( G_OBJECT(chart->drawarea), "leave-notify-event", G_CALLBACK(ui_chart_stack_leave), chart );
188 g_signal_connect( G_OBJECT(chart->drawarea), "enter-notify-event", G_CALLBACK(ui_chart_stack_enter), chart );
189 g_signal_connect( G_OBJECT(chart->drawarea), "button-press-event", G_CALLBACK(ui_chart_stack_button_press), chart );
190 g_signal_connect( G_OBJECT(chart->drawarea), "button-release-event", G_CALLBACK(ui_chart_stack_button_release), chart );
191 */
192
193
194 }
195
196
197 GtkWidget *
198 ui_chart_stack_new (void)
199 {
200 GtkWidget *chart;
201
202 chart = (GtkWidget *)g_object_new (GTK_TYPE_CHARTSTACK, NULL);
203
204 return chart;
205 }
206
207
208 void
209 ui_chart_stack_destroy (GtkWidget * object)
210 {
211 ChartStack *chart = GTK_CHARTSTACK(object);
212
213 g_return_if_fail (GTK_IS_CHARTSTACK (object));
214
215 ui_chart_stack_clear(GTK_CHARTSTACK (object), FALSE);
216
217 if(chart->pfd)
218 {
219 pango_font_description_free (chart->pfd);
220 chart->pfd = NULL;
221 }
222
223 if (chart->surface)
224 {
225 cairo_surface_destroy (chart->surface);
226 chart->surface = NULL;
227 }
228
229 GTK_WIDGET_CLASS (parent_class)->destroy (object);
230 }
231
232
233
234
235 /*
236 ** print a integer number
237 */
238 static gchar *ui_chart_stack_print_int(ChartStack *chart, gdouble value)
239 {
240
241 hb_strfmon(chart->buffer, CHART_BUFFER_LENGTH-1, value, chart->kcur, chart->minor);
242 return chart->buffer;
243 }
244
245
246 static void ui_chart_stack_clear(ChartStack *chart, gboolean store)
247 {
248
249 DB( g_print("\n[chartstack] clear\n") );
250
251 //free & clear any previous allocated datas
252 if(chart->title != NULL)
253 {
254 g_free(chart->title);
255 chart->title = NULL;
256 }
257
258 if(chart->subtitle != NULL)
259 {
260 g_free(chart->subtitle);
261 chart->subtitle = NULL;
262 }
263
264 if(chart->items != NULL)
265 {
266 /*for(i=0;i<chart->nb_items;i++)
267 {
268 StackItem *item = &g_array_index(chart->items, StackItem, i);
269
270 //g_free(item->legend);
271 }*/
272 g_array_free(chart->items, TRUE);
273 chart->items = NULL;
274 }
275
276 chart->nb_items = 0;
277
278 }
279
280
281 static void ui_chart_stack_setup_with_model(ChartStack *chart, GtkTreeModel *list_store, gchar *coltitle1, gchar *coltitle2)
282 {
283 guint i;
284 gboolean valid;
285 GtkTreeIter iter;
286
287 DB( g_print("\n[chartstack] setup with model\n") );
288
289 ui_chart_stack_clear(chart, TRUE);
290
291 chart->nb_items = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list_store), NULL);
292
293 chart->items = g_array_sized_new(FALSE, FALSE, sizeof(StackItem), chart->nb_items);
294
295 DB( g_print(" nb=%d\n", chart->nb_items) );
296
297 if(coltitle1)
298 chart->budget_title = coltitle1;
299 if(coltitle2)
300 chart->result_title = coltitle2;
301
302 /* Get the first iter in the list */
303 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(list_store), &iter);
304 i = 0;
305 while (valid)
306 {
307 gint id;
308 gchar *label, *status;
309 gdouble value1, value2;
310 StackItem item;
311
312 gtk_tree_model_get (GTK_TREE_MODEL(list_store), &iter,
313 0, &id,
314 //1, &pos,
315 2, &label,
316 3, &value1, //spent
317 4, &value2, //budget
318 //5, &result,
319 6, &status,
320 -1);
321
322 item.label = label;
323 item.spent = value1;
324 item.budget = value2;
325 item.status = status;
326
327 /* additional pre-compute */
328 item.result = item.spent - item.budget;
329 item.rawrate = 0;
330 if(ABS(item.budget) > 0)
331 {
332 item.rawrate = item.spent / item.budget;
333 }
334
335 item.warn = item.result < 0.0 ? TRUE : FALSE;
336
337 item.rate = CLAMP(item.rawrate, 0, 1.0);
338
339 g_array_append_vals(chart->items, &item, 1);
340
341 i++;
342 valid = gtk_tree_model_iter_next (list_store, &iter);
343 }
344
345 }
346
347
348 static void ui_chart_stack_set_font_size(ChartStack *chart, gint font_size)
349 {
350 gint size = 10;
351
352 DB( g_print("\n[chartstack] set font size\n") );
353
354 switch(font_size)
355 {
356 case CHART_FONT_SIZE_TITLE:
357 size = chart->pfd_size + 3;
358 break;
359 case CHART_FONT_SIZE_SUBTITLE:
360 size = chart->pfd_size + 1;
361 break;
362 case CHART_FONT_SIZE_NORMAL:
363 size = chart->pfd_size - 1;
364 break;
365 }
366
367 DB( g_print(" size=%d\n", size) );
368
369 pango_font_description_set_size(chart->pfd, size * PANGO_SCALE);
370
371 }
372
373
374
375 static void ui_chart_stack_calculation(ChartStack *chart)
376 {
377 GtkWidget *drawarea = chart->drawarea;
378 cairo_surface_t *surf;
379 cairo_t *cr;
380 gint blkw;
381 gint i;
382 int tw, th;
383 gchar *valstr;
384 GtkAllocation allocation;
385 PangoLayout *layout;
386
387 DB( g_print("\n[chartstack] bar calculation\n") );
388
389 gtk_widget_get_allocation(drawarea, &allocation);
390
391 chart->l = CHART_MARGIN;
392 chart->t = CHART_MARGIN;
393 chart->r = allocation.width - CHART_MARGIN;
394 chart->b = allocation.height - CHART_MARGIN;
395 chart->w = allocation.width - (CHART_MARGIN*2);
396 chart->h = allocation.height - (CHART_MARGIN*2);
397
398 //todo: seems not working well...
399 surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height);
400 cr = cairo_create (surf);
401
402 /* Create a PangoLayout, set the font and text */
403 layout = pango_cairo_create_layout (cr);
404
405
406 // compute title
407 chart->title_zh = 0;
408 if(chart->title)
409 {
410 //pango_font_description_set_size(chart->pfd, CHART_FONT_SIZE_TITLE * PANGO_SCALE);
411 ui_chart_stack_set_font_size(chart, CHART_FONT_SIZE_TITLE);
412 pango_layout_set_font_description (layout, chart->pfd);
413
414 pango_layout_set_text (layout, chart->title, -1);
415 pango_layout_get_size (layout, &tw, &th);
416 chart->title_zh = (th / PANGO_SCALE) + CHART_SPACING;
417 DB( g_print(" - title: %s w=%d h=%d\n", chart->title, tw, th) );
418 }
419
420 // compute period
421 chart->subtitle_zh = 0;
422 if(chart->subtitle)
423 {
424 //pango_font_description_set_size(chart->pfd, CHART_FONT_SIZE_PERIOD * PANGO_SCALE);
425 ui_chart_stack_set_font_size(chart, CHART_FONT_SIZE_SUBTITLE);
426 pango_layout_set_font_description (layout, chart->pfd);
427
428 pango_layout_set_text (layout, chart->subtitle, -1);
429 pango_layout_get_size (layout, &tw, &th);
430 chart->subtitle_zh = (th / PANGO_SCALE) + CHART_SPACING;
431 DB( g_print(" - period: %s w=%d h=%d\n", chart->subtitle, tw, th) );
432 }
433
434 // compute other text
435 //pango_font_description_set_size(chart->pfd, CHART_FONT_SIZE_NORMAL * PANGO_SCALE);
436 ui_chart_stack_set_font_size(chart, CHART_FONT_SIZE_NORMAL);
437 pango_layout_set_font_description (layout, chart->pfd);
438
439 double title_w = 0;
440 chart->bud_col_w = 0;
441 chart->rel_col_w = 0;
442
443 gdouble maxbudget = 0;
444 gdouble maxresult = 0;
445 gdouble result;
446 for(i=0;i<chart->nb_items;i++)
447 {
448 StackItem *item = &g_array_index(chart->items, StackItem, i);
449
450 // category width
451 pango_layout_set_text (layout, item->label, -1);
452 pango_layout_get_size (layout, &tw, &th);
453 title_w = MAX(title_w, (tw / PANGO_SCALE));
454
455 DB( g_print(" - calc '%s' title_w=%f (w=%d)\n", item->label, title_w, tw) );
456
457 //result = ABS(chart->spent[i]) - ABS(chart->budget[i]);
458 result = ABS(item->spent - item->budget);
459
460 maxbudget = MAX(maxbudget, ABS(item->budget) );
461 maxresult = MAX(maxresult, result);
462
463 DB( g_print(" - maxbudget maxbudget=%f (w=%d)\n", maxbudget, tw) );
464
465 pango_layout_set_text (layout, item->status, -1);
466 pango_layout_get_size (layout, &tw, &th);
467 chart->rel_col_w = MAX(chart->rel_col_w, (tw / PANGO_SCALE));
468 }
469
470 chart->rel_col_w += CHART_SPACING;
471
472 // compute budget/result width
473 valstr = ui_chart_stack_print_int(chart, -maxbudget);
474 pango_layout_set_text (layout, valstr, -1);
475 pango_layout_get_size (layout, &tw, &th);
476 chart->bud_col_w = (tw / PANGO_SCALE);
477 pango_layout_set_text (layout, chart->budget_title, -1);
478 pango_layout_get_size (layout, &tw, &th);
479 chart->bud_col_w = MAX(chart->bud_col_w, (tw / PANGO_SCALE));
480 DB( g_print(" - budget-col: w=%f, %.2f, '%s'\n", chart->bud_col_w, maxbudget, valstr) );
481
482
483 valstr = ui_chart_stack_print_int(chart, -maxresult);
484 pango_layout_set_text (layout, valstr, -1);
485 pango_layout_get_size (layout, &tw, &th);
486 chart->res_col_w = (tw / PANGO_SCALE);
487 pango_layout_set_text (layout, chart->result_title, -1);
488 pango_layout_get_size (layout, &tw, &th);
489 chart->res_col_w = MAX(chart->res_col_w, (tw / PANGO_SCALE));
490 DB( g_print(" - result-col: w=%f, %.2f, '%s'\n", chart->res_col_w, maxresult, valstr) );
491
492
493 // collect other width, add margins
494 chart->header_zh = (th / PANGO_SCALE) + CHART_SPACING;
495 chart->cat_col_w = title_w + CHART_SPACING;
496
497 //chart->title_y = chart->t;
498 chart->subtitle_y = chart->t + chart->title_zh;
499 chart->header_y = chart->subtitle_y + chart->subtitle_zh;
500
501
502 chart->graph_width = chart->w - chart->cat_col_w - chart->bud_col_w - chart->res_col_w - chart->rel_col_w - (double)(CHART_SPACING*4);
503 chart->graph_height = chart->h - chart->title_zh - chart->subtitle_zh -chart->header_zh;
504
505
506 DB( g_print("gfx_w = %.2f - %.2f - %.2f - %.2f - %.2f \n",
507 chart->w , chart->cat_col_w , chart->bud_col_w , chart->res_col_w , (double)(CHART_SPACING*4)) );
508
509 DB( g_print("gfx_w = %.2f\n", chart->graph_width) );
510
511 //if expand : we compute available space
512 //chart->barw = MAX(32, (chart->graph_width)/chart->nb_items);
513 //chart->barw = 32; // usr setted or defaut to BARW
514
515 blkw = chart->barw + floor(chart->barw * 0.2);
516 chart->blkw = blkw;
517
518 chart->visible = (chart->graph_height - chart->t) / blkw;
519 chart->visible = MIN(chart->visible, chart->nb_items);
520
521 g_object_unref (layout);
522
523 cairo_destroy(cr);
524 cairo_surface_destroy(surf);
525
526 }
527
528
529 #if HELPDRAW == 1
530 static void ui_chart_stack_draw_help(GtkWidget *widget, gpointer user_data)
531 {
532 ChartStack *chart = GTK_CHARTSTACK(user_data);
533 cairo_t *cr;
534 double x, y, y2;
535 gint first = 0;
536 gint i;
537
538 //cr = gdk_cairo_create (gtk_widget_get_window(widget));
539 cr = cairo_create (chart->surface);
540
541 cairo_set_line_width (cr, 1);
542
543
544 cairo_set_line_width(cr, 1.0);
545 cairo_set_source_rgb(cr, 0.0, 1.0, 0.0); //green
546 cairo_rectangle(cr, chart->l+0.5, chart->t+0.5, chart->w, chart->h);
547 cairo_stroke(cr);
548
549
550 //title rect
551 cairo_set_source_rgb(cr, .0, .0, 1.0);
552 cairo_rectangle(cr, chart->l+0.5, chart->t+0.5, chart->w, chart->title_zh);
553 cairo_stroke(cr);
554
555 //period rect
556 cairo_set_source_rgb(cr, .0, 0, 1.0);
557 cairo_rectangle(cr, chart->l+0.5, chart->subtitle_y+0.5, chart->w, chart->subtitle_zh);
558 cairo_stroke(cr);
559
560 //header rect
561 cairo_set_source_rgb(cr, .0, 1.0, 1.0);
562 cairo_rectangle(cr, chart->l+0.5, chart->header_y+0.5, chart->w, chart->header_zh);
563 cairo_stroke(cr);
564
565 //category column
566 y = chart->t + chart->title_zh + chart->header_zh + chart->subtitle_zh;
567 cairo_set_source_rgb(cr, 0.0, 0.0, 1.0); //blue
568 cairo_rectangle(cr, chart->l+0.5, y+0.5, chart->cat_col_w, chart->h - y);
569 cairo_stroke(cr);
570
571 //budget column
572 x = chart->l + chart->cat_col_w + chart->graph_width + CHART_SPACING ;
573 cairo_set_source_rgb(cr, 0.0, 0.0, 1.0); //blue
574 cairo_rectangle(cr, x+0.5, y+0.5, chart->bud_col_w, chart->h - y);
575 cairo_stroke(cr);
576
577 //result column
578 x = chart->l + chart->cat_col_w + chart->graph_width + chart->bud_col_w + (CHART_SPACING*3);
579 cairo_set_source_rgb(cr, 0.0, 0.0, 1.0); //blue
580 cairo_rectangle(cr, x+0.5, y+0.5, chart->res_col_w, chart->h - y);
581 cairo_stroke(cr);
582
583
584 // draw item lines
585 y = chart->header_y + chart->header_zh;
586
587 cairo_set_source_rgb(cr, 1.0, .0, .0);
588 cairo_rectangle(cr, chart->l+chart->cat_col_w+0.5, y+0.5, chart->graph_width+0.5, chart->graph_height+0.5);
589 cairo_stroke(cr);
590
591
592
593 y2 = y+0.5;
594 cairo_set_line_width(cr, 1.0);
595 double dashlength;
596 dashlength = 4;
597 cairo_set_dash (cr, &dashlength, 1, 0);
598 cairo_set_source_rgb(cr, 1.0, 0.0, 1.0); // violet
599 for(i=first; i<=(first+chart->visible) ;i++)
600 {
601 cairo_move_to(cr, chart->l, y2);
602 cairo_line_to(cr, chart->r, y2);
603
604 y2 += chart->blkw;
605 }
606 cairo_stroke(cr);
607
608 cairo_destroy(cr);
609
610 }
611 #endif
612
613
614 /*
615 ** draw all visible bars
616 */
617 static void ui_chart_stack_draw_bars(ChartStack *chart, cairo_t *cr)
618 {
619 double x, y, x2, y2, h;
620 gint first;
621 gint i, idx;
622 gchar *valstr;
623 PangoLayout *layout;
624 int tw, th;
625
626 DB( g_print("\n[chartstack] bar draw bars\n") );
627
628 layout = pango_cairo_create_layout (cr);
629
630 x = chart->l + chart->cat_col_w;
631 y = chart->t + chart->title_zh + chart->header_zh + chart->subtitle_zh;
632 first = (gint)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
633
634 // draw title
635 if(chart->title)
636 {
637 //pango_font_description_set_size(chart->pfd, CHART_FONT_SIZE_TITLE * PANGO_SCALE);
638 ui_chart_stack_set_font_size(chart, CHART_FONT_SIZE_TITLE);
639 pango_layout_set_font_description (layout, chart->pfd);
640 pango_layout_set_text (layout, chart->title, -1);
641 pango_layout_get_size (layout, &tw, &th);
642
643 cairo_user_set_rgbcol(cr, &global_colors[THTEXT]);
644 cairo_move_to(cr, chart->l, chart->t);
645 pango_cairo_show_layout (cr, layout);
646 }
647
648 // draw period
649 if(chart->subtitle)
650 {
651 //pango_font_description_set_size(chart->pfd, CHART_FONT_SIZE_PERIOD * PANGO_SCALE);
652 ui_chart_stack_set_font_size(chart, CHART_FONT_SIZE_SUBTITLE);
653 pango_layout_set_font_description (layout, chart->pfd);
654 pango_layout_set_text (layout, chart->subtitle, -1);
655 pango_layout_get_size (layout, &tw, &th);
656
657 cairo_user_set_rgbcol(cr, &global_colors[THTEXT]);
658 cairo_move_to(cr, chart->l, chart->subtitle_y);
659 pango_cairo_show_layout (cr, layout);
660 }
661
662 // draw column title
663 //cairo_user_set_rgbcol(cr, &global_colors[BLACK]);
664 cairo_user_set_rgbacol (cr, &global_colors[THTEXT], 0.78);
665 //pango_font_description_set_size(chart->pfd, CHART_FONT_SIZE_NORMAL * PANGO_SCALE);
666 ui_chart_stack_set_font_size(chart, CHART_FONT_SIZE_NORMAL);
667 pango_layout_set_font_description (layout, chart->pfd);
668
669 pango_layout_set_text (layout, chart->budget_title, -1);
670 pango_layout_get_size (layout, &tw, &th);
671 cairo_move_to(cr, chart->l + chart->cat_col_w + chart->graph_width + chart->bud_col_w + CHART_SPACING - (tw /PANGO_SCALE), chart->header_y);
672 pango_cairo_show_layout (cr, layout);
673
674 pango_layout_set_text (layout, chart->result_title, -1);
675 pango_layout_get_size (layout, &tw, &th);
676 cairo_move_to(cr, chart->l + chart->cat_col_w + chart->graph_width + chart->bud_col_w + chart->res_col_w - (tw /PANGO_SCALE) + (CHART_SPACING*3), chart->header_y);
677 pango_cairo_show_layout (cr, layout);
678
679
680 // draw items
681 //pango_font_description_set_size(chart->pfd, CHART_FONT_SIZE_NORMAL * PANGO_SCALE);
682 ui_chart_stack_set_font_size(chart, CHART_FONT_SIZE_NORMAL);
683 pango_layout_set_font_description (layout, chart->pfd);
684
685 for(i=0; i<chart->visible ;i++)
686 {
687 StackItem *item;
688 gint barw = chart->barw;
689 gint blkw = chart->blkw;
690
691 idx = i + first;
692
693 item = &g_array_index(chart->items, StackItem, idx);
694
695 x2 = x;
696 y2 = y + (CHART_SPACING/2) + (blkw * i);
697
698 DB( g_print("'%-32s' wrn=%d %.2f%% (%.2f%%) :: r=% 4.2f s=% 4.2f b=% 4.2f\n",
699 item->label, item->warn, item->rawrate, item->rate, item->result, item->spent, item->budget) );
700
701 valstr = item->label;
702 pango_layout_set_text (layout, valstr, -1);
703 pango_layout_get_size (layout, &tw, &th);
704
705 double ytext = y2 + ((barw - (th / PANGO_SCALE))/2);
706
707 //cairo_user_set_rgbcol(cr, &global_colors[BLACK]);
708 cairo_user_set_rgbacol (cr, &global_colors[THTEXT], 0.78);
709 cairo_move_to(cr, chart->l + chart->cat_col_w - (tw / PANGO_SCALE) - CHART_SPACING, ytext);
710 pango_cairo_show_layout (cr, layout);
711
712 // bar background
713 cairo_user_set_rgbacol(cr, &global_colors[THTEXT], 0.15);
714 cairo_rectangle(cr, x2, y2, chart->graph_width, barw);
715 cairo_fill(cr);
716
717 //bar with color :: todo migrate this
718 h = floor(item->rate * chart->graph_width);
719 if(item->warn)
720 {
721 cairo_user_set_rgbcol_over(cr, &chart->color_scheme.colors[chart->color_scheme.cs_red], idx == chart->active);
722 }
723 else
724 {
725 if(item->rate > 0.8 && item->rate < 1.0)
726 cairo_user_set_rgbcol_over(cr, &chart->color_scheme.colors[chart->color_scheme.cs_orange], idx == chart->active);
727 else
728 cairo_user_set_rgbcol_over(cr, &chart->color_scheme.colors[chart->color_scheme.cs_green], idx == chart->active);
729 }
730
731
732 cairo_rectangle(cr, x2, y2, h, barw);
733 cairo_fill(cr);
734
735 // spent value
736 if( item->result != 0)
737 {
738 valstr = ui_chart_stack_print_int(chart, item->spent);
739 pango_layout_set_text (layout, valstr, -1);
740 pango_layout_get_size (layout, &tw, &th);
741
742 if( h >= ( (tw / PANGO_SCALE) + (CHART_SPACING*2)) )
743 {
744 // draw inside
745 cairo_user_set_rgbcol(cr, &global_colors[WHITE]);
746 //cairo_user_set_rgbcol (cr, &global_colors[THBASE]);
747 cairo_move_to(cr, x2 + h - (tw / PANGO_SCALE) - CHART_SPACING, ytext);
748 }
749 else
750 {
751 // draw outside
752 //cairo_user_set_rgbcol(cr, &global_colors[TEXT]);
753 cairo_user_set_rgbacol (cr, &global_colors[THTEXT], 0.78);
754 cairo_move_to(cr, x2 + h + CHART_SPACING, ytext);
755 }
756
757 pango_cairo_show_layout (cr, layout);
758 }
759
760 // budget value
761 valstr = ui_chart_stack_print_int(chart, item->budget);
762 pango_layout_set_text (layout, valstr, -1);
763 pango_layout_get_size (layout, &tw, &th);
764 //cairo_user_set_rgbcol(cr, &global_colors[BLACK]);
765 cairo_user_set_rgbacol (cr, &global_colors[THTEXT], 0.78);
766 cairo_move_to(cr, chart->l + chart->cat_col_w + chart->graph_width + chart->bud_col_w + CHART_SPACING - (tw / PANGO_SCALE), ytext);
767 pango_cairo_show_layout (cr, layout);
768
769 // result value
770
771 if( item->result != 0)
772 {
773 valstr = ui_chart_stack_print_int(chart, item->result);
774
775 if(item->warn)
776 //cairo_set_source_rgb(cr, COLTOCAIRO(164), COLTOCAIRO(0), COLTOCAIRO(0));
777 cairo_user_set_rgbcol(cr, &chart->color_scheme.colors[chart->color_scheme.cs_red]);
778 else
779 //cairo_user_set_rgbcol(cr, &global_colors[TEXT]);
780 cairo_user_set_rgbacol (cr, &global_colors[THTEXT], 0.78);
781
782 pango_layout_set_text (layout, valstr, -1);
783 pango_layout_get_size (layout, &tw, &th);
784 cairo_move_to(cr, chart->l + chart->cat_col_w + chart->graph_width + chart->bud_col_w + chart->res_col_w - (tw / PANGO_SCALE) + (CHART_SPACING*3), ytext);
785 pango_cairo_show_layout (cr, layout);
786
787 // status
788 pango_layout_set_text (layout, item->status, -1);
789 pango_layout_get_size (layout, &tw, &th);
790 cairo_move_to(cr, chart->l + chart->cat_col_w + chart->graph_width + chart->bud_col_w + chart->res_col_w + (CHART_SPACING*4), ytext);
791 pango_cairo_show_layout (cr, layout);
792 }
793
794 //y += blkw;
795
796 }
797
798 g_object_unref (layout);
799
800 }
801
802
803 /*
804 ** get the bar under the mouse pointer
805 */
806 static gint ui_chart_stack_get_active(GtkWidget *widget, gint x, gint y, gpointer user_data)
807 {
808 ChartStack *chart = GTK_CHARTSTACK(user_data);
809 gint retval, first, index, py;
810 gint blkw = chart->blkw;
811 double oy;
812
813 retval = -1;
814
815 oy = chart->t + chart->title_zh + chart->header_zh + chart->subtitle_zh;
816
817 //DB( g_print(" y=%d, oy=%f, cb=%f\n", y, oy, chart->b) );
818
819
820 if( (y <= chart->b && y >= oy) && (x >= chart->l && x <= chart->r) )
821 {
822 first = gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
823 py = (y - oy);
824 index = first + (py / blkw);
825
826
827 if(index < chart->nb_items)
828 retval = index;
829
830 //DB( g_print(" hover=%d\n", retval) );
831 }
832
833 return(retval);
834 }
835
836
837 static void ui_chart_stack_first_changed( GtkAdjustment *adj, gpointer user_data)
838 {
839 ChartStack *chart = GTK_CHARTSTACK(user_data);
840 //gint first;
841
842 DB( g_print("\n[chartstack] bar first changed\n") );
843
844 //first = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj));
845
846 //DB( g_print(" first=%d\n", first) );
847
848 /*
849 DB( g_print("scrollbar\n adj=%8x, low=%.2f upp=%.2f val=%.2f step=%.2f page=%.2f size=%.2f\n", adj,
850 adj->lower, adj->upper, adj->value, adj->step_increment, adj->page_increment, adj->page_size) );
851 */
852 /* Set the number of decimal places to which adj->value is rounded */
853 //gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
854 //gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
855 gtk_widget_queue_draw(chart->drawarea);
856
857 }
858
859 /*
860 ** scrollbar set values for upper, page size, and also show/hide
861 */
862 static void ui_chart_stack_scrollbar_setvalues(ChartStack *chart)
863 {
864 GtkAdjustment *adj = chart->adjustment;
865 gint first;
866
867 g_return_if_fail (GTK_IS_ADJUSTMENT (adj));
868
869 DB( g_print("\n[chartstack] sb_set_values\n") );
870
871 //if(visible < entries)
872 //{
873 first = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj));
874
875 DB( g_print(" entries=%d, visible=%d\n", chart->nb_items, chart->visible) );
876 DB( g_print(" first=%d, upper=%d, pagesize=%d\n", first, chart->nb_items, chart->visible) );
877
878 gtk_adjustment_set_upper(adj, (gdouble)chart->nb_items);
879 gtk_adjustment_set_page_size(adj, (gdouble)chart->visible);
880 gtk_adjustment_set_page_increment(adj, (gdouble)chart->visible);
881
882 if(first+chart->visible > chart->nb_items)
883 {
884 gtk_adjustment_set_value(adj, (gdouble)chart->nb_items - chart->visible);
885 }
886
887 gtk_adjustment_changed (adj);
888
889 //gtk_widget_show(GTK_WIDGET(scrollbar));
890 //}
891 //else
892 //gtk_widget_hide(GTK_WIDGET(scrollbar));
893
894
895 }
896
897
898 static void ui_chart_stack_recompute(ChartStack *chart)
899 {
900
901 DB( g_print("\n[chartstack] recompute\n") );
902
903 ui_chart_stack_calculation(chart);
904 gtk_adjustment_set_value(chart->adjustment, 0);
905 ui_chart_stack_scrollbar_setvalues(chart);
906 gtk_widget_show(chart->scrollbar);
907
908 gtk_widget_queue_draw( chart->drawarea );
909 }
910
911
912 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
913 static gboolean drawarea_full_redraw(GtkWidget *widget, gpointer user_data)
914 {
915 ChartStack *chart = GTK_CHARTSTACK(user_data);
916 cairo_t *cr;
917
918 DB( g_print("\n[gtkchart] drawarea full redraw\n") );
919
920 cr = cairo_create (chart->surface);
921
922 /* fillin the back in white */
923 //cairo_user_set_rgbcol(cr, &global_colors[WHITE]);
924 cairo_user_set_rgbcol(cr, &global_colors[THBASE]);
925
926 cairo_paint(cr);
927
928 if(chart->nb_items == 0)
929 {
930 cairo_destroy(cr);
931 return FALSE;
932 }
933
934 #if HELPDRAW == 1
935 ui_chart_stack_draw_help(widget, user_data);
936 #endif
937
938 ui_chart_stack_draw_bars(chart, cr);
939
940 cairo_destroy(cr);
941
942 return TRUE;
943 }
944
945
946 static gboolean
947 drawarea_configure_event_callback (GtkWidget *widget,
948 GdkEventConfigure *event,
949 gpointer user_data)
950 {
951 ChartStack *chart = GTK_CHARTSTACK(user_data);
952 GtkAllocation allocation;
953 GtkStyleContext *context;
954 PangoFontDescription *desc;
955 gboolean colfound;
956 GdkRGBA color;
957
958 DB( g_print("\n[chartstack] drawarea configure \n") );
959
960 DB( g_print("w=%d h=%d\n", allocation.width, allocation.height) );
961
962 gtk_widget_get_allocation (widget, &allocation);
963
964 if (chart->surface)
965 cairo_surface_destroy (chart->surface);
966
967 chart->surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
968 CAIRO_CONTENT_COLOR,
969 allocation.width,
970 allocation.height);
971
972 context = gtk_widget_get_style_context (widget);
973
974 chart_color_global_default();
975
976 // get base color
977 colfound = gtk_style_context_lookup_color(context, "theme_base_color", &color);
978 if(!colfound)
979 colfound = gtk_style_context_lookup_color(context, "base_color", &color);
980
981 if( colfound )
982 {
983 struct rgbcol *tcol = &global_colors[THBASE];
984 tcol->r = color.red * 255;
985 tcol->g = color.green * 255;
986 tcol->b = color.blue * 255;
987 DB( g_print(" - theme base col: %x %x %x\n", tcol->r, tcol->g, tcol->b) );
988 }
989
990 //get text color
991 colfound = gtk_style_context_lookup_color(context, "theme_fg_color", &color);
992 if(!colfound)
993 gtk_style_context_lookup_color(context, "fg_color", &color);
994
995 if( colfound )
996 {
997 struct rgbcol *tcol = &global_colors[THTEXT];
998 tcol->r = color.red * 255;
999 tcol->g = color.green * 255;
1000 tcol->b = color.blue * 255;
1001 DB( g_print(" - theme text (bg) col: %x %x %x\n", tcol->r, tcol->g, tcol->b) );
1002 }
1003
1004 /* get and copy the font */
1005 gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, "font", &desc, NULL);
1006 if(chart->pfd)
1007 {
1008 pango_font_description_free (chart->pfd);
1009 chart->pfd = NULL;
1010 }
1011 chart->pfd = pango_font_description_copy(desc);
1012 chart->pfd_size = pango_font_description_get_size (desc) / PANGO_SCALE;
1013 chart->barw = (6 + chart->pfd_size) * PHI;
1014
1015 DB( g_print("family: %s\n", pango_font_description_get_family(chart->pfd) ) );
1016 DB( g_print("size : %d (%d)\n", chart->pfd_size, chart->pfd_size/PANGO_SCALE ) );
1017 DB( g_print("isabs : %d\n", pango_font_description_get_size_is_absolute (chart->pfd) ) );
1018
1019 if( gtk_widget_get_realized(widget) )
1020 {
1021 ui_chart_stack_recompute(chart);
1022 drawarea_full_redraw(widget, user_data);
1023 }
1024
1025 /* We've handled the configure event, no need for further processing. */
1026 return TRUE;
1027 }
1028
1029
1030 static gboolean drawarea_draw_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data)
1031 {
1032 ChartStack *chart = GTK_CHARTSTACK(user_data);
1033
1034 if( !gtk_widget_get_realized(widget) || chart->surface == NULL )
1035 return FALSE;
1036
1037 //DB( g_print("\n[chartstack] drawarea draw cb\n") );
1038
1039 cairo_set_source_surface (cr, chart->surface, 0, 0);
1040 cairo_paint (cr);
1041
1042 /* always redraw directly the active block */
1043 gint first;
1044 double ox, oy;
1045
1046 first = (gint)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
1047 ox = chart->l + chart->cat_col_w;
1048 oy = chart->t + chart->title_zh + chart->header_zh + chart->subtitle_zh;
1049
1050
1051 if(chart->active != -1)
1052 {
1053 DB( g_print(" draw active\n") );
1054
1055 oy += CHART_SPACING/2 + (chart->active - first) * chart->blkw;
1056 //cairo_user_set_rgbacol (cr, &global_colors[THTEXT], 0.78);
1057 cairo_user_set_rgbacol(cr, &global_colors[WHITE], OVER_ALPHA);
1058 //cairo_move_to(cr, chart->l, chart->t);
1059 cairo_rectangle(cr, ox, oy, chart->graph_width, chart->barw);
1060 cairo_fill(cr);
1061 }
1062
1063 return FALSE;
1064 }
1065
1066
1067 static gboolean drawarea_motionnotifyevent_callback(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
1068 {
1069 ChartStack *chart = GTK_CHARTSTACK(user_data);
1070 gint x, y;
1071
1072 if(chart->nb_items == 0)
1073 return FALSE;
1074
1075 DB( g_print("\n[chartstack] drawarea motion cb\n") );
1076 x = event->x;
1077 y = event->y;
1078
1079 //todo see this
1080 if(event->is_hint)
1081 {
1082 //DB( g_print(" is hint\n") );
1083
1084 gdk_window_get_device_position(event->window, event->device, &x, &y, NULL);
1085 //gdk_window_get_pointer(event->window, &x, &y, NULL);
1086 //return FALSE;
1087 }
1088
1089 chart->active = ui_chart_stack_get_active(widget, x, y, chart);
1090
1091
1092 // rollover redraw ?
1093 DB( g_print(" %d, %d :: active: last=%d, curr=%d\n", x, y, chart->lastactive, chart->active) );
1094
1095 if(chart->lastactive != chart->active)
1096 {
1097 GdkRectangle update_rect;
1098 gint first;
1099 double oy;
1100
1101 DB( g_print(" motion rollover redraw :: active=%d\n", chart->active) );
1102
1103 first = (gint)gtk_adjustment_get_value(GTK_ADJUSTMENT(chart->adjustment));
1104 oy = chart->t + chart->title_zh + chart->header_zh + chart->subtitle_zh;
1105
1106 if(chart->lastactive != -1)
1107 {
1108 update_rect.x = chart->l;
1109 update_rect.y = oy + (chart->lastactive - first) * chart->blkw;
1110 update_rect.width = chart->r;
1111 update_rect.height = chart->blkw;
1112
1113 /* Now invalidate the affected region of the drawing area. */
1114 gdk_window_invalidate_rect (gtk_widget_get_window (widget),
1115 &update_rect,
1116 FALSE);
1117 }
1118
1119 update_rect.x = chart->l;
1120 update_rect.y = oy + (chart->active - first) * chart->blkw;
1121 update_rect.width = chart->r;
1122 update_rect.height = chart->blkw;
1123
1124 /* Now invalidate the affected region of the drawing area. */
1125 gdk_window_invalidate_rect (gtk_widget_get_window (widget),
1126 &update_rect,
1127 FALSE);
1128
1129 //gtk_widget_queue_draw( widget );
1130 //retval = FALSE;
1131 }
1132
1133 chart->lastactive = chart->active;
1134
1135 return TRUE;
1136 }
1137
1138
1139
1140 static gboolean drawarea_scroll_event_callback( GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
1141 {
1142 ChartStack *chart = GTK_CHARTSTACK(user_data);
1143 GtkAdjustment *adj = chart->adjustment;
1144 gdouble first, upper, pagesize;
1145
1146 DB( g_print("\n[chartstack] scroll\n") );
1147
1148 first = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj));
1149 //lower = gtk_adjustment_get_lower(GTK_ADJUSTMENT(adj));
1150 upper = gtk_adjustment_get_upper(GTK_ADJUSTMENT(adj));
1151 pagesize = gtk_adjustment_get_page_size(GTK_ADJUSTMENT(adj));
1152
1153 DB( g_print("- pos is %.2f, [%.2f - %.2f]\n", first, 0.0, upper) );
1154
1155 switch(event->direction)
1156 {
1157 case GDK_SCROLL_UP:
1158 gtk_adjustment_set_value(adj, first - 1);
1159 break;
1160 case GDK_SCROLL_DOWN:
1161 gtk_adjustment_set_value(adj, CLAMP(first + 1, 0, upper - pagesize) );
1162 break;
1163 default:
1164 break;
1165 }
1166
1167 drawarea_full_redraw(widget, user_data);
1168
1169 return TRUE;
1170 }
1171
1172
1173 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1174 /* public functions */
1175 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1176
1177 static void ui_chart_stack_queue_redraw(ChartStack *chart)
1178 {
1179
1180 if( gtk_widget_get_realized(GTK_WIDGET(chart)) )
1181 {
1182 ui_chart_stack_recompute(chart);
1183 drawarea_full_redraw(chart->drawarea, chart);
1184 //gtk_widget_queue_draw( chart->drawarea );
1185 }
1186 }
1187
1188 /*
1189 ** change the model and/or column
1190 */
1191 void ui_chart_stack_set_dualdatas(ChartStack *chart, GtkTreeModel *model, gchar *coltitle1, gchar *coltitle2, gchar *title, gchar *subtitle)
1192 {
1193 g_return_if_fail (GTK_IS_CHARTSTACK (chart));
1194
1195 if( GTK_IS_TREE_MODEL(model) )
1196 {
1197 ui_chart_stack_setup_with_model(chart, model, coltitle1, coltitle2 );
1198 if(title != NULL)
1199 chart->title = g_strdup(title);
1200 if(subtitle != NULL)
1201 chart->subtitle = g_strdup(subtitle);
1202
1203 ui_chart_stack_queue_redraw(chart);
1204 }
1205 else
1206 {
1207 ui_chart_stack_clear(chart, TRUE);
1208 }
1209 }
1210
1211 /*
1212 ** change the tooltip title
1213 */
1214 void ui_chart_stack_set_title(ChartStack * chart, gchar *title)
1215 {
1216 g_return_if_fail (GTK_IS_CHARTSTACK (chart));
1217
1218 chart->title = g_strdup(title);
1219
1220 DB( g_print("\n[chartstack] set title = %s\n", chart->title) );
1221
1222 ui_chart_stack_recompute(chart);
1223
1224 }
1225
1226 void ui_chart_stack_set_subtitle(ChartStack * chart, gchar *subtitle)
1227 {
1228 g_return_if_fail (GTK_IS_CHARTSTACK (chart));
1229
1230 chart->subtitle = g_strdup(subtitle);
1231
1232 DB( g_print("\n[chartstack] set period = %s\n", chart->subtitle) );
1233
1234 ui_chart_stack_recompute(chart);
1235
1236 }
1237
1238
1239 /*
1240 ** change the minor visibility
1241 */
1242 void ui_chart_stack_show_minor(ChartStack * chart, gboolean minor)
1243 {
1244 g_return_if_fail (GTK_IS_CHARTSTACK (chart));
1245
1246 chart->minor = minor;
1247
1248 ui_chart_stack_queue_redraw(chart);
1249
1250 }
1251
1252 void ui_chart_stack_set_color_scheme(ChartStack * chart, gint index)
1253 {
1254 colorscheme_init(&chart->color_scheme, index);
1255 }
1256
1257
1258 /*
1259 ** set the minor parameters
1260 */
1261 /*void ui_chart_stack_set_minor_prefs(ChartStack * chart, gdouble rate, gchar *symbol)
1262 {
1263 g_return_if_fail (GTK_IS_CHARTSTACK (chart));
1264
1265 chart->minor_rate = rate;
1266 chart->minor_symbol = symbol;
1267 }*/
1268
1269 void ui_chart_stack_set_currency(ChartStack * chart, guint32 kcur)
1270 {
1271 g_return_if_fail (GTK_IS_CHARTSTACK (chart));
1272
1273 chart->kcur = kcur;
1274 }
1275
This page took 0.097198 seconds and 4 git commands to generate.