1 /* gtkplotcanvas - gtkplot canvas 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 /**
21 * SECTION: gtkplotcanvasplot
22 * @short_description:
23 *
24 * A #GtkPlotCanvas object is an interactive container for
25 * GtkPlots and some graphic primitives that can be used to
26 * illustrate the plots (see #GtkCanvasChild).
27 */
28
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <math.h>
34 #include <gtk/gtk.h>
35 #include "gtkplot.h"
36 #include "gtkplot3d.h"
37 #include "gtkplotdata.h"
38 #include "gtkplotcanvas.h"
39 #include "gtkplotcanvasplot.h"
40 #include "gtkplotgdk.h"
41 #include "gtkplotps.h"
42
43 #define DEFAULT_MARKER_SIZE 6
44
45 static void gtk_plot_canvas_plot_init (GtkPlotCanvasPlot *plot);
46 static void gtk_plot_canvas_plot_class_init(GtkPlotCanvasChildClass *klass);
47 static void gtk_plot_canvas_plot_destroy (GtkObject *object);
48 static void gtk_plot_canvas_plot_draw (GtkPlotCanvas *canvas,
49 GtkPlotCanvasChild *child);
50 static void gtk_plot_canvas_plot_move (GtkPlotCanvas *canvas,
51 GtkPlotCanvasChild *child,
52 gdouble x, gdouble y);
53 static void gtk_plot_canvas_plot_resize (GtkPlotCanvas *canvas,
54 GtkPlotCanvasChild *child,
55 gdouble x1, gdouble y1,
56 gdouble x2, gdouble y2);
57 static void gtk_plot_canvas_plot_size_allocate (GtkPlotCanvas *canvas,
58 GtkPlotCanvasChild *child);
59 static void gtk_plot_canvas_plot_set_magnification(GtkPlotCanvas *canvas,
60 GtkPlotCanvasChild *child,
61 gdouble m);
62 static void gtk_plot_canvas_plot_unselect (GtkPlotCanvas *canvas,
63 GtkPlotCanvasChild *child);
64 static GtkPlotCanvasPos gtk_plot_canvas_plot_button_press
65 (GtkPlotCanvas *canvas,
66 GtkPlotCanvasChild *child,
67 gint x, gint y);
68 static void gtk_plot_canvas_plot_button_release (GtkPlotCanvas *canvas,
69 GtkPlotCanvasChild *child);
70 static void reset_plot_allocation (GtkPlotCanvas *canvas,
71 GtkPlotCanvasPlot *child);
72 extern gint roundint (gdouble x);
73 static GtkPlotCanvasChildClass *parent_class = NULL;
74
75 extern GtkPlotCanvasPos possible_selection (GtkAllocation area,
76 gint x, gint y);
77
78 GType
gtk_plot_canvas_plot_get_type(void)79 gtk_plot_canvas_plot_get_type (void)
80 {
81 static GType plot_canvas_plot_type = 0;
82
83 if (!plot_canvas_plot_type)
84 {
85 plot_canvas_plot_type = g_type_register_static_simple (
86 gtk_plot_canvas_child_get_type(),
87 "GtkPlotCanvasPlot",
88 sizeof (GtkPlotCanvasPlotClass),
89 (GClassInitFunc) gtk_plot_canvas_plot_class_init,
90 sizeof (GtkPlotCanvasPlot),
91 (GInstanceInitFunc) gtk_plot_canvas_plot_init,
92 0);
93 }
94 return plot_canvas_plot_type;
95 }
96
97 /**
98 * gtk_plot_canvas_plot_new:
99 * @plot: a #GtkPlot.
100 *
101 *
102 *
103 * Return value:
104 */
105 GtkPlotCanvasChild*
gtk_plot_canvas_plot_new(GtkPlot * plot)106 gtk_plot_canvas_plot_new (GtkPlot *plot)
107 {
108 GtkPlotCanvasPlot *child;
109
110 child = g_object_new (gtk_plot_canvas_plot_get_type (), NULL);
111 child->plot = plot;
112
113 return GTK_PLOT_CANVAS_CHILD (child);
114 }
115
116 static void
gtk_plot_canvas_plot_init(GtkPlotCanvasPlot * plot)117 gtk_plot_canvas_plot_init (GtkPlotCanvasPlot *plot)
118 {
119 plot->plot = NULL;
120 plot->pos = GTK_PLOT_CANVAS_PLOT_IN_PLOT;
121 plot->axis = NULL;
122 plot->data = NULL;
123 plot->marker = NULL;
124 GTK_PLOT_CANVAS_PLOT(plot)->datapoint = -1;
125 GTK_PLOT_CANVAS_PLOT(plot)->flags = 0; /* GTK_PLOT_CANVAS_PLOT_SELECT_POINT; */
126 }
127
128 static void
gtk_plot_canvas_plot_class_init(GtkPlotCanvasChildClass * klass)129 gtk_plot_canvas_plot_class_init (GtkPlotCanvasChildClass *klass)
130 {
131 GtkObjectClass *object_class = (GtkObjectClass *)klass;
132
133 parent_class = g_type_class_ref (gtk_plot_canvas_child_get_type ());
134
135 klass->draw = gtk_plot_canvas_plot_draw;
136 klass->move = gtk_plot_canvas_plot_move;
137 klass->move_resize = gtk_plot_canvas_plot_resize;
138 klass->size_allocate = gtk_plot_canvas_plot_size_allocate;
139 klass->button_press = gtk_plot_canvas_plot_button_press;
140 klass->button_release = gtk_plot_canvas_plot_button_release;
141 klass->unselect = gtk_plot_canvas_plot_unselect;
142 klass->set_magnification = gtk_plot_canvas_plot_set_magnification;
143
144 object_class->destroy = gtk_plot_canvas_plot_destroy;
145 }
146
147 static void
gtk_plot_canvas_plot_destroy(GtkObject * object)148 gtk_plot_canvas_plot_destroy(GtkObject *object)
149 {
150 GtkWidget *widget = GTK_WIDGET(GTK_PLOT_CANVAS_PLOT(object)->plot);
151 g_object_unref(widget);
152
153 /* 28.06.13/fp - dropped the following line
154 - do not access widget data after g_object_unref()
155 - calling gtk_widget_unparent() before g_object_unref() -> invalid GObject warnings
156
157 widget->parent = NULL;
158 */
159 }
160
gtk_plot_canvas_plot_flags(GtkPlotCanvasPlot * plot)161 GtkPlotCanvasPlotFlags gtk_plot_canvas_plot_flags(GtkPlotCanvasPlot *plot)
162 {
163 g_return_val_if_fail(plot != NULL, 0);
164 return(plot->flags);
165 }
166
gtk_plot_canvas_plot_set_flags(GtkPlotCanvasPlot * plot,GtkPlotCanvasPlotFlags flags)167 void gtk_plot_canvas_plot_set_flags(GtkPlotCanvasPlot *plot,
168 GtkPlotCanvasPlotFlags flags)
169 {
170 g_return_if_fail(plot != NULL);
171 plot->flags |= flags;
172 }
173
gtk_plot_canvas_plot_unset_flags(GtkPlotCanvasPlot * plot,GtkPlotCanvasPlotFlags flags)174 void gtk_plot_canvas_plot_unset_flags(GtkPlotCanvasPlot *plot,
175 GtkPlotCanvasPlotFlags flags)
176 {
177 g_return_if_fail(plot != NULL);
178 plot->flags &= ~flags;
179 }
180
181
182 static void
gtk_plot_canvas_plot_draw(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child)183 gtk_plot_canvas_plot_draw (GtkPlotCanvas *canvas,
184 GtkPlotCanvasChild *child)
185 {
186 GtkPlotCanvasPlot *plot_child = GTK_PLOT_CANVAS_PLOT(child);
187 GtkPlot *plot = plot_child->plot;
188 gint width = child->allocation.width;
189 gint height = child->allocation.height;
190 gdouble m = canvas->magnification;
191 GtkPlotPC *pc;
192 GtkAllocation allocation;
193
194 if(width == 0 && height == 0) return;
195
196 gtk_plot_set_drawable(plot, canvas->pixmap);
197 allocation.x = 0;
198 allocation.y = 0;
199 allocation.width = canvas->pixmap_width;
200 allocation.height = canvas->pixmap_height;
201 gtk_widget_set_allocation(GTK_WIDGET(plot), &allocation);
202 gtk_plot_set_magnification(plot, m);
203 reset_plot_allocation(canvas, plot_child);
204
205 pc = plot->pc;
206 plot->pc = canvas->pc;
207
208 gtk_plot_paint(GTK_PLOT_CANVAS_PLOT(child)->plot);
209
210 plot->pc = pc;
211 }
212
213 static void
reset_plot_allocation(GtkPlotCanvas * canvas,GtkPlotCanvasPlot * child)214 reset_plot_allocation(GtkPlotCanvas *canvas, GtkPlotCanvasPlot *child)
215 {
216 GtkPlot *plot = child->plot;
217 gdouble x1 = plot->internal_allocation.x;
218 gdouble y1 = plot->internal_allocation.y;
219 gdouble x2 = x1 + plot->internal_allocation.width;
220 gdouble y2 = y1 + plot->internal_allocation.height;
221
222 GTK_PLOT_CANVAS_CHILD(child)->allocation = plot->internal_allocation;
223 GTK_PLOT_CANVAS_CHILD(child)->rx1 = x1 / (gdouble) canvas->pixmap_width;
224 GTK_PLOT_CANVAS_CHILD(child)->rx2 = x2 / (gdouble) canvas->pixmap_width;
225 GTK_PLOT_CANVAS_CHILD(child)->ry1 = y1 / (gdouble) canvas->pixmap_height;
226 GTK_PLOT_CANVAS_CHILD(child)->ry2 = y2 / (gdouble) canvas->pixmap_height;
227 /*
228 GTK_PLOT_CANVAS_CHILD(child)->selection = GTK_PLOT_CANVAS_SELECT_MARKERS;
229 GTK_PLOT_CANVAS_CHILD(child)->mode = GTK_PLOT_CANVAS_SELECT_CLICK_2;
230 GTK_PLOT_CANVAS_CHILD(child)->flags = GTK_PLOT_CANVAS_CHILD_CAN_MOVE | GTK_PLOT_CANVAS_CHILD_CAN_RESIZE;
231 */
232 }
233
234 static void
gtk_plot_canvas_plot_move(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,gdouble x,gdouble y)235 gtk_plot_canvas_plot_move (GtkPlotCanvas *canvas,
236 GtkPlotCanvasChild *child,
237 gdouble x, gdouble y)
238 {
239 GtkPlotCanvasPlot *cplot = GTK_PLOT_CANVAS_PLOT(child);
240 GtkPlot *plot = cplot->plot;
241 if(!plot) return;
242 }
243
244 static void
gtk_plot_canvas_plot_resize(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,gdouble x1,gdouble y1,gdouble x2,gdouble y2)245 gtk_plot_canvas_plot_resize (GtkPlotCanvas *canvas,
246 GtkPlotCanvasChild *child,
247 gdouble x1, gdouble y1,
248 gdouble x2, gdouble y2)
249 {
250 GtkPlotCanvasPlot *cplot = GTK_PLOT_CANVAS_PLOT(child);
251 GtkPlot *plot = cplot->plot;
252
253 if(!plot) return;
254
255 gtk_plot_move_resize(plot, x1, y1, fabs(x2-x1), fabs(y2-y1));
256 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->size_allocate(canvas, child);
257 gtk_plot_canvas_paint(canvas);
258 gtk_plot_canvas_refresh(canvas);
259 }
260
261 static void
gtk_plot_canvas_plot_button_release(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child)262 gtk_plot_canvas_plot_button_release (GtkPlotCanvas *canvas,
263 GtkPlotCanvasChild *child)
264 {
265 GtkPlotCanvasPlot *cplot = GTK_PLOT_CANVAS_PLOT(child);
266 GtkPlot *plot = cplot->plot;
267 gdouble fx, fy, fz, fa;
268 gdouble fdx, fdy, fdz, fda;
269 gdouble mx, my;
270 gchar *label = NULL;
271 gboolean error;
272 gint i;
273 gdouble new_x, new_y, new_width, new_height;
274 gdouble old_x, old_y;
275 gdouble dx, dy;
276 gdouble x1, x2, y1, y2;
277 gboolean moved = FALSE;
278
279 gtk_plot_canvas_get_position(canvas,
280 child->drag_area.x,
281 child->drag_area.y,
282 &old_x, &old_y);
283
284 gtk_plot_canvas_get_position(canvas,
285 canvas->drag_area.width,
286 canvas->drag_area.height,
287 &new_width, &new_height);
288
289 gtk_plot_canvas_get_position(canvas,
290 canvas->drag_area.x,
291 canvas->drag_area.y,
292 &new_x, &new_y);
293
294 dx = new_x - old_x;
295 dy = new_y - old_y;
296 x1 = MIN(child->rx1, child->rx2);
297 y1 = MIN(child->ry1, child->ry2);
298 x2 = MAX(child->rx1, child->rx2);
299 y2 = MAX(child->ry1, child->ry2);
300 x1 += dx;
301 y1 += dy;
302 x2 = x1 + new_width;
303 y2 = y1 + new_height;
304
305 if(!plot) return;
306
307 switch(cplot->pos){
308 case GTK_PLOT_CANVAS_PLOT_IN_LEGENDS:
309 gtk_plot_legends_move(plot, (new_x - plot->x)*canvas->pixmap_width/plot->internal_allocation.width, (new_y - plot->y)*canvas->pixmap_height/plot->internal_allocation.height);
310 child->drag_area = canvas->drag_area;
311 break;
312 case GTK_PLOT_CANVAS_PLOT_IN_TITLE:
313 if(!GTK_IS_PLOT3D(plot) && cplot->axis){
314 GtkPlotText *text = &cplot->axis->title;
315 text->x += (new_x - old_x);
316 text->y += (new_y - old_y);
317 child->drag_area = canvas->drag_area;
318 }
319 break;
320 case GTK_PLOT_CANVAS_PLOT_IN_DATA:
321 if(GTK_PLOT_CANVAS_PLOT_DND_POINT(cplot)){
322 gdouble *array_x = NULL;
323 gdouble *array_y = NULL;
324 gdouble px, py;
325 gint n;
326 gdouble x, y;
327 array_x = gtk_plot_data_get_x(cplot->data, &n);
328 array_y = gtk_plot_data_get_y(cplot->data, &n);
329 gtk_plot_get_pixel(plot, array_x[cplot->datapoint], array_y[cplot->datapoint], &px, &py);
330 new_x = px + (canvas->pointer_x - canvas->drag_x);
331 new_y = py + (canvas->pointer_y - canvas->drag_y);
332 gtk_plot_get_point(plot, new_x, new_y, &x, &y);
333 array_x[cplot->datapoint] = x;
334 array_y[cplot->datapoint] = y;
335 gtk_plot_canvas_get_position(canvas, new_x, new_y,
336 &child->rx1, &child->ry1);
337 child->drag_area.x = new_x - DEFAULT_MARKER_SIZE;
338 child->drag_area.y = new_y - DEFAULT_MARKER_SIZE;
339 }
340 break;
341 case GTK_PLOT_CANVAS_PLOT_IN_MARKER:
342 gtk_plot_data_get_point(cplot->marker->data, cplot->marker->point,
343 &fx, &fy, &fz, &fa, &fdx, &fdy, &fdz, &fda,
344 &label, &error);
345
346 gtk_plot_get_pixel(plot,
347 fx, fy,
348 &mx, &my);
349
350 new_x = mx + (canvas->pointer_x - canvas->drag_x);
351 new_y = my + (canvas->pointer_y - canvas->drag_y);
352
353 for(i = 0; i < cplot->marker->data->num_points; i++){
354 gdouble px, py;
355
356 gtk_plot_data_get_point(cplot->marker->data, i,
357 &fx, &fy, &fz, &fa, &fdx, &fdy, &fdz, &fda,
358 &label, &error);
359
360 gtk_plot_get_pixel(plot,
361 fx, fy,
362 &px, &py);
363
364 if(abs(new_x - px) <= DEFAULT_MARKER_SIZE &&
365 abs(new_y - py) <= DEFAULT_MARKER_SIZE){
366 cplot->marker->point = i;
367 cplot->datapoint = i;
368 gtk_plot_canvas_get_position(canvas, px, py,
369 &child->rx1, &child->ry1);
370 child->drag_area.x = px - 10;
371 child->drag_area.y = py - 10;
372 canvas->drag_area = child->drag_area;
373 moved = TRUE;
374 break;
375 }
376 }
377 if(!moved){
378 child->drag_area.x = mx - 10;
379 child->drag_area.y = my - 10;
380 canvas->drag_area = child->drag_area;
381 }
382 break;
383 case GTK_PLOT_CANVAS_PLOT_IN_GRADIENT:
384 gtk_plot_data_move_gradient(cplot->data, (new_x - plot->x)*canvas->pixmap_width/plot->internal_allocation.width, (new_y - plot->y)*canvas->pixmap_height/plot->internal_allocation.height);
385 child->drag_area = canvas->drag_area;
386 break;
387 case GTK_PLOT_CANVAS_PLOT_IN_AXIS:
388 break;
389 case GTK_PLOT_CANVAS_PLOT_IN_PLOT:
390 default:
391 child->rx1 = x1;
392 child->ry1 = y1;
393 child->rx2 = x2;
394 child->ry2 = y2;
395 child->drag_area = canvas->drag_area;
396 gtk_plot_move_resize(plot,
397 x1, y1, fabs(x2-x1), fabs(y2-y1));
398 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->size_allocate(canvas, child);
399 break;
400 }
401 gtk_plot_canvas_paint(canvas);
402 gtk_plot_canvas_refresh(canvas);
403 }
404
405 static void
gtk_plot_canvas_plot_set_magnification(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,gdouble m)406 gtk_plot_canvas_plot_set_magnification (GtkPlotCanvas *canvas,
407 GtkPlotCanvasChild *child,
408 gdouble m)
409 {
410 GtkPlot *plot = GTK_PLOT_CANVAS_PLOT(child)->plot;
411
412 gtk_plot_set_magnification(plot, m);
413 }
414
415 static void
gtk_plot_canvas_plot_size_allocate(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child)416 gtk_plot_canvas_plot_size_allocate (GtkPlotCanvas *canvas,
417 GtkPlotCanvasChild *child)
418 {
419 GtkAllocation allocation;
420 GtkPlot *plot = GTK_PLOT_CANVAS_PLOT(child)->plot;
421 if(!plot) return;
422
423 switch(GTK_PLOT_CANVAS_PLOT(child)->pos){
424 case GTK_PLOT_CANVAS_PLOT_IN_PLOT:
425 case GTK_PLOT_CANVAS_PLOT_OUT:
426 allocation.x = 0;
427 allocation.y = 0;
428 allocation.width = canvas->pixmap_width;
429 allocation.height = canvas->pixmap_height;
430 gtk_widget_set_allocation(GTK_WIDGET(plot), &allocation);
431
432 if(!gtk_widget_get_parent(GTK_WIDGET(plot)))
433 gtk_widget_set_parent(GTK_WIDGET(plot), GTK_WIDGET(canvas));
434
435 gtk_plot_move_resize(plot, child->rx1, child->ry1,
436 fabs(child->rx2-child->rx1), fabs(child->ry2-child->ry1));
437 reset_plot_allocation(canvas, GTK_PLOT_CANVAS_PLOT(child));
438 break;
439 case GTK_PLOT_CANVAS_PLOT_IN_LEGENDS:
440 break;
441 case GTK_PLOT_CANVAS_PLOT_IN_GRADIENT:
442 child->drag_area.x = roundint(child->rx1 * canvas->pixmap_width);
443 child->drag_area.y = roundint(child->ry1 * canvas->pixmap_height);
444 break;
445 case GTK_PLOT_CANVAS_PLOT_IN_TITLE:
446 {
447 GtkPlotText text = GTK_PLOT_CANVAS_PLOT(child)->axis->title;
448 gint tx, ty, twidth, theight;
449 gint rx, ry;
450
451 gtk_plot_text_get_area(text.text, text.angle,
452 text.justification,
453 text.font,
454 roundint(canvas->magnification * text.height),
455 &tx, &ty, &twidth, &theight);
456
457 gtk_plot_canvas_get_pixel(canvas,
458 text.x, text.y,
459 &rx, &ry);
460
461 if(text.border != GTK_PLOT_BORDER_NONE){
462 tx -= text.border_space;
463 ty -= text.border_space;
464 twidth += 2 * text.border_space;
465 theight += 2 * text.border_space;
466 }
467
468 child->drag_area.x = tx + rx;
469 child->drag_area.y = ty + ry;
470 child->drag_area.width = twidth;
471 child->drag_area.height = theight;
472 }
473 break;
474 default:
475 break;
476 }
477 }
478
479 static void
gtk_plot_canvas_plot_unselect(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child)480 gtk_plot_canvas_plot_unselect(GtkPlotCanvas *canvas, GtkPlotCanvasChild *child)
481 {
482 reset_plot_allocation(canvas, GTK_PLOT_CANVAS_PLOT(child));
483 }
484
485 static void
canvas_unselect(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child)486 canvas_unselect(GtkPlotCanvas *canvas, GtkPlotCanvasChild *child)
487 {
488 gtk_plot_canvas_unselect(canvas);
489 reset_plot_allocation(canvas, GTK_PLOT_CANVAS_PLOT(child));
490 GTK_PLOT_CANVAS_CHILD(child)->selection = GTK_PLOT_CANVAS_SELECT_MARKERS;
491 GTK_PLOT_CANVAS_CHILD(child)->mode = GTK_PLOT_CANVAS_SELECT_CLICK_2;
492 GTK_PLOT_CANVAS_CHILD(child)->flags = GTK_PLOT_CANVAS_CHILD_CAN_MOVE | GTK_PLOT_CANVAS_CHILD_CAN_RESIZE;
493 }
494
495 static GtkPlotCanvasPos
gtk_plot_canvas_plot_button_press(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,gint x,gint y)496 gtk_plot_canvas_plot_button_press(GtkPlotCanvas *canvas,
497 GtkPlotCanvasChild *child,
498 gint x, gint y)
499 {
500 GtkAllocation area;
501 GtkPlot *plot = GTK_PLOT_CANVAS_PLOT(child)->plot;
502 GtkPlotCanvasPos pos;
503 GList *dataset = NULL;
504
505 if(!plot) return GTK_PLOT_CANVAS_OUT;
506
507 /* Legends */
508
509 area = gtk_plot_legends_get_allocation(plot);
510 if((pos = possible_selection(area, x, y)) != GTK_PLOT_CANVAS_OUT) {
511 if(canvas->active_item == child &&
512 GTK_PLOT_CANVAS_PLOT(child)->pos == GTK_PLOT_CANVAS_PLOT_IN_LEGENDS)
513 return pos;
514
515 canvas_unselect(canvas, child);
516 child->drag_area = area;
517
518 GTK_PLOT_CANVAS_PLOT(child)->pos = GTK_PLOT_CANVAS_PLOT_IN_LEGENDS;
519 child->selection = GTK_PLOT_CANVAS_SELECT_MARKERS;
520 child->mode = GTK_PLOT_CANVAS_SELECT_CLICK_2;
521 child->flags = GTK_PLOT_CANVAS_CHILD_CAN_MOVE;
522 child->state = GTK_STATE_SELECTED;
523 return pos;
524 }
525
526 /* Gradient */
527
528 dataset = plot->data_sets;
529
530 while(dataset) {
531 GtkPlotData *data;
532 data = GTK_PLOT_DATA(dataset->data);
533
534 area = gtk_plot_data_get_gradient_allocation(data);
535 if((pos = possible_selection(area, x, y)) != GTK_PLOT_CANVAS_OUT) {
536 if(canvas->active_item == child &&
537 GTK_PLOT_CANVAS_PLOT(child)->pos == GTK_PLOT_CANVAS_PLOT_IN_GRADIENT &&
538 GTK_PLOT_CANVAS_PLOT(child)->data == data) return pos;
539
540 canvas_unselect(canvas, child);
541 child->drag_area = area;
542
543 GTK_PLOT_CANVAS_PLOT(child)->pos = GTK_PLOT_CANVAS_PLOT_IN_GRADIENT;
544 GTK_PLOT_CANVAS_PLOT(child)->data = data;
545 child->selection = GTK_PLOT_CANVAS_SELECT_MARKERS;
546 child->mode = GTK_PLOT_CANVAS_SELECT_CLICK_2;
547 child->flags = GTK_PLOT_CANVAS_CHILD_CAN_MOVE;
548 child->state = GTK_STATE_SELECTED;
549 return pos;
550 }
551 dataset = dataset->next;
552 }
553
554 /* Titles */
555
556 if(!GTK_IS_PLOT3D(plot)){
557 GtkPlotAxis *axis[4];
558 gint i;
559
560 axis[0]=plot->left;
561 axis[1]=plot->right;
562 axis[2]=plot->top;
563 axis[3]=plot->bottom;
564
565 for(i = 0; i <= 3; i++){
566 if(axis[i]->title_visible){
567 GtkPlotText *child_text = &axis[i]->title;
568 gint tx, ty, twidth, theight;
569 gint rx, ry;
570
571 gtk_plot_canvas_get_pixel(canvas,
572 child_text->x, child_text->y,
573 &rx, &ry);
574
575 gtk_plot_text_get_area(child_text->text,
576 child_text->angle,
577 child_text->justification,
578 child_text->font,
579 roundint(child_text->height * canvas->magnification),
580 &tx, &ty, &twidth, &theight);
581
582 area.x = rx + tx;
583 area.y = ry + ty;
584 area.width = twidth;
585 area.height = theight;
586
587 if(child_text->border != GTK_PLOT_BORDER_NONE){
588 area.x -= child_text->border_space;
589 area.y -= child_text->border_space;
590 area.width += 2 * child_text->border_space;
591 area.height += 2 * child_text->border_space;
592 }
593
594 if((pos = possible_selection(area, x, y)) != GTK_PLOT_CANVAS_OUT){
595 if(canvas->active_item == child &&
596 GTK_PLOT_CANVAS_PLOT(child)->pos == GTK_PLOT_CANVAS_PLOT_IN_TITLE &&
597 GTK_PLOT_CANVAS_PLOT(child)->axis == axis[i])
598 return pos;
599
600 canvas_unselect(canvas, child);
601 child->drag_area = area;
602
603 GTK_PLOT_CANVAS_PLOT(child)->pos = GTK_PLOT_CANVAS_PLOT_IN_TITLE;
604 GTK_PLOT_CANVAS_PLOT(child)->axis = axis[i];
605 child->selection = GTK_PLOT_CANVAS_SELECT_MARKERS;
606 child->mode = GTK_PLOT_CANVAS_SELECT_CLICK_2;
607 child->flags = GTK_PLOT_CANVAS_CHILD_CAN_MOVE;
608 child->state = GTK_STATE_SELECTED;
609 return pos;
610 }
611 }
612 }
613
614 }
615
616 /* Plot markers */
617
618 area = plot->internal_allocation;
619 if((pos = possible_selection(area, x, y)) != GTK_PLOT_CANVAS_OUT &&
620 pos != GTK_PLOT_CANVAS_IN) {
621 if(canvas->active_item == child &&
622 GTK_PLOT_CANVAS_PLOT(child)->pos == GTK_PLOT_CANVAS_PLOT_IN_PLOT)
623 return pos;
624
625 canvas_unselect(canvas, child);
626 child->drag_area = area;
627
628 GTK_PLOT_CANVAS_PLOT(child)->pos = GTK_PLOT_CANVAS_PLOT_IN_PLOT;
629 child->selection = GTK_PLOT_CANVAS_SELECT_MARKERS;
630 child->mode = GTK_PLOT_CANVAS_SELECT_CLICK_2;
631 child->flags = GTK_PLOT_CANVAS_CHILD_CAN_MOVE;
632 child->state = GTK_STATE_SELECTED;
633 return pos;
634 }
635
636 /* Axes */
637
638 if(!GTK_IS_PLOT3D(plot)){
639 gint px, py, pwidth, pheight;
640 GtkAllocation _area[4];
641 GtkPlotAxis *axis[4];
642 gint i;
643
644 axis[0]=plot->left;
645 axis[1]=plot->right;
646 axis[2]=plot->top;
647 axis[3]=plot->bottom;
648
649 px = plot->internal_allocation.x;
650 py = plot->internal_allocation.y;
651 pwidth = plot->internal_allocation.width;
652 pheight = plot->internal_allocation.height;
653
654 _area[0].x = px - 6;
655 _area[0].y = _area[1].y = py;
656 _area[0].width = _area[1].width = 6;
657 _area[0].height = _area[1].height = pheight;
658 _area[1].x = px + pwidth;
659 _area[2].x = _area[3].x = px;
660 _area[2].y = py - 6;
661 _area[2].width = _area[3].width = pwidth;
662 _area[2].height = _area[3].height = 6;
663 _area[3].y = py + pheight;
664
665 for(i = 0; i < 4; i++){
666 area = _area[i];
667 if((pos = possible_selection(area, x, y)) != GTK_PLOT_CANVAS_OUT){
668
669 if(canvas->active_item == child &&
670 GTK_PLOT_CANVAS_PLOT(child)->pos == GTK_PLOT_CANVAS_PLOT_IN_AXIS &&
671 GTK_PLOT_CANVAS_PLOT(child)->axis == axis[i])
672 return pos;
673
674 canvas_unselect(canvas, child);
675 child->drag_area = area;
676
677 GTK_PLOT_CANVAS_PLOT(child)->pos = GTK_PLOT_CANVAS_PLOT_IN_AXIS;
678 GTK_PLOT_CANVAS_PLOT(child)->axis = axis[i];
679 child->state = GTK_STATE_SELECTED;
680 child->flags = GTK_PLOT_CANVAS_CHILD_FROZEN;
681 child->selection = GTK_PLOT_CANVAS_SELECT_MARKERS;
682 child->mode = GTK_PLOT_CANVAS_SELECT_CLICK_2;
683 return pos;
684 }
685 }
686 }
687
688 /* Markers */
689
690 if(!GTK_IS_PLOT3D(plot)){
691 dataset = plot->data_sets;
692
693 while(dataset) {
694 GtkPlotData *data = GTK_PLOT_DATA(dataset->data);
695 GList *markers = data->markers;
696 while(markers){
697 GtkPlotMarker *marker;
698 gdouble fx, fy, fz, fa, fdx, fdy, fdz, fda;
699 gboolean error;
700 gchar *label;
701 gdouble xi, yi;
702
703 marker = (GtkPlotMarker *) markers->data;
704
705 gtk_plot_data_get_point(data, marker->point,
706 &fx, &fy, &fz, &fa, &fdx, &fdy, &fdz, &fda,
707 &label, &error);
708 gtk_plot_get_pixel(GTK_PLOT(plot), fx, fy, &xi, &yi);
709 if(abs(xi-x) <= 20 && abs(yi-y) <= 20){
710
711 if(canvas->active_item == child &&
712 GTK_PLOT_CANVAS_PLOT(child)->pos == GTK_PLOT_CANVAS_PLOT_IN_MARKER &&
713 GTK_PLOT_CANVAS_PLOT(child)->marker == marker)
714 return GTK_PLOT_CANVAS_IN;
715
716 canvas_unselect(canvas, child);
717
718 GTK_PLOT_CANVAS_PLOT(child)->pos = GTK_PLOT_CANVAS_PLOT_IN_MARKER;
719 GTK_PLOT_CANVAS_PLOT(child)->data = data;
720 GTK_PLOT_CANVAS_PLOT(child)->marker = marker;
721 GTK_PLOT_CANVAS_PLOT(child)->datapoint = marker->point;
722 child->drag_area.x = xi - 10;
723 child->drag_area.y = yi - 10;
724 child->drag_area.width = 20;
725 child->drag_area.height = 20;
726 canvas->drag_area = child->drag_area;
727 child->state = GTK_STATE_SELECTED;
728 child->flags = GTK_PLOT_CANVAS_CHILD_CAN_MOVE;
729 child->selection = GTK_PLOT_CANVAS_SELECT_TARGET;
730 child->mode = GTK_PLOT_CANVAS_SELECT_CLICK_1;
731 return GTK_PLOT_CANVAS_IN;
732 }
733 markers = markers->next;
734 }
735 dataset = dataset->next;
736 }
737 }
738
739 /* Dataset */
740
741 if(!GTK_IS_PLOT3D(plot)
742 && GTK_PLOT_CANVAS_PLOT_SELECT_POINT(GTK_PLOT_CANVAS_PLOT(child))){
743 dataset = plot->data_sets;
744
745 while(dataset) {
746 GtkPlotData *data = GTK_PLOT_DATA(dataset->data);
747
748 if(!data->is_function){
749 gdouble fx, fy, fz, fa, fdx, fdy, fdz, fda;
750 gboolean error;
751 gchar *label;
752 gint i;
753
754 for(i = 0; i < data->num_points; i++){
755 gdouble xi, yi;
756 gtk_plot_data_get_point(data, i,
757 &fx, &fy, &fz, &fa, &fdx, &fdy, &fdz, &fda,
758 &label, &error);
759 gtk_plot_get_pixel(GTK_PLOT(plot), fx, fy, &xi, &yi);
760 if(abs(xi-x) <= DEFAULT_MARKER_SIZE &&
761 abs(yi-y) <= DEFAULT_MARKER_SIZE){
762
763 if(canvas->active_item == child &&
764 GTK_PLOT_CANVAS_PLOT(child)->pos == GTK_PLOT_CANVAS_PLOT_IN_DATA &&
765 GTK_PLOT_CANVAS_PLOT(child)->data == data &&
766 GTK_PLOT_CANVAS_PLOT(child)->datapoint == i)
767 return GTK_PLOT_CANVAS_IN;
768
769 canvas_unselect(canvas, child);
770
771 GTK_PLOT_CANVAS_PLOT(child)->pos = GTK_PLOT_CANVAS_PLOT_IN_DATA;
772 GTK_PLOT_CANVAS_PLOT(child)->data = data;
773 GTK_PLOT_CANVAS_PLOT(child)->datapoint = i;
774 child->drag_area.x = xi - DEFAULT_MARKER_SIZE;
775 child->drag_area.y = yi - DEFAULT_MARKER_SIZE;
776 child->drag_area.width = 2*DEFAULT_MARKER_SIZE;
777 child->drag_area.height = 2*DEFAULT_MARKER_SIZE;
778 canvas->drag_area = child->drag_area;
779 child->state = GTK_STATE_SELECTED;
780 child->flags = GTK_PLOT_CANVAS_CHILD_FROZEN;
781 if(GTK_PLOT_CANVAS_PLOT_DND_POINT(GTK_PLOT_CANVAS_PLOT(child)))
782 child->flags = GTK_PLOT_CANVAS_CHILD_CAN_MOVE;
783 child->selection = GTK_PLOT_CANVAS_SELECT_TARGET;
784 child->mode = GTK_PLOT_CANVAS_SELECT_CLICK_1;
785 return GTK_PLOT_CANVAS_IN;
786 }
787 }
788 }
789 dataset = dataset->next;
790 }
791 }
792
793 /* Actual plot */
794
795 area = plot->internal_allocation;
796 if((pos = possible_selection(area, x, y)) != GTK_PLOT_CANVAS_OUT) {
797 if(canvas->active_item == child &&
798 GTK_PLOT_CANVAS_PLOT(child)->pos == GTK_PLOT_CANVAS_PLOT_IN_PLOT)
799 return pos;
800
801 canvas_unselect(canvas, child);
802 child->drag_area = area;
803
804 GTK_PLOT_CANVAS_PLOT(child)->pos = GTK_PLOT_CANVAS_PLOT_IN_PLOT;
805 child->state = GTK_STATE_SELECTED;
806 return pos;
807 }
808
809
810 GTK_PLOT_CANVAS_PLOT(child)->pos = GTK_PLOT_CANVAS_PLOT_OUT;
811 return GTK_PLOT_CANVAS_OUT;
812 }
813
814