Mercurial > hg > xmms-sid
comparison src/xs_curve.c @ 908:8b4c016802ea
Cosmetics.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 10 Nov 2012 11:58:59 +0200 |
parents | 9321ffa2ea7e |
children | 79f20427c99d |
comparison
equal
deleted
inserted
replaced
907:cc2789a06d44 | 908:8b4c016802ea |
---|---|
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 CP_RADIUS 3 /* radius of the control points */ |
37 #define RADIUS2 (RADIUS * 2) | 37 #define CP_RADIUS2 (CP_RADIUS * 2) |
38 #define MIN_DISTANCE 7 /* min distance between control points */ | 38 #define CP_MIN_DISTANCE 7 /* min distance between control points */ |
39 | 39 |
40 | 40 |
41 #define GRAPH_MASK (GDK_EXPOSURE_MASK | \ | 41 #define GRAPH_MASK ( \ |
42 GDK_POINTER_MOTION_MASK | \ | 42 GDK_EXPOSURE_MASK | \ |
43 GDK_POINTER_MOTION_HINT_MASK | \ | 43 GDK_POINTER_MOTION_MASK | \ |
44 GDK_ENTER_NOTIFY_MASK | \ | 44 GDK_POINTER_MOTION_HINT_MASK | \ |
45 GDK_BUTTON_PRESS_MASK | \ | 45 GDK_ENTER_NOTIFY_MASK | \ |
46 GDK_BUTTON_RELEASE_MASK | \ | 46 GDK_BUTTON_PRESS_MASK | \ |
47 GDK_BUTTON1_MOTION_MASK) | 47 GDK_BUTTON_RELEASE_MASK | \ |
48 GDK_BUTTON1_MOTION_MASK) | |
48 | 49 |
49 #define GET_X(i) curve->ctlpoints[i].x | 50 #define GET_X(i) curve->ctlpoints[i].x |
50 #define GET_Y(i) curve->ctlpoints[i].y | 51 #define GET_Y(i) curve->ctlpoints[i].y |
51 | 52 |
52 | 53 |
71 | 72 |
72 GtkType xs_curve_get_type(void) | 73 GtkType xs_curve_get_type(void) |
73 { | 74 { |
74 static GtkType curve_type = 0; | 75 static GtkType curve_type = 0; |
75 | 76 |
76 if (!curve_type) { | 77 if (!curve_type) |
77 static const GtkTypeInfo curve_info = { | 78 { |
79 static const GtkTypeInfo curve_info = | |
80 { | |
78 "XSCurve", | 81 "XSCurve", |
79 sizeof(XSCurve), | 82 sizeof(XSCurve), |
80 sizeof(XSCurveClass), | 83 sizeof(XSCurveClass), |
81 (GtkClassInitFunc) xs_curve_class_init, | 84 (GtkClassInitFunc) xs_curve_class_init, |
82 (GtkObjectInitFunc) xs_curve_init, | 85 (GtkObjectInitFunc) xs_curve_init, |
134 | 137 |
135 static void xs_curve_set_arg(GtkObject *object, GtkArg *arg, guint arg_id) | 138 static void xs_curve_set_arg(GtkObject *object, GtkArg *arg, guint arg_id) |
136 { | 139 { |
137 XSCurve *curve = XS_CURVE(object); | 140 XSCurve *curve = XS_CURVE(object); |
138 | 141 |
139 switch (arg_id) { | 142 switch (arg_id) |
140 case ARG_MIN_X: | 143 { |
141 xs_curve_set_range(curve, GTK_VALUE_FLOAT(*arg), curve->max_x, curve->min_y, curve->max_y); | 144 case ARG_MIN_X: |
142 break; | 145 xs_curve_set_range(curve, GTK_VALUE_FLOAT(*arg), curve->max_x, curve->min_y, curve->max_y); |
143 case ARG_MAX_X: | 146 break; |
144 xs_curve_set_range(curve, curve->min_x, GTK_VALUE_FLOAT(*arg), curve->min_y, curve->max_y); | 147 case ARG_MAX_X: |
145 break; | 148 xs_curve_set_range(curve, curve->min_x, GTK_VALUE_FLOAT(*arg), curve->min_y, curve->max_y); |
146 case ARG_MIN_Y: | 149 break; |
147 xs_curve_set_range(curve, curve->min_x, curve->max_x, GTK_VALUE_FLOAT(*arg), curve->max_y); | 150 case ARG_MIN_Y: |
148 break; | 151 xs_curve_set_range(curve, curve->min_x, curve->max_x, GTK_VALUE_FLOAT(*arg), curve->max_y); |
149 case ARG_MAX_Y: | 152 break; |
150 xs_curve_set_range(curve, curve->min_x, curve->max_x, curve->min_y, GTK_VALUE_FLOAT(*arg)); | 153 case ARG_MAX_Y: |
151 break; | 154 xs_curve_set_range(curve, curve->min_x, curve->max_x, curve->min_y, GTK_VALUE_FLOAT(*arg)); |
155 break; | |
152 } | 156 } |
153 } | 157 } |
154 | 158 |
155 | 159 |
156 static void xs_curve_get_arg(GtkObject *object, GtkArg *arg, guint arg_id) | 160 static void xs_curve_get_arg(GtkObject *object, GtkArg *arg, guint arg_id) |
157 { | 161 { |
158 XSCurve *curve = XS_CURVE(object); | 162 XSCurve *curve = XS_CURVE(object); |
159 | 163 |
160 switch (arg_id) { | 164 switch (arg_id) |
161 case ARG_MIN_X: | 165 { |
162 GTK_VALUE_FLOAT(*arg) = curve->min_x; | 166 case ARG_MIN_X: |
163 break; | 167 GTK_VALUE_FLOAT(*arg) = curve->min_x; |
164 case ARG_MAX_X: | 168 break; |
165 GTK_VALUE_FLOAT(*arg) = curve->max_x; | 169 case ARG_MAX_X: |
166 break; | 170 GTK_VALUE_FLOAT(*arg) = curve->max_x; |
167 case ARG_MIN_Y: | 171 break; |
168 GTK_VALUE_FLOAT(*arg) = curve->min_y; | 172 case ARG_MIN_Y: |
169 break; | 173 GTK_VALUE_FLOAT(*arg) = curve->min_y; |
170 case ARG_MAX_Y: | 174 break; |
171 GTK_VALUE_FLOAT(*arg) = curve->max_y; | 175 case ARG_MAX_Y: |
172 break; | 176 GTK_VALUE_FLOAT(*arg) = curve->max_y; |
173 default: | 177 break; |
174 arg->type = GTK_TYPE_INVALID; | 178 default: |
175 break; | 179 arg->type = GTK_TYPE_INVALID; |
180 break; | |
176 } | 181 } |
177 } | 182 } |
178 | 183 |
179 | 184 |
180 static int xs_project(gfloat value, gfloat min, gfloat max, int norm) | 185 static int xs_project(gfloat value, gfloat min, gfloat max, int norm) |
224 /* Clear the pixmap */ | 229 /* Clear the pixmap */ |
225 gtk_paint_flat_box(style, curve->pixmap, | 230 gtk_paint_flat_box(style, curve->pixmap, |
226 GTK_STATE_NORMAL, GTK_SHADOW_NONE, | 231 GTK_STATE_NORMAL, GTK_SHADOW_NONE, |
227 NULL, GTK_WIDGET(curve), "curve_bg", | 232 NULL, GTK_WIDGET(curve), "curve_bg", |
228 0, 0, | 233 0, 0, |
229 width + RADIUS2, | 234 width + CP_RADIUS2, |
230 height + RADIUS2); | 235 height + CP_RADIUS2); |
231 | 236 |
232 | 237 |
233 /* Draw the grid */ | 238 /* Draw the grid */ |
234 for (i = 0; i < 5; i++) { | 239 for (i = 0; i < 5; i++) |
240 { | |
235 gdk_draw_line(curve->pixmap, style->dark_gc[state], | 241 gdk_draw_line(curve->pixmap, style->dark_gc[state], |
236 RADIUS, i * (height / 4.0) + RADIUS, | 242 CP_RADIUS, i * (height / 4.0) + CP_RADIUS, |
237 width + RADIUS, i * (height / 4.0) + RADIUS); | 243 width + CP_RADIUS, i * (height / 4.0) + CP_RADIUS); |
238 | 244 |
239 gdk_draw_line(curve->pixmap, style->dark_gc[state], | 245 gdk_draw_line(curve->pixmap, style->dark_gc[state], |
240 i * (width / 4.0) + RADIUS, RADIUS, | 246 i * (width / 4.0) + CP_RADIUS, CP_RADIUS, |
241 i * (width / 4.0) + RADIUS, height + RADIUS); | 247 i * (width / 4.0) + CP_RADIUS, height + CP_RADIUS); |
242 } | 248 } |
243 | 249 |
244 #if 1 | 250 #if 1 |
245 /* Draw the spline/curve itself */ | 251 /* Draw the spline/curve itself */ |
246 p0 = curve->ctlpoints; | 252 p0 = curve->ctlpoints; |
248 p2 = p1; p2++; | 254 p2 = p1; p2++; |
249 p3 = p2; p3++; | 255 p3 = p2; p3++; |
250 | 256 |
251 /* Draw each curve segment */ | 257 /* Draw each curve segment */ |
252 if (curve->nctlpoints > 5) | 258 if (curve->nctlpoints > 5) |
253 for (i = 0; i < curve->nctlpoints; i++, ++p0, ++p1, ++p2, ++p3) { | 259 for (i = 0; i < curve->nctlpoints; i++, ++p0, ++p1, ++p2, ++p3) |
260 { | |
254 gint n; | 261 gint n; |
255 gfloat k1, k2, a, b, c, d, x; | 262 gfloat k1, k2, a, b, c, d, x; |
256 | 263 |
257 if (p1->x == p2->x) | 264 if (p1->x == p2->x) |
258 continue; | 265 continue; |
259 | 266 |
260 if (p0->x == p1->x && p2->x == p3->x) { | 267 if (p0->x == p1->x && p2->x == p3->x) |
268 { | |
261 k1 = k2 = (p2->y - p1->y) / (p2->x - p1->x); | 269 k1 = k2 = (p2->y - p1->y) / (p2->x - p1->x); |
262 } else if (p0->x == p1->x) { | 270 } |
271 else if (p0->x == p1->x) | |
272 { | |
263 k2 = (p3->y - p1->y) / (p3->x - p1->x); | 273 k2 = (p3->y - p1->y) / (p3->x - p1->x); |
264 k1 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k2) / 2; | 274 k1 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k2) / 2; |
265 } else if (p2->x == p3->x) { | 275 } |
276 else if (p2->x == p3->x) | |
277 { | |
266 k1 = (p2->y - p0->y) / (p2->x - p0->x); | 278 k1 = (p2->y - p0->y) / (p2->x - p0->x); |
267 k2 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k1) / 2; | 279 k2 = (3 * (p2->y - p1->y) / (p2->x - p1->x) - k1) / 2; |
268 } else { | 280 } |
281 else | |
282 { | |
269 k1 = (p2->y - p0->y) / (p2->x - p0->x); | 283 k1 = (p2->y - p0->y) / (p2->x - p0->x); |
270 k2 = (p3->y - p1->y) / (p3->x - p1->x); | 284 k2 = (p3->y - p1->y) / (p3->x - p1->x); |
271 } | 285 } |
272 | 286 |
273 xs_cubic_coeff(p1->x, p1->y, p2->x, p2->y, k1, k2, &a, &b, &c, &d); | 287 xs_cubic_coeff(p1->x, p1->y, p2->x, p2->y, k1, k2, &a, &b, &c, &d); |
274 | 288 |
275 for (x = p1->x; x <= p2->x; x += res, n++) { | 289 for (x = p1->x; x <= p2->x; x += res, n++) |
290 { | |
276 gfloat y = ((a * x + b) * x + c) * x + d; | 291 gfloat y = ((a * x + b) * x + c) * x + d; |
277 gint qx, qy; | 292 gint qx, qy; |
278 qx = RADIUS + xs_project(x, curve->min_x, curve->max_x, width); | 293 qx = CP_RADIUS + xs_project(x, curve->min_x, curve->max_x, width); |
279 qy = RADIUS + xs_project(y, curve->min_y, curve->max_y, height); | 294 qy = CP_RADIUS + xs_project(y, curve->min_y, curve->max_y, height); |
280 | 295 |
281 if (ox != -1) { | 296 if (ox != -1) |
297 { | |
282 gdk_draw_line(curve->pixmap, style->fg_gc[state], | 298 gdk_draw_line(curve->pixmap, style->fg_gc[state], |
283 ox, oy, qx, qy); | 299 ox, oy, qx, qy); |
284 } | 300 } |
285 ox = qx; oy = qy; | 301 ox = qx; oy = qy; |
286 } | 302 } |
287 } | 303 } |
288 | 304 |
289 #endif | 305 #endif |
290 | 306 |
291 /* Draw control points */ | 307 /* Draw control points */ |
292 for (i = 0; i < curve->nctlpoints; ++i) { | 308 for (i = 0; i < curve->nctlpoints; ++i) |
309 { | |
293 gint x, y; | 310 gint x, y; |
294 GtkStateType cstate; | 311 GtkStateType cstate; |
295 | 312 |
296 if (GET_X(i) < curve->min_x || GET_Y(i) < curve->min_y || | 313 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) | 314 GET_X(i) >= curve->max_x || GET_Y(i) >= curve->max_y) |
298 continue; | 315 continue; |
299 | 316 |
300 x = xs_project(GET_X(i), curve->min_x, curve->max_x, width); | 317 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); | 318 y = xs_project(GET_Y(i), curve->min_y, curve->max_y, height); |
302 | 319 |
303 if (i == curve->grab_point) { | 320 if (i == curve->grab_point) |
321 { | |
304 cstate = GTK_STATE_SELECTED; | 322 cstate = GTK_STATE_SELECTED; |
305 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], | 323 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], |
306 x + RADIUS, RADIUS, x + RADIUS, height + RADIUS); | 324 x + CP_RADIUS, CP_RADIUS, x + CP_RADIUS, height + CP_RADIUS); |
307 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], | 325 gdk_draw_line(curve->pixmap, style->fg_gc[cstate], |
308 RADIUS, y + RADIUS, width + RADIUS, y + RADIUS); | 326 CP_RADIUS, y + CP_RADIUS, width + CP_RADIUS, y + CP_RADIUS); |
309 } else | 327 } else |
310 cstate = state; | 328 cstate = state; |
311 | 329 |
312 gdk_draw_arc(curve->pixmap, style->fg_gc[cstate], TRUE, | 330 gdk_draw_arc(curve->pixmap, style->fg_gc[cstate], TRUE, |
313 x, y, RADIUS2, RADIUS2, 0, 360 * 64); | 331 x, y, CP_RADIUS2, CP_RADIUS2, 0, 360 * 64); |
314 } | 332 } |
315 | 333 |
316 /* Draw pixmap in the widget */ | 334 /* Draw pixmap in the widget */ |
317 gdk_draw_pixmap(GTK_WIDGET(curve)->window, | 335 gdk_draw_pixmap(GTK_WIDGET(curve)->window, |
318 style->fg_gc[state], curve->pixmap, | 336 style->fg_gc[state], curve->pixmap, |
319 0, 0, 0, 0, | 337 0, 0, 0, 0, |
320 width + RADIUS2, | 338 width + CP_RADIUS2, |
321 height + RADIUS2); | 339 height + CP_RADIUS2); |
322 } | 340 } |
323 | 341 |
324 | 342 |
325 static gint xs_curve_graph_events(GtkWidget *widget, GdkEvent *event, XSCurve *curve) | 343 static gint xs_curve_graph_events(GtkWidget *widget, GdkEvent *event, XSCurve *curve) |
326 { | 344 { |
329 GtkWidget *w; | 347 GtkWidget *w; |
330 gint i, width, height, x, y, tx, ty, cx, closest_point = 0, min_x; | 348 gint i, width, height, x, y, tx, ty, cx, closest_point = 0, min_x; |
331 guint distance; | 349 guint distance; |
332 | 350 |
333 w = GTK_WIDGET(curve); | 351 w = GTK_WIDGET(curve); |
334 width = w->allocation.width - RADIUS2; | 352 width = w->allocation.width - CP_RADIUS2; |
335 height = w->allocation.height - RADIUS2; | 353 height = w->allocation.height - CP_RADIUS2; |
336 | 354 |
337 if ((width < 0) || (height < 0)) | 355 if ((width < 0) || (height < 0)) |
338 return FALSE; | 356 return FALSE; |
339 | 357 |
340 /* get the pointer position */ | 358 /* get the pointer position */ |
341 gdk_window_get_pointer(w->window, &tx, &ty, NULL); | 359 gdk_window_get_pointer(w->window, &tx, &ty, NULL); |
342 x = CLAMP((tx - RADIUS), 0, width - 1); | 360 x = CLAMP((tx - CP_RADIUS), 0, width - 1); |
343 y = CLAMP((ty - RADIUS), 0, height - 1); | 361 y = CLAMP((ty - CP_RADIUS), 0, height - 1); |
344 min_x = curve->min_x; | 362 min_x = curve->min_x; |
345 | 363 |
346 distance = ~0U; | 364 distance = ~0U; |
347 for (i = 0; i < curve->nctlpoints; ++i) { | 365 for (i = 0; i < curve->nctlpoints; ++i) |
366 { | |
348 cx = xs_project(GET_X(i), min_x, curve->max_x, width); | 367 cx = xs_project(GET_X(i), min_x, curve->max_x, width); |
349 if ((guint) abs(x - cx) < distance) { | 368 if ((guint) abs(x - cx) < distance) |
369 { | |
350 distance = abs(x - cx); | 370 distance = abs(x - cx); |
351 closest_point = i; | 371 closest_point = i; |
352 } | 372 } |
353 } | 373 } |
354 | 374 |
355 /* Act based on event type */ | 375 /* Act based on event type */ |
356 switch (event->type) { | 376 switch (event->type) |
357 case GDK_CONFIGURE: | 377 { |
358 if (curve->pixmap) | 378 case GDK_CONFIGURE: |
359 gdk_pixmap_unref(curve->pixmap); | 379 if (curve->pixmap) |
360 curve->pixmap = 0; | 380 gdk_pixmap_unref(curve->pixmap); |
361 | 381 curve->pixmap = 0; |
362 /* fall through */ | 382 |
363 | 383 /* fall through */ |
364 case GDK_EXPOSE: | 384 |
365 if (!curve->pixmap) { | 385 case GDK_EXPOSE: |
366 curve->pixmap = gdk_pixmap_new(w->window, | 386 if (!curve->pixmap) |
367 w->allocation.width, w->allocation.height, -1); | 387 { |
368 } | 388 curve->pixmap = gdk_pixmap_new(w->window, |
369 xs_curve_draw(curve, width, height); | 389 w->allocation.width, w->allocation.height, -1); |
370 break; | 390 } |
371 | 391 xs_curve_draw(curve, width, height); |
372 case GDK_BUTTON_PRESS: | 392 break; |
373 gtk_grab_add(widget); | 393 |
374 | 394 case GDK_BUTTON_PRESS: |
375 bevent = (GdkEventButton *) event; | 395 gtk_grab_add(widget); |
376 new_type = GDK_TCROSS; | 396 |
377 | 397 bevent = (GdkEventButton *) event; |
378 if (distance > MIN_DISTANCE) { | 398 new_type = GDK_TCROSS; |
379 /* insert a new control point */ | 399 |
380 if (curve->nctlpoints > 0) { | 400 if (distance > CP_MIN_DISTANCE) |
381 cx = xs_project(GET_X(closest_point), min_x, curve->max_x, width); | 401 { |
382 if (x > cx) closest_point++; | 402 /* insert a new control point */ |
403 if (curve->nctlpoints > 0) | |
404 { | |
405 cx = xs_project(GET_X(closest_point), min_x, curve->max_x, width); | |
406 if (x > cx) closest_point++; | |
407 } | |
408 | |
409 curve->nctlpoints++; | |
410 | |
411 curve->ctlpoints = g_realloc(curve->ctlpoints, | |
412 curve->nctlpoints * sizeof(*curve->ctlpoints)); | |
413 | |
414 for (i = curve->nctlpoints - 1; i > closest_point; --i) | |
415 { | |
416 memcpy(curve->ctlpoints + i, | |
417 curve->ctlpoints + i - 1, | |
418 sizeof(*curve->ctlpoints)); | |
419 } | |
383 } | 420 } |
384 | 421 |
385 curve->nctlpoints++; | 422 curve->grab_point = closest_point; |
423 GET_X(curve->grab_point) = xs_unproject(x, min_x, curve->max_x, width); | |
424 GET_Y(curve->grab_point) = xs_unproject(y, curve->min_y, curve->max_y, height); | |
425 | |
426 xs_curve_draw(curve, width, height); | |
427 break; | |
428 | |
429 case GDK_BUTTON_RELEASE: | |
430 { | |
431 gint src, dst; | |
386 | 432 |
387 curve->ctlpoints = g_realloc(curve->ctlpoints, | 433 gtk_grab_remove(widget); |
388 curve->nctlpoints * sizeof(*curve->ctlpoints)); | 434 |
435 /* delete inactive points: */ | |
436 for (src = dst = 0; src < curve->nctlpoints; ++src) | |
437 { | |
438 if (GET_X(src) >= min_x) | |
439 { | |
440 memcpy(curve->ctlpoints + dst, | |
441 curve->ctlpoints + src, | |
442 sizeof(*curve->ctlpoints)); | |
443 dst++; | |
444 } | |
445 } | |
446 | |
447 if (dst < src) | |
448 { | |
449 curve->nctlpoints -= (src - dst); | |
450 if (curve->nctlpoints <= 0) | |
451 { | |
452 curve->nctlpoints = 1; | |
453 GET_X(0) = min_x; | |
454 GET_Y(0) = curve->min_y; | |
455 xs_curve_draw(curve, width, height); | |
456 } | |
457 curve->ctlpoints = g_realloc(curve->ctlpoints, | |
458 curve->nctlpoints * sizeof(*curve->ctlpoints)); | |
459 } | |
460 | |
461 new_type = GDK_FLEUR; | |
462 curve->grab_point = -1; | |
463 } | |
464 xs_curve_draw(curve, width, height); | |
465 break; | |
466 | |
467 case GDK_MOTION_NOTIFY: | |
468 if (curve->grab_point == -1) | |
469 { | |
470 /* if no point is grabbed... */ | |
471 if (distance <= CP_MIN_DISTANCE) | |
472 new_type = GDK_FLEUR; | |
473 else | |
474 new_type = GDK_TCROSS; | |
475 } else { | |
476 gint leftbound, rightbound; | |
477 | |
478 /* drag the grabbed point */ | |
479 new_type = GDK_TCROSS; | |
480 | |
481 leftbound = -CP_MIN_DISTANCE; | |
482 if (curve->grab_point > 0) | |
483 { | |
484 leftbound = xs_project( | |
485 GET_X(curve->grab_point-1), | |
486 min_x, curve->max_x, width); | |
487 } | |
488 | |
489 rightbound = width + CP_RADIUS2 + CP_MIN_DISTANCE; | |
490 if (curve->grab_point + 1 < curve->nctlpoints) | |
491 { | |
492 rightbound = xs_project( | |
493 GET_X(curve->grab_point+1), | |
494 min_x, curve->max_x, width); | |
495 } | |
496 | |
497 if ((tx <= leftbound) || (tx >= rightbound) || | |
498 (ty > height + CP_RADIUS2 + CP_MIN_DISTANCE) || (ty < -CP_MIN_DISTANCE)) { | |
499 GET_X(curve->grab_point) = min_x - 1.0; | |
500 } | |
501 else | |
502 { | |
503 GET_X(curve->grab_point) = | |
504 xs_unproject(x, min_x, curve->max_x, width); | |
505 GET_Y(curve->grab_point) = | |
506 xs_unproject(y, curve->min_y, curve->max_y, height); | |
507 } | |
508 | |
509 xs_curve_draw(curve, width, height); | |
510 } | |
389 | 511 |
390 for (i = curve->nctlpoints - 1; i > closest_point; --i) { | 512 /* See if cursor type was changed and update accordingly */ |
391 memcpy(curve->ctlpoints + i, | 513 if (new_type != (GdkCursorType) curve->cursor_type) |
392 curve->ctlpoints + i - 1, | 514 { |
393 sizeof(*curve->ctlpoints)); | 515 GdkCursor *cursor; |
394 } | 516 curve->cursor_type = new_type; |
395 } | 517 cursor = gdk_cursor_new(curve->cursor_type); |
396 | 518 gdk_window_set_cursor(w->window, cursor); |
397 curve->grab_point = closest_point; | 519 gdk_cursor_destroy(cursor); |
398 GET_X(curve->grab_point) = xs_unproject(x, min_x, curve->max_x, width); | 520 } |
399 GET_Y(curve->grab_point) = xs_unproject(y, curve->min_y, curve->max_y, height); | 521 break; |
400 | 522 |
401 xs_curve_draw(curve, width, height); | 523 default: |
402 break; | 524 break; |
403 | |
404 case GDK_BUTTON_RELEASE: | |
405 { | |
406 gint src, dst; | |
407 | |
408 gtk_grab_remove(widget); | |
409 | |
410 /* delete inactive points: */ | |
411 for (src = dst = 0; src < curve->nctlpoints; ++src) { | |
412 if (GET_X(src) >= min_x) { | |
413 memcpy(curve->ctlpoints + dst, | |
414 curve->ctlpoints + src, | |
415 sizeof(*curve->ctlpoints)); | |
416 dst++; | |
417 } | |
418 } | |
419 | |
420 if (dst < src) { | |
421 curve->nctlpoints -= (src - dst); | |
422 if (curve->nctlpoints <= 0) { | |
423 curve->nctlpoints = 1; | |
424 GET_X(0) = min_x; | |
425 GET_Y(0) = curve->min_y; | |
426 xs_curve_draw(curve, width, height); | |
427 } | |
428 curve->ctlpoints = g_realloc(curve->ctlpoints, | |
429 curve->nctlpoints * sizeof(*curve->ctlpoints)); | |
430 } | |
431 | |
432 new_type = GDK_FLEUR; | |
433 curve->grab_point = -1; | |
434 } | |
435 xs_curve_draw(curve, width, height); | |
436 break; | |
437 | |
438 case GDK_MOTION_NOTIFY: | |
439 if (curve->grab_point == -1) { | |
440 /* if no point is grabbed... */ | |
441 if (distance <= MIN_DISTANCE) | |
442 new_type = GDK_FLEUR; | |
443 else | |
444 new_type = GDK_TCROSS; | |
445 } else { | |
446 gint leftbound, rightbound; | |
447 | |
448 /* drag the grabbed point */ | |
449 new_type = GDK_TCROSS; | |
450 | |
451 leftbound = -MIN_DISTANCE; | |
452 if (curve->grab_point > 0) { | |
453 leftbound = xs_project( | |
454 GET_X(curve->grab_point-1), | |
455 min_x, curve->max_x, width); | |
456 } | |
457 | |
458 rightbound = width + RADIUS2 + MIN_DISTANCE; | |
459 if (curve->grab_point + 1 < curve->nctlpoints) { | |
460 rightbound = xs_project( | |
461 GET_X(curve->grab_point+1), | |
462 min_x, curve->max_x, width); | |
463 } | |
464 | |
465 if ((tx <= leftbound) || (tx >= rightbound) || | |
466 (ty > height + RADIUS2 + MIN_DISTANCE) || (ty < -MIN_DISTANCE)) { | |
467 GET_X(curve->grab_point) = min_x - 1.0; | |
468 } else { | |
469 GET_X(curve->grab_point) = | |
470 xs_unproject(x, min_x, curve->max_x, width); | |
471 GET_Y(curve->grab_point) = | |
472 xs_unproject(y, curve->min_y, curve->max_y, height); | |
473 } | |
474 | |
475 xs_curve_draw(curve, width, height); | |
476 } | |
477 | |
478 /* See if cursor type was changed and update accordingly */ | |
479 if (new_type != (GdkCursorType) curve->cursor_type) { | |
480 GdkCursor *cursor; | |
481 curve->cursor_type = new_type; | |
482 cursor = gdk_cursor_new(curve->cursor_type); | |
483 gdk_window_set_cursor(w->window, cursor); | |
484 gdk_cursor_destroy(cursor); | |
485 } | |
486 break; | |
487 | |
488 default: | |
489 break; | |
490 } | 525 } |
491 | 526 |
492 return FALSE; | 527 return FALSE; |
493 } | 528 } |
494 | 529 |
511 if (aspect < 1.0) | 546 if (aspect < 1.0) |
512 width = height * aspect; | 547 width = height * aspect; |
513 else | 548 else |
514 height = width / aspect; | 549 height = width / aspect; |
515 | 550 |
516 gtk_drawing_area_size(GTK_DRAWING_AREA(curve), width + RADIUS2, height + RADIUS2); | 551 gtk_drawing_area_size(GTK_DRAWING_AREA(curve), width + CP_RADIUS2, height + CP_RADIUS2); |
517 } | 552 } |
518 | 553 |
519 | 554 |
520 static void xs_curve_update(XSCurve *curve) | 555 static void xs_curve_update(XSCurve *curve) |
521 { | 556 { |
522 if (curve->pixmap) { | 557 if (curve->pixmap) |
558 { | |
523 gint width, height; | 559 gint width, height; |
524 | 560 |
525 width = GTK_WIDGET(curve)->allocation.width - RADIUS2; | 561 width = GTK_WIDGET(curve)->allocation.width - CP_RADIUS2; |
526 height = GTK_WIDGET(curve)->allocation.height - RADIUS2; | 562 height = GTK_WIDGET(curve)->allocation.height - CP_RADIUS2; |
527 xs_curve_draw(curve, width, height); | 563 xs_curve_draw(curve, width, height); |
528 } | 564 } |
529 } | 565 } |
530 | 566 |
531 | 567 |
564 } | 600 } |
565 | 601 |
566 | 602 |
567 gboolean xs_curve_realloc_data(XSCurve *curve, gint npoints) | 603 gboolean xs_curve_realloc_data(XSCurve *curve, gint npoints) |
568 { | 604 { |
569 if (npoints != curve->nctlpoints) { | 605 if (npoints != curve->nctlpoints) |
606 { | |
570 curve->nctlpoints = npoints; | 607 curve->nctlpoints = npoints; |
571 curve->ctlpoints = (xs_point_t *) g_realloc(curve->ctlpoints, | 608 curve->ctlpoints = (xs_point_t *) g_realloc(curve->ctlpoints, |
572 curve->nctlpoints * sizeof(*curve->ctlpoints)); | 609 curve->nctlpoints * sizeof(*curve->ctlpoints)); |
573 | 610 |
574 if (curve->ctlpoints == NULL) | 611 if (curve->ctlpoints == NULL) |
596 GET_X(0) = curve->min_x; | 633 GET_X(0) = curve->min_x; |
597 GET_Y(0) = curve->min_y; | 634 GET_Y(0) = curve->min_y; |
598 GET_X(1) = curve->min_x; | 635 GET_X(1) = curve->min_x; |
599 GET_Y(1) = curve->min_y; | 636 GET_Y(1) = curve->min_y; |
600 | 637 |
601 for (i = 0; i < npoints; i++) { | 638 for (i = 0; i < npoints; i++) |
639 { | |
602 GET_X(i+2) = points[i].x; | 640 GET_X(i+2) = points[i].x; |
603 GET_Y(i+2) = points[i].y; | 641 GET_Y(i+2) = points[i].y; |
604 } | 642 } |
605 | 643 |
606 GET_X(npoints+2) = curve->max_x; | 644 GET_X(npoints+2) = curve->max_x; |
622 *points = g_malloc(n * sizeof(xs_int_point_t)); | 660 *points = g_malloc(n * sizeof(xs_int_point_t)); |
623 if (*points == NULL) | 661 if (*points == NULL) |
624 return FALSE; | 662 return FALSE; |
625 | 663 |
626 *npoints = n; | 664 *npoints = n; |
627 for (i = 2; i < curve->nctlpoints - 2; i++) { | 665 for (i = 2; i < curve->nctlpoints - 2; i++) |
666 { | |
628 (*points)[i].x = GET_X(i); | 667 (*points)[i].x = GET_X(i); |
629 (*points)[i].y = GET_Y(i); | 668 (*points)[i].y = GET_Y(i); |
630 } | 669 } |
631 | 670 |
632 return TRUE; | 671 return TRUE; |