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