1 /* gtkplotflux - flux plots widget for gtk+
2  * Copyright 1999-2001  Adrian E. Feiguin <feiguin@ifir.edu.ar>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <math.h>
24 #include <gtk/gtk.h>
25 #include "gtkplot.h"
26 #include "gtkplot3d.h"
27 #include "gtkplotdata.h"
28 #include "gtkplotflux.h"
29 #include "gtkpsfont.h"
30 
31 #define P_(string) string
32 
33 static void gtk_plot_flux_class_init 	(GtkPlotFluxClass *klass);
34 static void gtk_plot_flux_init 		(GtkPlotFlux *data);
35 static void gtk_plot_flux_destroy 	(GtkObject *data);
36 static void gtk_plot_flux_get_property  (GObject      *object,
37                                          guint            prop_id,
38                                          GValue          *value,
39                                          GParamSpec      *pspec);
40 static void gtk_plot_flux_set_property  (GObject      *object,
41                                          guint            prop_id,
42                                          const GValue          *value,
43                                          GParamSpec      *pspec);
44 
45 static void gtk_plot_flux_get_legend_size(GtkPlotData *data,
46 					 gint *width, gint *height);
47 static void gtk_plot_flux_draw_legend	(GtkPlotData *data,
48 					 gint x, gint y);
49 static void gtk_plot_flux_draw_symbol	(GtkPlotData *data,
50                                          gdouble x,
51 					 gdouble y,
52 					 gdouble z,
53 					 gdouble a,
54                                          gdouble dx,
55 					 gdouble dy,
56 					 gdouble dz,
57 					 gdouble da);
58 static void gtk_plot_flux_draw_arrow	(GtkPlotFlux *flux,
59                                          gdouble x1, gdouble y1,
60                                          gdouble x2, gdouble y2);
61 
62 
63 extern gint roundint (gdouble x);
64 
65 enum {
66   ARG_0,
67   ARG_CENTERED,
68   ARG_STYLE,
69   ARG_WIDTH,
70   ARG_LENGTH,
71   ARG_SCALE_MAX,
72   ARG_SIZE_MAX,
73   ARG_SHOW_SCALE,
74   ARG_LABEL_PRECISION,
75   ARG_LABEL_STYLE,
76   ARG_LABEL_PREFIX,
77   ARG_LABEL_SUFFIX,
78 };
79 
80 static GtkPlotDataClass *parent_class = NULL;
81 
82 GtkType
gtk_plot_flux_get_type(void)83 gtk_plot_flux_get_type (void)
84 {
85   static GtkType data_type = 0;
86 
87   if (!data_type)
88     {
89       GtkTypeInfo data_info =
90       {
91 	"GtkPlotFlux",
92 	sizeof (GtkPlotFlux),
93 	sizeof (GtkPlotFluxClass),
94 	(GtkClassInitFunc) gtk_plot_flux_class_init,
95 	(GtkObjectInitFunc) gtk_plot_flux_init,
96 	/* reserved 1*/ NULL,
97         /* reserved 2 */ NULL,
98         (GtkClassInitFunc) NULL,
99       };
100 
101       data_type = gtk_type_unique (gtk_plot_data_get_type(), &data_info);
102     }
103   return data_type;
104 }
105 
106 static void
gtk_plot_flux_class_init(GtkPlotFluxClass * klass)107 gtk_plot_flux_class_init (GtkPlotFluxClass *klass)
108 {
109   GtkObjectClass *object_class;
110   GtkWidgetClass *widget_class;
111   GtkPlotDataClass *data_class;
112   GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
113 
114   parent_class = gtk_type_class (gtk_plot_data_get_type ());
115 
116   object_class = (GtkObjectClass *) klass;
117   widget_class = (GtkWidgetClass *) klass;
118   data_class = (GtkPlotDataClass *) klass;
119 
120   gobject_class->set_property = gtk_plot_flux_set_property;
121   gobject_class->get_property = gtk_plot_flux_get_property;
122   object_class->destroy = gtk_plot_flux_destroy;
123 
124   g_object_class_install_property (gobject_class,
125                            ARG_CENTERED,
126   g_param_spec_boolean ("centered",
127                            P_(""),
128                            P_(""),
129                            FALSE,
130                            G_PARAM_READABLE|G_PARAM_WRITABLE));
131   g_object_class_install_property (gobject_class,
132                            ARG_STYLE,
133   g_param_spec_int ("style",
134                            P_(""),
135                            P_(""),
136                            0,G_MAXINT,0,
137                            G_PARAM_READABLE|G_PARAM_WRITABLE));
138   g_object_class_install_property (gobject_class,
139                            ARG_WIDTH,
140   g_param_spec_int ("width",
141                            P_(""),
142                            P_(""),
143                            0,G_MAXINT,0,
144                            G_PARAM_READABLE|G_PARAM_WRITABLE));
145   g_object_class_install_property (gobject_class,
146                            ARG_LENGTH,
147   g_param_spec_int ("length",
148                            P_(""),
149                            P_(""),
150                            0,G_MAXINT,0,
151                            G_PARAM_READABLE|G_PARAM_WRITABLE));
152   g_object_class_install_property (gobject_class,
153                            ARG_SCALE_MAX,
154   g_param_spec_double ("scale_max",
155                            P_(""),
156                            P_(""),
157                            0,G_MAXDOUBLE,0,
158                            G_PARAM_READABLE|G_PARAM_WRITABLE));
159   g_object_class_install_property (gobject_class,
160                            ARG_SIZE_MAX,
161   g_param_spec_int ("size_max",
162                            P_(""),
163                            P_(""),
164                            0,G_MAXINT,0,
165                            G_PARAM_READABLE|G_PARAM_WRITABLE));
166   g_object_class_install_property (gobject_class,
167                            ARG_SHOW_SCALE,
168   g_param_spec_boolean ("show_scale",
169                            P_(""),
170                            P_(""),
171                            FALSE,
172                            G_PARAM_READABLE|G_PARAM_WRITABLE));
173   g_object_class_install_property (gobject_class,
174                            ARG_LABEL_PRECISION,
175   g_param_spec_int ("labels_precision",
176                            P_(""),
177                            P_(""),
178                            0,G_MAXINT,0,
179                            G_PARAM_READABLE|G_PARAM_WRITABLE));
180   g_object_class_install_property (gobject_class,
181                            ARG_LABEL_STYLE,
182   g_param_spec_int ("labels_style",
183                            P_(""),
184                            P_(""),
185                            0,G_MAXINT,0,
186                            G_PARAM_READABLE|G_PARAM_WRITABLE));
187   g_object_class_install_property (gobject_class,
188                            ARG_LABEL_PREFIX,
189   g_param_spec_string ("labels_prefix",
190                            P_(""),
191                            P_(""),
192                            NULL,
193                            G_PARAM_READABLE|G_PARAM_WRITABLE));
194   g_object_class_install_property (gobject_class,
195                            ARG_LABEL_SUFFIX,
196   g_param_spec_string ("labels_suffix",
197                            P_(""),
198                            P_(""),
199                            NULL,
200                            G_PARAM_READABLE|G_PARAM_WRITABLE));
201 
202   data_class->draw_legend = gtk_plot_flux_draw_legend;
203   data_class->get_legend_size = gtk_plot_flux_get_legend_size;
204   data_class->draw_symbol = gtk_plot_flux_draw_symbol;
205 }
206 
207 
208 static void
gtk_plot_flux_init(GtkPlotFlux * dataset)209 gtk_plot_flux_init (GtkPlotFlux *dataset)
210 {
211   GtkWidget *widget;
212   GdkColor black, white;
213   GdkColormap *colormap;
214   GtkPlotArray *dim;
215 
216   widget = GTK_WIDGET(dataset);
217 
218   colormap = gdk_colormap_get_system();
219 
220   gdk_color_black(colormap, &black);
221   gdk_color_white(colormap, &white);
222 
223   GTK_PLOT_DATA(dataset)->symbol.symbol_style = GTK_PLOT_SYMBOL_EMPTY;
224   GTK_PLOT_DATA(dataset)->symbol.color = black;
225   GTK_PLOT_DATA(dataset)->line.line_style = GTK_PLOT_LINE_SOLID;
226   GTK_PLOT_DATA(dataset)->line.line_width = 1;
227   GTK_PLOT_DATA(dataset)->line.color = black;
228 
229   dataset->centered = TRUE;
230   dataset->arrow_length = 8;
231   dataset->arrow_width = 8;
232   dataset->arrow_style = GTK_PLOT_SYMBOL_FILLED;
233 
234   dataset->size_max = 1;
235   dataset->scale_max = 1.;
236   dataset->show_scale = TRUE;
237 
238   dataset->labels_precision = 3;
239   dataset->labels_style = GTK_PLOT_LABEL_FLOAT;
240   dataset->labels_prefix = NULL;
241   dataset->labels_suffix = NULL;
242 
243   dim = gtk_plot_data_find_dimension(GTK_PLOT_DATA(dataset), "x");
244   gtk_plot_array_set_description(dim, "Position X");
245   dim = gtk_plot_data_find_dimension(GTK_PLOT_DATA(dataset), "y");
246   gtk_plot_array_set_description(dim, "Position Y");
247   gtk_plot_array_set_required(dim, TRUE);
248   gtk_plot_array_set_independent(dim, TRUE);
249   dim = gtk_plot_data_find_dimension(GTK_PLOT_DATA(dataset), "z");
250   gtk_plot_array_set_description(dim, "Position Z");
251   gtk_plot_array_set_required(dim, TRUE);
252   gtk_plot_array_set_independent(dim, TRUE);
253   dim = gtk_plot_data_find_dimension(GTK_PLOT_DATA(dataset), "dx");
254   gtk_plot_array_set_required(dim, TRUE);
255   gtk_plot_array_set_label(dim, "DX");
256   gtk_plot_array_set_description(dim, "Size X");
257   dim = gtk_plot_data_find_dimension(GTK_PLOT_DATA(dataset), "dy");
258   gtk_plot_array_set_required(dim, TRUE);
259   gtk_plot_array_set_label(dim, "DY");
260   gtk_plot_array_set_description(dim, "Size Y");
261   dim = gtk_plot_data_find_dimension(GTK_PLOT_DATA(dataset), "dz");
262   gtk_plot_array_set_required(dim, TRUE);
263   gtk_plot_array_set_label(dim, "DZ");
264   gtk_plot_array_set_description(dim, "Size Z");
265 }
266 
267 static void
gtk_plot_flux_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)268 gtk_plot_flux_set_property (GObject      *object,
269                              guint            prop_id,
270                              const GValue          *value,
271                              GParamSpec      *pspec)
272 {
273   GtkPlotFlux *data;
274 
275   data = GTK_PLOT_FLUX (object);
276 
277   switch (prop_id)
278     {
279       case ARG_CENTERED:
280         data->centered  = g_value_get_boolean(value);
281         break;
282       case ARG_WIDTH:
283         data->arrow_width  = g_value_get_int(value);
284         break;
285       case ARG_LENGTH:
286         data->arrow_length  = g_value_get_int(value);
287         break;
288       case ARG_STYLE:
289         data->arrow_style  = g_value_get_int(value);
290         break;
291       case ARG_SCALE_MAX:
292         data->scale_max  = g_value_get_double(value);
293         break;
294       case ARG_SIZE_MAX:
295         data->size_max  = g_value_get_int(value);
296         break;
297       case ARG_SHOW_SCALE:
298         data->show_scale  = g_value_get_boolean(value);
299         break;
300       case ARG_LABEL_PRECISION:
301         data->labels_precision  = g_value_get_int(value);
302         break;
303       case ARG_LABEL_STYLE:
304         data->labels_style  = g_value_get_int(value);
305         break;
306       case ARG_LABEL_PREFIX:
307         gtk_plot_flux_set_labels_prefix(data, g_value_get_string(value));
308         break;
309       case ARG_LABEL_SUFFIX:
310         gtk_plot_flux_set_labels_suffix(data, g_value_get_string(value));
311         break;
312     }
313 }
314 
315 static void
gtk_plot_flux_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)316 gtk_plot_flux_get_property (GObject      *object,
317                              guint            prop_id,
318                              GValue          *value,
319                              GParamSpec      *pspec)
320 {
321   GtkPlotFlux *data;
322 
323   data = GTK_PLOT_FLUX (object);
324 
325   switch (prop_id)
326     {
327       case ARG_CENTERED:
328         g_value_set_boolean(value, data->centered);
329         break;
330       case ARG_WIDTH:
331         g_value_set_int(value, data->arrow_width);
332         break;
333       case ARG_LENGTH:
334         g_value_set_int(value, data->arrow_length);
335         break;
336       case ARG_STYLE:
337         g_value_set_int(value, data->arrow_style);
338         break;
339       case ARG_SCALE_MAX:
340         g_value_set_double(value, data->scale_max);
341         break;
342       case ARG_SIZE_MAX:
343         g_value_set_int(value, data->size_max);
344         break;
345       case ARG_SHOW_SCALE:
346         g_value_set_boolean(value, data->show_scale);
347         break;
348       case ARG_LABEL_PRECISION:
349         g_value_set_int(value, data->labels_precision);
350         break;
351       case ARG_LABEL_STYLE:
352         g_value_set_int(value, data->labels_style);
353         break;
354       case ARG_LABEL_PREFIX:
355         g_value_set_string(value, data->labels_prefix);
356         break;
357       case ARG_LABEL_SUFFIX:
358         g_value_set_string(value, data->labels_suffix);
359         break;
360       default:
361         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
362         break;
363     }
364 }
365 
366 GtkWidget*
gtk_plot_flux_new()367 gtk_plot_flux_new ()
368 {
369   GtkWidget *widget;
370 
371   widget = gtk_type_new (gtk_plot_flux_get_type ());
372 
373   return (widget);
374 }
375 
376 static void
gtk_plot_flux_destroy(GtkObject * object)377 gtk_plot_flux_destroy(GtkObject *object)
378 {
379   GtkPlotFlux *flux = GTK_PLOT_FLUX(object);
380 
381   if(flux->labels_prefix) g_free(flux->labels_prefix);
382   flux->labels_prefix = NULL;
383   if(flux->labels_suffix) g_free(flux->labels_suffix);
384   flux->labels_suffix = NULL;
385 
386   if (GTK_OBJECT_CLASS (parent_class)->destroy)
387     (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
388 }
389 
390 static void
gtk_plot_flux_draw_symbol(GtkPlotData * dataset,gdouble x,gdouble y,gdouble z,gdouble a,gdouble dx,gdouble dy,gdouble dz,gdouble da)391 gtk_plot_flux_draw_symbol(GtkPlotData *dataset,
392                           gdouble x, gdouble y, gdouble z, gdouble a,
393                           gdouble dx, gdouble dy, gdouble dz, gdouble da)
394 {
395   GtkPlot *plot;
396   GtkPlotFlux *flux = NULL;
397   GdkRectangle area, clip_area;
398   gdouble m;
399   gdouble x1 = 0.0, y1 = 0.0, x2 = 0.0, y2=0.0;
400   gdouble factor, size, xm;
401 
402   g_return_if_fail(GTK_IS_PLOT_FLUX(dataset));
403 
404   flux = GTK_PLOT_FLUX(dataset);
405 
406   g_return_if_fail(dataset->plot != NULL);
407   g_return_if_fail(GTK_WIDGET_VISIBLE(dataset->plot));
408 
409   plot = dataset->plot;
410 
411   m = plot->magnification;
412   area.x = GTK_WIDGET(plot)->allocation.x;
413   area.y = GTK_WIDGET(plot)->allocation.y;
414   area.width = GTK_WIDGET(plot)->allocation.width;
415   area.height = GTK_WIDGET(plot)->allocation.height;
416 
417   clip_area.x = area.x + roundint(plot->x * area.width);
418   clip_area.y = area.y + roundint(plot->y * area.height);
419   clip_area.width = roundint(plot->width * area.width);
420   clip_area.height = roundint(plot->height * area.height);
421 
422 /*
423   gtk_plot_pc_clip(plot->pc, &clip_area);
424 */
425 
426 
427   if(GTK_IS_PLOT3D(plot)){
428        gdouble z1, z2 = 0;
429 
430        xm = sqrt(dx * dx + dy * dy + dz * dz);
431        factor = xm / flux->scale_max;
432        size = factor * flux->size_max;
433        x2 = size * dx / xm;
434        y2 = size * dy / xm;
435        z2 = size * dz / xm;
436 
437        gtk_plot3d_get_pixel(GTK_PLOT3D(plot), x, y, z,
438                             &x1, &y1, &z1);
439   }else{
440        if(plot->clip_data &&
441           (x < plot->xmin || x > plot->xmax || y <plot->ymin || y > plot->ymax))
442             return;
443 
444        xm = sqrt(dx * dx + dy * dy);
445        factor = xm / flux->scale_max;
446        size = factor * flux->size_max;
447        x2 = size * dx / xm;
448        y2 = size * dy / xm;
449 
450        gtk_plot_get_pixel(plot, x, y, &x1, &y1);
451 
452        gtk_plot_flux_draw_arrow (flux, x1, y1, x1+x2*m, y1-y2*m);
453        gtk_plot_data_draw_symbol(dataset, x1, y1);
454   }
455 
456 /*
457   gtk_plot_pc_clip(plot->pc, NULL);
458 */
459 }
460 
461 static void
gtk_plot_flux_get_legend_size(GtkPlotData * data,gint * width,gint * height)462 gtk_plot_flux_get_legend_size(GtkPlotData *data, gint *width, gint *height)
463 {
464   GtkPlotFlux *flux;
465   GtkPlot *plot = NULL;
466   GtkPlotText legend;
467   gint lascent, ldescent, lheight, lwidth;
468   gdouble m;
469   gchar new_label[100], text[100];
470 
471   flux = GTK_PLOT_FLUX(data);
472   plot = data->plot;
473 
474   m = plot->magnification;
475   legend = plot->legends_attr;
476 
477   if(data->legend)
478     legend.text = data->legend;
479   else
480     legend.text = "";
481 
482   *width = *height = 0;
483   if(data->show_legend)
484     gtk_plot_text_get_size(legend.text, legend.angle, legend.font,
485                            roundint(legend.height * m),
486                            width, height,
487                            &lascent, &ldescent);
488 
489 
490   if(flux->show_scale){
491     gchar aux_text[100];
492     gtk_plot_axis_parse_label(data->gradient, flux->scale_max, flux->labels_precision, flux->labels_style, text);
493     if(flux->labels_prefix){
494       g_snprintf(aux_text, 100, "%s%s", flux->labels_prefix, text);
495       g_snprintf(text, 100, aux_text);
496     }
497     if(flux->labels_suffix) {
498       g_snprintf(aux_text, 100, "%s%s", text, flux->labels_suffix);
499       g_snprintf(text, 100, aux_text);
500     }
501 
502     g_snprintf(new_label, 100, "%s", text);
503 
504     legend.text = new_label;
505     gtk_plot_text_get_size(legend.text, 0, legend.font,
506                            roundint(legend.height * m),
507                            &lwidth, &lheight,
508                            &lascent, &ldescent);
509 
510     *width = MAX(*width, lwidth + roundint(m*(flux->size_max + 8)));
511     *height += MAX(lheight , roundint(m*flux->arrow_width));
512   }
513 }
514 
515 
516 static void
gtk_plot_flux_draw_legend(GtkPlotData * data,gint x,gint y)517 gtk_plot_flux_draw_legend(GtkPlotData *data, gint x, gint y)
518 {
519   GtkPlotFlux *flux;
520   GtkPlot *plot = NULL;
521   GtkPlotText legend;
522   GdkRectangle area;
523   gint lascent, ldescent, lheight, lwidth;
524   gdouble m;
525   gint line_width;
526   gboolean centered;
527 
528   flux = GTK_PLOT_FLUX(data);
529   centered = flux->centered;
530 
531   g_return_if_fail(data->plot != NULL);
532   g_return_if_fail(GTK_IS_PLOT(data->plot));
533   g_return_if_fail(GTK_WIDGET_VISIBLE(data->plot));
534 
535   plot = data->plot;
536   area.x = GTK_WIDGET(plot)->allocation.x;
537   area.y = GTK_WIDGET(plot)->allocation.y;
538   area.width = GTK_WIDGET(plot)->allocation.width;
539   area.height = GTK_WIDGET(plot)->allocation.height;
540 
541   m = plot->magnification;
542   legend = plot->legends_attr;
543 
544   if(data->legend)
545     legend.text = data->legend;
546   else
547     legend.text = "";
548 
549   gtk_plot_text_get_size(legend.text, legend.angle, legend.font,
550                          roundint(legend.height * m),
551                          &lwidth, &lheight,
552                          &lascent, &ldescent);
553 
554   if(data->show_legend){
555     line_width = plot->legends_line_width;
556 
557     legend.x = (gdouble)(area.x + x) / (gdouble)area.width;
558     legend.y = (gdouble)(area.y + y + lascent) / (gdouble)area.height;
559 
560     gtk_plot_draw_text(plot, legend);
561   }
562   if(flux->show_scale){
563     gchar new_label[100], text_max[100];
564 
565     flux->centered = FALSE;
566 
567     gtk_plot_flux_draw_arrow(flux,
568                              area.x + x,
569                              area.y + y + lheight * 3 / 2,
570                              area.x + x + roundint(flux->size_max*m),
571                              area.y + y + lheight * 3 / 2);
572     y += MAX(lheight, roundint(m*flux->arrow_width));
573 
574     gtk_plot_axis_parse_label(data->gradient, flux->scale_max, flux->labels_precision, flux->labels_style, text_max);
575     if(flux->labels_prefix){
576       gchar aux_text[100];
577       g_snprintf(aux_text, 100, "%s%s", flux->labels_prefix, text_max);
578       g_snprintf(text_max, 100, aux_text);
579     }
580     if(flux->labels_suffix){
581       gchar aux_text[100];
582       g_snprintf(aux_text, 100, "%s%s", text_max, flux->labels_suffix);
583       g_snprintf(text_max, 100, aux_text);
584     }
585     g_snprintf(new_label, 100, "%s", text_max);
586 
587     legend.x = (gdouble)(area.x + x + m*(flux->size_max + 4)) / (gdouble)area.width;
588     legend.y = (gdouble)(area.y + y + lascent) / (gdouble)area.height;
589     legend.text = new_label;
590     gtk_plot_draw_text(plot, legend);
591 
592     flux->centered = centered;
593     y += lheight;
594 
595   } else
596     y += lheight;
597 }
598 
599 static void
gtk_plot_flux_draw_arrow(GtkPlotFlux * flux,gdouble x1,gdouble y1,gdouble x2,gdouble y2)600 gtk_plot_flux_draw_arrow(GtkPlotFlux *flux, gdouble x1, gdouble y1, gdouble x2, gdouble y2)
601 {
602   GtkPlot *plot;
603   GtkPlotData *data;
604   GtkPlotPoint arrow[3];
605   gdouble xm, ym;
606   gdouble width, height;
607   gdouble arrow_width;
608   gdouble line_width;
609   gdouble angle;
610   gdouble length;
611   gdouble m;
612 
613   data = GTK_PLOT_DATA(flux);
614   plot = data->plot;
615 
616   m = plot->magnification;
617 
618   width = fabs(x2 - x1);
619   height = fabs(y2 - y1);
620 
621   if(width == 0 && height == 0) return;
622   if(width != 0)
623       angle = atan2((y2 - y1), (x2 - x1));
624   else
625       angle = asin((y2 - y1)/height);
626 
627   length = (y2 - y1)*(y2 - y1) + (x2 - x1)*(x2 - x1);
628   if(length > 0.0) length = sqrt(length);
629 
630   arrow_width = flux->arrow_width;
631   line_width = data->symbol.border.line_width;
632   gtk_plot_pc_set_color(plot->pc, &data->symbol.color);
633   gtk_plot_pc_set_lineattr (plot->pc, line_width, 0, 0, 0);
634   gtk_plot_pc_set_dash (plot->pc, 0, 0, 0);
635 
636   if(flux->centered && width != 0){
637     x1 -= cos(angle) * length / 2.0;
638     x2 -= cos(angle) * length / 2.0;
639   }
640   if(flux->centered && height != 0){
641     y1 -= sin(angle) * length / 2.0;
642     y2 -= sin(angle) * length / 2.0;
643   }
644 
645 
646   if(flux->arrow_style == GTK_PLOT_SYMBOL_EMPTY)
647     gtk_plot_pc_draw_line(plot->pc, x1, y1, x2, y2);
648   else
649     gtk_plot_pc_draw_line(plot->pc, x1, y1,
650                           x2 - flux->arrow_length * m * cos(angle) / 2.,
651                           y2 - flux->arrow_length * m * sin(angle) / 2.);
652 
653   arrow[1].x = x2;
654   arrow[1].y = y2;
655   xm = x2 - cos(angle) * flux->arrow_length * m;
656   ym = y2 - sin(angle) * flux->arrow_length * m;
657   arrow[0].x = xm - sin(angle)* arrow_width * m / 2.0;
658   arrow[0].y = ym + cos(angle)* arrow_width * m / 2.0;
659   arrow[2].x = xm + sin(angle)* arrow_width * m / 2.0;
660   arrow[2].y = ym - cos(angle)* arrow_width * m / 2.0;
661 
662   switch(flux->arrow_style){
663     case GTK_PLOT_SYMBOL_EMPTY:
664       gtk_plot_pc_draw_lines (plot->pc, arrow, 3);
665       break;
666     case GTK_PLOT_SYMBOL_OPAQUE:
667       gtk_plot_pc_set_color(plot->pc, &plot->background);
668       gtk_plot_pc_draw_polygon (plot->pc, TRUE, arrow, 3);
669       gtk_plot_pc_set_color(plot->pc, &data->symbol.color);
670       gtk_plot_pc_draw_polygon (plot->pc, FALSE, arrow, 3);
671       break;
672     case GTK_PLOT_SYMBOL_FILLED:
673       gtk_plot_pc_draw_polygon (plot->pc, TRUE, arrow, 3);
674   }
675 }
676 
677 void
gtk_plot_flux_set_arrow(GtkPlotFlux * flux,gint arrow_length,gint arrow_width,GtkPlotSymbolStyle arrow_style)678 gtk_plot_flux_set_arrow (GtkPlotFlux *flux,
679                          gint arrow_length,
680                          gint arrow_width,
681                          GtkPlotSymbolStyle arrow_style)
682 {
683   flux->arrow_length = arrow_length;
684   flux->arrow_width = arrow_width;
685   flux->arrow_style = arrow_style;
686 }
687 
688 void
gtk_plot_flux_get_arrow(GtkPlotFlux * flux,gint * arrow_length,gint * arrow_width,GtkPlotSymbolStyle * arrow_style)689 gtk_plot_flux_get_arrow (GtkPlotFlux *flux,
690                          gint *arrow_length,
691                          gint *arrow_width,
692                          GtkPlotSymbolStyle *arrow_style)
693 {
694   *arrow_length = flux->arrow_length;
695   *arrow_width = flux->arrow_width;
696   *arrow_style = flux->arrow_style;
697 }
698 
699 void
gtk_plot_flux_center(GtkPlotFlux * flux,gboolean center)700 gtk_plot_flux_center (GtkPlotFlux *flux, gboolean center)
701 {
702   flux->centered = center;
703 }
704 
705 gboolean
gtk_plot_flux_is_centered(GtkPlotFlux * flux)706 gtk_plot_flux_is_centered (GtkPlotFlux *flux)
707 {
708   return(flux->centered);
709 }
710 
711 void
gtk_plot_flux_show_scale(GtkPlotFlux * flux,gboolean show)712 gtk_plot_flux_show_scale        (GtkPlotFlux *flux, gboolean show)
713 {
714   flux->show_scale = show;
715 }
716 
717 void
gtk_plot_flux_set_scale_max(GtkPlotFlux * flux,gdouble scale_max)718 gtk_plot_flux_set_scale_max     (GtkPlotFlux *flux, gdouble scale_max)
719 {
720   flux->scale_max = fabs(scale_max);
721 }
722 
723 void
gtk_plot_flux_set_size_max(GtkPlotFlux * flux,guint size_max)724 gtk_plot_flux_set_size_max      (GtkPlotFlux *flux, guint size_max)
725 {
726   flux->size_max = size_max;
727 }
728 
729 void
gtk_plot_flux_set_labels_precision(GtkPlotFlux * flux,gint precision)730 gtk_plot_flux_set_labels_precision (GtkPlotFlux *flux, gint precision)
731 {
732   flux->labels_precision = precision;
733 }
734 
735 void
gtk_plot_flux_set_labels_style(GtkPlotFlux * flux,GtkPlotLabelStyle style)736 gtk_plot_flux_set_labels_style (GtkPlotFlux *flux, GtkPlotLabelStyle style)
737 {
738   flux->labels_style = style;
739 }
740 
741 void
gtk_plot_flux_set_labels_prefix(GtkPlotFlux * flux,const gchar * prefix)742 gtk_plot_flux_set_labels_prefix (GtkPlotFlux *flux, const gchar *prefix)
743 {
744   if(flux->labels_prefix) g_free(flux->labels_prefix);
745   flux->labels_prefix = NULL;
746   if(prefix)
747     flux->labels_prefix = g_strdup(prefix);
748 }
749 
750 void
gtk_plot_flux_set_labels_suffix(GtkPlotFlux * flux,const gchar * suffix)751 gtk_plot_flux_set_labels_suffix (GtkPlotFlux *flux, const gchar *suffix)
752 {
753   if(flux->labels_suffix) g_free(flux->labels_suffix);
754   flux->labels_suffix = NULL;
755   if(suffix)
756     flux->labels_suffix = g_strdup(suffix);
757 }
758 
759