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