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 "gtkplot.h"
26 #include "gtkplotcanvas.h"
27 #include "gtkplotcanvasellipse.h"
28 #include "gtkplotgdk.h"
29 #include "gtkplotps.h"
30 
31 #define DEFAULT_MARKER_SIZE 6
32 #define P_(string) string
33 
34 enum {
35   ARG_0,
36   ARG_LINE,
37   ARG_FILLED,
38   ARG_BG
39 };
40 
41 static void gtk_plot_canvas_ellipse_init	(GtkPlotCanvasEllipse *ellipse);
42 static void gtk_plot_canvas_ellipse_class_init  (GtkPlotCanvasChildClass *klass);
43 static void gtk_plot_canvas_ellipse_draw 	(GtkPlotCanvas *canvas,
44 						 GtkPlotCanvasChild *child);
45 static void gtk_plot_canvas_ellipse_select	(GtkPlotCanvas *canvas,
46 						 GtkPlotCanvasChild *child,
47 						 GtkAllocation area);
48 static void gtk_plot_canvas_ellipse_move	(GtkPlotCanvas *canvas,
49 						 GtkPlotCanvasChild *child,
50 						 gdouble x, gdouble y);
51 static void gtk_plot_canvas_ellipse_resize	(GtkPlotCanvas *canvas,
52 						 GtkPlotCanvasChild *child,
53 						 gdouble x1, gdouble y1,
54 						 gdouble x2, gdouble y2);
55 static void gtk_plot_canvas_ellipse_get_property(GObject      *object,
56                                                  guint            prop_id,
57                                                  GValue          *value,
58                                                  GParamSpec      *pspec);
59 static void gtk_plot_canvas_ellipse_set_property(GObject      *object,
60                                                  guint            prop_id,
61                                                  const GValue          *value,
62                                                  GParamSpec      *pspec);
63 
64 
65 extern gint roundint                     (gdouble x);
66 static GtkPlotCanvasChildClass *parent_class = NULL;
67 
68 GtkType
gtk_plot_canvas_ellipse_get_type(void)69 gtk_plot_canvas_ellipse_get_type (void)
70 {
71   static GtkType plot_canvas_ellipse_type = 0;
72 
73   if (!plot_canvas_ellipse_type)
74     {
75       GtkTypeInfo plot_canvas_ellipse_info =
76       {
77 	"GtkPlotCanvasEllipse",
78 	sizeof (GtkPlotCanvasEllipse),
79 	sizeof (GtkPlotCanvasEllipseClass),
80 	(GtkClassInitFunc) gtk_plot_canvas_ellipse_class_init,
81 	(GtkObjectInitFunc) gtk_plot_canvas_ellipse_init,
82 	/* reserved 1*/ NULL,
83         /* reserved 2 */ NULL,
84         (GtkClassInitFunc) NULL,
85       };
86 
87       plot_canvas_ellipse_type = gtk_type_unique (gtk_plot_canvas_child_get_type(), &plot_canvas_ellipse_info);
88     }
89   return plot_canvas_ellipse_type;
90 }
91 
92 GtkPlotCanvasChild*
gtk_plot_canvas_ellipse_new(GtkPlotLineStyle style,gfloat width,const GdkColor * fg,const GdkColor * bg,gboolean fill)93 gtk_plot_canvas_ellipse_new (GtkPlotLineStyle style,
94                           gfloat width,
95                           const GdkColor *fg,
96                           const GdkColor *bg,
97                           gboolean fill)
98 {
99   GtkPlotCanvasEllipse *ellipse;
100 
101   ellipse = gtk_type_new (gtk_plot_canvas_ellipse_get_type ());
102 
103   ellipse->line.line_width = width;
104   if(fg) ellipse->line.color = *fg;
105   if(bg) ellipse->bg = *bg;
106   ellipse->filled = fill;
107 
108   return GTK_PLOT_CANVAS_CHILD (ellipse);
109 }
110 
111 static void
gtk_plot_canvas_ellipse_init(GtkPlotCanvasEllipse * ellipse)112 gtk_plot_canvas_ellipse_init (GtkPlotCanvasEllipse *ellipse)
113 {
114   gdk_color_black(gdk_colormap_get_system(), &ellipse->line.color);
115   gdk_color_white(gdk_colormap_get_system(), &ellipse->bg);
116 
117   ellipse->line.line_style = GTK_PLOT_LINE_SOLID;
118   ellipse->line.line_width = 0;
119   ellipse->filled = TRUE;
120 }
121 
122 static void
gtk_plot_canvas_ellipse_class_init(GtkPlotCanvasChildClass * klass)123 gtk_plot_canvas_ellipse_class_init (GtkPlotCanvasChildClass *klass)
124 {
125   GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
126 
127   parent_class = gtk_type_class (gtk_plot_canvas_child_get_type ());
128 
129   klass->draw = gtk_plot_canvas_ellipse_draw;
130   klass->move = gtk_plot_canvas_ellipse_move;
131   klass->move_resize = gtk_plot_canvas_ellipse_resize;
132   klass->draw_selection = gtk_plot_canvas_ellipse_select;
133 
134   gobject_class->get_property = gtk_plot_canvas_ellipse_get_property;
135   gobject_class->set_property = gtk_plot_canvas_ellipse_set_property;
136 
137   g_object_class_install_property (gobject_class,
138                            ARG_LINE,
139   g_param_spec_pointer ("line",
140                            P_("Line"),
141                            P_("Line Attributes"),
142                            G_PARAM_READABLE|G_PARAM_WRITABLE));
143   g_object_class_install_property (gobject_class,
144                            ARG_FILLED,
145   g_param_spec_boolean ("filled",
146                            P_("Filled"),
147                            P_("Fill Figure"),
148                            FALSE,
149                            G_PARAM_READABLE|G_PARAM_WRITABLE));
150   g_object_class_install_property (gobject_class,
151                            ARG_BG,
152   g_param_spec_pointer ("color_bg",
153                            P_("Filling Color"),
154                            P_("Filling Color"),
155                            G_PARAM_READABLE|G_PARAM_WRITABLE));
156 
157 }
158 
159 static void
gtk_plot_canvas_ellipse_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)160 gtk_plot_canvas_ellipse_get_property (GObject      *object,
161                                     guint            prop_id,
162                                     GValue          *value,
163                                     GParamSpec      *pspec)
164 {
165   GtkPlotCanvasEllipse *ellipse = GTK_PLOT_CANVAS_ELLIPSE (object);
166 
167   switch(prop_id){
168     case ARG_LINE:
169       g_value_set_pointer(value, &ellipse->line);
170       break;
171     case ARG_FILLED:
172       g_value_set_boolean(value, ellipse->filled);
173       break;
174     case ARG_BG:
175       g_value_set_pointer(value, &ellipse->bg);
176       break;
177   }
178 }
179 
180 static void
gtk_plot_canvas_ellipse_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)181 gtk_plot_canvas_ellipse_set_property (GObject      *object,
182                                     guint            prop_id,
183                                     const GValue          *value,
184                                     GParamSpec      *pspec)
185 {
186   GtkPlotCanvasEllipse *ellipse = GTK_PLOT_CANVAS_ELLIPSE (object);
187 
188   switch(prop_id){
189     case ARG_LINE:
190       ellipse->line = *((GtkPlotLine *)g_value_get_pointer(value));
191       break;
192     case ARG_FILLED:
193       ellipse->filled = g_value_get_boolean(value);
194       break;
195     case ARG_BG:
196       ellipse->bg = *((GdkColor *)g_value_get_pointer(value));
197       break;
198   }
199 }
200 
201 static void
gtk_plot_canvas_ellipse_draw(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child)202 gtk_plot_canvas_ellipse_draw 		(GtkPlotCanvas *canvas,
203 					 GtkPlotCanvasChild *child)
204 {
205   GtkPlotCanvasEllipse *ellipse = GTK_PLOT_CANVAS_ELLIPSE(child);
206   gint width = child->allocation.width;
207   gint height = child->allocation.height;
208 
209   if(width == 0 && height == 0) return;
210 
211   if(ellipse->filled){
212      gtk_plot_pc_set_color(canvas->pc, &ellipse->bg);
213      gtk_plot_pc_draw_ellipse(canvas->pc, TRUE,
214                               child->allocation.x, child->allocation.y,
215                               width, height);
216   }
217   gtk_plot_canvas_set_line_attributes(canvas, ellipse->line);
218   if(ellipse->line.line_style != GTK_PLOT_LINE_NONE)
219      gtk_plot_pc_draw_ellipse(canvas->pc, FALSE,
220                               child->allocation.x, child->allocation.y,
221                               width, height);
222 
223 }
224 
225 static void
draw_marker(GtkPlotCanvas * canvas,GdkGC * gc,gint x,gint y)226 draw_marker(GtkPlotCanvas *canvas, GdkGC *gc, gint x, gint y)
227 {
228   GdkDrawable *darea;
229 
230   darea = GTK_WIDGET(canvas)->window;
231 
232   gdk_draw_rectangle(darea, gc, TRUE,
233                      x - DEFAULT_MARKER_SIZE / 2, y - DEFAULT_MARKER_SIZE / 2,
234                      DEFAULT_MARKER_SIZE + 1, DEFAULT_MARKER_SIZE + 1);
235 }
236 
237 static void
gtk_plot_canvas_ellipse_select(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,GtkAllocation area)238 gtk_plot_canvas_ellipse_select(GtkPlotCanvas *canvas, GtkPlotCanvasChild *child, GtkAllocation area)
239 {
240   GdkGC *xor_gc = NULL;
241   GdkGCValues values;
242 
243   gdk_gc_get_values(GTK_WIDGET(canvas)->style->fg_gc[0], &values);
244   values.function = GDK_INVERT;
245   values.foreground = GTK_WIDGET(canvas)->style->white;
246   values.subwindow_mode = GDK_INCLUDE_INFERIORS;
247   xor_gc = gdk_gc_new_with_values(GTK_WIDGET(canvas)->window,
248                                   &values,
249                                   GDK_GC_FOREGROUND |
250                                   GDK_GC_FUNCTION |
251                                   GDK_GC_SUBWINDOW);
252 
253   gdk_draw_rectangle (GTK_WIDGET(canvas)->window,
254                       xor_gc,
255                       FALSE,
256                       area.x, area.y,
257                       area.width, area.height);
258   draw_marker(canvas, xor_gc, area.x, area.y);
259   draw_marker(canvas, xor_gc, area.x, area.y + area.height);
260   draw_marker(canvas, xor_gc, area.x + area.width, area.y);
261   draw_marker(canvas, xor_gc, area.x + area.width, area.y + area.height);
262   if(area.height > DEFAULT_MARKER_SIZE * 2){
263     draw_marker(canvas, xor_gc, area.x, area.y + area.height / 2);
264     draw_marker(canvas, xor_gc, area.x + area.width,
265                                 area.y + area.height / 2);
266   }
267   if(area.width > DEFAULT_MARKER_SIZE * 2){
268     draw_marker(canvas, xor_gc, area.x + area.width / 2, area.y);
269     draw_marker(canvas, xor_gc, area.x + area.width / 2,
270                                 area.y + area.height);
271   }
272 
273   gdk_gc_set_line_attributes(xor_gc, 1, 1, 0, 0);
274   gdk_draw_arc (GTK_WIDGET(canvas)->window, xor_gc,
275                 FALSE,
276                 roundint(area.x), roundint(area.y),
277                 roundint(area.width), roundint(area.height), 0, 25000);
278 
279   if(xor_gc) gdk_gc_unref(xor_gc);
280 }
281 
282 
283 static void
gtk_plot_canvas_ellipse_move(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,gdouble x,gdouble y)284 gtk_plot_canvas_ellipse_move		(GtkPlotCanvas *canvas,
285 					 GtkPlotCanvasChild *child,
286 					 gdouble x, gdouble y)
287 {
288   return;
289 }
290 
291 static void
gtk_plot_canvas_ellipse_resize(GtkPlotCanvas * canvas,GtkPlotCanvasChild * child,gdouble x1,gdouble y1,gdouble x2,gdouble y2)292 gtk_plot_canvas_ellipse_resize		(GtkPlotCanvas *canvas,
293 					 GtkPlotCanvasChild *child,
294 					 gdouble x1, gdouble y1,
295 					 gdouble x2, gdouble y2)
296 {
297   return;
298 }
299 
300 void
gtk_plot_canvas_ellipse_set_attributes(GtkPlotCanvasEllipse * ellipse,GtkPlotLineStyle style,gdouble width,const GdkColor * fg,const GdkColor * bg,gboolean fill)301 gtk_plot_canvas_ellipse_set_attributes	(GtkPlotCanvasEllipse *ellipse,
302                                     	 GtkPlotLineStyle style,
303 					 gdouble width,
304                                          const GdkColor *fg,
305                                          const GdkColor *bg,
306                                          gboolean fill)
307 {
308   if(fg) ellipse->line.color = *fg;
309   if(bg) ellipse->bg = *bg;
310   ellipse->line.line_width = width;
311   ellipse->line.line_style = style;
312   ellipse->filled = fill;
313 }
314 
315