1 /* gtkplotbox - box 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 "gtkplotbox.h"
29 #include "gtkpsfont.h"
30 
31 #define P_(string) string
32 
33 static void gtk_plot_box_class_init 	(GtkPlotBoxClass *klass);
34 static void gtk_plot_box_init 		(GtkPlotBox *data);
35 static void gtk_plot_box_set_property   (GObject *object,
36                                          guint prop_id,
37                                          const GValue *value,
38                                          GParamSpec *pspec);
39 static void gtk_plot_box_get_property   (GObject *object,
40                                          guint prop_id,
41                                          GValue *value,
42                                          GParamSpec *pspec);
43 static void gtk_plot_box_draw_legend	(GtkPlotData *data,
44 					 gint x, gint y);
45 static void gtk_plot_box_draw_symbol	(GtkPlotData *data,
46                                      	 gdouble x,
47 					 gdouble y,
48 					 gdouble z,
49 					 gdouble a,
50                                      	 gdouble dx,
51 					 gdouble dy,
52 					 gdouble dz,
53 					 gdouble da);
54 static void gtk_plot_box_clone          (GtkPlotData *data, GtkPlotData *copy);
55 
56 extern gint roundint (gdouble x);
57 
58 enum {
59   ARG_0,
60   ARG_ORIENTATION,
61 };
62 
63 static GtkPlotDataClass *parent_class = NULL;
64 
65 GtkType
gtk_plot_box_get_type(void)66 gtk_plot_box_get_type (void)
67 {
68   static GtkType data_type = 0;
69 
70   if (!data_type)
71     {
72       GtkTypeInfo data_info =
73       {
74 	"GtkPlotBox",
75 	sizeof (GtkPlotBox),
76 	sizeof (GtkPlotBoxClass),
77 	(GtkClassInitFunc) gtk_plot_box_class_init,
78 	(GtkObjectInitFunc) gtk_plot_box_init,
79 	/* reserved 1*/ NULL,
80         /* reserved 2 */ NULL,
81         (GtkClassInitFunc) NULL,
82       };
83 
84       data_type = gtk_type_unique (gtk_plot_data_get_type(), &data_info);
85     }
86   return data_type;
87 }
88 
89 static void
gtk_plot_box_class_init(GtkPlotBoxClass * klass)90 gtk_plot_box_class_init (GtkPlotBoxClass *klass)
91 {
92   GtkObjectClass *object_class;
93   GtkWidgetClass *widget_class;
94   GtkPlotDataClass *data_class;
95   GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
96 
97   parent_class = gtk_type_class (gtk_plot_data_get_type ());
98 
99   object_class = (GtkObjectClass *) klass;
100   widget_class = (GtkWidgetClass *) klass;
101   data_class = (GtkPlotDataClass *) klass;
102 
103   gobject_class->set_property = gtk_plot_box_set_property;
104   gobject_class->get_property = gtk_plot_box_get_property;
105 
106   g_object_class_install_property(gobject_class,
107                            ARG_ORIENTATION,
108   g_param_spec_enum ("orientation",
109                      P_("Orientation"),
110                      P_("Orientation"),
111                      GTK_TYPE_ORIENTATION, 0,
112                      G_PARAM_READABLE|G_PARAM_WRITABLE));
113 
114   data_class->clone = gtk_plot_box_clone;
115   data_class->draw_legend = gtk_plot_box_draw_legend;
116   data_class->draw_symbol = gtk_plot_box_draw_symbol;
117 /*
118   data_class->draw_data = gtk_plot_box_draw;
119 */
120 }
121 
122 static void
gtk_plot_box_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)123 gtk_plot_box_set_property (GObject      *object,
124                          guint prop_id,
125                          const GValue *value,
126                          GParamSpec *pspec)
127 {
128   GtkPlotBox *data;
129 
130   data = GTK_PLOT_BOX (object);
131 
132   switch (prop_id)
133     {
134       case ARG_ORIENTATION:
135         data->orientation  = g_value_get_enum(value);
136         break;
137     }
138 }
139 
140 static void
gtk_plot_box_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)141 gtk_plot_box_get_property (GObject      *object,
142                          guint prop_id,
143                          GValue *value,
144                          GParamSpec *pspec)
145 {
146   GtkPlotBox *data;
147 
148   data = GTK_PLOT_BOX (object);
149 
150   switch (prop_id)
151     {
152       case ARG_ORIENTATION:
153         g_value_set_enum(value, data->orientation);
154         break;
155       default:
156         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
157         break;
158     }
159 }
160 
161 
162 static void
gtk_plot_box_init(GtkPlotBox * dataset)163 gtk_plot_box_init (GtkPlotBox *dataset)
164 {
165   GtkWidget *widget;
166   GdkColor black, white;
167   GdkColormap *colormap;
168 
169   widget = GTK_WIDGET(dataset);
170 
171   colormap = gdk_colormap_get_system();
172 
173   gdk_color_black(colormap, &black);
174   gdk_color_white(colormap, &white);
175 
176   GTK_PLOT_DATA(dataset)->symbol.symbol_style = GTK_PLOT_SYMBOL_FILLED;
177   GTK_PLOT_DATA(dataset)->symbol.color = white;
178   GTK_PLOT_DATA(dataset)->line.line_style = GTK_PLOT_LINE_SOLID;
179   GTK_PLOT_DATA(dataset)->line.line_width = 1;
180   GTK_PLOT_DATA(dataset)->line.color = black;
181 }
182 
183 GtkWidget*
gtk_plot_box_new(GtkOrientation orientation)184 gtk_plot_box_new (GtkOrientation orientation)
185 {
186   GtkWidget *widget;
187 
188   widget = gtk_type_new (gtk_plot_box_get_type ());
189 
190   gtk_plot_box_construct(GTK_PLOT_BOX(widget), orientation);
191 
192   return (widget);
193 }
194 
195 void
gtk_plot_box_construct(GtkPlotBox * box,GtkOrientation orientation)196 gtk_plot_box_construct (GtkPlotBox *box, GtkOrientation orientation)
197 {
198   box->orientation = orientation;
199 }
200 
201 static void
gtk_plot_box_clone(GtkPlotData * data,GtkPlotData * copy)202 gtk_plot_box_clone(GtkPlotData *data, GtkPlotData *copy)
203 {
204   GTK_PLOT_DATA_CLASS(parent_class)->clone(data, copy);
205 
206   GTK_PLOT_BOX(copy)->orientation = GTK_PLOT_BOX(data)->orientation;
207 }
208 
209 static void
gtk_plot_box_draw_symbol(GtkPlotData * dataset,gdouble x,gdouble y,gdouble z,gdouble a,gdouble dx,gdouble dy,gdouble dz,gdouble da)210 gtk_plot_box_draw_symbol(GtkPlotData *dataset,
211                          gdouble x, gdouble y, gdouble z, gdouble a,
212                          gdouble dx, gdouble dy, gdouble dz, gdouble da)
213 {
214   GtkPlot *plot;
215   GtkPlotBox *box = NULL;
216   GtkPlotPoint errbar[6];
217   gdouble px, py;
218   gdouble px0, py0;
219   gdouble px1, py1;
220   gdouble x1 = 0.0, y1 = 0.0, width = 0.0, height = 0.0;
221   gdouble el_x, el_y, er_x, er_y, ed_x, ed_y, eu_x, eu_y;
222   gdouble m;
223   gdouble a_scale;
224 
225 
226   g_return_if_fail(GTK_IS_PLOT_BOX(dataset));
227 
228   box = GTK_PLOT_BOX(dataset);
229 
230   g_return_if_fail(dataset->plot != NULL);
231 
232   plot = dataset->plot;
233 
234   a_scale = gtk_plot_data_get_a_scale(dataset);
235   m = plot->magnification * a_scale;
236 
237   gtk_plot_pc_set_lineattr (plot->pc, dataset->symbol.border.line_width,
238                             0, 0, 0);
239   gtk_plot_pc_set_dash (plot->pc, 0, 0, 0);
240 
241   if(x >= plot->xmin && x <= plot->xmax){
242     if(GTK_IS_PLOT3D(plot)){
243     }else{
244       if(dataset->show_zerrbars){
245         gtk_plot_pc_set_color(plot->pc, &dataset->symbol.border.color);
246         switch(box->orientation){
247           case GTK_ORIENTATION_VERTICAL:
248             gtk_plot_get_pixel(plot, x, y, &px, &py);
249             gtk_plot_get_pixel(plot, x, y, &px0, &py0);
250             gtk_plot_get_pixel(plot, x, z, &px1, &py1);
251             width = roundint(dataset->symbol.size * m);
252             height = abs(py1 - py0);
253 
254             gtk_plot_get_pixel(plot, x, z + dy, &eu_x, &eu_y);
255             gtk_plot_get_pixel(plot, x, y - dy, &ed_x, &ed_y);
256 
257             errbar[0].x = px-roundint(m * dataset->symbol.size/2);
258             errbar[0].y = eu_y;
259             errbar[1].x = px+roundint(m * dataset->symbol.size/2);
260             errbar[1].y = eu_y;
261             gtk_plot_pc_draw_lines(plot->pc, errbar, 2);
262 
263             errbar[0].x = px;
264             errbar[0].y = eu_y;
265             errbar[1].x = px;
266             errbar[1].y = py1;
267             gtk_plot_pc_draw_lines(plot->pc, errbar, 2);
268 
269             errbar[0].x = px-roundint(m * dataset->symbol.size/2);
270             errbar[0].y = ed_y;
271             errbar[1].x = px+roundint(m * dataset->symbol.size/2);
272             errbar[1].y = ed_y;
273             gtk_plot_pc_draw_lines(plot->pc, errbar, 2);
274 
275             errbar[0].x = px;
276             errbar[0].y = ed_y;
277             errbar[1].x = px;
278             errbar[1].y = py0;
279             gtk_plot_pc_draw_lines(plot->pc, errbar, 2);
280 
281             break;
282           case GTK_ORIENTATION_HORIZONTAL:
283             gtk_plot_get_pixel(plot, y, x, &px, &py);
284             gtk_plot_get_pixel(plot, y, x, &px0, &py0);
285             gtk_plot_get_pixel(plot, z, x, &px1, &py1);
286             height = roundint(dataset->symbol.size * m);
287 
288             gtk_plot_get_pixel(plot, z + dy, x, &er_x, &er_y);
289             gtk_plot_get_pixel(plot, y - dy, x, &el_x, &el_y);
290 
291             errbar[0].x = el_x;
292             errbar[0].y = py-roundint(m * dataset->symbol.size / 2.);
293             errbar[1].x = el_x;
294             errbar[1].y = py+roundint(m * dataset->symbol.size / 2.);
295             gtk_plot_pc_draw_lines(plot->pc, errbar, 2);
296 
297             errbar[0].x = el_x;
298             errbar[0].y = py;
299             errbar[1].x = px0;
300             errbar[1].y = py;
301             gtk_plot_pc_draw_lines(plot->pc, errbar, 2);
302 
303             errbar[0].x = er_x;
304             errbar[0].y = py-roundint(m * dataset->symbol.size / 2.);
305             errbar[1].x = er_x;
306             errbar[1].y = py+roundint(m * dataset->symbol.size / 2.);
307             gtk_plot_pc_draw_lines(plot->pc, errbar, 2);
308 
309             errbar[0].x = er_x;
310             errbar[0].y = py;
311             errbar[1].x = px1;
312             errbar[1].y = py;
313             gtk_plot_pc_draw_lines(plot->pc, errbar, 2);
314 
315             break;
316         }
317       }
318 
319       switch(box->orientation){
320         case GTK_ORIENTATION_VERTICAL:
321           gtk_plot_get_pixel(plot, x, y, &px, &py);
322           gtk_plot_get_pixel(plot, x, y, &px0, &py0);
323           gtk_plot_get_pixel(plot, x, z, &px1, &py1);
324           y1 = MIN(py0,py1);
325           height = fabs(py0-py1);
326           width = roundint(dataset->symbol.size * m);
327           x1 = px0 - width / 2;
328           break;
329         case GTK_ORIENTATION_HORIZONTAL:
330           gtk_plot_get_pixel(plot, y, x, &px, &py);
331           gtk_plot_get_pixel(plot, y, x, &px0, &py0);
332           gtk_plot_get_pixel(plot, z, x, &px1, &py1);
333           x1 = MIN(px0,px1);
334           width = fabs(px0-px1);
335           height = roundint(dataset->symbol.size * m);
336           y1 = py0 - height / 2;
337           break;
338       }
339 
340       if(dataset->symbol.symbol_style == GTK_PLOT_SYMBOL_OPAQUE){
341         gtk_plot_pc_set_color(plot->pc, &plot->background);
342         gtk_plot_pc_draw_rectangle (plot->pc,
343                                     TRUE,
344                                     x1, y1, width, height);
345       }
346 
347       if(dataset->symbol.symbol_style == GTK_PLOT_SYMBOL_FILLED){
348         gtk_plot_pc_set_color(plot->pc, &dataset->symbol.color);
349         gtk_plot_pc_draw_rectangle (plot->pc,
350                                     TRUE,
351                                     x1, y1, width, height);
352       }
353 
354       gtk_plot_pc_set_color(plot->pc, &dataset->symbol.border.color);
355       gtk_plot_pc_draw_rectangle (plot->pc,
356                                   FALSE,
357                                   x1, y1, width, height);
358 
359       switch(box->orientation){
360         case GTK_ORIENTATION_VERTICAL:
361           gtk_plot_pc_draw_line(plot->pc, px-width/2, py, px+width/2, py);
362           break;
363         case GTK_ORIENTATION_HORIZONTAL:
364           gtk_plot_pc_draw_line(plot->pc, px, py-height/2, px, py+height/2);
365           break;
366       }
367 
368     }
369   }
370 
371 }
372 
373 
374 static void
gtk_plot_box_draw_legend(GtkPlotData * data,gint x,gint y)375 gtk_plot_box_draw_legend(GtkPlotData *data, gint x, gint y)
376 {
377   GtkPlotBox *box;
378   GtkPlot *plot = NULL;
379   GtkPlotText legend;
380   GdkRectangle area;
381   gint lascent, ldescent, lheight, lwidth;
382   gdouble m;
383 
384   box = GTK_PLOT_BOX(data);
385 
386   g_return_if_fail(data->plot != NULL);
387   g_return_if_fail(GTK_IS_PLOT(data->plot));
388   g_return_if_fail(GTK_WIDGET_REALIZED(data->plot));
389 
390   plot = data->plot;
391   area.x = GTK_WIDGET(plot)->allocation.x;
392   area.y = GTK_WIDGET(plot)->allocation.y;
393   area.width = GTK_WIDGET(plot)->allocation.width;
394   area.height = GTK_WIDGET(plot)->allocation.height;
395 
396   m = plot->magnification;
397   legend = plot->legends_attr;
398 
399   if(data->legend)
400     legend.text = data->legend;
401   else
402     legend.text = "";
403 
404   gtk_plot_text_get_size(legend.text, legend.angle, legend.font,
405                          roundint(legend.height * m),
406                          &lwidth, &lheight,
407                          &lascent, &ldescent);
408 
409 
410   legend.x = (gdouble)(area.x + x + roundint((plot->legends_line_width + 4) * m))
411              / (gdouble)area.width;
412   legend.y = (gdouble)(area.y + y + lascent) / (gdouble)area.height;
413 
414   gtk_plot_draw_text(plot, legend);
415 
416   if(data->symbol.symbol_style == GTK_PLOT_SYMBOL_OPAQUE){
417     gtk_plot_pc_set_color(plot->pc, &plot->background);
418     gtk_plot_pc_draw_rectangle(plot->pc, TRUE,
419                                x, y,
420                                roundint(plot->legends_line_width * m),
421                                lascent + ldescent);
422   }
423 
424   gtk_plot_pc_set_lineattr (plot->pc, data->symbol.border.line_width, 0, 0, 0);
425   gtk_plot_pc_set_dash (plot->pc, 0, 0, 0);
426 
427   if(data->symbol.symbol_style == GTK_PLOT_SYMBOL_FILLED){
428     gtk_plot_pc_set_color(plot->pc, &data->symbol.color);
429     gtk_plot_pc_draw_rectangle(plot->pc, TRUE,
430                                x, y,
431                                roundint(plot->legends_line_width * m),
432                                lascent + ldescent);
433   }
434 
435   gtk_plot_pc_set_color(plot->pc, &data->symbol.border.color);
436   gtk_plot_pc_draw_rectangle(plot->pc, FALSE,
437                              x, y,
438                              roundint(plot->legends_line_width * m),
439                              lascent + ldescent);
440 
441 }
442 
443