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