Code

BUG 322116, PDF export does not use the highest quality for rasterized filter
[inkscape.git] / src / knot.cpp
1 #define __SP_KNOT_C__
3 /** \file
4  * SPKnot implementation
5  *
6  * Authors:
7  *   Lauris Kaplinski <lauris@kaplinski.com>
8  *   bulia byak <buliabyak@users.sf.net>
9  *
10  * Copyright (C) 1999-2005 authors
11  * Copyright (C) 2001-2002 Ximian, Inc.
12  *
13  * Released under GNU GPL, read the file 'COPYING' for more information
14  */
16 #ifdef HAVE_CONFIG_H
17 # include <config.h>
18 #endif
19 #include <gdk/gdkkeysyms.h>
20 #include <glibmm/i18n.h>
21 #include "helper/sp-marshal.h"
22 #include "display/sodipodi-ctrl.h"
23 #include "desktop.h"
24 #include "desktop-handles.h"
25 #include "knot.h"
26 #include "document.h"
27 #include "preferences.h"
28 #include "message-stack.h"
29 #include "message-context.h"
30 #include "event-context.h"
32 #define KNOT_EVENT_MASK (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | \
33                          GDK_POINTER_MOTION_MASK | \
34                          GDK_POINTER_MOTION_HINT_MASK | \
35                          GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK)
37 static bool nograb = false;
39 static bool grabbed = FALSE;
40 static bool moved = FALSE;
42 static gint xp = 0, yp = 0; // where drag started
43 static gint tolerance = 0;
44 static bool within_tolerance = false;
46 static bool transform_escaped = false; // true iff resize or rotate was cancelled by esc.
48 enum {
49     EVENT,
50     CLICKED,
51     DOUBLECLICKED,
52     GRABBED,
53     UNGRABBED,
54     MOVED,
55     REQUEST,
56     DISTANCE,
57     LAST_SIGNAL
58 };
60 static void sp_knot_class_init(SPKnotClass *klass);
61 static void sp_knot_init(SPKnot *knot);
62 static void sp_knot_dispose(GObject *object);
64 static int sp_knot_handler(SPCanvasItem *item, GdkEvent *event, SPKnot *knot);
65 static void sp_knot_set_ctrl_state(SPKnot *knot);
67 static GObjectClass *parent_class;
68 static guint knot_signals[LAST_SIGNAL] = { 0 };
70 /**
71  * Registers SPKnot class and returns its type number.
72  */
73 GType sp_knot_get_type()
74 {
75     static GType type = 0;
76     if (!type) {
77         GTypeInfo info = {
78             sizeof(SPKnotClass),
79             NULL,       /* base_init */
80             NULL,       /* base_finalize */
81             (GClassInitFunc) sp_knot_class_init,
82             NULL,       /* class_finalize */
83             NULL,       /* class_data */
84             sizeof (SPKnot),
85             16, /* n_preallocs */
86             (GInstanceInitFunc) sp_knot_init,
87             NULL
88         };
89         type = g_type_register_static (G_TYPE_OBJECT, "SPKnot", &info, (GTypeFlags) 0);
90     }
91     return type;
92 }
94 /**
95  * SPKnot vtable initialization.
96  */
97 static void sp_knot_class_init(SPKnotClass *klass)
98 {
99     GObjectClass *object_class = (GObjectClass*)klass;
101     parent_class = (GObjectClass*) g_type_class_peek_parent(klass);
103     object_class->dispose = sp_knot_dispose;
105     knot_signals[EVENT] = g_signal_new("event",
106                                        G_TYPE_FROM_CLASS(klass),
107                                        G_SIGNAL_RUN_LAST,
108                                        G_STRUCT_OFFSET(SPKnotClass, event),
109                                        NULL, NULL,
110                                        sp_marshal_BOOLEAN__POINTER,
111                                        G_TYPE_BOOLEAN, 1,
112                                        GDK_TYPE_EVENT);
114     knot_signals[CLICKED] = g_signal_new("clicked",
115                                          G_TYPE_FROM_CLASS(klass),
116                                          G_SIGNAL_RUN_FIRST,
117                                          G_STRUCT_OFFSET(SPKnotClass, clicked),
118                                          NULL, NULL,
119                                          sp_marshal_NONE__UINT,
120                                          G_TYPE_NONE, 1,
121                                          G_TYPE_UINT);
123     knot_signals[DOUBLECLICKED] = g_signal_new("doubleclicked",
124                                                G_TYPE_FROM_CLASS(klass),
125                                                G_SIGNAL_RUN_FIRST,
126                                                G_STRUCT_OFFSET(SPKnotClass, doubleclicked),
127                                                NULL, NULL,
128                                                sp_marshal_NONE__UINT,
129                                                G_TYPE_NONE, 1,
130                                                G_TYPE_UINT);
132     knot_signals[GRABBED] = g_signal_new("grabbed",
133                                           G_TYPE_FROM_CLASS(klass),
134                                           G_SIGNAL_RUN_FIRST,
135                                           G_STRUCT_OFFSET(SPKnotClass, grabbed),
136                                           NULL, NULL,
137                                           sp_marshal_NONE__UINT,
138                                           G_TYPE_NONE, 1,
139                                           G_TYPE_UINT);
141     knot_signals[UNGRABBED] = g_signal_new("ungrabbed",
142                                             G_TYPE_FROM_CLASS(klass),
143                                             G_SIGNAL_RUN_FIRST,
144                                             G_STRUCT_OFFSET(SPKnotClass, ungrabbed),
145                                             NULL, NULL,
146                                             sp_marshal_NONE__UINT,
147                                             G_TYPE_NONE, 1,
148                                             G_TYPE_UINT);
150     knot_signals[MOVED] = g_signal_new("moved",
151                                         G_TYPE_FROM_CLASS(klass),
152                                         G_SIGNAL_RUN_FIRST,
153                                         G_STRUCT_OFFSET(SPKnotClass, moved),
154                                         NULL, NULL,
155                                         sp_marshal_NONE__POINTER_UINT,
156                                         G_TYPE_NONE, 2,
157                                         G_TYPE_POINTER, G_TYPE_UINT);
159     knot_signals[REQUEST] = g_signal_new("request",
160                                          G_TYPE_FROM_CLASS(klass),
161                                          G_SIGNAL_RUN_LAST,
162                                          G_STRUCT_OFFSET(SPKnotClass, request),
163                                          NULL, NULL,
164                                          sp_marshal_BOOLEAN__POINTER_UINT,
165                                          G_TYPE_BOOLEAN, 2,
166                                          G_TYPE_POINTER, G_TYPE_UINT);
168     knot_signals[DISTANCE] = g_signal_new("distance",
169                                            G_TYPE_FROM_CLASS(klass),
170                                            G_SIGNAL_RUN_LAST,
171                                            G_STRUCT_OFFSET(SPKnotClass, distance),
172                                            NULL, NULL,
173                                            sp_marshal_DOUBLE__POINTER_UINT,
174                                            G_TYPE_DOUBLE, 2,
175                                            G_TYPE_POINTER, G_TYPE_UINT);
177     const gchar *nograbenv = getenv("INKSCAPE_NO_GRAB");
178     nograb = (nograbenv && *nograbenv && (*nograbenv != '0'));
181 /**
182  * Callback for SPKnot initialization.
183  */
184 static void sp_knot_init(SPKnot *knot)
186     knot->desktop = NULL;
187     knot->item = NULL;
188     knot->flags = 0;
190     knot->size = 8;
191     knot->pos = Geom::Point(0, 0);
192     knot->grabbed_rel_pos = Geom::Point(0, 0);
193     knot->anchor = GTK_ANCHOR_CENTER;
194     knot->shape = SP_KNOT_SHAPE_SQUARE;
195     knot->mode = SP_KNOT_MODE_XOR;
196     knot->tip = NULL;
197     knot->_event_handler_id = 0;
198     knot->pressure = 0;
200     knot->fill[SP_KNOT_STATE_NORMAL] = 0xffffff00;
201     knot->fill[SP_KNOT_STATE_MOUSEOVER] = 0xff0000ff;
202     knot->fill[SP_KNOT_STATE_DRAGGING] = 0x0000ffff;
204     knot->stroke[SP_KNOT_STATE_NORMAL] = 0x01000000;
205     knot->stroke[SP_KNOT_STATE_MOUSEOVER] = 0x01000000;
206     knot->stroke[SP_KNOT_STATE_DRAGGING] = 0x01000000;
208     knot->image[SP_KNOT_STATE_NORMAL] = NULL;
209     knot->image[SP_KNOT_STATE_MOUSEOVER] = NULL;
210     knot->image[SP_KNOT_STATE_DRAGGING] = NULL;
212     knot->cursor[SP_KNOT_STATE_NORMAL] = NULL;
213     knot->cursor[SP_KNOT_STATE_MOUSEOVER] = NULL;
214     knot->cursor[SP_KNOT_STATE_DRAGGING] = NULL;
216     knot->saved_cursor = NULL;
217     knot->pixbuf = NULL;
220 /**
221  * Called before SPKnot destruction.
222  */
223 static void sp_knot_dispose(GObject *object)
225     SPKnot *knot = (SPKnot *) object;
227     if ((knot->flags & SP_KNOT_GRABBED) && gdk_pointer_is_grabbed ()) {
228         // This happens e.g. when deleting a node in node tool while dragging it
229         gdk_pointer_ungrab (GDK_CURRENT_TIME);
230     }
232     if (knot->_event_handler_id > 0)
233         {
234         g_signal_handler_disconnect(G_OBJECT (knot->item), knot->_event_handler_id);
235         knot->_event_handler_id = 0;
236         }
238     if (knot->item) {
239         gtk_object_destroy (GTK_OBJECT (knot->item));
240         knot->item = NULL;
241     }
243     for (gint i = 0; i < SP_KNOT_VISIBLE_STATES; i++) {
244         if (knot->cursor[i]) {
245             gdk_cursor_unref(knot->cursor[i]);
246             knot->cursor[i] = NULL;
247         }
248     }
250     if (knot->tip) {
251         g_free(knot->tip);
252         knot->tip = NULL;
253     }
255     if (parent_class->dispose) {
256         (*parent_class->dispose) (object);
257     }
260 /**
261  * Update knot for dragging and tell canvas an item was grabbed.
262  */
263 void sp_knot_start_dragging(SPKnot *knot, Geom::Point const &p, gint x, gint y, guint32 etime)
265     // save drag origin
266     xp = x;
267     yp = y;
268     within_tolerance = true;
270     knot->grabbed_rel_pos = p - knot->pos;
271     knot->drag_origin = knot->pos;
272     if (!nograb) {
273         sp_canvas_item_grab(knot->item,
274                             KNOT_EVENT_MASK,
275                             knot->cursor[SP_KNOT_STATE_DRAGGING],
276                             etime);
277     }
278     sp_knot_set_flag(knot, SP_KNOT_GRABBED, TRUE);
279     grabbed = TRUE;
282 /**
283  * Called to handle events on knots.
284  */
285 static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot)
287         static bool snap_delay_temporarily_active = false;
289         g_assert(knot != NULL);
290     g_assert(SP_IS_KNOT(knot));
292     /* Run client universal event handler, if present */
294     gboolean consumed = FALSE;
296     g_signal_emit(knot, knot_signals[EVENT], 0, event, &consumed);
298     if (consumed) {
299         return TRUE;
300     }
302     g_object_ref(knot);
303     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
304     tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
306     switch (event->type) {
307         case GDK_2BUTTON_PRESS:
308             if (event->button.button == 1) {
309                 g_signal_emit(knot, knot_signals[DOUBLECLICKED], 0, event->button.state);
311                 grabbed = FALSE;
312                 moved = FALSE;
313                 consumed = TRUE;
314             }
315             break;
316         case GDK_BUTTON_PRESS:
317             if (event->button.button == 1 && !knot->desktop->event_context->space_panning) {
318                 Geom::Point const p = knot->desktop->w2d(Geom::Point(event->button.x, event->button.y));
319                 sp_knot_start_dragging(knot, p, (gint) event->button.x, (gint) event->button.y, event->button.time);
320                 if (knot->desktop->event_context->_snap_window_open == false) {
321                                         sp_event_context_snap_window_open(knot->desktop->event_context);
322                                         snap_delay_temporarily_active = true;
323                                 }
324                 consumed = TRUE;
325             }
326             break;
327         case GDK_BUTTON_RELEASE:
328                         if (event->button.button == 1 && !knot->desktop->event_context->space_panning) {
329                                 // If we have any pending snap event, then invoke it now
330                                 if (knot->desktop->event_context->_delayed_snap_event) {
331                                         sp_event_context_snap_watchdog_callback(knot->desktop->event_context->_delayed_snap_event);
332                                 }
334                                 // now we can safely close the snapping window
335                                 if (snap_delay_temporarily_active) {
336                         if (knot->desktop->event_context->_snap_window_open == true) {
337                                 sp_event_context_snap_window_closed(knot->desktop->event_context);
338                         }
339                                         snap_delay_temporarily_active = false;
340                                 }
342                 knot->pressure = 0;
343                 if (transform_escaped) {
344                     transform_escaped = false;
345                     consumed = TRUE;
346                 } else {
347                     sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
348                     if (!nograb) {
349                         sp_canvas_item_ungrab(knot->item, event->button.time);
350                     }
351                     if (moved) {
352                         sp_knot_set_flag(knot,
353                                          SP_KNOT_DRAGGING,
354                                          FALSE);
355                         g_signal_emit(knot,
356                                       knot_signals[UNGRABBED], 0,
357                                       event->button.state);
358                         knot->_ungrabbed_signal.emit(knot);
359                     } else {
360                         g_signal_emit(knot,
361                                       knot_signals[CLICKED], 0,
362                                       event->button.state);
363                         knot->_click_signal.emit(knot, event->button.state);
364                     }
365                     grabbed = FALSE;
366                     moved = FALSE;
367                     consumed = TRUE;
368                 }
369             }
370             break;
371         case GDK_MOTION_NOTIFY:
372             if (grabbed && !knot->desktop->event_context->space_panning) {
373                 consumed = TRUE;
375                 if ( within_tolerance
376                      && ( abs( (gint) event->motion.x - xp ) < tolerance )
377                      && ( abs( (gint) event->motion.y - yp ) < tolerance ) ) {
378                     break; // do not drag if we're within tolerance from origin
379                 }
381                 // Once the user has moved farther than tolerance from the original location
382                 // (indicating they intend to move the object, not click), then always process the
383                 // motion notify coordinates as given (no snapping back to origin)
384                 within_tolerance = false;
386                 if (gdk_event_get_axis (event, GDK_AXIS_PRESSURE, &knot->pressure))
387                     knot->pressure = CLAMP (knot->pressure, 0, 1);
388                 else
389                     knot->pressure = 0.5;
391                 if (!moved) {
392                     g_signal_emit(knot,
393                                   knot_signals[GRABBED], 0,
394                                   event->motion.state);
395                     sp_knot_set_flag(knot,
396                                      SP_KNOT_DRAGGING,
397                                      TRUE);
398                 }
399                 sp_event_context_snap_delay_handler(knot->desktop->event_context, NULL, knot, (GdkEventMotion *)event, DelayedSnapEvent::KNOT_HANDLER);
400                 sp_knot_handler_request_position(event, knot);
401                 moved = TRUE;
402             }
403             break;
404         case GDK_ENTER_NOTIFY:
405             sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, TRUE);
406             sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
408             if (knot->tip) {
409                 knot->desktop->event_context->defaultMessageContext()->set(Inkscape::NORMAL_MESSAGE, knot->tip);
410             }
412             grabbed = FALSE;
413             moved = FALSE;
414             consumed = TRUE;
415             break;
416         case GDK_LEAVE_NOTIFY:
417             sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, FALSE);
418             sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
420             if (knot->tip) {
421                 knot->desktop->event_context->defaultMessageContext()->clear();
422             }
424             grabbed = FALSE;
425             moved = FALSE;
426             consumed = TRUE;
427             break;
428         case GDK_KEY_PRESS: // keybindings for knot
429             switch (get_group0_keyval(&event->key)) {
430                                 case GDK_Escape:
431                                                         sp_knot_set_flag(knot, SP_KNOT_GRABBED, FALSE);
432                                                         if (!nograb) {
433                                                                 sp_canvas_item_ungrab(knot->item, event->button.time);
434                                                         }
435                                                         if (moved) {
436                                                                 sp_knot_set_flag(knot,
437                                                                                                  SP_KNOT_DRAGGING,
438                                                                                                  FALSE);
439                                                                 g_signal_emit(knot,
440                                                                                           knot_signals[UNGRABBED], 0,
441                                                                                           event->button.state);
442                                                                 sp_document_undo(sp_desktop_document(knot->desktop));
443                                                                 knot->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Node or handle drag canceled."));
444                                                                 transform_escaped = true;
445                                                                 consumed = TRUE;
446                                                         }
447                                                         grabbed = FALSE;
448                                                         moved = FALSE;
449                                                         if (snap_delay_temporarily_active) {
450                                                                 sp_event_context_snap_window_closed(knot->desktop->event_context);
451                                                                 snap_delay_temporarily_active = false;
452                                                         }
453                                                         break;
454                                 default:
455                                                         consumed = FALSE;
456                                                         break;
457                                         }
458                                         break;
459         default:
460             break;
461     }
463     g_object_unref(knot);
465     return consumed;
468 void sp_knot_handler_request_position(GdkEvent *event, SPKnot *knot)
470         Geom::Point const motion_w(event->motion.x, event->motion.y);
471         Geom::Point const motion_dt = knot->desktop->w2d(motion_w);
472         Geom::Point p = motion_dt - knot->grabbed_rel_pos;
473         sp_knot_request_position (knot, p, event->motion.state);
474         knot->desktop->scroll_to_point (motion_dt);
475         knot->desktop->set_coordinate_status(knot->pos); // display the coordinate of knot, not cursor - they may be different!
476         if (event->motion.state & GDK_BUTTON1_MASK)
477                 gobble_motion_events(GDK_BUTTON1_MASK);
480 /**
481  * Return new knot object.
482  */
483 SPKnot *sp_knot_new(SPDesktop *desktop, const gchar *tip)
485     g_return_val_if_fail(desktop != NULL, NULL);
487     SPKnot * knot = (SPKnot*) g_object_new(SP_TYPE_KNOT, 0);
489     knot->desktop = desktop;
490     knot->flags = SP_KNOT_VISIBLE;
491     if (tip) {
492         knot->tip = g_strdup (tip);
493     }
495     knot->item = sp_canvas_item_new(sp_desktop_controls (desktop),
496                                     SP_TYPE_CTRL,
497                                     "anchor", GTK_ANCHOR_CENTER,
498                                     "size", 8.0,
499                                     "filled", TRUE,
500                                     "fill_color", 0xffffff00,
501                                     "stroked", TRUE,
502                                     "stroke_color", 0x01000000,
503                                     "mode", SP_KNOT_MODE_XOR,
504                                     NULL);
506     knot->_event_handler_id = gtk_signal_connect(GTK_OBJECT(knot->item), "event",
507                                                  GTK_SIGNAL_FUNC(sp_knot_handler), knot);
509     return knot;
512 /**
513  * Show knot on its canvas.
514  */
515 void sp_knot_show(SPKnot *knot)
517     g_return_if_fail(knot != NULL);
518     g_return_if_fail(SP_IS_KNOT (knot));
520     sp_knot_set_flag(knot, SP_KNOT_VISIBLE, TRUE);
523 /**
524  * Hide knot on its canvas.
525  */
526 void sp_knot_hide(SPKnot *knot)
528     g_return_if_fail(knot != NULL);
529     g_return_if_fail(SP_IS_KNOT(knot));
531     sp_knot_set_flag(knot, SP_KNOT_VISIBLE, FALSE);
534 /**
535  * Request or set new position for knot.
536  */
537 void sp_knot_request_position(SPKnot *knot, Geom::Point const &p, guint state)
539     g_return_if_fail(knot != NULL);
540     g_return_if_fail(SP_IS_KNOT(knot));
542     gboolean done = FALSE;
544     g_signal_emit(knot,
545                   knot_signals[REQUEST], 0,
546                   &p,
547                   state,
548                   &done);
550     /* If user did not complete, we simply move knot to new position */
552     if (!done) {
553         sp_knot_set_position (knot, p, state);
554     }
557 /**
558  * Return distance of point to knot's position; unused.
559  */
560 gdouble sp_knot_distance(SPKnot * knot, Geom::Point const &p, guint state)
562     g_return_val_if_fail(knot != NULL, 1e18);
563     g_return_val_if_fail(SP_IS_KNOT(knot), 1e18);
565     gdouble distance = Geom::L2(p - knot->pos);
567     g_signal_emit(knot,
568                   knot_signals[DISTANCE], 0,
569                   &p,
570                   state,
571                   &distance);
573     return distance;
576 /**
577  * Move knot to new position.
578  */
579 void sp_knot_set_position(SPKnot *knot, Geom::Point const &p, guint state)
581     g_return_if_fail(knot != NULL);
582     g_return_if_fail(SP_IS_KNOT (knot));
584     knot->pos = p;
586     if (knot->item) {
587         SP_CTRL(knot->item)->moveto (p);
588     }
590     g_signal_emit(knot,
591                   knot_signals[MOVED], 0,
592                   &p,
593                   state);
594     knot->_moved_signal.emit(knot, p, state);
597 /**
598  * Move knot to new position, without emitting a MOVED signal.
599  */
600 void sp_knot_moveto(SPKnot *knot, Geom::Point const &p)
602     g_return_if_fail(knot != NULL);
603     g_return_if_fail(SP_IS_KNOT(knot));
605     knot->pos = p;
607     if (knot->item) {
608         SP_CTRL(knot->item)->moveto (p);
609     }
612 /**
613  * Returns position of knot.
614  */
615 Geom::Point sp_knot_position(SPKnot const *knot)
617     g_assert(knot != NULL);
618     g_assert(SP_IS_KNOT (knot));
620     return knot->pos;
623 /**
624  * Set flag in knot, with side effects.
625  */
626 void sp_knot_set_flag(SPKnot *knot, guint flag, bool set)
628     g_assert(knot != NULL);
629     g_assert(SP_IS_KNOT(knot));
631     if (set) {
632         knot->flags |= flag;
633     } else {
634         knot->flags &= ~flag;
635     }
637     switch (flag) {
638         case SP_KNOT_VISIBLE:
639             if (set) {
640                 sp_canvas_item_show(knot->item);
641             } else {
642                 sp_canvas_item_hide(knot->item);
643             }
644             break;
645         case SP_KNOT_MOUSEOVER:
646         case SP_KNOT_DRAGGING:
647             sp_knot_set_ctrl_state(knot);
648             break;
649         case SP_KNOT_GRABBED:
650             break;
651         default:
652             g_assert_not_reached();
653             break;
654     }
657 /**
658  * Update knot's pixbuf and set its control state.
659  */
660 void sp_knot_update_ctrl(SPKnot *knot)
662     if (!knot->item) {
663         return;
664     }
666     gtk_object_set(GTK_OBJECT(knot->item), "shape", knot->shape, NULL);
667     gtk_object_set(GTK_OBJECT(knot->item), "mode", knot->mode, NULL);
668     gtk_object_set(GTK_OBJECT(knot->item), "size", (gdouble) knot->size, NULL);
669     gtk_object_set(GTK_OBJECT(knot->item), "anchor", knot->anchor, NULL);
670     if (knot->pixbuf) {
671         gtk_object_set(GTK_OBJECT (knot->item), "pixbuf", knot->pixbuf, NULL);
672     }
674     sp_knot_set_ctrl_state(knot);
677 /**
678  * Set knot control state (dragging/mouseover/normal).
679  */
680 static void sp_knot_set_ctrl_state(SPKnot *knot)
682     if (knot->flags & SP_KNOT_DRAGGING) {
683         gtk_object_set(GTK_OBJECT (knot->item),
684                        "fill_color",
685                        knot->fill[SP_KNOT_STATE_DRAGGING],
686                        NULL);
687         gtk_object_set(GTK_OBJECT (knot->item),
688                        "stroke_color",
689                        knot->stroke[SP_KNOT_STATE_DRAGGING],
690                        NULL);
691     } else if (knot->flags & SP_KNOT_MOUSEOVER) {
692         gtk_object_set(GTK_OBJECT(knot->item),
693                        "fill_color",
694                        knot->fill[SP_KNOT_STATE_MOUSEOVER],
695                        NULL);
696         gtk_object_set(GTK_OBJECT(knot->item),
697                        "stroke_color",
698                        knot->stroke[SP_KNOT_STATE_MOUSEOVER],
699                        NULL);
700     } else {
701         gtk_object_set(GTK_OBJECT(knot->item),
702                        "fill_color",
703                         knot->fill[SP_KNOT_STATE_NORMAL],
704                        NULL);
705         gtk_object_set(GTK_OBJECT(knot->item),
706                        "stroke_color",
707                        knot->stroke[SP_KNOT_STATE_NORMAL],
708                        NULL);
709     }
714 /*
715   Local Variables:
716   mode:c++
717   c-file-style:"stroustrup"
718   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
719   indent-tabs-mode:nil
720   fill-column:99
721   End:
722 */
723 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :