Mercurial > hg > xmms-sid
comparison src/xs_curve.c @ 660:b0743dc9165d
Change tabs to 4 spaces, everywhere.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 02 Apr 2008 22:10:05 +0300 |
parents | ce1fe59627f2 |
children | b5b6b13a6d85 |
comparison
equal
deleted
inserted
replaced
659:04ea91a61225 | 660:b0743dc9165d |
---|---|
31 #include <gtk/gtkdrawingarea.h> | 31 #include <gtk/gtkdrawingarea.h> |
32 #include <gtk/gtkmain.h> | 32 #include <gtk/gtkmain.h> |
33 #include <gtk/gtksignal.h> | 33 #include <gtk/gtksignal.h> |
34 | 34 |
35 | 35 |
36 #define RADIUS 3 /* radius of the control points */ | 36 #define RADIUS 3 /* radius of the control points */ |
37 #define RADIUS2 (RADIUS * 2) | 37 #define RADIUS2 (RADIUS * 2) |
38 #define MIN_DISTANCE 7 /* min distance between control points */ | 38 #define MIN_DISTANCE 7 /* min distance between control points */ |
39 | 39 |
40 | 40 |
41 #define GRAPH_MASK (GDK_EXPOSURE_MASK | \ | 41 #define GRAPH_MASK (GDK_EXPOSURE_MASK | \ |
42 GDK_POINTER_MOTION_MASK | \ | 42 GDK_POINTER_MOTION_MASK | \ |
43 GDK_POINTER_MOTION_HINT_MASK | \ | 43 GDK_POINTER_MOTION_HINT_MASK | \ |
44 GDK_ENTER_NOTIFY_MASK | \ | 44 GDK_ENTER_NOTIFY_MASK | \ |
45 GDK_BUTTON_PRESS_MASK | \ | 45 GDK_BUTTON_PRESS_MASK | \ |
46 GDK_BUTTON_RELEASE_MASK | \ | 46 GDK_BUTTON_RELEASE_MASK | \ |
47 GDK_BUTTON1_MOTION_MASK) | 47 GDK_BUTTON1_MOTION_MASK) |
48 | 48 |
49 #define GET_X(i) curve->ctlpoints[i].x | 49 #define GET_X(i) curve->ctlpoints[i].x |
50 #define GET_Y(i) curve->ctlpoints[i].y | 50 #define GET_Y(i) curve->ctlpoints[i].y |
51 | 51 |
52 | 52 |
53 enum { | 53 enum { |
54 ARG_0, | 54 ARG_0, |
55 ARG_MIN_X, | 55 ARG_MIN_X, |
56 ARG_MAX_X, | 56 ARG_MAX_X, |
57 ARG_MIN_Y, | 57 ARG_MIN_Y, |
58 ARG_MAX_Y | 58 ARG_MAX_Y |
59 }; | 59 }; |
60 | 60 |
61 static GtkDrawingAreaClass *parent_class = NULL; | 61 static GtkDrawingAreaClass *parent_class = NULL; |
62 | 62 |
63 static void xs_curve_class_init(XSCurveClass * class); | 63 static void xs_curve_class_init(XSCurveClass * class); |
69 static void xs_curve_size_graph(XSCurve * curve); | 69 static void xs_curve_size_graph(XSCurve * curve); |
70 | 70 |
71 | 71 |
72 GtkType xs_curve_get_type(void) | 72 GtkType xs_curve_get_type(void) |
73 { | 73 { |
74 static GtkType curve_type = 0; | 74 static GtkType curve_type = 0; |
75 | 75 |
76 if (!curve_type) { | 76 if (!curve_type) { |
77 static const GtkTypeInfo curve_info = { | 77 static const GtkTypeInfo curve_info = { |
78 "XSCurve", | 78 "XSCurve", |
79 sizeof(XSCurve), | 79 sizeof(XSCurve), |
80 sizeof(XSCurveClass), | 80 sizeof(XSCurveClass), |
81 (GtkClassInitFunc) xs_curve_class_init, | 81 (GtkClassInitFunc) xs_curve_class_init, |
82 (GtkObjectInitFunc) xs_curve_init, | 82 (GtkObjectInitFunc) xs_curve_init, |
83 /* reserved_1 */ NULL, | 83 /* reserved_1 */ NULL, |
84 /* reserved_2 */ NULL, | 84 /* reserved_2 */ NULL, |
85 (GtkClassInitFunc) NULL, | 85 (GtkClassInitFunc) NULL, |
86 }; | 86 }; |
87 | 87 |
88 curve_type = gtk_type_unique(GTK_TYPE_DRAWING_AREA, &curve_info); | 88 curve_type = gtk_type_unique(GTK_TYPE_DRAWING_AREA, &curve_info); |
89 } | 89 } |
90 return curve_type; | 90 return curve_type; |
91 } | 91 } |
92 | 92 |
93 | 93 |
94 static void xs_curve_class_init(XSCurveClass *class) | 94 static void xs_curve_class_init(XSCurveClass *class) |
95 { | 95 { |
96 GtkObjectClass *object_class; | 96 GtkObjectClass *object_class; |
97 | 97 |
98 parent_class = gtk_type_class(GTK_TYPE_DRAWING_AREA); | 98 parent_class = gtk_type_class(GTK_TYPE_DRAWING_AREA); |
99 | 99 |
100 object_class = (GtkObjectClass *) class; | 100 object_class = (GtkObjectClass *) class; |
101 | 101 |
102 object_class->set_arg = xs_curve_set_arg; | 102 object_class->set_arg = xs_curve_set_arg; |
103 object_class->get_arg = xs_curve_get_arg; | 103 object_class->get_arg = xs_curve_get_arg; |
104 object_class->finalize = xs_curve_finalize; | 104 object_class->finalize = xs_curve_finalize; |
105 | 105 |
106 gtk_object_add_arg_type("XSCurve::min_x", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_MIN_X); | 106 gtk_object_add_arg_type("XSCurve::min_x", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_MIN_X); |
107 gtk_object_add_arg_type("XSCurve::max_x", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_MAX_X); | 107 gtk_object_add_arg_type("XSCurve::max_x", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_MAX_X); |
108 gtk_object_add_arg_type("XSCurve::min_y", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_MIN_Y); | 108 gtk_object_add_arg_type("XSCurve::min_y", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_MIN_Y); |
109 gtk_object_add_arg_type("XSCurve::max_y", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_MAX_Y); | 109 gtk_object_add_arg_type("XSCurve::max_y", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_MAX_Y); |
110 } | 110 } |
111 | 111 |
112 | 112 |
113 static void xs_curve_init(XSCurve *curve) | 113 static void xs_curve_init(XSCurve *curve) |
114 { | 114 { |
115 gint old_mask; | 115 gint old_mask; |
116 | 116 |
117 curve->pixmap = NULL; | 117 curve->pixmap = NULL; |
118 curve->grab_point = -1; | 118 curve->grab_point = -1; |
119 | 119 |
120 curve->nctlpoints = 0; | 120 curve->nctlpoints = 0; |
121 curve->ctlpoints = NULL; | 121 curve->ctlpoints = NULL; |
122 | 122 |
123 curve->min_x = 0.0; | 123 curve->min_x = 0.0; |
124 curve->max_x = 2047.0; | 124 curve->max_x = 2047.0; |
125 curve->min_y = 0.0; | 125 curve->min_y = 0.0; |
126 curve->max_y = 24000.0; | 126 curve->max_y = 24000.0; |
127 | 127 |
128 old_mask = gtk_widget_get_events(GTK_WIDGET(curve)); | 128 old_mask = gtk_widget_get_events(GTK_WIDGET(curve)); |
129 gtk_widget_set_events(GTK_WIDGET(curve), old_mask | GRAPH_MASK); | 129 gtk_widget_set_events(GTK_WIDGET(curve), old_mask | GRAPH_MASK); |
130 gtk_signal_connect(GTK_OBJECT(curve), "event", (GtkSignalFunc) xs_curve_graph_events, curve); | 130 gtk_signal_connect(GTK_OBJECT(curve), "event", (GtkSignalFunc) xs_curve_graph_events, curve); |
131 xs_curve_size_graph(curve); | 131 xs_curve_size_graph(curve); |
132 } | 132 } |
133 | 133 |
134 | 134 |
135 static void xs_curve_set_arg(GtkObject *object, GtkArg *arg, guint arg_id) | 135 static void xs_curve_set_arg(GtkObject *object, GtkArg *arg, guint arg_id) |
136 { | 136 { |
137 XSCurve *curve = XS_CURVE(object); | 137 XSCurve *curve = XS_CURVE(object); |
138 | 138 |
139 switch (arg_id) { | 139 switch (arg_id) { |
140 case ARG_MIN_X: | 140 case ARG_MIN_X: |
141 xs_curve_set_range(curve, GTK_VALUE_FLOAT(*arg), curve->max_x, curve->min_y, curve->max_y); | 141 xs_curve_set_range(curve, GTK_VALUE_FLOAT(*arg), curve->max_x, curve->min_y, curve->max_y); |
142 break; | 142 break; |
143 case ARG_MAX_X: | 143 case ARG_MAX_X: |
144 xs_curve_set_range(curve, curve->min_x, GTK_VALUE_FLOAT(*arg), curve->min_y, curve->max_y); | 144 xs_curve_set_range(curve, curve->min_x, GTK_VALUE_FLOAT(*arg), curve->min_y, curve->max_y); |
145 break; | 145 break; |
146 case ARG_MIN_Y: | 146 case ARG_MIN_Y: |
147 xs_curve_set_range(curve, curve->min_x, curve->max_x, GTK_VALUE_FLOAT(*arg), curve->max_y); | 147 xs_curve_set_range(curve, curve->min_x, curve->max_x, GTK_VALUE_FLOAT(*arg), curve->max_y); |
148 break; | 148 break; |
149 case ARG_MAX_Y: | 149 case ARG_MAX_Y: |
150 xs_curve_set_range(curve, curve->min_x, curve->max_x, curve->min_y, GTK_VALUE_FLOAT(*arg)); | 150 xs_curve_set_range(curve, curve->min_x, curve->max_x, curve->min_y, GTK_VALUE_FLOAT(*arg)); |
151 break; | 151 break; |
152 } | 152 } |
153 } | 153 } |
154 | 154 |
155 | 155 |
156 static void xs_curve_get_arg(GtkObject *object, GtkArg *arg, guint arg_id) | 156 static void xs_curve_get_arg(GtkObject *object, GtkArg *arg, guint arg_id) |
157 { | 157 { |
158 XSCurve *curve = XS_CURVE(object); | 158 XSCurve *curve = XS_CURVE(object); |
159 | 159 |
160 switch (arg_id) { | 160 switch (arg_id) { |
161 case ARG_MIN_X: | 161 case ARG_MIN_X: |
162 GTK_VALUE_FLOAT(*arg) = curve->min_x; | 162 GTK_VALUE_FLOAT(*arg) = curve->min_x; |
163 break; | 163 break; |
164 case ARG_MAX_X: | 164 case ARG_MAX_X: |
165 GTK_VALUE_FLOAT(*arg) = curve->max_x; | 165 GTK_VALUE_FLOAT(*arg) = curve->max_x; |
166 break; | 166 break; |
167 case ARG_MIN_Y: | 167 case ARG_MIN_Y: |
168 GTK_VALUE_FLOAT(*arg) = curve->min_y; | 168 GTK_VALUE_FLOAT(*arg) = curve->min_y; |
169 break; | 169 break; |
170 case ARG_MAX_Y: | 170 case ARG_MAX_Y: |
171 GTK_VALUE_FLOAT(*arg) = curve->max_y; | 171 GTK_VALUE_FLOAT(*arg) = curve->max_y; |
172 break; | 172 break; |
173 default: | 173 default: |
174 arg->type = GTK_TYPE_INVALID; | 174 arg->type = GTK_TYPE_INVALID; |
175 break; | 175 break; |
176 } | 176 } |
177 } | 177 } |
178 | 178 |
179 | 179 |
180 static int xs_project(gfloat value, gfloat min, gfloat max, int norm) | 180 static int xs_project(gfloat value, gfloat min, gfloat max, int norm) |
181 { | 181 { |
182 return (norm - 1) * ((value - min) / (max - min)) + 0.5; | 182 return (norm - 1) * ((value - min) / (max - min)) + 0.5; |
183 } | 183 } |
184 | 184 |
185 | 185 |
186 static gfloat xs_unproject(gint value, gfloat min, gfloat max, int norm) | 186 static gfloat xs_unproject(gint value, gfloat min, gfloat max, int norm) |
187 { | 187 { |
188 return value / (gfloat) (norm - 1) * (max - min) + min; | 188 return value / (gfloat) (norm - 1) * (max - min) + min; |
189 } | 189 } |
190 | 190 |
191 | 191 |
192 static inline void xs_cubic_coeff(gfloat x1, gfloat y1, | 192 static inline void xs_cubic_coeff(gfloat x1, gfloat y1, |
193 gfloat x2, gfloat y2, | 193 gfloat x2, gfloat y2, |
194 gfloat k1, gfloat k2, | 194 gfloat k1, gfloat k2, |
195 gfloat *a, gfloat *b, | 195 gfloat *a, gfloat *b, |
196 gfloat *c, gfloat *d) | 196 gfloat *c, gfloat *d) |
197 { | 197 { |
198 gfloat dx = x2 - x1, dy = y2 - y1; | 198 gfloat dx = x2 - x1, dy = y2 - y1; |
199 | 199 |
200 *a = ((k1 + k2) - 2 * dy / dx) / (dx * dx); | 200 *a = ((k1 + k2) - 2 * dy / dx) / (dx * dx); |
201 *b = ((k2 - k1) / dx - 3 * (x1 + x2) * (*a)) / 2; | 201 *b = ((k2 - k1) / dx - 3 * (x1 + x2) * (*a)) / 2; |
202 *c = k1 - (3 * x1 * (*a) + 2 * (*b)) * x1; | 202 *c = k1 - (3 * x1 * (*a) + 2 * (*b)) * x1; |
203 *d = y1 - ((x1 * (*a) + (*b)) * x1 + (*c)) * x1; | 203 *d = y1 - ((x1 * (*a) + (*b)) * x1 + (*c)) * x1; |
204 } | 204 } |
205 | 205 |
206 | 206 |
207 static void xs_curve_draw(XSCurve *curve, gint width, gint height) | 207 static void xs_curve_draw(XSCurve *curve, gint width, gint height) |
208 { | 208 { |
209 gfloat res = 5.0f; | 209 gfloat res = 5.0f; |
210 GtkStateType state; | 210 GtkStateType state; |
211 GtkStyle *style; | 211 GtkStyle *style; |
212 gint i, ox = -1, oy = -1; | 212 gint i, ox = -1, oy = -1; |
213 t_xs_point *p0, *p1, *p2, *p3; | 213 t_xs_point *p0, *p1, *p2, *p3; |
214 | 214 |
215 if (!curve->pixmap) | 215 if (!curve->pixmap) |
216 return; | 216 return; |
217 | 217 |
218 state = GTK_STATE_NORMAL; | 218 state = GTK_STATE_NORMAL; |
219 if (!GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(curve))) | 219 if (!GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(curve))) |
220 state = GTK_STATE_INSENSITIVE; | 220 state = GTK_STATE_INSENSITIVE; |
221 | 221 |
222 style = GTK_WIDGET(curve)->style; | 222 style = GTK_WIDGET(curve)->style; |
223 | 223 |
224 /* Clear the pixmap */ | 224 /* Clear the pixmap */ |
225 gtk_paint_flat_box(style, curve->pixmap, | 225 gtk_paint_flat_box(style, curve->pixmap, |
226 GTK_STATE_NORMAL, GTK_SHADOW_NONE, | 226 GTK_STATE_NORMAL, GTK_SHADOW_NONE, |
227 NULL, GTK_WIDGET(curve), "curve_bg", | 227 NULL, GTK_WIDGET(curve), "curve_bg", |
228 0, 0, | 228 0, 0, |
229 width + RADIUS2, | 229 width + RADIUS2, |
230 height + RADIUS2); | 230 height + RADIUS2); |
231 | 231 |
232 | 232 |
233 /* Draw the grid */ | 233 /* Draw the grid */ |
234 for (i = 0; i < 5; i++) { | 234 for (i = 0; i < 5; i++) { |
235 gdk_draw_line(curve->pixmap, style->dark_gc[state], | 235 gdk_draw_line(curve->pixmap, style->dark_gc[state], |
236 RADIUS, i * (height / 4.0) + RADIUS, | 236 RADIUS, i * (height / 4.0) + RADIUS, |
237 width + RADIUS, i * (height / 4.0) + RADIUS); | 237 width + RADIUS, i * (height / 4.0) + RADIUS); |
238 | 238 |
239 gdk_draw_line(curve->pixmap, style->dark_gc[state], | 239 gdk_draw_line(curve->pixmap, style->dark_gc[state], |
240 i * (width / 4.0) + RADIUS, RADIUS, | 240 i * (width / 4.0) + RADIUS, RADIUS, |
241 i * (width / 4.0) + RADIUS, height + RADIUS); | 241 i * (width / 4.0) + RADIUS, height + RADIUS); |
242 } | 242 } |
243 | 243 |
244 #if 1 | 244 #if 1 |
245 /* Draw the spline/curve itself */ | 245 /* Draw the spline/curve itself */ |
246 p0 = curve->ctlpoints; | 246 p0 = curve->ctlpoints; |
247 p1 = p0; | 247 p1 = p0; |
248 p2 = p1; p2++; | 248 p2 = p1; p2++; |
249 p3 = p2; p3++; | 249 p3 = p2; p3++; |
250 | 250 |
251 /* Draw each curve segment */ | 251 /* Draw each curve segment */ |
252 if (curve->nctlpoints > 5) | 252 if (curve->nctlpoints > 5) |
253 for (i = 0; i < curve->nctlpoints; i++, ++p0, ++p1, ++p2, ++p3) { | 253 for (i = 0; i < curve->nctlpoints; i++, ++p0, ++p1, ++p2, ++p3) { |
254 gint n; | 254 gint n; |
255 gfloat k1, k2, a, b, c, d, x; | 255 gfloat k1, k2, a, b, c, d, x; |
256 | 256 |
257 if (p1->x == p2->x) | 257 if (p1->x == p2->x) |
258 continue; | 258 continue; |
259 | 259 |
260 if (p0->x == p1->x && p2->x == p3->x) { | 260 if (p0->x == p1->x && p2->x == p3->x) { |
261 k1 = k2 = (p2->y - p1->y) / (p2->x - p1->x); | 261 k1 = k2 = (p2->y - p1->y) / (p2->x - p1->x); |
262 } else if (p0->x == p1->x) { | 262 } else if (p0->x == p1->x) { |
263 k2 = (p3->y - p1->y) / (p3->x - p1->x); | 263 k2 = (p3->y - p1->y) / (p3->x - p1->x); |
264 k1 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k2) / 2; | 264 k1 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k2) / 2; |
265 } else if (p2->x == p3->x) { | 265 } else if (p2->x == p3->x) { |
266 k1 = (p2->y - p0->y) / (p2->x - p0->x); | 266 k1 = (p2->y - p0->y) / (p2->x - p0->x); |
267 k2 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k1) / 2; | 267 k2 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k1) / 2; |
268 } else { | 268 } else { |
269 k1 = (p2->y - p0->y) / (p2->x - p0->x); | 269 k1 = (p2->y - p0->y) / (p2->x - p0->x); |
270 k2 = (p3->y - p1->y) / (p3->x - p1->x); | 270 k2 = (p3->y - p1->y) / (p3->x - p1->x); |
271 } | 271 } |
272 | 272 |
273 xs_cubic_coeff(p1->x, p1->y, p2->x, p2->y, k1, k2, &a, &b, &c, &d); | 273 xs_cubic_coeff(p1->x, p1->y, p2->x, p2->y, k1, k2, &a, &b, &c, &d); |
274 | 274 |
275 for (x = p1->x; x <= p2->x; x += res, n++) { | 275 for (x = p1->x; x <= p2->x; x += res, n++) { |
276 gfloat y = ((a * x + b) * x + c) * x + d; | 276 gfloat y = ((a * x + b) * x + c) * x + d; |
277 gint qx, qy; | 277 gint qx, qy; |
278 qx = RADIUS + xs_project(x, curve->min_x, curve->max_x, width); | 278 qx = RADIUS + xs_project(x, curve->min_x, curve->max_x, width); |
279 qy = RADIUS + xs_project(y, curve->min_y, curve->max_y, height); | 279 qy = RADIUS + xs_project(y, curve->min_y, curve->max_y, height); |
280 | 280 |
281 if (ox != -1) { | 281 if (ox != -1) { |
282 gdk_draw_line(curve->pixmap, style->fg_gc[state], | 282 gdk_draw_line(curve->pixmap, style->fg_gc[state], |
283 ox, oy, qx, qy); | 283 ox, oy, qx, qy); |
284 } | 284 } |
285 ox = qx; oy = qy; | 285 ox = qx; oy = qy; |
286 } | 286 } |
287 } | 287 } |
288 | 288 |
289 #endif | 289 #endif |
290 | 290 |
291 /* Draw control points */ | 291 /* Draw control points */ |
292 for (i = 0; i < curve->nctlpoints; ++i) { | 292 for (i = 0; i < curve->nctlpoints; ++i) { |
293 gint x, y; | 293 gint x, y; |
294 GtkStateType cstate; | 294 GtkStateType cstate; |
295 | 295 |
296 if (GET_X(i) < curve->min_x || GET_Y(i) < curve->min_y || | 296 if (GET_X(i) < curve->min_x || GET_Y(i) < curve->min_y || |
297 GET_X(i) >= curve->max_x || GET_Y(i) >= curve->max_y) | 297 GET_X(i) >= curve->max_x || GET_Y(i) >= curve->max_y) |
298 continue; | 298 continue; |
299 | 299 |
300 x = xs_project(GET_X(i), curve->min_x, curve->max_x, width); | 300 x = xs_project(GET_X(i), curve->min_x, curve->max_x, width); |
301 y = xs_project(GET_Y(i), curve->min_y, curve->max_y, height); | 301 y = xs_project(GET_Y(i), curve->min_y, curve->max_y, height); |
302 | 302 |
303 if (i == curve->grab_point) { | 303 if (i == curve->grab_point) { |
304 cstate = GTK_STATE_SELECTED; | 304 cstate = GTK_STATE_SELECTED; |
305 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], | 305 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], |
306 x + RADIUS, RADIUS, x + RADIUS, height + RADIUS); | 306 x + RADIUS, RADIUS, x + RADIUS, height + RADIUS); |
307 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], | 307 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], |
308 RADIUS, y + RADIUS, width + RADIUS, y + RADIUS); | 308 RADIUS, y + RADIUS, width + RADIUS, y + RADIUS); |
309 } else | 309 } else |
310 cstate = state; | 310 cstate = state; |
311 | 311 |
312 gdk_draw_arc(curve->pixmap, style->fg_gc[cstate], TRUE, | 312 gdk_draw_arc(curve->pixmap, style->fg_gc[cstate], TRUE, |
313 x, y, RADIUS2, RADIUS2, 0, 360 * 64); | 313 x, y, RADIUS2, RADIUS2, 0, 360 * 64); |
314 } | 314 } |
315 | 315 |
316 /* Draw pixmap in the widget */ | 316 /* Draw pixmap in the widget */ |
317 gdk_draw_pixmap(GTK_WIDGET(curve)->window, | 317 gdk_draw_pixmap(GTK_WIDGET(curve)->window, |
318 style->fg_gc[state], curve->pixmap, | 318 style->fg_gc[state], curve->pixmap, |
319 0, 0, 0, 0, | 319 0, 0, 0, 0, |
320 width + RADIUS2, | 320 width + RADIUS2, |
321 height + RADIUS2); | 321 height + RADIUS2); |
322 } | 322 } |
323 | 323 |
324 | 324 |
325 static gint xs_curve_graph_events(GtkWidget *widget, GdkEvent *event, XSCurve *curve) | 325 static gint xs_curve_graph_events(GtkWidget *widget, GdkEvent *event, XSCurve *curve) |
326 { | 326 { |
327 GdkCursorType new_type = curve->cursor_type; | 327 GdkCursorType new_type = curve->cursor_type; |
328 GdkEventButton *bevent; | 328 GdkEventButton *bevent; |
329 GtkWidget *w; | 329 GtkWidget *w; |
330 gint i, width, height, x, y, tx, ty, cx, closest_point = 0, min_x; | 330 gint i, width, height, x, y, tx, ty, cx, closest_point = 0, min_x; |
331 guint distance; | 331 guint distance; |
332 | 332 |
333 w = GTK_WIDGET(curve); | 333 w = GTK_WIDGET(curve); |
334 width = w->allocation.width - RADIUS2; | 334 width = w->allocation.width - RADIUS2; |
335 height = w->allocation.height - RADIUS2; | 335 height = w->allocation.height - RADIUS2; |
336 | 336 |
337 if ((width < 0) || (height < 0)) | 337 if ((width < 0) || (height < 0)) |
338 return FALSE; | 338 return FALSE; |
339 | 339 |
340 /* get the pointer position */ | 340 /* get the pointer position */ |
341 gdk_window_get_pointer(w->window, &tx, &ty, NULL); | 341 gdk_window_get_pointer(w->window, &tx, &ty, NULL); |
342 x = CLAMP((tx - RADIUS), 0, width - 1); | 342 x = CLAMP((tx - RADIUS), 0, width - 1); |
343 y = CLAMP((ty - RADIUS), 0, height - 1); | 343 y = CLAMP((ty - RADIUS), 0, height - 1); |
344 min_x = curve->min_x; | 344 min_x = curve->min_x; |
345 | 345 |
346 distance = ~0U; | 346 distance = ~0U; |
347 for (i = 0; i < curve->nctlpoints; ++i) { | 347 for (i = 0; i < curve->nctlpoints; ++i) { |
348 cx = xs_project(GET_X(i), min_x, curve->max_x, width); | 348 cx = xs_project(GET_X(i), min_x, curve->max_x, width); |
349 if ((guint) abs(x - cx) < distance) { | 349 if ((guint) abs(x - cx) < distance) { |
350 distance = abs(x - cx); | 350 distance = abs(x - cx); |
351 closest_point = i; | 351 closest_point = i; |
352 } | 352 } |
353 } | 353 } |
354 | 354 |
355 /* Act based on event type */ | 355 /* Act based on event type */ |
356 switch (event->type) { | 356 switch (event->type) { |
357 case GDK_CONFIGURE: | 357 case GDK_CONFIGURE: |
358 if (curve->pixmap) | 358 if (curve->pixmap) |
359 gdk_pixmap_unref(curve->pixmap); | 359 gdk_pixmap_unref(curve->pixmap); |
360 curve->pixmap = 0; | 360 curve->pixmap = 0; |
361 | 361 |
362 /* fall through */ | 362 /* fall through */ |
363 | 363 |
364 case GDK_EXPOSE: | 364 case GDK_EXPOSE: |
365 if (!curve->pixmap) { | 365 if (!curve->pixmap) { |
366 curve->pixmap = gdk_pixmap_new(w->window, | 366 curve->pixmap = gdk_pixmap_new(w->window, |
367 w->allocation.width, w->allocation.height, -1); | 367 w->allocation.width, w->allocation.height, -1); |
368 } | 368 } |
369 xs_curve_draw(curve, width, height); | 369 xs_curve_draw(curve, width, height); |
370 break; | 370 break; |
371 | 371 |
372 case GDK_BUTTON_PRESS: | 372 case GDK_BUTTON_PRESS: |
373 gtk_grab_add(widget); | 373 gtk_grab_add(widget); |
374 | 374 |
375 bevent = (GdkEventButton *) event; | 375 bevent = (GdkEventButton *) event; |
376 new_type = GDK_TCROSS; | 376 new_type = GDK_TCROSS; |
377 | 377 |
378 if (distance > MIN_DISTANCE) { | 378 if (distance > MIN_DISTANCE) { |
379 /* insert a new control point */ | 379 /* insert a new control point */ |
380 if (curve->nctlpoints > 0) { | 380 if (curve->nctlpoints > 0) { |
381 cx = xs_project(GET_X(closest_point), min_x, curve->max_x, width); | 381 cx = xs_project(GET_X(closest_point), min_x, curve->max_x, width); |
382 if (x > cx) closest_point++; | 382 if (x > cx) closest_point++; |
383 } | 383 } |
384 | 384 |
385 curve->nctlpoints++; | 385 curve->nctlpoints++; |
386 | 386 |
387 curve->ctlpoints = g_realloc(curve->ctlpoints, | 387 curve->ctlpoints = g_realloc(curve->ctlpoints, |
388 curve->nctlpoints * sizeof(*curve->ctlpoints)); | 388 curve->nctlpoints * sizeof(*curve->ctlpoints)); |
389 | 389 |
390 for (i = curve->nctlpoints - 1; i > closest_point; --i) { | 390 for (i = curve->nctlpoints - 1; i > closest_point; --i) { |
391 memcpy(curve->ctlpoints + i, | 391 memcpy(curve->ctlpoints + i, |
392 curve->ctlpoints + i - 1, | 392 curve->ctlpoints + i - 1, |
393 sizeof(*curve->ctlpoints)); | 393 sizeof(*curve->ctlpoints)); |
394 } | 394 } |
395 } | 395 } |
396 | 396 |
397 curve->grab_point = closest_point; | 397 curve->grab_point = closest_point; |
398 GET_X(curve->grab_point) = xs_unproject(x, min_x, curve->max_x, width); | 398 GET_X(curve->grab_point) = xs_unproject(x, min_x, curve->max_x, width); |
399 GET_Y(curve->grab_point) = xs_unproject(y, curve->min_y, curve->max_y, height); | 399 GET_Y(curve->grab_point) = xs_unproject(y, curve->min_y, curve->max_y, height); |
400 | 400 |
401 xs_curve_draw(curve, width, height); | 401 xs_curve_draw(curve, width, height); |
402 break; | 402 break; |
403 | 403 |
404 case GDK_BUTTON_RELEASE: | 404 case GDK_BUTTON_RELEASE: |
405 { | 405 { |
406 gint src, dst; | 406 gint src, dst; |
407 | 407 |
408 gtk_grab_remove(widget); | 408 gtk_grab_remove(widget); |
409 | 409 |
410 /* delete inactive points: */ | 410 /* delete inactive points: */ |
411 for (src = dst = 0; src < curve->nctlpoints; ++src) { | 411 for (src = dst = 0; src < curve->nctlpoints; ++src) { |
412 if (GET_X(src) >= min_x) { | 412 if (GET_X(src) >= min_x) { |
413 memcpy(curve->ctlpoints + dst, | 413 memcpy(curve->ctlpoints + dst, |
414 curve->ctlpoints + src, | 414 curve->ctlpoints + src, |
415 sizeof(*curve->ctlpoints)); | 415 sizeof(*curve->ctlpoints)); |
416 dst++; | 416 dst++; |
417 } | 417 } |
418 } | 418 } |
419 | 419 |
420 if (dst < src) { | 420 if (dst < src) { |
421 curve->nctlpoints -= (src - dst); | 421 curve->nctlpoints -= (src - dst); |
422 if (curve->nctlpoints <= 0) { | 422 if (curve->nctlpoints <= 0) { |
423 curve->nctlpoints = 1; | 423 curve->nctlpoints = 1; |
424 GET_X(0) = min_x; | 424 GET_X(0) = min_x; |
425 GET_Y(0) = curve->min_y; | 425 GET_Y(0) = curve->min_y; |
426 xs_curve_draw(curve, width, height); | 426 xs_curve_draw(curve, width, height); |
427 } | 427 } |
428 curve->ctlpoints = g_realloc(curve->ctlpoints, | 428 curve->ctlpoints = g_realloc(curve->ctlpoints, |
429 curve->nctlpoints * sizeof(*curve->ctlpoints)); | 429 curve->nctlpoints * sizeof(*curve->ctlpoints)); |
430 } | 430 } |
431 | 431 |
432 new_type = GDK_FLEUR; | 432 new_type = GDK_FLEUR; |
433 curve->grab_point = -1; | 433 curve->grab_point = -1; |
434 } | 434 } |
435 xs_curve_draw(curve, width, height); | 435 xs_curve_draw(curve, width, height); |
436 break; | 436 break; |
437 | 437 |
438 case GDK_MOTION_NOTIFY: | 438 case GDK_MOTION_NOTIFY: |
439 if (curve->grab_point == -1) { | 439 if (curve->grab_point == -1) { |
440 /* if no point is grabbed... */ | 440 /* if no point is grabbed... */ |
441 if (distance <= MIN_DISTANCE) | 441 if (distance <= MIN_DISTANCE) |
442 new_type = GDK_FLEUR; | 442 new_type = GDK_FLEUR; |
443 else | 443 else |
444 new_type = GDK_TCROSS; | 444 new_type = GDK_TCROSS; |
445 } else { | 445 } else { |
446 gint leftbound, rightbound; | 446 gint leftbound, rightbound; |
447 | 447 |
448 /* drag the grabbed point */ | 448 /* drag the grabbed point */ |
449 new_type = GDK_TCROSS; | 449 new_type = GDK_TCROSS; |
450 | 450 |
451 leftbound = -MIN_DISTANCE; | 451 leftbound = -MIN_DISTANCE; |
452 if (curve->grab_point > 0) { | 452 if (curve->grab_point > 0) { |
453 leftbound = xs_project( | 453 leftbound = xs_project( |
454 GET_X(curve->grab_point-1), | 454 GET_X(curve->grab_point-1), |
455 min_x, curve->max_x, width); | 455 min_x, curve->max_x, width); |
456 } | 456 } |
457 | 457 |
458 rightbound = width + RADIUS2 + MIN_DISTANCE; | 458 rightbound = width + RADIUS2 + MIN_DISTANCE; |
459 if (curve->grab_point + 1 < curve->nctlpoints) { | 459 if (curve->grab_point + 1 < curve->nctlpoints) { |
460 rightbound = xs_project( | 460 rightbound = xs_project( |
461 GET_X(curve->grab_point+1), | 461 GET_X(curve->grab_point+1), |
462 min_x, curve->max_x, width); | 462 min_x, curve->max_x, width); |
463 } | 463 } |
464 | 464 |
465 if ((tx <= leftbound) || (tx >= rightbound) || | 465 if ((tx <= leftbound) || (tx >= rightbound) || |
466 (ty > height + RADIUS2 + MIN_DISTANCE) || (ty < -MIN_DISTANCE)) { | 466 (ty > height + RADIUS2 + MIN_DISTANCE) || (ty < -MIN_DISTANCE)) { |
467 GET_X(curve->grab_point) = min_x - 1.0; | 467 GET_X(curve->grab_point) = min_x - 1.0; |
468 } else { | 468 } else { |
469 GET_X(curve->grab_point) = | 469 GET_X(curve->grab_point) = |
470 xs_unproject(x, min_x, curve->max_x, width); | 470 xs_unproject(x, min_x, curve->max_x, width); |
471 GET_Y(curve->grab_point) = | 471 GET_Y(curve->grab_point) = |
472 xs_unproject(y, curve->min_y, curve->max_y, height); | 472 xs_unproject(y, curve->min_y, curve->max_y, height); |
473 } | 473 } |
474 | 474 |
475 xs_curve_draw(curve, width, height); | 475 xs_curve_draw(curve, width, height); |
476 } | 476 } |
477 | 477 |
478 /* See if cursor type was changed and update accordingly */ | 478 /* See if cursor type was changed and update accordingly */ |
479 if (new_type != (GdkCursorType) curve->cursor_type) { | 479 if (new_type != (GdkCursorType) curve->cursor_type) { |
480 GdkCursor *cursor; | 480 GdkCursor *cursor; |
481 curve->cursor_type = new_type; | 481 curve->cursor_type = new_type; |
482 cursor = gdk_cursor_new(curve->cursor_type); | 482 cursor = gdk_cursor_new(curve->cursor_type); |
483 gdk_window_set_cursor(w->window, cursor); | 483 gdk_window_set_cursor(w->window, cursor); |
484 gdk_cursor_destroy(cursor); | 484 gdk_cursor_destroy(cursor); |
485 } | 485 } |
486 break; | 486 break; |
487 | 487 |
488 default: | 488 default: |
489 break; | 489 break; |
490 } | 490 } |
491 | 491 |
492 return FALSE; | 492 return FALSE; |
493 } | 493 } |
494 | 494 |
495 | 495 |
496 static void xs_curve_size_graph(XSCurve *curve) | 496 static void xs_curve_size_graph(XSCurve *curve) |
497 { | 497 { |
498 gint width, height; | 498 gint width, height; |
499 gfloat aspect; | 499 gfloat aspect; |
500 | 500 |
501 width = (curve->max_x - curve->min_x) + 1; | 501 width = (curve->max_x - curve->min_x) + 1; |
502 height = (curve->max_y - curve->min_y) + 1; | 502 height = (curve->max_y - curve->min_y) + 1; |
503 aspect = width / (gfloat) height; | 503 aspect = width / (gfloat) height; |
504 | 504 |
505 if (width > gdk_screen_width() / 4) | 505 if (width > gdk_screen_width() / 4) |
506 width = gdk_screen_width() / 4; | 506 width = gdk_screen_width() / 4; |
507 | 507 |
508 if (height > gdk_screen_height() / 4) | 508 if (height > gdk_screen_height() / 4) |
509 height = gdk_screen_height() / 4; | 509 height = gdk_screen_height() / 4; |
510 | 510 |
511 if (aspect < 1.0) | 511 if (aspect < 1.0) |
512 width = height * aspect; | 512 width = height * aspect; |
513 else | 513 else |
514 height = width / aspect; | 514 height = width / aspect; |
515 | 515 |
516 gtk_drawing_area_size(GTK_DRAWING_AREA(curve), width + RADIUS2, height + RADIUS2); | 516 gtk_drawing_area_size(GTK_DRAWING_AREA(curve), width + RADIUS2, height + RADIUS2); |
517 } | 517 } |
518 | 518 |
519 | 519 |
520 static void xs_curve_update(XSCurve *curve) | 520 static void xs_curve_update(XSCurve *curve) |
521 { | 521 { |
522 if (curve->pixmap) { | 522 if (curve->pixmap) { |
523 gint width, height; | 523 gint width, height; |
524 | 524 |
525 width = GTK_WIDGET(curve)->allocation.width - RADIUS2; | 525 width = GTK_WIDGET(curve)->allocation.width - RADIUS2; |
526 height = GTK_WIDGET(curve)->allocation.height - RADIUS2; | 526 height = GTK_WIDGET(curve)->allocation.height - RADIUS2; |
527 xs_curve_draw(curve, width, height); | 527 xs_curve_draw(curve, width, height); |
528 } | 528 } |
529 } | 529 } |
530 | 530 |
531 | 531 |
532 void xs_curve_reset(XSCurve *curve) | 532 void xs_curve_reset(XSCurve *curve) |
533 { | 533 { |
534 if (curve->ctlpoints) | 534 if (curve->ctlpoints) |
535 g_free(curve->ctlpoints); | 535 g_free(curve->ctlpoints); |
536 | 536 |
537 curve->nctlpoints = 4; | 537 curve->nctlpoints = 4; |
538 curve->ctlpoints = g_malloc(curve->nctlpoints * sizeof(curve->ctlpoints[0])); | 538 curve->ctlpoints = g_malloc(curve->nctlpoints * sizeof(curve->ctlpoints[0])); |
539 | 539 |
540 GET_X(0) = curve->min_x; | 540 GET_X(0) = curve->min_x; |
541 GET_Y(0) = curve->min_y; | 541 GET_Y(0) = curve->min_y; |
542 GET_X(1) = curve->min_x; | 542 GET_X(1) = curve->min_x; |
543 GET_Y(1) = curve->min_y; | 543 GET_Y(1) = curve->min_y; |
544 | 544 |
545 GET_X(2) = curve->max_x; | 545 GET_X(2) = curve->max_x; |
546 GET_Y(2) = curve->max_y; | 546 GET_Y(2) = curve->max_y; |
547 GET_X(3) = curve->max_x; | 547 GET_X(3) = curve->max_x; |
548 GET_Y(3) = curve->max_y; | 548 GET_Y(3) = curve->max_y; |
549 | 549 |
550 xs_curve_update(curve); | 550 xs_curve_update(curve); |
551 } | 551 } |
552 | 552 |
553 | 553 |
554 void xs_curve_set_range(XSCurve *curve, gfloat min_x, gfloat min_y, gfloat max_x, gfloat max_y) | 554 void xs_curve_set_range(XSCurve *curve, gfloat min_x, gfloat min_y, gfloat max_x, gfloat max_y) |
555 { | 555 { |
556 curve->min_x = min_x; | 556 curve->min_x = min_x; |
557 curve->max_x = max_x; | 557 curve->max_x = max_x; |
558 | 558 |
559 curve->min_y = min_y; | 559 curve->min_y = min_y; |
560 curve->max_y = max_y; | 560 curve->max_y = max_y; |
561 | 561 |
562 xs_curve_size_graph(curve); | 562 xs_curve_size_graph(curve); |
563 xs_curve_reset(curve); | 563 xs_curve_reset(curve); |
564 } | 564 } |
565 | 565 |
566 | 566 |
567 gboolean xs_curve_realloc_data(XSCurve *curve, gint npoints) | 567 gboolean xs_curve_realloc_data(XSCurve *curve, gint npoints) |
568 { | 568 { |
569 if (npoints != curve->nctlpoints) { | 569 if (npoints != curve->nctlpoints) { |
570 curve->nctlpoints = npoints; | 570 curve->nctlpoints = npoints; |
571 curve->ctlpoints = (t_xs_point *) g_realloc(curve->ctlpoints, | 571 curve->ctlpoints = (t_xs_point *) g_realloc(curve->ctlpoints, |
572 curve->nctlpoints * sizeof(*curve->ctlpoints)); | 572 curve->nctlpoints * sizeof(*curve->ctlpoints)); |
573 | 573 |
574 if (curve->ctlpoints == NULL) | 574 if (curve->ctlpoints == NULL) |
575 return FALSE; | 575 return FALSE; |
576 } | 576 } |
577 | 577 |
578 return TRUE; | 578 return TRUE; |
579 } | 579 } |
580 | 580 |
581 | 581 |
582 void xs_curve_get_data(XSCurve *curve, t_xs_point ***points, gint **npoints) | 582 void xs_curve_get_data(XSCurve *curve, t_xs_point ***points, gint **npoints) |
583 { | 583 { |
584 *points = &(curve->ctlpoints); | 584 *points = &(curve->ctlpoints); |
585 *npoints = &(curve->nctlpoints); | 585 *npoints = &(curve->nctlpoints); |
586 } | 586 } |
587 | 587 |
588 | 588 |
589 gboolean xs_curve_set_points(XSCurve *curve, t_xs_int_point *points, gint npoints) | 589 gboolean xs_curve_set_points(XSCurve *curve, t_xs_int_point *points, gint npoints) |
590 { | 590 { |
591 gint i; | 591 gint i; |
592 | 592 |
593 if (!xs_curve_realloc_data(curve, npoints + 4)) | 593 if (!xs_curve_realloc_data(curve, npoints + 4)) |
594 return FALSE; | 594 return FALSE; |
595 | 595 |
596 GET_X(0) = curve->min_x; | 596 GET_X(0) = curve->min_x; |
597 GET_Y(0) = curve->min_y; | 597 GET_Y(0) = curve->min_y; |
598 GET_X(1) = curve->min_x; | 598 GET_X(1) = curve->min_x; |
599 GET_Y(1) = curve->min_y; | 599 GET_Y(1) = curve->min_y; |
600 | 600 |
601 for (i = 0; i < npoints; i++) { | 601 for (i = 0; i < npoints; i++) { |
602 GET_X(i+2) = points[i].x; | 602 GET_X(i+2) = points[i].x; |
603 GET_Y(i+2) = points[i].y; | 603 GET_Y(i+2) = points[i].y; |
604 } | 604 } |
605 | 605 |
606 GET_X(npoints+2) = curve->max_x; | 606 GET_X(npoints+2) = curve->max_x; |
607 GET_Y(npoints+2) = curve->max_y; | 607 GET_Y(npoints+2) = curve->max_y; |
608 GET_X(npoints+3) = curve->max_x; | 608 GET_X(npoints+3) = curve->max_x; |
609 GET_Y(npoints+3) = curve->max_y; | 609 GET_Y(npoints+3) = curve->max_y; |
610 | 610 |
611 xs_curve_update(curve); | 611 xs_curve_update(curve); |
612 return TRUE; | 612 return TRUE; |
613 } | 613 } |
614 | 614 |
615 | 615 |
616 gboolean xs_curve_get_points(XSCurve *curve, t_xs_int_point **points, gint *npoints) | 616 gboolean xs_curve_get_points(XSCurve *curve, t_xs_int_point **points, gint *npoints) |
617 { | 617 { |
618 gint i, n; | 618 gint i, n; |
619 | 619 |
620 n = curve->nctlpoints - 4; | 620 n = curve->nctlpoints - 4; |
621 | 621 |
622 *points = g_malloc(n * sizeof(t_xs_int_point)); | 622 *points = g_malloc(n * sizeof(t_xs_int_point)); |
623 if (*points == NULL) | 623 if (*points == NULL) |
624 return FALSE; | 624 return FALSE; |
625 | 625 |
626 *npoints = n; | 626 *npoints = n; |
627 for (i = 2; i < curve->nctlpoints - 2; i++) { | 627 for (i = 2; i < curve->nctlpoints - 2; i++) { |
628 (*points)[i].x = GET_X(i); | 628 (*points)[i].x = GET_X(i); |
629 (*points)[i].y = GET_Y(i); | 629 (*points)[i].y = GET_Y(i); |
630 } | 630 } |
631 | 631 |
632 return TRUE; | 632 return TRUE; |
633 } | 633 } |
634 | 634 |
635 | 635 |
636 GtkWidget *xs_curve_new(void) | 636 GtkWidget *xs_curve_new(void) |
637 { | 637 { |
638 return gtk_type_new(xs_curve_get_type()); | 638 return gtk_type_new(xs_curve_get_type()); |
639 } | 639 } |
640 | 640 |
641 | 641 |
642 static void xs_curve_finalize(GtkObject *object) | 642 static void xs_curve_finalize(GtkObject *object) |
643 { | 643 { |
644 XSCurve *curve; | 644 XSCurve *curve; |
645 | 645 |
646 g_return_if_fail(object != NULL); | 646 g_return_if_fail(object != NULL); |
647 g_return_if_fail(XS_IS_CURVE(object)); | 647 g_return_if_fail(XS_IS_CURVE(object)); |
648 | 648 |
649 curve = XS_CURVE(object); | 649 curve = XS_CURVE(object); |
650 if (curve->pixmap) | 650 if (curve->pixmap) |
651 gdk_pixmap_unref(curve->pixmap); | 651 gdk_pixmap_unref(curve->pixmap); |
652 if (curve->ctlpoints) | 652 if (curve->ctlpoints) |
653 g_free(curve->ctlpoints); | 653 g_free(curve->ctlpoints); |
654 | 654 |
655 (*GTK_OBJECT_CLASS(parent_class)->finalize) (object); | 655 (*GTK_OBJECT_CLASS(parent_class)->finalize) (object); |
656 } | 656 } |