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 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <math.h>
24 #include <gtk/gtk.h>
25 #include <gdk/gdkkeysyms.h>
26 #include "gtkplotcanvas.h"
27 #include "gtkplotgdk.h"
28 #include "gtkplotps.h"
29 #include "gtkextra-marshal.h"
30
31 #define P_(string) string
32
33 #define DEFAULT_WIDTH 100
34 #define DEFAULT_HEIGHT 150
35 #define DEFAULT_MARKER_SIZE 6
36 #define SHADOW_WIDTH 3
37 #define GRAPH_MASK (GDK_EXPOSURE_MASK | \
38 GDK_POINTER_MOTION_MASK | \
39 GDK_POINTER_MOTION_HINT_MASK | \
40 GDK_BUTTON_PRESS_MASK | \
41 GDK_BUTTON_RELEASE_MASK)
42
43 enum {
44 ARG_CANVAS_0,
45 ARG_CANVAS_FLAGS,
46 ARG_CANVAS_WIDTH,
47 ARG_CANVAS_HEIGHT,
48 ARG_CANVAS_MAGNIFICATION,
49 ARG_CANVAS_SHOW_GRID,
50 ARG_CANVAS_GRID_STEP,
51 ARG_CANVAS_LINE_GRID,
52 ARG_CANVAS_COLOR_BG,
53 ARG_CANVAS_TRANSPARENT,
54 };
55
56 enum {
57 ARG_CHILD_0,
58 ARG_CHILD_RX1,
59 ARG_CHILD_RY1,
60 ARG_CHILD_RX2,
61 ARG_CHILD_RY2,
62 ARG_CHILD_ALLOCATION,
63 ARG_CHILD_MIN_WIDTH,
64 ARG_CHILD_MIN_HEIGHT,
65 ARG_CHILD_STATE,
66 ARG_CHILD_FLAGS,
67 ARG_CHILD_SELECTION,
68 ARG_CHILD_SELECTION_MODE,
69 };
70
71 static void gtk_plot_canvas_class_init (GtkPlotCanvasClass *klass);
72 static void gtk_plot_canvas_init (GtkPlotCanvas *plot_canvas);
73 static void gtk_plot_canvas_set_property (GObject *object,
74 guint prop_id,
75 const GValue *value,
76 GParamSpec *pspec);
77 static void gtk_plot_canvas_get_property (GObject *object,
78 guint prop_id,
79 GValue *value,
80 GParamSpec *pspec);
81 static void gtk_plot_canvas_child_class_init (GtkPlotCanvasChildClass *klass);
82 static void gtk_plot_canvas_child_init (GtkPlotCanvasChild *child);
83 static void gtk_plot_canvas_child_set_property (GObject *object,
84 guint prop_id,
85 const GValue *value,
86 GParamSpec *pspec);
87 static void gtk_plot_canvas_child_get_property (GObject *object,
88 guint prop_id,
89 GValue *value,
90 GParamSpec *pspec);
91 static void gtk_plot_canvas_destroy (GtkObject *object);
92 static void gtk_plot_canvas_map (GtkWidget *widget);
93 static void gtk_plot_canvas_size_request (GtkWidget *widget,
94 GtkRequisition *requisition);
95 static gint gtk_plot_canvas_motion (GtkWidget *widget,
96 GdkEventMotion *event);
97 static gint gtk_plot_canvas_button_press (GtkWidget *widget,
98 GdkEventButton *event);
99 static gint gtk_plot_canvas_key_press (GtkWidget *widget,
100 GdkEventKey *event);
101 static gint gtk_plot_canvas_button_release (GtkWidget *widget,
102 GdkEventButton *event);
103 static gint gtk_plot_canvas_focus_in (GtkWidget *widget,
104 GdkEventFocus *event);
105 static gint gtk_plot_canvas_focus_out (GtkWidget *widget,
106 GdkEventFocus *event);
107 static void gtk_plot_canvas_child_size_allocate (GtkPlotCanvas *canvas,
108 GtkPlotCanvasChild *child);
109 static GtkPlotCanvasPos gtk_plot_canvas_child_button_press
110 (GtkPlotCanvas *canvas,
111 GtkPlotCanvasChild *child,
112 gint x, gint y);
113 static void gtk_plot_canvas_child_button_release(GtkPlotCanvas *canvas,
114 GtkPlotCanvasChild *child);
115 /* Drawing functions */
116 static gint gtk_plot_canvas_expose (GtkWidget *widget,
117 GdkEventExpose *event);
118 static void gtk_plot_canvas_create_pixmap (GtkWidget *widget,
119 gint width, gint height);
120 static void gtk_plot_canvas_child_draw (GtkPlotCanvas *canvas,
121 GtkPlotCanvasChild *child);
122 static void gtk_plot_canvas_child_draw_selection(GtkPlotCanvas *canvas,
123 GtkPlotCanvasChild *child,
124 GtkAllocation area);
125 static void draw_selection (GtkPlotCanvas *canvas,
126 GtkPlotCanvasChild *child,
127 GtkAllocation area);
128 static void draw_marker (GtkPlotCanvas *canvas,
129 GdkGC *gc, gint x, gint y);
130
131 static void gtk_plot_canvas_draw_grid (GtkPlotCanvas *canvas);
132 static void gtk_plot_canvas_child_draw (GtkPlotCanvas *canvas,
133 GtkPlotCanvasChild *child);
134 /* Auxiliary functions */
135 GtkPlotCanvasPos possible_selection (GtkAllocation area,
136 gint x, gint y);
137 extern gint roundint (gdouble x);
138
139
140 /* Signals */
141
142 extern void
143 _gtkextra_signal_emit(GtkObject *object, guint signal_id, ...);
144
145 enum {
146 SELECT_ITEM,
147 MOVE_ITEM,
148 RESIZE_ITEM,
149 DELETE_ITEM,
150 ADD_ITEM,
151 SELECT_REGION,
152 CHANGED,
153 LAST_SIGNAL
154 };
155
156 typedef gboolean (*GtkPlotCanvasSignal1) (GtkObject *object,
157 gpointer arg1,
158 gdouble arg2,
159 gdouble arg3,
160 gpointer user_data);
161
162 typedef gboolean (*GtkPlotCanvasSignal2) (GtkObject *object,
163 gpointer arg1,
164 gpointer arg2,
165 gpointer user_data);
166
167 typedef gboolean (*GtkPlotCanvasSignal3) (GtkObject *object,
168 gdouble arg1,
169 gdouble arg2,
170 gdouble arg3,
171 gdouble arg4,
172 gpointer user_data);
173
174 static GtkFixedClass *parent_class = NULL;
175 static guint canvas_signals[LAST_SIGNAL] = {0};
176
177 GtkType
gtk_plot_canvas_get_type(void)178 gtk_plot_canvas_get_type (void)
179 {
180 static GtkType plot_canvas_type = 0;
181
182 if (!plot_canvas_type)
183 {
184 GtkTypeInfo plot_canvas_info =
185 {
186 "GtkPlotCanvas",
187 sizeof (GtkPlotCanvas),
188 sizeof (GtkPlotCanvasClass),
189 (GtkClassInitFunc) gtk_plot_canvas_class_init,
190 (GtkObjectInitFunc) gtk_plot_canvas_init,
191 /* reserved 1*/ NULL,
192 /* reserved 2 */ NULL,
193 (GtkClassInitFunc) NULL,
194 };
195
196 plot_canvas_type = gtk_type_unique (gtk_fixed_get_type(), &plot_canvas_info);
197 }
198 return plot_canvas_type;
199 }
200
201 GtkType
gtk_plot_canvas_child_get_type(void)202 gtk_plot_canvas_child_get_type (void)
203 {
204 static GtkType plot_canvas_child_type = 0;
205
206 if (!plot_canvas_child_type)
207 {
208 GtkTypeInfo plot_canvas_child_info =
209 {
210 "GtkPlotCanvasChild",
211 sizeof(GtkPlotCanvasChild),
212 sizeof(GtkPlotCanvasChildClass),
213 (GtkClassInitFunc) gtk_plot_canvas_child_class_init,
214 (GtkObjectInitFunc) gtk_plot_canvas_child_init,
215 /* reserved 1*/ NULL,
216 /* reserved 2 */ NULL,
217 (GtkClassInitFunc) NULL,
218 };
219
220 plot_canvas_child_type = gtk_type_unique (gtk_object_get_type(),
221 &plot_canvas_child_info);
222 }
223 return plot_canvas_child_type;
224 }
225
226 static void
gtk_plot_canvas_child_class_init(GtkPlotCanvasChildClass * klass)227 gtk_plot_canvas_child_class_init (GtkPlotCanvasChildClass *klass)
228 {
229 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
230
231 klass->size_allocate = gtk_plot_canvas_child_size_allocate;
232 klass->draw = NULL;
233 klass->unselect = NULL;
234 klass->move = NULL;
235 klass->move_resize = NULL;
236 klass->draw_selection = draw_selection;
237 klass->button_press = gtk_plot_canvas_child_button_press;
238 klass->button_release = gtk_plot_canvas_child_button_release;
239 klass->set_magnification = NULL;
240
241 gobject_class->get_property = gtk_plot_canvas_child_get_property;
242 gobject_class->set_property = gtk_plot_canvas_child_set_property;
243
244 g_object_class_install_property (gobject_class,
245 ARG_CHILD_RX1,
246 g_param_spec_double ("rx1",
247 P_(""),
248 P_(""),
249 -G_MAXDOUBLE,G_MAXDOUBLE,0.0,
250 G_PARAM_READABLE|G_PARAM_WRITABLE));
251 g_object_class_install_property (gobject_class,
252 ARG_CHILD_RY1,
253 g_param_spec_double ("ry1",
254 P_(""),
255 P_(""),
256 -G_MAXDOUBLE,G_MAXDOUBLE,0.0,
257 G_PARAM_READABLE|G_PARAM_WRITABLE));
258 g_object_class_install_property (gobject_class,
259 ARG_CHILD_RX2,
260 g_param_spec_double ("rx2",
261 P_(""),
262 P_(""),
263 -G_MAXDOUBLE,G_MAXDOUBLE,0.0,
264 G_PARAM_READABLE|G_PARAM_WRITABLE));
265 g_object_class_install_property (gobject_class,
266 ARG_CHILD_RY2,
267 g_param_spec_double ("ry2",
268 P_(""),
269 P_(""),
270 -G_MAXDOUBLE,G_MAXDOUBLE,0.0,
271 G_PARAM_READABLE|G_PARAM_WRITABLE));
272 g_object_class_install_property (gobject_class,
273 ARG_CHILD_ALLOCATION,
274 g_param_spec_pointer ("allocation",
275 P_(""),
276 P_(""),
277 G_PARAM_READABLE|G_PARAM_WRITABLE));
278 g_object_class_install_property (gobject_class,
279 ARG_CHILD_MIN_WIDTH,
280 g_param_spec_int ("min_width",
281 P_(""),
282 P_(""),
283 -1,G_MAXINT,0,
284 G_PARAM_READABLE|G_PARAM_WRITABLE));
285 g_object_class_install_property (gobject_class,
286 ARG_CHILD_MIN_HEIGHT,
287 g_param_spec_int ("min_height",
288 P_(""),
289 P_(""),
290 -1,G_MAXINT,0,
291 G_PARAM_READABLE|G_PARAM_WRITABLE));
292 g_object_class_install_property (gobject_class,
293 ARG_CHILD_STATE,
294 g_param_spec_int ("state",
295 P_(""),
296 P_(""),
297 0,G_MAXINT,0,
298 G_PARAM_READABLE|G_PARAM_WRITABLE));
299 g_object_class_install_property (gobject_class,
300 ARG_CHILD_FLAGS,
301 g_param_spec_int ("flags",
302 P_(""),
303 P_(""),
304 0,G_MAXINT,0,
305 G_PARAM_READABLE|G_PARAM_WRITABLE));
306 g_object_class_install_property (gobject_class,
307 ARG_CHILD_SELECTION,
308 g_param_spec_int ("selection",
309 P_(""),
310 P_(""),
311 0,G_MAXINT,0,
312 G_PARAM_READABLE|G_PARAM_WRITABLE));
313 g_object_class_install_property (gobject_class,
314 ARG_CHILD_SELECTION_MODE,
315 g_param_spec_int ("selection_mode",
316 P_(""),
317 P_(""),
318 0,G_MAXINT,0,
319 G_PARAM_READABLE|G_PARAM_WRITABLE));
320
321 }
322
323 static void
gtk_plot_canvas_child_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)324 gtk_plot_canvas_child_get_property (GObject *object,
325 guint prop_id,
326 GValue *value,
327 GParamSpec *pspec)
328 {
329 GtkPlotCanvasChild *child = GTK_PLOT_CANVAS_CHILD(object);
330
331 switch(prop_id){
332 case ARG_CHILD_RX1:
333 g_value_set_double(value, child->rx1);
334 break;
335 case ARG_CHILD_RY1:
336 g_value_set_double(value, child->ry1);
337 break;
338 case ARG_CHILD_RX2:
339 g_value_set_double(value, child->rx2);
340 break;
341 case ARG_CHILD_RY2:
342 g_value_set_double(value, child->ry2);
343 break;
344 case ARG_CHILD_ALLOCATION:
345 g_value_set_pointer(value, &child->allocation);
346 break;
347 case ARG_CHILD_MIN_WIDTH:
348 g_value_set_int(value, child->min_width);
349 break;
350 case ARG_CHILD_MIN_HEIGHT:
351 g_value_set_int(value, child->min_height);
352 break;
353 case ARG_CHILD_STATE:
354 g_value_set_int(value, child->state);
355 break;
356 case ARG_CHILD_FLAGS:
357 g_value_set_int(value, child->flags);
358 break;
359 case ARG_CHILD_SELECTION:
360 g_value_set_int(value, child->selection);
361 break;
362 case ARG_CHILD_SELECTION_MODE:
363 g_value_set_int(value, child->mode);
364 break;
365 }
366 }
367
368 static void
gtk_plot_canvas_child_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)369 gtk_plot_canvas_child_set_property (GObject *object,
370 guint prop_id,
371 const GValue *value,
372 GParamSpec *pspec)
373 {
374 GtkPlotCanvasChild *child = GTK_PLOT_CANVAS_CHILD(object);
375
376 switch(prop_id){
377 case ARG_CHILD_RX1:
378 child->rx1 = g_value_get_double(value);
379 break;
380 case ARG_CHILD_RY1:
381 child->ry1 = g_value_get_double(value);
382 break;
383 case ARG_CHILD_RX2:
384 child->rx2 = g_value_get_double(value);
385 break;
386 case ARG_CHILD_RY2:
387 child->ry2 = g_value_get_double(value);
388 break;
389 case ARG_CHILD_ALLOCATION:
390 child->allocation = *((GtkAllocation *)g_value_get_pointer(value));
391 break;
392 case ARG_CHILD_MIN_WIDTH:
393 child->min_width = g_value_get_int(value);
394 break;
395 case ARG_CHILD_MIN_HEIGHT:
396 child->min_height = g_value_get_int(value);
397 break;
398 case ARG_CHILD_STATE:
399 child->state = g_value_get_int(value);
400 break;
401 case ARG_CHILD_FLAGS:
402 child->flags = g_value_get_int(value);
403 break;
404 case ARG_CHILD_SELECTION:
405 child->selection = g_value_get_int(value);
406 break;
407 case ARG_CHILD_SELECTION_MODE:
408 child->mode = g_value_get_int(value);
409 break;
410 }
411 }
412
413 static void
gtk_plot_canvas_child_init(GtkPlotCanvasChild * child)414 gtk_plot_canvas_child_init(GtkPlotCanvasChild *child)
415 {
416 child->flags = GTK_PLOT_CANVAS_CAN_MOVE |
417 GTK_PLOT_CANVAS_CAN_RESIZE;
418
419 child->min_width = -1;
420 child->min_height = -1;
421
422 child->selection = GTK_PLOT_CANVAS_SELECT_MARKERS;
423 child->mode = GTK_PLOT_CANVAS_SELECT_CLICK_2;
424 child->parent = NULL;
425 }
426
427 static void
gtk_plot_canvas_class_init(GtkPlotCanvasClass * klass)428 gtk_plot_canvas_class_init (GtkPlotCanvasClass *klass)
429 {
430 GtkObjectClass *object_class;
431 GtkWidgetClass *widget_class;
432 GtkContainerClass *container_class;
433 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
434
435 parent_class = gtk_type_class (gtk_fixed_get_type ());
436
437 object_class = (GtkObjectClass *) klass;
438 widget_class = (GtkWidgetClass *) klass;
439 container_class = (GtkContainerClass *) klass;
440
441 canvas_signals[SELECT_ITEM] =
442 gtk_signal_new ("select_item",
443 GTK_RUN_LAST,
444 GTK_CLASS_TYPE(object_class),
445 GTK_SIGNAL_OFFSET (GtkPlotCanvasClass, select_item),
446 gtkextra_BOOLEAN__BOXED_BOXED,
447 GTK_TYPE_BOOL, 2, GDK_TYPE_EVENT,
448 GTK_TYPE_PLOT_CANVAS_CHILD);
449
450 canvas_signals[MOVE_ITEM] =
451 gtk_signal_new ("move_item",
452 GTK_RUN_LAST,
453 GTK_CLASS_TYPE(object_class),
454 GTK_SIGNAL_OFFSET (GtkPlotCanvasClass, move_item),
455 gtkextra_BOOLEAN__BOXED_DOUBLE_DOUBLE,
456 GTK_TYPE_BOOL, 3, GTK_TYPE_PLOT_CANVAS_CHILD,
457 GTK_TYPE_DOUBLE,
458 GTK_TYPE_DOUBLE);
459
460 canvas_signals[RESIZE_ITEM] =
461 gtk_signal_new ("resize_item",
462 GTK_RUN_LAST,
463 GTK_CLASS_TYPE(object_class),
464 GTK_SIGNAL_OFFSET (GtkPlotCanvasClass, resize_item),
465 gtkextra_BOOLEAN__BOXED_DOUBLE_DOUBLE,
466 GTK_TYPE_BOOL, 3, GTK_TYPE_PLOT_CANVAS_CHILD,
467 GTK_TYPE_DOUBLE,
468 GTK_TYPE_DOUBLE);
469
470 canvas_signals[ADD_ITEM] =
471 gtk_signal_new ("add_item",
472 GTK_RUN_LAST,
473 GTK_CLASS_TYPE(object_class),
474 GTK_SIGNAL_OFFSET (GtkPlotCanvasClass, add_item),
475 gtkextra_VOID__POINTER,
476 GTK_TYPE_NONE, 1,
477 GTK_TYPE_PLOT_CANVAS_CHILD);
478
479 canvas_signals[DELETE_ITEM] =
480 gtk_signal_new ("delete_item",
481 GTK_RUN_LAST,
482 GTK_CLASS_TYPE(object_class),
483 GTK_SIGNAL_OFFSET (GtkPlotCanvasClass, delete_item),
484 gtkextra_BOOL__POINTER,
485 GTK_TYPE_BOOL, 1,
486 GTK_TYPE_PLOT_CANVAS_CHILD);
487
488 canvas_signals[SELECT_REGION] =
489 gtk_signal_new ("select_region",
490 GTK_RUN_LAST,
491 GTK_CLASS_TYPE(object_class),
492 GTK_SIGNAL_OFFSET (GtkPlotCanvasClass, select_region),
493 gtkextra_VOID__DOUBLE_DOUBLE_DOUBLE_DOUBLE,
494 GTK_TYPE_NONE, 4,
495 GTK_TYPE_DOUBLE, GTK_TYPE_DOUBLE,
496 GTK_TYPE_DOUBLE, GTK_TYPE_DOUBLE);
497
498 canvas_signals[CHANGED] =
499 gtk_signal_new("changed",
500 GTK_RUN_LAST,
501 GTK_CLASS_TYPE(object_class),
502 GTK_SIGNAL_OFFSET (GtkPlotCanvasClass, changed),
503 gtkextra_VOID__VOID,
504 GTK_TYPE_NONE, 0);
505
506 object_class->destroy = gtk_plot_canvas_destroy;
507
508 gobject_class->get_property = gtk_plot_canvas_get_property;
509 gobject_class->set_property = gtk_plot_canvas_set_property;
510
511 widget_class->map = gtk_plot_canvas_map;
512 widget_class->expose_event = gtk_plot_canvas_expose;
513 widget_class->size_request = gtk_plot_canvas_size_request;
514 widget_class->focus_in_event = gtk_plot_canvas_focus_in;
515 widget_class->focus_out_event = gtk_plot_canvas_focus_out;
516 widget_class->motion_notify_event = gtk_plot_canvas_motion;
517 widget_class->button_press_event = gtk_plot_canvas_button_press;
518 widget_class->button_release_event = gtk_plot_canvas_button_release;
519 widget_class->key_press_event = gtk_plot_canvas_key_press;
520
521 klass->move_item = NULL;
522 klass->resize_item = NULL;
523 klass->select_item = NULL;
524 klass->delete_item = NULL;
525 klass->select_region = NULL;
526
527 g_object_class_install_property (gobject_class,
528 ARG_CANVAS_FLAGS,
529 g_param_spec_int ("flags",
530 P_(""),
531 P_(""),
532 0,G_MAXINT,0,
533 G_PARAM_READABLE|G_PARAM_WRITABLE));
534 g_object_class_install_property (gobject_class,
535 ARG_CANVAS_MAGNIFICATION,
536 g_param_spec_double ("magnification",
537 P_(""),
538 P_(""),
539 0,G_MAXDOUBLE,1.0,
540 G_PARAM_READABLE|G_PARAM_WRITABLE));
541 g_object_class_install_property (gobject_class,
542 ARG_CANVAS_WIDTH,
543 g_param_spec_int ("width",
544 P_(""),
545 P_(""),
546 0,G_MAXINT,1,
547 G_PARAM_READABLE|G_PARAM_WRITABLE));
548 g_object_class_install_property (gobject_class,
549 ARG_CANVAS_HEIGHT,
550 g_param_spec_int ("height",
551 P_(""),
552 P_(""),
553 0,G_MAXINT,1,
554 G_PARAM_READABLE|G_PARAM_WRITABLE));
555 g_object_class_install_property (gobject_class,
556 ARG_CANVAS_SHOW_GRID,
557 g_param_spec_boolean ("show_grid",
558 P_(""),
559 P_(""),
560 FALSE,
561 G_PARAM_READABLE|G_PARAM_WRITABLE));
562 g_object_class_install_property (gobject_class,
563 ARG_CANVAS_GRID_STEP,
564 g_param_spec_double ("grid_step",
565 P_(""),
566 P_(""),
567 0,G_MAXDOUBLE,0.0,
568 G_PARAM_READABLE|G_PARAM_WRITABLE));
569 g_object_class_install_property (gobject_class,
570 ARG_CANVAS_LINE_GRID,
571 g_param_spec_pointer ("line_grid",
572 P_(""),
573 P_(""),
574 G_PARAM_READABLE|G_PARAM_WRITABLE));
575 g_object_class_install_property (gobject_class,
576 ARG_CANVAS_COLOR_BG,
577 g_param_spec_pointer ("color_bg",
578 P_(""),
579 P_(""),
580 G_PARAM_READABLE|G_PARAM_WRITABLE));
581 g_object_class_install_property (gobject_class,
582 ARG_CANVAS_TRANSPARENT,
583 g_param_spec_boolean ("transparent",
584 P_(""),
585 P_(""),
586 TRUE,
587 G_PARAM_READABLE|G_PARAM_WRITABLE));
588 }
589
590 static void
gtk_plot_canvas_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)591 gtk_plot_canvas_get_property (GObject *object,
592 guint prop_id,
593 GValue *value,
594 GParamSpec *pspec)
595 {
596 GtkPlotCanvas *canvas = GTK_PLOT_CANVAS(object);
597
598 switch(prop_id){
599 case ARG_CANVAS_FLAGS:
600 g_value_set_int(value, canvas->flags);
601 break;
602 case ARG_CANVAS_WIDTH:
603 g_value_set_int(value, canvas->width);
604 break;
605 case ARG_CANVAS_HEIGHT:
606 g_value_set_int(value, canvas->height);
607 break;
608 case ARG_CANVAS_MAGNIFICATION:
609 g_value_set_double(value, canvas->magnification);
610 break;
611 case ARG_CANVAS_SHOW_GRID:
612 g_value_set_boolean(value, canvas->show_grid);
613 break;
614 case ARG_CANVAS_GRID_STEP:
615 g_value_set_double(value, canvas->grid_step);
616 break;
617 case ARG_CANVAS_LINE_GRID:
618 g_value_set_pointer(value, &canvas->grid);
619 break;
620 case ARG_CANVAS_COLOR_BG:
621 g_value_set_pointer(value, &canvas->background);
622 break;
623 case ARG_CANVAS_TRANSPARENT:
624 g_value_set_boolean(value, canvas->transparent);
625 break;
626 }
627 }
628
629 static void
gtk_plot_canvas_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)630 gtk_plot_canvas_set_property (GObject *object,
631 guint prop_id,
632 const GValue *value,
633 GParamSpec *pspec)
634 {
635 GtkPlotCanvas *canvas;
636
637 canvas = GTK_PLOT_CANVAS (object);
638
639 switch(prop_id){
640 case ARG_CANVAS_FLAGS:
641 canvas->flags = g_value_get_int(value);
642 break;
643 case ARG_CANVAS_WIDTH:
644 canvas->width = g_value_get_int(value);
645 break;
646 case ARG_CANVAS_HEIGHT:
647 canvas->height = g_value_get_int(value);
648 break;
649 case ARG_CANVAS_MAGNIFICATION:
650 canvas->magnification = g_value_get_double(value);
651 break;
652 case ARG_CANVAS_SHOW_GRID:
653 canvas->show_grid = g_value_get_boolean(value);
654 break;
655 case ARG_CANVAS_GRID_STEP:
656 canvas->grid_step = g_value_get_double(value);
657 break;
658 case ARG_CANVAS_LINE_GRID:
659 canvas->grid = *((GtkPlotLine *)g_value_get_pointer(value));
660 break;
661 case ARG_CANVAS_COLOR_BG:
662 canvas->background = *((GdkColor *)g_value_get_pointer(value));
663 break;
664 case ARG_CANVAS_TRANSPARENT:
665 canvas->transparent = g_value_get_boolean(value);
666 break;
667 }
668 }
669
670 static void
gtk_plot_canvas_init(GtkPlotCanvas * plot_canvas)671 gtk_plot_canvas_init (GtkPlotCanvas *plot_canvas)
672 {
673 GtkWidget *widget;
674 GdkColor color;
675
676 widget = GTK_WIDGET(plot_canvas);
677 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
678
679 gdk_color_black(gtk_widget_get_colormap(widget), &widget->style->black);
680 gdk_color_white(gtk_widget_get_colormap(widget), &widget->style->white);
681
682 gtk_widget_set_events (widget, gtk_widget_get_events(widget)|
683 GRAPH_MASK);
684
685 plot_canvas->freeze_count = 0;
686 plot_canvas->cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
687
688 plot_canvas->background = widget->style->white;
689 plot_canvas->transparent = TRUE;
690
691 plot_canvas->flags = 0;
692 plot_canvas->state = GTK_STATE_NORMAL;
693 plot_canvas->action = GTK_PLOT_CANVAS_ACTION_INACTIVE;
694 plot_canvas->magnification = 1.;
695
696 plot_canvas->show_grid = FALSE;
697 plot_canvas->grid_step = 20.;
698 plot_canvas->grid.line_style = GTK_PLOT_LINE_SOLID;
699 plot_canvas->grid.line_width = 0;
700
701 gdk_color_parse("grey90", &color);
702 gdk_color_alloc(gdk_colormap_get_system(), &color);
703 plot_canvas->grid.color = color;
704
705 plot_canvas->drag_x = plot_canvas->drag_y = 0;
706 plot_canvas->pointer_x = plot_canvas->pointer_y = 0;
707
708 plot_canvas->childs = NULL;
709
710 plot_canvas->width = DEFAULT_WIDTH;
711 plot_canvas->height = DEFAULT_HEIGHT;
712 plot_canvas->pixmap_width = DEFAULT_WIDTH;
713 plot_canvas->pixmap_height = DEFAULT_HEIGHT;
714
715 gtk_psfont_init();
716
717 plot_canvas->pc = NULL;
718 gtk_plot_canvas_set_pc(plot_canvas, NULL);
719
720 plot_canvas->pixmap = NULL;
721 }
722
723 void
gtk_plot_canvas_set_pc(GtkPlotCanvas * canvas,GtkPlotPC * pc)724 gtk_plot_canvas_set_pc(GtkPlotCanvas *canvas, GtkPlotPC *pc)
725 {
726 if(canvas->pc)
727 gtk_object_unref(GTK_OBJECT(canvas->pc));
728
729 if(!pc){
730 canvas->pc = GTK_PLOT_PC(gtk_plot_gdk_new(GTK_WIDGET(canvas)));
731 gtk_object_ref(GTK_OBJECT(canvas->pc));
732 gtk_object_sink(GTK_OBJECT(canvas->pc));
733 } else {
734 canvas->pc = pc;
735 gtk_object_ref(GTK_OBJECT(pc));
736 gtk_object_sink(GTK_OBJECT(pc));
737 }
738
739 if(canvas->pc && GTK_IS_PLOT_GDK(canvas->pc)){
740 GTK_PLOT_GDK(canvas->pc)->drawable = canvas->pixmap;
741 }
742 gtk_plot_pc_set_viewport(canvas->pc, canvas->pixmap_width, canvas->pixmap_height);
743 }
744
745 GtkWidget*
gtk_plot_canvas_new(gint width,gint height,gdouble magnification)746 gtk_plot_canvas_new (gint width, gint height, gdouble magnification)
747 {
748 GtkPlotCanvas *plot_canvas;
749
750 plot_canvas = gtk_type_new (gtk_plot_canvas_get_type ());
751
752 gtk_plot_canvas_construct(GTK_PLOT_CANVAS(plot_canvas),
753 width, height, magnification);
754
755 return GTK_WIDGET (plot_canvas);
756 }
757
758 void
gtk_plot_canvas_construct(GtkPlotCanvas * plot_canvas,gint width,gint height,gdouble magnification)759 gtk_plot_canvas_construct(GtkPlotCanvas *plot_canvas,
760 gint width, gint height, gdouble magnification)
761 {
762 gdouble m = magnification;
763
764 plot_canvas->width = width;
765 plot_canvas->height = height;
766 plot_canvas->pixmap_width = roundint(width * m);
767 plot_canvas->pixmap_height = roundint(height * m);
768 gtk_plot_canvas_set_magnification(plot_canvas, m);
769
770 gtk_fixed_set_has_window (GTK_FIXED(plot_canvas), TRUE);
771 }
772
773 void
gtk_plot_canvas_freeze(GtkPlotCanvas * canvas)774 gtk_plot_canvas_freeze(GtkPlotCanvas *canvas)
775 {
776 canvas->freeze_count++;
777 }
778
779 void
gtk_plot_canvas_thaw(GtkPlotCanvas * canvas)780 gtk_plot_canvas_thaw(GtkPlotCanvas *canvas)
781 {
782 if(canvas->freeze_count == 0) return;
783 canvas->freeze_count--;
784 }
785
786 static void
gtk_plot_canvas_destroy(GtkObject * object)787 gtk_plot_canvas_destroy (GtkObject *object)
788 {
789 GtkPlotCanvas *plot_canvas;
790 GList *list;
791 gboolean veto = TRUE;
792
793 g_return_if_fail (object != NULL);
794 g_return_if_fail (GTK_IS_PLOT_CANVAS (object));
795
796 plot_canvas = GTK_PLOT_CANVAS (object);
797
798 list = plot_canvas->childs;
799 while(list){
800 gtk_signal_emit(GTK_OBJECT(plot_canvas), canvas_signals[DELETE_ITEM],
801 GTK_PLOT_CANVAS_CHILD(list->data), &veto);
802
803 gtk_object_unref(GTK_OBJECT(list->data));
804
805 plot_canvas->childs = g_list_remove_link(plot_canvas->childs, list);
806 g_list_free_1(list);
807
808 list = plot_canvas->childs;
809 }
810
811 plot_canvas->childs = NULL;
812
813 if( plot_canvas->cursor ){
814 gdk_cursor_destroy(plot_canvas->cursor);
815 plot_canvas->cursor = NULL;
816 }
817 if( plot_canvas->pc ){
818 gtk_object_unref(GTK_OBJECT(plot_canvas->pc));
819 plot_canvas->pc = NULL;
820 }
821
822 if (GTK_OBJECT_CLASS (parent_class)->destroy)
823 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
824
825 gtk_psfont_unref();
826 }
827
828 void
gtk_plot_canvas_remove_child(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child)829 gtk_plot_canvas_remove_child(GtkPlotCanvas *canvas, GtkPlotCanvasChild *child)
830 {
831 GList *list;
832
833 gtk_plot_canvas_cancel_action(canvas);
834
835 list = canvas->childs;
836 while(list){
837 if(list->data == child){
838 gboolean veto = TRUE;
839
840 _gtkextra_signal_emit(GTK_OBJECT(canvas), canvas_signals[DELETE_ITEM],
841 child, &veto);
842
843 if(veto){
844 child->parent = NULL;
845 gtk_object_unref(GTK_OBJECT(child));
846 canvas->childs = g_list_remove_link(canvas->childs, list);
847 g_list_free_1(list);
848 }
849 break;
850 }
851 list = list->next;
852 }
853 }
854
855 /*
856 static void
857 gtk_plot_canvas_draw (GtkWidget *widget, GdkRectangle *area)
858 {
859 GtkPlotCanvas *canvas;
860
861 canvas = GTK_PLOT_CANVAS(widget);
862
863 if(!GTK_WIDGET_REALIZED(widget)) return;
864 if(!canvas->pixmap) return;
865
866 GTK_WIDGET_CLASS(parent_class)->draw(widget, area);
867
868 gtk_plot_canvas_paint(canvas);
869 gtk_plot_canvas_refresh(canvas);
870 }
871 */
872
873 void
gtk_plot_canvas_paint(GtkPlotCanvas * canvas)874 gtk_plot_canvas_paint (GtkPlotCanvas *canvas)
875 {
876 GtkWidget *widget;
877 GList *childs;
878
879 widget = GTK_WIDGET(canvas);
880
881 if(GTK_WIDGET_REALIZED(widget) && !canvas->pixmap) return;
882 if(canvas->freeze_count > 0) return;
883
884 if(!gtk_plot_pc_init(canvas->pc)) return;
885
886 gtk_plot_pc_gsave(canvas->pc);
887
888 if(!GTK_IS_PLOT_PS(canvas->pc) || !canvas->transparent){
889 if(canvas->transparent){
890 GdkColor white;
891 gdk_color_white(gtk_widget_get_colormap(GTK_WIDGET(canvas)), &white);
892 gtk_plot_pc_set_color(canvas->pc, &white);
893 } else
894 gtk_plot_pc_set_color(canvas->pc, &canvas->background);
895 gtk_plot_pc_draw_rectangle(canvas->pc,
896 TRUE,
897 0,0,canvas->pixmap_width, canvas->pixmap_height);
898 }
899
900 gtk_plot_canvas_draw_grid(canvas);
901
902 childs = canvas->childs;
903 while(childs)
904 {
905 GtkPlotCanvasChild *child;
906
907 child = GTK_PLOT_CANVAS_CHILD(childs->data);
908 gtk_plot_canvas_child_draw(canvas, child);
909 childs = childs->next;
910 }
911
912 gtk_plot_pc_grestore(canvas->pc);
913 gtk_plot_pc_leave(canvas->pc);
914 }
915
916 void
gtk_plot_canvas_refresh(GtkPlotCanvas * canvas)917 gtk_plot_canvas_refresh(GtkPlotCanvas *canvas)
918 {
919 GList *children = NULL;
920 GtkFixed *fixed = GTK_FIXED(canvas);
921
922 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(canvas))) return;
923 if(!canvas->pixmap) return;
924
925 gdk_draw_drawable(GTK_WIDGET(canvas)->window,
926 GTK_WIDGET(canvas)->style->fg_gc[GTK_STATE_NORMAL],
927 canvas->pixmap,
928 0, 0,
929 0, 0,
930 -1, -1);
931
932 children = fixed->children;
933 while (children)
934 {
935 GtkFixedChild *child;
936 child = children->data;
937 gtk_widget_queue_draw(child->widget);
938 children = children->next;
939 }
940
941 }
942
943 static void
gtk_plot_canvas_draw_grid(GtkPlotCanvas * canvas)944 gtk_plot_canvas_draw_grid(GtkPlotCanvas *canvas)
945 {
946 gdouble x, y;
947
948 if(!canvas->pixmap) return;
949 if(!canvas->show_grid) return;
950
951 if(!GTK_IS_PLOT_GDK(canvas->pc)) return;
952
953 gtk_plot_canvas_set_line_attributes(canvas, canvas->grid);
954
955 for(x = 0; x < canvas->pixmap_width; x += canvas->grid_step)
956 gtk_plot_pc_draw_line(canvas->pc,
957 roundint(x), 0, roundint(x), canvas->pixmap_height);
958
959 for(y = 0; y < canvas->pixmap_height; y += canvas->grid_step)
960 gtk_plot_pc_draw_line(canvas->pc,
961 0, roundint(y), canvas->pixmap_width, roundint(y));
962 }
963
964 static void
gtk_plot_canvas_map(GtkWidget * widget)965 gtk_plot_canvas_map(GtkWidget *widget)
966 {
967 GtkPlotCanvas *plot_canvas;
968
969 plot_canvas=GTK_PLOT_CANVAS(widget);
970
971 GTK_WIDGET_CLASS(parent_class)->map(widget);
972
973 if(!plot_canvas->pixmap){
974 gtk_plot_canvas_create_pixmap(widget,
975 plot_canvas->pixmap_width,
976 plot_canvas->pixmap_height);
977 }
978 gtk_plot_canvas_paint(plot_canvas);
979 gdk_window_set_cursor(widget->window, plot_canvas->cursor);
980 }
981
982 static gint
gtk_plot_canvas_key_press(GtkWidget * widget,GdkEventKey * key)983 gtk_plot_canvas_key_press(GtkWidget *widget, GdkEventKey *key)
984 {
985 GtkPlotCanvas *canvas = GTK_PLOT_CANVAS(widget);
986
987 switch(key->keyval){
988 case GDK_Escape:
989 gtk_plot_canvas_cancel_action(canvas);
990 break;
991 default:
992 break;
993 }
994
995 return TRUE;
996 }
997
998 static gint
gtk_plot_canvas_motion(GtkWidget * widget,GdkEventMotion * event)999 gtk_plot_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
1000 {
1001 GtkPlotCanvas *canvas;
1002 GtkAllocation area;
1003 gint x, y;
1004 gint new_x = 0, new_y = 0;
1005 gint new_width = 0, new_height = 0;
1006 gint cursor = GDK_TOP_LEFT_ARROW;
1007 gint pivot_x, pivot_y;
1008
1009 canvas = GTK_PLOT_CANVAS(widget);
1010 gtk_widget_get_pointer(widget, &x, &y);
1011
1012 if(canvas->active_item && canvas->active_item->flags == GTK_PLOT_CANVAS_FROZEN) return TRUE;
1013
1014 if(canvas->active_item){
1015 area = canvas->active_item->drag_area;
1016 new_x = area.x;
1017 new_y = area.y;
1018 new_width = area.width;
1019 new_height = area.height;
1020 }
1021 pivot_x = x;
1022 pivot_y = y;
1023
1024 if(canvas->action == GTK_PLOT_CANVAS_ACTION_INACTIVE)
1025 cursor = GDK_TOP_LEFT_ARROW;
1026 else if(canvas->action == GTK_PLOT_CANVAS_ACTION_DRAG)
1027 cursor = GDK_FLEUR;
1028 else
1029 switch(canvas->drag_point){
1030 case GTK_PLOT_CANVAS_TOP_LEFT:
1031 cursor = GDK_UL_ANGLE;
1032 pivot_x = area.x + area.width;
1033 pivot_y = area.y + area.height;
1034 break;
1035 case GTK_PLOT_CANVAS_TOP_RIGHT:
1036 cursor = GDK_UR_ANGLE;
1037 pivot_x = area.x;
1038 pivot_y = area.y + area.height;
1039 break;
1040 case GTK_PLOT_CANVAS_TOP:
1041 cursor = GDK_TOP_SIDE;
1042 pivot_y = area.y + area.height;
1043 break;
1044 case GTK_PLOT_CANVAS_BOTTOM_LEFT:
1045 cursor = GDK_LL_ANGLE;
1046 pivot_x = area.x + area.width;
1047 pivot_y = area.y;
1048 break;
1049 case GTK_PLOT_CANVAS_BOTTOM_RIGHT:
1050 cursor = GDK_LR_ANGLE;
1051 pivot_x = area.x;
1052 pivot_y = area.y;
1053 break;
1054 case GTK_PLOT_CANVAS_BOTTOM:
1055 cursor = GDK_BOTTOM_SIDE;
1056 pivot_y = area.y;
1057 break;
1058 case GTK_PLOT_CANVAS_LEFT:
1059 cursor = GDK_LEFT_SIDE;
1060 pivot_x = area.x + area.width;
1061 break;
1062 case GTK_PLOT_CANVAS_RIGHT:
1063 cursor = GDK_RIGHT_SIDE;
1064 pivot_x = area.x;
1065 break;
1066 default:
1067 cursor = GDK_TOP_LEFT_ARROW;
1068 }
1069
1070 if(cursor != canvas->cursor->type){
1071 gdk_cursor_destroy(canvas->cursor);
1072 canvas->cursor = gdk_cursor_new(cursor);
1073 gdk_window_set_cursor(widget->window, canvas->cursor);
1074 }
1075
1076
1077 if(canvas->action == GTK_PLOT_CANVAS_ACTION_INACTIVE) return TRUE;
1078
1079 switch(canvas->action){
1080 case GTK_PLOT_CANVAS_ACTION_DRAG:
1081 if(canvas->active_item && canvas->active_item->flags & GTK_PLOT_CANVAS_CAN_MOVE){
1082 gint dx, dy;
1083
1084 gtk_plot_canvas_child_draw_selection(canvas, canvas->active_item, canvas->drag_area);
1085 canvas->pointer_x = x;
1086 canvas->pointer_y = y;
1087 dx = x - canvas->drag_x;
1088 dy = y - canvas->drag_y;
1089 area.x = canvas->active_item->drag_area.x + dx;
1090 area.y = canvas->active_item->drag_area.y + dy;
1091 gtk_plot_canvas_child_draw_selection(canvas, canvas->active_item, area);
1092 canvas->drag_area = area;
1093 }
1094 break;
1095 case GTK_PLOT_CANVAS_ACTION_RESIZE:
1096 switch(canvas->drag_point){
1097 case GTK_PLOT_CANVAS_TOP_LEFT:
1098 case GTK_PLOT_CANVAS_TOP_RIGHT:
1099 if(canvas->active_item && canvas->active_item->flags & GTK_PLOT_CANVAS_CAN_RESIZE){
1100 new_x = MIN(x, pivot_x);
1101 new_width = abs(x - pivot_x);
1102 }
1103 case GTK_PLOT_CANVAS_TOP:
1104 if(canvas->active_item && canvas->active_item->flags & GTK_PLOT_CANVAS_CAN_RESIZE){
1105 new_y = MIN(y, pivot_y);
1106 new_height = abs(y - pivot_y);
1107 }
1108 gdk_cursor_destroy(canvas->cursor);
1109 canvas->cursor = gdk_cursor_new(cursor);
1110 gdk_window_set_cursor(widget->window, canvas->cursor);
1111 break;
1112 case GTK_PLOT_CANVAS_BOTTOM_LEFT:
1113 case GTK_PLOT_CANVAS_BOTTOM_RIGHT:
1114 if(canvas->active_item && canvas->active_item->flags & GTK_PLOT_CANVAS_CAN_RESIZE){
1115 new_x = MIN(x, pivot_x);
1116 new_width = abs(x - pivot_x);
1117 }
1118 case GTK_PLOT_CANVAS_BOTTOM:
1119 if(canvas->active_item && canvas->active_item->flags & GTK_PLOT_CANVAS_CAN_RESIZE){
1120 new_y = MIN(y, pivot_y);
1121 new_height = abs(y - pivot_y);
1122 }
1123 break;
1124 case GTK_PLOT_CANVAS_LEFT:
1125 case GTK_PLOT_CANVAS_RIGHT:
1126 if(canvas->active_item && canvas->active_item->flags & GTK_PLOT_CANVAS_CAN_RESIZE){
1127 new_x = MIN(x, pivot_x);
1128 new_width = abs(x - pivot_x);
1129 }
1130 break;
1131 case GTK_PLOT_CANVAS_IN:
1132 case GTK_PLOT_CANVAS_OUT:
1133 default:
1134 break;
1135 }
1136
1137
1138 if(canvas->active_item && new_width >= canvas->active_item->min_width &&
1139 new_height >= canvas->active_item->min_height){
1140
1141 gtk_plot_canvas_child_draw_selection(canvas, canvas->active_item, canvas->drag_area);
1142 canvas->pointer_x = x;
1143 canvas->pointer_y = y;
1144 if(canvas->active_item->flags & GTK_PLOT_CANVAS_CAN_MOVE || canvas->active_item->flags & GTK_PLOT_CANVAS_CAN_RESIZE){
1145 area.x = new_x;
1146 area.y = new_y;
1147 }
1148 if(canvas->active_item->flags & GTK_PLOT_CANVAS_CAN_RESIZE){
1149 area.width = new_width;
1150 area.height = new_height;
1151 }
1152 gtk_plot_canvas_child_draw_selection(canvas, canvas->active_item, area);
1153 canvas->drag_area = area;
1154
1155 }
1156
1157 break;
1158 case GTK_PLOT_CANVAS_ACTION_SELECTION:
1159 draw_selection(canvas, NULL, canvas->drag_area);
1160 canvas->pointer_x = x;
1161 canvas->pointer_y = y;
1162 area.x = MIN(canvas->pointer_x, canvas->drag_x);
1163 area.y = MIN(canvas->pointer_y, canvas->drag_y);
1164 area.width = abs(x - canvas->drag_x);
1165 area.height = abs(y - canvas->drag_y);
1166 canvas->drag_area = area;
1167 draw_selection(canvas, NULL, canvas->drag_area);
1168 break;
1169 case GTK_PLOT_CANVAS_ACTION_INACTIVE:
1170 default:
1171 break;
1172 }
1173
1174 return TRUE;
1175
1176 }
1177
1178 static GtkPlotCanvasPos
gtk_plot_canvas_child_button_press(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,gint x,gint y)1179 gtk_plot_canvas_child_button_press(GtkPlotCanvas *canvas,
1180 GtkPlotCanvasChild *child,
1181 gint x, gint y)
1182 {
1183 GtkPlotCanvasPos pos;
1184 GtkAllocation area;
1185
1186 area = child->allocation;
1187
1188 if((pos = possible_selection(area, x, y)) != GTK_PLOT_CANVAS_OUT){
1189 child->state = GTK_STATE_SELECTED;
1190 child->drag_area = area;
1191 }
1192 return pos;
1193 }
1194
1195 static gint
gtk_plot_canvas_button_press(GtkWidget * widget,GdkEventButton * event)1196 gtk_plot_canvas_button_press(GtkWidget *widget, GdkEventButton *event)
1197 {
1198 GtkPlotCanvas *canvas = NULL;
1199 GtkPlotCanvasChild *active_item = NULL;
1200 GList *childs = NULL;
1201 GdkModifierType mods;
1202 gint x = 0, y = 0;
1203 gboolean veto;
1204 gboolean double_click = FALSE;
1205 gdouble m;
1206 gboolean new_item = FALSE;
1207 GtkPlotCanvasPos pos = GTK_PLOT_CANVAS_OUT;
1208
1209 gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
1210 if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
1211 double_click = (event->button == GDK_2BUTTON_PRESS);
1212
1213 canvas = GTK_PLOT_CANVAS(widget);
1214 m = canvas->magnification;
1215
1216 /*
1217 if(double_click && canvas->state == GTK_STATE_SELECTED) return TRUE;
1218 */
1219 /*
1220 gdk_pointer_ungrab(event->time);
1221 */
1222
1223 if(!GTK_WIDGET_HAS_FOCUS(widget)) gtk_widget_grab_focus(widget);
1224
1225 gtk_widget_get_pointer(widget, &x, &y);
1226
1227 /**********************************************************************/
1228
1229 if(GTK_PLOT_CANVAS_CAN_SELECT_ITEM(canvas)){
1230 childs = g_list_last(canvas->childs);
1231 while(childs)
1232 {
1233 GtkPlotCanvasChild *child = GTK_PLOT_CANVAS_CHILD(childs->data);
1234
1235 pos = GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->button_press(canvas, child, x, y);
1236 if(pos != GTK_PLOT_CANVAS_OUT && child->state == GTK_STATE_SELECTED){
1237 active_item = child;
1238 break;
1239 }
1240
1241 childs = childs->prev;
1242 }
1243
1244 /**********************************************************************/
1245
1246 new_item = active_item && ((canvas->state != GTK_STATE_SELECTED ||
1247 active_item != canvas->active_item));
1248
1249 veto = TRUE;
1250 if(active_item && active_item->state == GTK_STATE_SELECTED)
1251 _gtkextra_signal_emit(GTK_OBJECT(canvas), canvas_signals[SELECT_ITEM],
1252 event, active_item, &veto);
1253
1254 if(new_item){
1255
1256 if(veto){
1257 gtk_plot_canvas_unselect(canvas);
1258 canvas->active_item = active_item;
1259 canvas->drag_area = active_item->drag_area;
1260 canvas->state = GTK_STATE_SELECTED;
1261 canvas->action = GTK_PLOT_CANVAS_ACTION_INACTIVE;
1262
1263 canvas->drag_point = pos;
1264
1265 canvas->drag_x = x;
1266 canvas->drag_y = y;
1267 canvas->pointer_x = x;
1268 canvas->pointer_y = y;
1269
1270 gtk_plot_canvas_child_draw_selection(canvas, active_item, active_item->drag_area);
1271
1272 if(active_item->mode == GTK_PLOT_CANVAS_SELECT_CLICK_2)
1273 return TRUE;
1274 }
1275 }
1276 if(active_item && veto){
1277 if((!new_item && active_item->mode == GTK_PLOT_CANVAS_SELECT_CLICK_2) || active_item->mode == GTK_PLOT_CANVAS_SELECT_CLICK_1) {
1278
1279 if(GTK_PLOT_CANVAS_CAN_DND(canvas)) {
1280 switch(pos){
1281 case GTK_PLOT_CANVAS_IN:
1282 canvas->action = GTK_PLOT_CANVAS_ACTION_DRAG;
1283 break;
1284 default:
1285 if(active_item->flags & GTK_PLOT_CANVAS_CAN_RESIZE)
1286 canvas->action = GTK_PLOT_CANVAS_ACTION_RESIZE;
1287 else
1288 canvas->action = GTK_PLOT_CANVAS_ACTION_DRAG;
1289 }
1290 /*
1291 gdk_pointer_grab (widget->window, FALSE,
1292 GDK_POINTER_MOTION_HINT_MASK |
1293 GDK_BUTTON1_MOTION_MASK |
1294 GDK_BUTTON_RELEASE_MASK,
1295 NULL, NULL, event->time);
1296 */
1297 canvas->drag_point = pos;
1298
1299 canvas->drag_x = x;
1300 canvas->drag_y = y;
1301 canvas->pointer_x = x;
1302 canvas->pointer_y = y;
1303
1304 return TRUE;
1305 }
1306 }
1307 }
1308 }
1309 gtk_plot_canvas_unselect(canvas);
1310
1311 if(GTK_PLOT_CANVAS_CAN_SELECT(canvas)){
1312 veto = TRUE;
1313
1314 _gtkextra_signal_emit(GTK_OBJECT(canvas), canvas_signals[SELECT_ITEM],
1315 event, NULL, &veto);
1316 if(veto){
1317 canvas->active_item = NULL;
1318 canvas->state = GTK_STATE_SELECTED;
1319 canvas->action = GTK_PLOT_CANVAS_ACTION_SELECTION;
1320 canvas->drag_point = pos;
1321 canvas->drag_x = x;
1322 canvas->drag_y = y;
1323 canvas->pointer_x = x;
1324 canvas->pointer_y = y;
1325 canvas->drag_area.x = x;
1326 canvas->drag_area.y = y;
1327 canvas->drag_area.width = 0;
1328 canvas->drag_area.height = 0;
1329 /*
1330 gdk_pointer_grab (widget->window, FALSE,
1331 GDK_POINTER_MOTION_HINT_MASK |
1332 GDK_BUTTON1_MOTION_MASK |
1333 GDK_BUTTON_RELEASE_MASK,
1334 NULL, NULL, event->time);
1335 */
1336 draw_selection(canvas, NULL, canvas->drag_area);
1337 }
1338 }
1339
1340 return TRUE;
1341 }
1342
1343 static void
gtk_plot_canvas_child_button_release(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child)1344 gtk_plot_canvas_child_button_release(GtkPlotCanvas *canvas, GtkPlotCanvasChild *child)
1345 {
1346 gdouble new_x, new_y, new_width, new_height;
1347 double dx, dy;
1348 gdouble x1, x2, y1, y2;
1349
1350 gtk_plot_canvas_get_position(canvas,
1351 canvas->drag_area.width,
1352 canvas->drag_area.height,
1353 &new_width, &new_height);
1354
1355 gtk_plot_canvas_get_position(canvas,
1356 canvas->drag_area.x,
1357 canvas->drag_area.y,
1358 &new_x, &new_y);
1359
1360 gtk_plot_canvas_get_position(canvas,
1361 canvas->drag_area.x - child->drag_area.x,
1362 canvas->drag_area.y - child->drag_area.y,
1363 &dx, &dy);
1364
1365 x1 = MIN(child->rx1, child->rx2);
1366 y1 = MIN(child->ry1, child->ry2);
1367 x2 = MAX(child->rx1, child->rx2);
1368 y2 = MAX(child->ry1, child->ry2);
1369 x1 += dx;
1370 y1 += dy;
1371 x2 = x1 + new_width;
1372 y2 = y1 + new_height;
1373
1374 gtk_plot_canvas_child_move_resize(canvas, child, x1, y1, x2, y2);
1375 child->drag_area = canvas->drag_area;
1376 }
1377
1378 static gint
gtk_plot_canvas_button_release(GtkWidget * widget,GdkEventButton * event)1379 gtk_plot_canvas_button_release(GtkWidget *widget, GdkEventButton *event)
1380 {
1381 GtkPlotCanvas *canvas;
1382 gdouble new_x, new_y;
1383 gdouble new_width, new_height;
1384 gdouble x1 = 0., y1 = 0., x2 = 0., y2 = 0.;
1385 gboolean veto = TRUE;
1386 gdouble dx = 0., dy = 0.;
1387
1388 canvas = GTK_PLOT_CANVAS(widget);
1389
1390 /*
1391 gdk_pointer_ungrab(event->time);
1392 */
1393
1394 if(GTK_WIDGET_MAPPED(widget)){
1395 gdk_cursor_destroy(canvas->cursor);
1396 canvas->cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
1397 gdk_window_set_cursor(widget->window,
1398 canvas->cursor);
1399 }
1400
1401 if(canvas->action == GTK_PLOT_CANVAS_ACTION_INACTIVE) return TRUE;
1402
1403 gtk_plot_canvas_get_position(canvas,
1404 canvas->drag_area.width,
1405 canvas->drag_area.height,
1406 &new_width, &new_height);
1407
1408 gtk_plot_canvas_get_position(canvas,
1409 canvas->drag_area.x,
1410 canvas->drag_area.y,
1411 &new_x, &new_y);
1412
1413 if(canvas->action != GTK_PLOT_CANVAS_ACTION_SELECTION && canvas->active_item){
1414 GtkPlotCanvasChild *child = canvas->active_item;
1415
1416 gtk_plot_canvas_get_position(canvas,
1417 canvas->drag_area.x -
1418 canvas->active_item->drag_area.x,
1419 canvas->drag_area.y -
1420 canvas->active_item->drag_area.y,
1421 &dx, &dy);
1422
1423 x1 = MIN(child->rx1, child->rx2);
1424 y1 = MIN(child->ry1, child->ry2);
1425 x2 = MAX(child->rx1, child->rx2);
1426 y2 = MAX(child->ry1, child->ry2);
1427 x1 += dx;
1428 y1 += dy;
1429 x2 = x1 + new_width;
1430 y2 = y1 + new_height;
1431
1432 if(canvas->action == GTK_PLOT_CANVAS_ACTION_DRAG){
1433 _gtkextra_signal_emit(GTK_OBJECT(canvas), canvas_signals[MOVE_ITEM],
1434 child,
1435 x1, y1, &veto);
1436 }
1437 if(canvas->action == GTK_PLOT_CANVAS_ACTION_RESIZE){
1438 _gtkextra_signal_emit(GTK_OBJECT(canvas),
1439 canvas_signals[RESIZE_ITEM],
1440 child, new_width, new_height, &veto);
1441 }
1442 if(canvas->action != GTK_PLOT_CANVAS_ACTION_INACTIVE && veto) {
1443 if(GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(canvas->active_item)))->button_release)
1444 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(canvas->active_item)))->button_release(canvas, canvas->active_item);
1445
1446 gtk_signal_emit (GTK_OBJECT(canvas), canvas_signals[CHANGED]);
1447 canvas->pointer_x = canvas->pointer_y = canvas->drag_x = canvas->drag_y = 0;
1448 gtk_plot_canvas_child_draw_selection(canvas, canvas->active_item, canvas->active_item->drag_area);
1449 canvas->action = GTK_PLOT_CANVAS_ACTION_INACTIVE;
1450 return TRUE;
1451 } else {
1452 canvas->state = GTK_STATE_NORMAL;
1453 }
1454
1455 } else {
1456 gtk_plot_canvas_get_position(canvas,
1457 canvas->drag_x, canvas->drag_y,
1458 &x1, &y1);
1459 gtk_plot_canvas_get_position(canvas,
1460 canvas->pointer_x, canvas->pointer_y,
1461 &x2, &y2);
1462 new_width = abs(canvas->pointer_x - canvas->drag_x);
1463 new_height = abs(canvas->pointer_y - canvas->drag_y);
1464 draw_selection(canvas, NULL, canvas->drag_area);
1465 gtk_signal_emit(GTK_OBJECT(canvas), canvas_signals[SELECT_REGION],
1466 x1, y1, x2, y2);
1467 canvas->state = GTK_STATE_NORMAL;
1468 canvas->action = GTK_PLOT_CANVAS_ACTION_INACTIVE;
1469 return TRUE;
1470 }
1471
1472 canvas->drag_x = canvas->pointer_x;
1473 canvas->drag_y = canvas->pointer_y;
1474
1475 if(canvas->action != GTK_PLOT_CANVAS_ACTION_SELECTION)
1476 canvas->state = GTK_STATE_NORMAL;
1477 canvas->action = GTK_PLOT_CANVAS_ACTION_INACTIVE;
1478
1479 return TRUE;
1480
1481 }
1482
1483 static gint
gtk_plot_canvas_focus_in(GtkWidget * widget,GdkEventFocus * event)1484 gtk_plot_canvas_focus_in(GtkWidget *widget, GdkEventFocus *event)
1485 {
1486 GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
1487 return FALSE;
1488 }
1489
1490
1491 static gint
gtk_plot_canvas_focus_out(GtkWidget * widget,GdkEventFocus * event)1492 gtk_plot_canvas_focus_out(GtkWidget *widget, GdkEventFocus *event)
1493 {
1494 GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
1495 gtk_plot_canvas_unselect(GTK_PLOT_CANVAS(widget));
1496 return FALSE;
1497 }
1498
1499 void
gtk_plot_canvas_set_transparent(GtkPlotCanvas * canvas,gboolean transparent)1500 gtk_plot_canvas_set_transparent (GtkPlotCanvas *canvas, gboolean transparent)
1501 {
1502 g_return_if_fail (canvas != NULL);
1503 g_return_if_fail (GTK_IS_PLOT_CANVAS (canvas));
1504
1505 canvas->transparent = transparent;
1506 }
1507
1508 gboolean
gtk_plot_canvas_transparent(GtkPlotCanvas * canvas)1509 gtk_plot_canvas_transparent (GtkPlotCanvas *canvas)
1510 {
1511 g_return_val_if_fail (canvas != NULL, TRUE);
1512 g_return_val_if_fail (GTK_IS_PLOT_CANVAS (canvas), TRUE);
1513
1514 return(canvas->transparent);
1515 }
1516
1517 void
gtk_plot_canvas_set_background(GtkPlotCanvas * canvas,const GdkColor * color)1518 gtk_plot_canvas_set_background (GtkPlotCanvas *canvas, const GdkColor *color)
1519 {
1520
1521 g_return_if_fail (canvas != NULL);
1522 g_return_if_fail (GTK_IS_PLOT_CANVAS (canvas));
1523
1524 if(!color) {
1525 canvas->transparent = TRUE;
1526 return;
1527 } else {
1528 canvas->background = *color;
1529 canvas->transparent = FALSE;
1530 }
1531
1532 if(GTK_WIDGET_REALIZED(GTK_WIDGET(canvas)))
1533 gtk_plot_canvas_paint(canvas);
1534
1535 gtk_signal_emit (GTK_OBJECT(canvas), canvas_signals[CHANGED]);
1536 }
1537
1538 void
gtk_plot_canvas_get_pixel(GtkPlotCanvas * canvas,gdouble px,gdouble py,gint * x,gint * y)1539 gtk_plot_canvas_get_pixel(GtkPlotCanvas *canvas, gdouble px, gdouble py,
1540 gint *x, gint *y)
1541 {
1542 *x = roundint(canvas->pixmap_width * px);
1543 *y = roundint(canvas->pixmap_height * py);
1544 }
1545
1546 void
gtk_plot_canvas_get_position(GtkPlotCanvas * plot_canvas,gint x,gint y,gdouble * px,gdouble * py)1547 gtk_plot_canvas_get_position(GtkPlotCanvas *plot_canvas, gint x, gint y,
1548 gdouble *px, gdouble *py)
1549 {
1550 *px = (gdouble) x / (gdouble) plot_canvas->pixmap_width;
1551 *py = (gdouble) y / (gdouble) plot_canvas->pixmap_height;
1552 }
1553
1554 void
gtk_plot_canvas_unselect(GtkPlotCanvas * plot_canvas)1555 gtk_plot_canvas_unselect (GtkPlotCanvas *plot_canvas)
1556 {
1557
1558 if(plot_canvas->state == GTK_STATE_SELECTED){
1559 if(plot_canvas->active_item)
1560 gtk_plot_canvas_child_draw_selection(plot_canvas, plot_canvas->active_item, plot_canvas->drag_area);
1561 else
1562 draw_selection(plot_canvas, NULL, plot_canvas->drag_area);
1563 }
1564
1565 plot_canvas->action = GTK_PLOT_CANVAS_ACTION_INACTIVE;
1566 plot_canvas->state = GTK_STATE_NORMAL;
1567 if(plot_canvas->active_item){
1568 plot_canvas->active_item->state = GTK_STATE_NORMAL;
1569 if(GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(plot_canvas->active_item)))->unselect)
1570 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(plot_canvas->active_item)))->unselect(plot_canvas, plot_canvas->active_item);
1571 }
1572 plot_canvas->active_item = NULL;
1573
1574 if(GTK_WIDGET_MAPPED(GTK_WIDGET(plot_canvas))){
1575 gdk_cursor_destroy(plot_canvas->cursor);
1576 plot_canvas->cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
1577 gdk_window_set_cursor(GTK_WIDGET(plot_canvas)->window,
1578 plot_canvas->cursor);
1579 }
1580 }
1581
1582 void
gtk_plot_canvas_cancel_action(GtkPlotCanvas * plot_canvas)1583 gtk_plot_canvas_cancel_action (GtkPlotCanvas *plot_canvas)
1584 {
1585 gtk_plot_canvas_unselect(plot_canvas);
1586 /*
1587 gdk_pointer_ungrab(GDK_CURRENT_TIME);
1588 */
1589 }
1590
1591
1592 GtkPlotCanvasChild *
gtk_plot_canvas_get_active_item(GtkPlotCanvas * canvas)1593 gtk_plot_canvas_get_active_item(GtkPlotCanvas *canvas)
1594 {
1595 return (canvas->active_item);
1596 }
1597
1598 gboolean
gtk_plot_canvas_child_get_position(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,double * x1,double * y1,double * x2,double * y2)1599 gtk_plot_canvas_child_get_position(GtkPlotCanvas *canvas,
1600 GtkPlotCanvasChild *child,
1601 double *x1, double *y1,
1602 double *x2, double *y2)
1603 {
1604 GList *list;
1605 gpointer data;
1606
1607 *x1 = child->rx1;
1608 *x2 = child->rx2;
1609 *y1 = child->ry1;
1610 *y2 = child->ry2;
1611
1612 list = canvas->childs;
1613
1614 /* Return TRUE if child is actually contained w/in canvas, and
1615 coordinates of the childs bounding box, else FALSE */
1616 while(list)
1617 {
1618 data = list->data;
1619 if(GTK_PLOT_CANVAS_CHILD(data) == child) return TRUE;
1620 list = list->next;
1621 }
1622
1623 return FALSE;
1624
1625 }
1626
1627 void
gtk_plot_canvas_set_size(GtkPlotCanvas * canvas,gint width,gint height)1628 gtk_plot_canvas_set_size(GtkPlotCanvas *canvas, gint width, gint height)
1629 {
1630 GList *list = NULL;
1631 gdouble m = canvas->magnification;
1632 GtkAllocation allocation = GTK_WIDGET(canvas)->allocation;
1633
1634 gtk_plot_canvas_cancel_action(canvas);
1635
1636 canvas->width = width;
1637 canvas->height = height;
1638 canvas->pixmap_width = roundint(m * width);
1639 canvas->pixmap_height = roundint(m * height);
1640
1641 if(GTK_WIDGET_MAPPED(canvas)){
1642 gtk_plot_canvas_create_pixmap(GTK_WIDGET(canvas),
1643 canvas->pixmap_width,
1644 canvas->pixmap_height);
1645 }
1646
1647 /*
1648 gtk_widget_set_usize(GTK_WIDGET(canvas),
1649 canvas->pixmap_width, canvas->pixmap_height);
1650 */
1651
1652 allocation.width = canvas->pixmap_width;
1653 allocation.height = canvas->pixmap_height;
1654 gtk_widget_size_allocate(GTK_WIDGET(canvas), &allocation);
1655
1656 list = canvas->childs;
1657 while(list){
1658 GtkPlotCanvasChild *child = GTK_PLOT_CANVAS_CHILD(list->data);
1659 if(GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->size_allocate)
1660 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->size_allocate(canvas, child);
1661 list = list->next;
1662 }
1663
1664
1665 gtk_signal_emit (GTK_OBJECT(canvas), canvas_signals[CHANGED]);
1666 }
1667
1668 static void
gtk_plot_canvas_create_pixmap(GtkWidget * widget,gint width,gint height)1669 gtk_plot_canvas_create_pixmap(GtkWidget *widget, gint width, gint height)
1670 {
1671 GtkPlotCanvas *canvas;
1672 gint pixmap_width, pixmap_height;
1673
1674 canvas = GTK_PLOT_CANVAS(widget);
1675 if (!canvas->pixmap)
1676 canvas->pixmap = gdk_pixmap_new (widget->window,
1677 width,
1678 height, -1);
1679 else{
1680 gdk_window_get_size(canvas->pixmap, &pixmap_width, &pixmap_height);
1681 if(width != pixmap_width || height != pixmap_height) {
1682 gdk_pixmap_unref(canvas->pixmap);
1683 canvas->pixmap = gdk_pixmap_new (widget->window,
1684 width,
1685 height, -1);
1686 }
1687 }
1688
1689 if(canvas->pc && GTK_IS_PLOT_GDK(canvas->pc)){
1690 GTK_PLOT_GDK(canvas->pc)->drawable = canvas->pixmap;
1691 }
1692 gtk_plot_pc_set_viewport(canvas->pc, width, height);
1693 }
1694
1695 static gint
gtk_plot_canvas_expose(GtkWidget * widget,GdkEventExpose * event)1696 gtk_plot_canvas_expose(GtkWidget *widget, GdkEventExpose *event)
1697 {
1698 GtkPlotCanvas *canvas;
1699 GdkPixmap *pixmap;
1700
1701 if(!GTK_WIDGET_DRAWABLE(widget)) return FALSE;
1702
1703 canvas = GTK_PLOT_CANVAS(widget);
1704
1705 if(!canvas->pixmap){
1706 gtk_plot_canvas_create_pixmap(widget,
1707 canvas->pixmap_width,
1708 canvas->pixmap_height);
1709 gtk_plot_canvas_paint(canvas);
1710 return FALSE;
1711 }
1712
1713 pixmap = canvas->pixmap;
1714 gdk_draw_pixmap(GTK_WIDGET(canvas)->window,
1715 widget->style->fg_gc[GTK_STATE_NORMAL],
1716 pixmap,
1717 event->area.x,
1718 event->area.y,
1719 event->area.x,
1720 event->area.y,
1721 event->area.width, event->area.height);
1722
1723 GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event);
1724
1725 return FALSE;
1726
1727 }
1728
1729
1730 static void
gtk_plot_canvas_size_request(GtkWidget * widget,GtkRequisition * requisition)1731 gtk_plot_canvas_size_request (GtkWidget *widget, GtkRequisition *requisition)
1732 {
1733 GtkPlotCanvas *canvas;
1734
1735 canvas = GTK_PLOT_CANVAS(widget);
1736
1737 GTK_WIDGET_CLASS(parent_class)->size_request(widget, requisition);
1738
1739 widget->requisition.width = MAX(canvas->pixmap_width, requisition->width);
1740 widget->requisition.height = MAX(canvas->pixmap_height, requisition->height);
1741 }
1742
1743
1744 void
gtk_plot_canvas_set_magnification(GtkPlotCanvas * canvas,gdouble magnification)1745 gtk_plot_canvas_set_magnification(GtkPlotCanvas *canvas,
1746 gdouble magnification)
1747 {
1748 GList *list;
1749
1750 canvas->magnification = magnification;
1751
1752 list = canvas->childs;
1753 while(list){
1754 GtkPlotCanvasChild *child = GTK_PLOT_CANVAS_CHILD(list->data);
1755
1756 if(GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->set_magnification)
1757 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->set_magnification(canvas, child, magnification);
1758
1759 list = list->next;
1760 }
1761
1762 gtk_plot_canvas_set_size(canvas,
1763 canvas->width,
1764 canvas->height);
1765 gtk_signal_emit (GTK_OBJECT(canvas), canvas_signals[CHANGED]);
1766 }
1767
1768 static void
gtk_plot_canvas_child_draw_selection(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,GtkAllocation area)1769 gtk_plot_canvas_child_draw_selection(GtkPlotCanvas *canvas, GtkPlotCanvasChild *child, GtkAllocation area)
1770 {
1771 if(GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->draw_selection)
1772 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->draw_selection(canvas, child, area);
1773 }
1774
1775 static void
draw_selection(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,GtkAllocation area)1776 draw_selection(GtkPlotCanvas *canvas, GtkPlotCanvasChild *child, GtkAllocation area)
1777 {
1778 GdkGC *xor_gc = NULL;
1779 GdkGCValues values;
1780
1781 gdk_gc_get_values(GTK_WIDGET(canvas)->style->fg_gc[0], &values);
1782 values.function = GDK_INVERT;
1783 values.foreground = GTK_WIDGET(canvas)->style->white;
1784 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
1785 xor_gc = gdk_gc_new_with_values(GTK_WIDGET(canvas)->window,
1786 &values,
1787 GDK_GC_FOREGROUND |
1788 GDK_GC_FUNCTION |
1789 GDK_GC_SUBWINDOW);
1790
1791 if(canvas->active_item){
1792 if(canvas->active_item->selection == GTK_PLOT_CANVAS_SELECT_TARGET){
1793 area.x += area.width / 2 - 10;
1794 area.y += area.height / 2 - 10;
1795 area.width = 20;
1796 area.height = 20;
1797 gdk_draw_rectangle (GTK_WIDGET(canvas)->window,
1798 xor_gc,
1799 FALSE,
1800 area.x, area.y,
1801 area.width, area.height);
1802
1803 gdk_draw_line(GTK_WIDGET(canvas)->window, xor_gc,
1804 area.x + 1, area.y + area.height/2,
1805 area.x + 6, area.y + area.height/2);
1806 gdk_draw_line(GTK_WIDGET(canvas)->window, xor_gc,
1807 area.x + area.width - 1, area.y + area.height / 2,
1808 area.x + area.width - 6, area.y + area.height / 2);
1809 gdk_draw_line(GTK_WIDGET(canvas)->window, xor_gc,
1810 area.x + area.width/2, area.y + 1,
1811 area.x + area.width/2, area.y + 6);
1812 gdk_draw_line(GTK_WIDGET(canvas)->window, xor_gc,
1813 area.x + area.width/2, area.y + area.height - 1,
1814 area.x + area.width/2, area.y + area.height - 6);
1815
1816 if(xor_gc) gdk_gc_destroy(xor_gc);
1817 return;
1818 }
1819
1820
1821 if(canvas->active_item->selection == GTK_PLOT_CANVAS_SELECT_MARKERS){
1822 gdk_draw_rectangle (GTK_WIDGET(canvas)->window,
1823 xor_gc,
1824 FALSE,
1825 area.x, area.y,
1826 area.width, area.height);
1827 draw_marker(canvas, xor_gc, area.x, area.y);
1828 draw_marker(canvas, xor_gc, area.x, area.y + area.height);
1829 draw_marker(canvas, xor_gc, area.x + area.width, area.y);
1830 draw_marker(canvas, xor_gc, area.x + area.width, area.y + area.height);
1831 if(area.height > DEFAULT_MARKER_SIZE * 2){
1832 draw_marker(canvas, xor_gc, area.x, area.y + area.height / 2);
1833 draw_marker(canvas, xor_gc, area.x + area.width,
1834 area.y + area.height / 2);
1835 }
1836 if(area.width > DEFAULT_MARKER_SIZE * 2){
1837 draw_marker(canvas, xor_gc, area.x + area.width / 2, area.y);
1838 draw_marker(canvas, xor_gc, area.x + area.width / 2,
1839 area.y + area.height);
1840 }
1841 }
1842 } else {
1843 gdk_gc_set_line_attributes(xor_gc, 1, 1, 0 ,0 );
1844
1845 gdk_draw_rectangle (GTK_WIDGET(canvas)->window,
1846 xor_gc,
1847 FALSE,
1848 area.x, area.y,
1849 area.width, area.height);
1850 }
1851 if(xor_gc) gdk_gc_unref(xor_gc);
1852 }
1853
1854 static void
draw_marker(GtkPlotCanvas * canvas,GdkGC * gc,gint x,gint y)1855 draw_marker(GtkPlotCanvas *canvas, GdkGC *gc, gint x, gint y)
1856 {
1857 GdkDrawable *darea;
1858
1859 darea = GTK_WIDGET(canvas)->window;
1860
1861 gdk_draw_rectangle(darea, gc, TRUE,
1862 x - DEFAULT_MARKER_SIZE / 2, y - DEFAULT_MARKER_SIZE / 2,
1863 DEFAULT_MARKER_SIZE + 1, DEFAULT_MARKER_SIZE + 1);
1864 }
1865
1866 GtkPlotCanvasPos
possible_selection(GtkAllocation area,gint x,gint y)1867 possible_selection(GtkAllocation area, gint x, gint y)
1868 {
1869 GtkPlotCanvasPos return_value = GTK_PLOT_CANVAS_OUT;
1870
1871 if(x >= area.x - DEFAULT_MARKER_SIZE / 2 &&
1872 x <= area.x + DEFAULT_MARKER_SIZE / 2){
1873 if(y >= area.y - DEFAULT_MARKER_SIZE / 2. &&
1874 y <= area.y + DEFAULT_MARKER_SIZE / 2.)
1875 return_value = GTK_PLOT_CANVAS_TOP_LEFT;
1876 if(y >= area.y + area.height - DEFAULT_MARKER_SIZE / 2. &&
1877 y <= area.y + area.height + DEFAULT_MARKER_SIZE / 2.)
1878 return_value = GTK_PLOT_CANVAS_BOTTOM_LEFT;
1879 if(y >= area.y + area.height / 2 - DEFAULT_MARKER_SIZE / 2. &&
1880 y <= area.y + area.height / 2 + DEFAULT_MARKER_SIZE / 2. &&
1881 area.height > DEFAULT_MARKER_SIZE * 2)
1882 return_value = GTK_PLOT_CANVAS_LEFT;
1883 }
1884
1885 if(x >= area.x + area.width - DEFAULT_MARKER_SIZE / 2 &&
1886 x <= area.x + area.width + DEFAULT_MARKER_SIZE / 2){
1887 if(y >= area.y - DEFAULT_MARKER_SIZE / 2. &&
1888 y <= area.y + DEFAULT_MARKER_SIZE / 2.)
1889 return_value = GTK_PLOT_CANVAS_TOP_RIGHT;
1890 if(y >= area.y + area.height - DEFAULT_MARKER_SIZE / 2. &&
1891 y <= area.y + area.height + DEFAULT_MARKER_SIZE / 2.)
1892 return_value = GTK_PLOT_CANVAS_BOTTOM_RIGHT;
1893 if(y >= area.y + area.height / 2 - DEFAULT_MARKER_SIZE / 2. &&
1894 y <= area.y + area.height / 2 + DEFAULT_MARKER_SIZE / 2. &&
1895 area.height > DEFAULT_MARKER_SIZE * 2)
1896 return_value = GTK_PLOT_CANVAS_RIGHT;
1897 }
1898
1899 if(x >= area.x + area.width / 2 - DEFAULT_MARKER_SIZE / 2 &&
1900 x <= area.x + area.width / 2 + DEFAULT_MARKER_SIZE / 2 &&
1901 area.width > DEFAULT_MARKER_SIZE * 2){
1902 if(y >= area.y - DEFAULT_MARKER_SIZE / 2. &&
1903 y <= area.y + DEFAULT_MARKER_SIZE / 2.)
1904 return_value = GTK_PLOT_CANVAS_TOP;
1905 if(y >= area.y + area.height - DEFAULT_MARKER_SIZE / 2. &&
1906 y <= area.y + area.height + DEFAULT_MARKER_SIZE / 2.)
1907 return_value = GTK_PLOT_CANVAS_BOTTOM;
1908 }
1909
1910 if(return_value == GTK_PLOT_CANVAS_OUT){
1911 if (x >= area.x && x <= area.x + area.width &&
1912 y >= area.y && y <= area.y + area.height)
1913 return_value = GTK_PLOT_CANVAS_IN;
1914 }
1915
1916 return (return_value);
1917 }
1918
1919 /**********************************************************************/
1920
1921 void
gtk_plot_canvas_grid_set_visible(GtkPlotCanvas * canvas,gboolean visible)1922 gtk_plot_canvas_grid_set_visible(GtkPlotCanvas *canvas, gboolean visible)
1923 {
1924 canvas->show_grid= visible;
1925 gtk_signal_emit (GTK_OBJECT(canvas), canvas_signals[CHANGED]);
1926 }
1927
1928 void
gtk_plot_canvas_grid_set_step(GtkPlotCanvas * canvas,gdouble step)1929 gtk_plot_canvas_grid_set_step(GtkPlotCanvas *canvas, gdouble step)
1930 {
1931 canvas->grid_step = step;
1932 gtk_signal_emit (GTK_OBJECT(canvas), canvas_signals[CHANGED]);
1933 }
1934
1935 void
gtk_plot_canvas_grid_set_attributes(GtkPlotCanvas * canvas,GtkPlotLineStyle style,gint width,const GdkColor * color)1936 gtk_plot_canvas_grid_set_attributes(GtkPlotCanvas *canvas,
1937 GtkPlotLineStyle style,
1938 gint width,
1939 const GdkColor *color)
1940 {
1941 if(color)
1942 canvas->grid.color = *color;
1943 canvas->grid.line_width = width;
1944 canvas->grid.line_style = style;
1945 gtk_signal_emit (GTK_OBJECT(canvas), canvas_signals[CHANGED]);
1946 }
1947
1948 /**********************************************************************/
1949 void
gtk_plot_canvas_put_child(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,gdouble x1,gdouble y1,gdouble x2,gdouble y2)1950 gtk_plot_canvas_put_child(GtkPlotCanvas *canvas,
1951 GtkPlotCanvasChild *child,
1952 gdouble x1, gdouble y1,
1953 gdouble x2, gdouble y2)
1954 {
1955 child->rx1 = x1;
1956 child->ry1 = y1;
1957 child->rx2 = x2;
1958 child->ry2 = y2;
1959
1960 child->parent = canvas;
1961 canvas->childs = g_list_append(canvas->childs, child);
1962 gtk_object_ref(GTK_OBJECT(child));
1963 gtk_object_sink(GTK_OBJECT(child));
1964
1965 if(GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->size_allocate)
1966 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->size_allocate(canvas, child);
1967 if(GTK_WIDGET_REALIZED(canvas) && GTK_WIDGET_VISIBLE(canvas))
1968 gtk_plot_canvas_child_draw(canvas, child);
1969 gtk_signal_emit (GTK_OBJECT(canvas), canvas_signals[CHANGED]);
1970 gtk_signal_emit(GTK_OBJECT(canvas), canvas_signals[ADD_ITEM], child);
1971 }
1972
1973 void
gtk_plot_canvas_child_move(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,gdouble x1,gdouble y1)1974 gtk_plot_canvas_child_move(GtkPlotCanvas *canvas,
1975 GtkPlotCanvasChild *child,
1976 gdouble x1, gdouble y1)
1977 {
1978 child->rx2 += (x1 - child->rx1);
1979 child->ry2 += (y1 - child->ry1);
1980 child->rx1 = x1;
1981 child->ry1 = y1;
1982
1983 if(GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->move)
1984 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->move(canvas, child, x1, y1);
1985 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->size_allocate(canvas, child);
1986 gtk_plot_canvas_paint(canvas);
1987 gtk_plot_canvas_refresh(canvas);
1988 gtk_signal_emit (GTK_OBJECT(canvas), canvas_signals[CHANGED]);
1989 }
1990
1991 void
gtk_plot_canvas_child_move_resize(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,gdouble x1,gdouble y1,gdouble x2,gdouble y2)1992 gtk_plot_canvas_child_move_resize(GtkPlotCanvas *canvas,
1993 GtkPlotCanvasChild *child,
1994 gdouble x1, gdouble y1,
1995 gdouble x2, gdouble y2)
1996 {
1997 child->rx1 = x1;
1998 child->ry1 = y1;
1999 child->rx2 = x2;
2000 child->ry2 = y2;
2001
2002 if(GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->move_resize)
2003 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->move_resize(canvas, child, x1, y1, x2, y2);
2004 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->size_allocate(canvas, child);
2005 gtk_plot_canvas_paint(canvas);
2006 gtk_plot_canvas_refresh(canvas);
2007 gtk_signal_emit (GTK_OBJECT(canvas), canvas_signals[CHANGED]);
2008 }
2009
2010 static void
gtk_plot_canvas_child_size_allocate(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child)2011 gtk_plot_canvas_child_size_allocate(GtkPlotCanvas *canvas, GtkPlotCanvasChild *child)
2012 {
2013 gint x1, x2, y1, y2;
2014
2015 gtk_plot_canvas_get_pixel(canvas, child->rx1, child->ry1, &x1, &y1);
2016 gtk_plot_canvas_get_pixel(canvas, child->rx2, child->ry2, &x2, &y2);
2017 child->allocation.x = MIN(x1, x2);
2018 child->allocation.y = MIN(y1, y2);
2019 child->allocation.width = abs(x1 - x2);
2020 child->allocation.height = abs(y1 - y2);
2021 }
2022
2023 void
gtk_plot_canvas_child_set_selection(GtkPlotCanvasChild * child,GtkPlotCanvasSelection selection)2024 gtk_plot_canvas_child_set_selection (GtkPlotCanvasChild *child,
2025 GtkPlotCanvasSelection selection)
2026 {
2027 if(!child) return;
2028 child->selection = selection;
2029 }
2030
2031 void
gtk_plot_canvas_child_set_selection_mode(GtkPlotCanvasChild * child,GtkPlotCanvasSelectionMode mode)2032 gtk_plot_canvas_child_set_selection_mode (GtkPlotCanvasChild *child,
2033 GtkPlotCanvasSelectionMode mode)
2034 {
2035 if(!child) return;
2036 child->mode = mode;
2037 }
2038
2039 void
gtk_plot_canvas_child_draw(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child)2040 gtk_plot_canvas_child_draw(GtkPlotCanvas *canvas,
2041 GtkPlotCanvasChild *child)
2042 {
2043 gtk_plot_pc_gsave(canvas->pc);
2044
2045 GTK_PLOT_CANVAS_CHILD_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(child)))->draw(canvas, child);
2046
2047 gtk_plot_pc_grestore(canvas->pc);
2048 }
2049
2050 void
gtk_plot_canvas_set_line_attributes(GtkPlotCanvas * canvas,GtkPlotLine line)2051 gtk_plot_canvas_set_line_attributes(GtkPlotCanvas *canvas, GtkPlotLine line)
2052 {
2053 gdouble dot[] = {2., 3.};
2054 gdouble dash[] = {6., 4.};
2055 gdouble dot_dash[] = {6., 4., 2., 4.};
2056 gdouble dot_dot_dash[] = {6., 4., 2., 4., 2., 4.};
2057 gdouble dot_dash_dash[] = {6., 4., 6., 4., 2., 4.};
2058
2059 gtk_plot_pc_set_color(canvas->pc, &line.color);
2060
2061 switch(line.line_style){
2062 case GTK_PLOT_LINE_SOLID:
2063 gtk_plot_pc_set_lineattr(canvas->pc, line.line_width, 0, 0, 0);
2064 break;
2065 case GTK_PLOT_LINE_DOTTED:
2066 gtk_plot_pc_set_lineattr(canvas->pc, line.line_width,
2067 GDK_LINE_ON_OFF_DASH, 0, 0);
2068 gtk_plot_pc_set_dash(canvas->pc, 0, dot, 2);
2069 break;
2070 case GTK_PLOT_LINE_DASHED:
2071 gtk_plot_pc_set_lineattr(canvas->pc, line.line_width,
2072 GDK_LINE_ON_OFF_DASH, 0, 0);
2073 gtk_plot_pc_set_dash(canvas->pc, 0, dash, 2);
2074 case GTK_PLOT_LINE_DOT_DASH:
2075 gtk_plot_pc_set_lineattr(canvas->pc, line.line_width,
2076 GDK_LINE_ON_OFF_DASH, 0, 0);
2077 gtk_plot_pc_set_dash(canvas->pc, 0, dot_dash, 4);
2078 break;
2079 case GTK_PLOT_LINE_DOT_DOT_DASH:
2080 gtk_plot_pc_set_lineattr(canvas->pc, line.line_width,
2081 GDK_LINE_ON_OFF_DASH, 0, 0);
2082 gtk_plot_pc_set_dash(canvas->pc, 0, dot_dot_dash, 6);
2083 break;
2084 case GTK_PLOT_LINE_DOT_DASH_DASH:
2085 gtk_plot_pc_set_lineattr(canvas->pc, line.line_width,
2086 GDK_LINE_ON_OFF_DASH, 0, 0);
2087 gtk_plot_pc_set_dash(canvas->pc, 0, dot_dash_dash, 6);
2088 break;
2089 case GTK_PLOT_LINE_NONE:
2090 default:
2091 break;
2092 }
2093 }
2094