1 #define __SP_GRADIENT_VECTOR_C__
3 /*
4 * Gradient vector selection widget
5 *
6 * Authors:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 * bulia byak <buliabyak@users.sf.net>
9 *
10 * Copyright (C) 2001-2002 Lauris Kaplinski
11 * Copyright (C) 2001 Ximian, Inc.
12 * Copyright (C) 2004 Monash University
13 * Copyright (C) 2004 David Turner
14 *
15 * Released under GNU GPL, read the file 'COPYING' for more information
16 *
17 */
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22 #ifdef HAVE_STRING_H
23 #endif
24 #include <gtk/gtk.h>
25 #include "macros.h"
26 #include <glibmm/i18n.h>
27 #include "../widgets/gradient-image.h"
28 #include "../inkscape.h"
29 #include "../document-private.h"
30 #include "../gradient-chemistry.h"
31 #include "gradient-vector.h"
32 #include "../helper/window.h"
34 #include "xml/repr.h"
36 #include "../dialogs/dialog-events.h"
37 #include "../prefs-utils.h"
38 #include "svg/css-ostringstream.h"
39 #include "sp-stop.h"
41 enum {
42 VECTOR_SET,
43 LAST_SIGNAL
44 };
46 static void sp_gradient_vector_selector_class_init (SPGradientVectorSelectorClass *klass);
47 static void sp_gradient_vector_selector_init (SPGradientVectorSelector *gvs);
48 static void sp_gradient_vector_selector_destroy (GtkObject *object);
50 static void sp_gvs_gradient_release (SPGradient *gr, SPGradientVectorSelector *gvs);
51 static void sp_gvs_defs_release (SPObject *defs, SPGradientVectorSelector *gvs);
52 static void sp_gvs_defs_modified (SPObject *defs, guint flags, SPGradientVectorSelector *gvs);
54 static void sp_gvs_rebuild_gui_full (SPGradientVectorSelector *gvs);
55 static void sp_gvs_gradient_activate (GtkMenuItem *mi, SPGradientVectorSelector *gvs);
57 static GtkVBoxClass *parent_class;
58 static guint signals[LAST_SIGNAL] = {0};
60 static GtkWidget *dlg = NULL;
61 static win_data wd;
62 static gint x = -1000, y = -1000, w = 0, h = 0; // impossible original values to make sure they are read from prefs
63 static gchar const *prefs_path = "dialogs.gradienteditor";
65 GtkType
66 sp_gradient_vector_selector_get_type (void)
67 {
68 static GtkType type = 0;
69 if (!type) {
70 GtkTypeInfo info = {
71 "SPGradientVectorSelector",
72 sizeof (SPGradientVectorSelector),
73 sizeof (SPGradientVectorSelectorClass),
74 (GtkClassInitFunc) sp_gradient_vector_selector_class_init,
75 (GtkObjectInitFunc) sp_gradient_vector_selector_init,
76 NULL, NULL, NULL
77 };
78 type = gtk_type_unique (GTK_TYPE_VBOX, &info);
79 }
80 return type;
81 }
83 static void
84 sp_gradient_vector_selector_class_init (SPGradientVectorSelectorClass *klass)
85 {
86 GtkObjectClass *object_class;
88 object_class = GTK_OBJECT_CLASS (klass);
90 parent_class = (GtkVBoxClass*)gtk_type_class (GTK_TYPE_VBOX);
92 signals[VECTOR_SET] = gtk_signal_new ("vector_set",
93 GTK_RUN_LAST,
94 GTK_CLASS_TYPE(object_class),
95 GTK_SIGNAL_OFFSET (SPGradientVectorSelectorClass, vector_set),
96 gtk_marshal_NONE__POINTER,
97 GTK_TYPE_NONE, 1,
98 GTK_TYPE_POINTER);
100 object_class->destroy = sp_gradient_vector_selector_destroy;
101 }
103 static void
104 sp_gradient_vector_selector_init (SPGradientVectorSelector *gvs)
105 {
106 gvs->idlabel = TRUE;
108 gvs->doc = NULL;
109 gvs->gr = NULL;
111 gvs->menu = gtk_option_menu_new ();
112 gtk_widget_show (gvs->menu);
113 gtk_box_pack_start (GTK_BOX (gvs), gvs->menu, TRUE, TRUE, 0);
114 }
116 static void
117 sp_gradient_vector_selector_destroy (GtkObject *object)
118 {
119 SPGradientVectorSelector *gvs;
121 gvs = SP_GRADIENT_VECTOR_SELECTOR (object);
123 if (gvs->gr) {
124 sp_signal_disconnect_by_data (gvs->gr, gvs);
125 gvs->gr = NULL;
126 }
128 if (gvs->doc) {
129 sp_signal_disconnect_by_data (SP_DOCUMENT_DEFS (gvs->doc), gvs);
130 gvs->doc = NULL;
131 }
133 if (((GtkObjectClass *) (parent_class))->destroy)
134 (* ((GtkObjectClass *) (parent_class))->destroy) (object);
135 }
137 GtkWidget *
138 sp_gradient_vector_selector_new (SPDocument *doc, SPGradient *gr)
139 {
140 GtkWidget *gvs;
142 g_return_val_if_fail (!gr || SP_IS_GRADIENT (gr), NULL);
143 g_return_val_if_fail (!gr || (SP_OBJECT_DOCUMENT (gr) == doc), NULL);
145 gvs = (GtkWidget*)gtk_type_new (SP_TYPE_GRADIENT_VECTOR_SELECTOR);
147 if (doc) {
148 sp_gradient_vector_selector_set_gradient (SP_GRADIENT_VECTOR_SELECTOR (gvs), doc, gr);
149 } else {
150 sp_gvs_rebuild_gui_full (SP_GRADIENT_VECTOR_SELECTOR (gvs));
151 }
153 return gvs;
154 }
156 void
157 sp_gradient_vector_selector_set_gradient (SPGradientVectorSelector *gvs, SPDocument *doc, SPGradient *gr)
158 {
159 static gboolean suppress = FALSE;
161 g_return_if_fail (gvs != NULL);
162 g_return_if_fail (SP_IS_GRADIENT_VECTOR_SELECTOR (gvs));
163 g_return_if_fail (!gr || (doc != NULL));
164 g_return_if_fail (!gr || SP_IS_GRADIENT (gr));
165 g_return_if_fail (!gr || (SP_OBJECT_DOCUMENT (gr) == doc));
166 g_return_if_fail (!gr || SP_GRADIENT_HAS_STOPS (gr));
168 if (doc != gvs->doc) {
169 /* Disconnect signals */
170 if (gvs->gr) {
171 sp_signal_disconnect_by_data (gvs->gr, gvs);
172 g_signal_handlers_disconnect_matched (G_OBJECT(gvs->gr), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, gvs);
173 gvs->gr = NULL;
174 }
175 if (gvs->doc) {
176 sp_signal_disconnect_by_data (SP_DOCUMENT_DEFS (gvs->doc), gvs);
177 gvs->doc = NULL;
178 }
179 /* Connect signals */
180 if (doc) {
181 g_signal_connect (G_OBJECT (SP_DOCUMENT_DEFS (doc)), "release", G_CALLBACK (sp_gvs_defs_release), gvs);
182 g_signal_connect (G_OBJECT (SP_DOCUMENT_DEFS (doc)), "modified", G_CALLBACK (sp_gvs_defs_modified), gvs);
183 }
184 if (gr) {
185 g_signal_connect (G_OBJECT (gr), "release", G_CALLBACK (sp_gvs_gradient_release), gvs);
186 }
187 gvs->doc = doc;
188 gvs->gr = gr;
189 sp_gvs_rebuild_gui_full (gvs);
190 if (!suppress) g_signal_emit (G_OBJECT (gvs), signals[VECTOR_SET], 0, gr);
191 } else if (gr != gvs->gr) {
192 /* Harder case - keep document, rebuild menus and stuff */
193 /* fixme: (Lauris) */
194 suppress = TRUE;
195 sp_gradient_vector_selector_set_gradient (gvs, NULL, NULL);
196 sp_gradient_vector_selector_set_gradient (gvs, doc, gr);
197 suppress = FALSE;
198 g_signal_emit (G_OBJECT (gvs), signals[VECTOR_SET], 0, gr);
199 }
200 /* The case of setting NULL -> NULL is not very interesting */
201 }
203 SPDocument *
204 sp_gradient_vector_selector_get_document (SPGradientVectorSelector *gvs)
205 {
206 g_return_val_if_fail (gvs != NULL, NULL);
207 g_return_val_if_fail (SP_IS_GRADIENT_VECTOR_SELECTOR (gvs), NULL);
209 return gvs->doc;
210 }
212 SPGradient *
213 sp_gradient_vector_selector_get_gradient (SPGradientVectorSelector *gvs)
214 {
215 g_return_val_if_fail (gvs != NULL, NULL);
216 g_return_val_if_fail (SP_IS_GRADIENT_VECTOR_SELECTOR (gvs), NULL);
218 return gvs->gr;
219 }
221 static void
222 sp_gvs_rebuild_gui_full (SPGradientVectorSelector *gvs)
223 {
224 /* Clear old menu, if there is any */
225 if (gtk_option_menu_get_menu (GTK_OPTION_MENU (gvs->menu))) {
226 gtk_option_menu_remove_menu (GTK_OPTION_MENU (gvs->menu));
227 }
229 /* Create new menu widget */
230 GtkWidget *m = gtk_menu_new ();
231 gtk_widget_show (m);
233 /* Pick up all gradients with vectors */
234 GSList *gl = NULL;
235 if (gvs->gr) {
236 const GSList *gradients = sp_document_get_resource_list (SP_OBJECT_DOCUMENT (gvs->gr), "gradient");
237 for (const GSList *l = gradients; l != NULL; l = l->next) {
238 if (SP_GRADIENT_HAS_STOPS (l->data)) {
239 gl = g_slist_prepend (gl, l->data);
240 }
241 }
242 }
243 gl = g_slist_reverse (gl);
245 gint pos = 0;
246 gint idx = 0;
248 if (!gvs->doc) {
249 GtkWidget *i;
250 i = gtk_menu_item_new_with_label (_("No document selected"));
251 gtk_widget_show (i);
252 gtk_menu_append (GTK_MENU (m), i);
253 gtk_widget_set_sensitive (gvs->menu, FALSE);
254 } else if (!gl) {
255 GtkWidget *i;
256 i = gtk_menu_item_new_with_label (_("No gradients in document"));
257 gtk_widget_show (i);
258 gtk_menu_append (GTK_MENU (m), i);
259 gtk_widget_set_sensitive (gvs->menu, FALSE);
260 } else if (!gvs->gr) {
261 GtkWidget *i;
262 i = gtk_menu_item_new_with_label (_("No gradient selected"));
263 gtk_widget_show (i);
264 gtk_menu_append (GTK_MENU (m), i);
265 gtk_widget_set_sensitive (gvs->menu, FALSE);
266 } else {
267 while (gl) {
268 SPGradient *gr;
269 GtkWidget *i, *w;
270 gr = SP_GRADIENT (gl->data);
271 gl = g_slist_remove (gl, gr);
273 /* We have to know: */
274 /* Gradient destroy */
275 /* Gradient name change */
276 i = gtk_menu_item_new ();
277 gtk_widget_show (i);
278 g_object_set_data (G_OBJECT (i), "gradient", gr);
279 g_signal_connect (G_OBJECT (i), "activate", G_CALLBACK (sp_gvs_gradient_activate), gvs);
281 w = sp_gradient_image_new (gr);
282 gtk_widget_show (w);
284 if (gvs->idlabel) {
285 GtkWidget *hb, *l;
286 hb = gtk_hbox_new (FALSE, 4);
287 gtk_widget_show (hb);
288 l = gtk_label_new (SP_OBJECT_ID (gr));
289 gtk_widget_show (l);
290 gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
291 gtk_box_pack_start (GTK_BOX (hb), l, TRUE, TRUE, 0);
292 gtk_box_pack_start (GTK_BOX (hb), w, FALSE, FALSE, 0);
293 w = hb;
294 }
296 gtk_container_add (GTK_CONTAINER (i), w);
298 gtk_menu_append (GTK_MENU (m), i);
300 if (gr == gvs->gr) pos = idx;
301 idx += 1;
302 }
303 gtk_widget_set_sensitive (gvs->menu, TRUE);
304 }
306 gtk_option_menu_set_menu (GTK_OPTION_MENU (gvs->menu), m);
307 /* Set history */
308 gtk_option_menu_set_history (GTK_OPTION_MENU (gvs->menu), pos);
309 }
311 static void
312 sp_gvs_gradient_activate (GtkMenuItem *mi, SPGradientVectorSelector *gvs)
313 {
314 SPGradient *gr, *norm;
316 gr = (SPGradient*)g_object_get_data (G_OBJECT (mi), "gradient");
317 /* Hmmm... bad things may happen here, if actual gradient is something new */
318 /* Namely - menuitems etc. will be fucked up */
319 /* Hmmm - probably we can just re-set it as menuitem data (Lauris) */
321 //g_print ("SPGradientVectorSelector: gradient %s activated\n", SP_OBJECT_ID (gr));
323 norm = sp_gradient_ensure_vector_normalized (gr);
324 if (norm != gr) {
325 //g_print ("SPGradientVectorSelector: become %s after normalization\n", SP_OBJECT_ID (norm));
326 /* But be careful that we do not have gradient saved anywhere else */
327 g_object_set_data (G_OBJECT (mi), "gradient", norm);
328 }
330 /* fixme: Really we would want to use _set_vector */
331 /* Detach old */
332 if (gvs->gr) {
333 sp_signal_disconnect_by_data (gvs->gr, gvs);
334 gvs->gr = NULL;
335 }
336 /* Attach new */
337 if (norm) {
338 g_signal_connect (G_OBJECT (norm), "release", G_CALLBACK (sp_gvs_gradient_release), gvs);
339 /* fixme: Connect 'modified'? (Lauris) */
340 /* fixme: I think we do not need it (Lauris) */
341 gvs->gr = norm;
342 }
344 g_signal_emit (G_OBJECT (gvs), signals[VECTOR_SET], 0, norm);
346 if (norm != gr) {
347 /* We do extra undo push here */
348 /* If handler has already done it, it is just NOP */
349 sp_document_done (SP_OBJECT_DOCUMENT (norm));
350 }
351 }
353 static void
354 sp_gvs_gradient_release (SPGradient *gr, SPGradientVectorSelector *gvs)
355 {
356 /* Disconnect gradient */
357 if (gvs->gr) {
358 sp_signal_disconnect_by_data (gvs->gr, gvs);
359 gvs->gr = NULL;
360 }
362 /* Rebuild GUI */
363 sp_gvs_rebuild_gui_full (gvs);
364 }
366 static void
367 sp_gvs_defs_release (SPObject *defs, SPGradientVectorSelector *gvs)
368 {
369 gvs->doc = NULL;
370 /* Disconnect gradient as well */
371 if (gvs->gr) {
372 sp_signal_disconnect_by_data (gvs->gr, gvs);
373 gvs->gr = NULL;
374 }
376 /* Rebuild GUI */
377 sp_gvs_rebuild_gui_full (gvs);
378 }
380 static void
381 sp_gvs_defs_modified (SPObject *defs, guint flags, SPGradientVectorSelector *gvs)
382 {
383 /* fixme: We probably have to check some flags here (Lauris) */
385 sp_gvs_rebuild_gui_full (gvs);
386 }
388 /*##################################################################
389 ### Vector Editing Widget
390 ##################################################################*/
392 #include "../widgets/sp-color-notebook.h"
393 #include "../widgets/sp-color-preview.h"
394 #include "../widgets/widget-sizes.h"
395 #include "../xml/node-event-vector.h"
396 #include "../svg/svg-color.h"
399 #define PAD 4
401 static GtkWidget *sp_gradient_vector_widget_new (SPGradient *gradient, SPStop *stop);
403 static void sp_gradient_vector_widget_load_gradient (GtkWidget *widget, SPGradient *gradient);
404 static gint sp_gradient_vector_dialog_delete (GtkWidget *widget, GdkEvent *event, GtkWidget *dialog);
405 static void sp_gradient_vector_dialog_destroy (GtkObject *object, gpointer data);
407 static void sp_gradient_vector_widget_destroy (GtkObject *object, gpointer data);
408 static void sp_gradient_vector_gradient_release (SPGradient *gradient, GtkWidget *widget);
409 static void sp_gradient_vector_gradient_modified (SPGradient *gradient, guint flags, GtkWidget *widget);
410 static void sp_gradient_vector_color_dragged (SPColorSelector *csel, GtkObject *object);
411 static void sp_gradient_vector_color_changed (SPColorSelector *csel, GtkObject *object);
412 static void update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_stop);
414 static gboolean blocked = FALSE;
416 static void grad_edit_dia_stop_added_or_removed (Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, gpointer data)
417 {
418 GtkWidget *vb = GTK_WIDGET(data);
419 GtkWidget *mnu = (GtkWidget *)g_object_get_data (G_OBJECT(vb), "stopmenu");
420 SPGradient *gradient = (SPGradient *)g_object_get_data (G_OBJECT(vb), "gradient");
421 update_stop_list (mnu, gradient, NULL);
422 }
424 //FIXME!!! We must also listen to attr changes on all children (i.e. stops) too,
425 //otherwise the dialog does not reflect undoing color or offset change. This is a major
426 //hassle, unless we have a "one of the descendants changed in some way" signal.
427 static Inkscape::XML::NodeEventVector grad_edit_dia_repr_events =
428 {
429 grad_edit_dia_stop_added_or_removed, /* child_added */
430 grad_edit_dia_stop_added_or_removed, /* child_removed */
431 NULL, /* attr_changed*/
432 NULL, /* content_changed */
433 NULL /* order_changed */
434 };
436 static void
437 verify_grad(SPGradient *gradient)
438 {
439 int i = 0;
440 SPStop *stop = NULL;
441 /* count stops */
442 for ( SPObject *ochild = sp_object_first_child(SP_OBJECT(gradient)) ; ochild != NULL ; ochild = SP_OBJECT_NEXT(ochild) ) {
443 if (SP_IS_STOP (ochild)) {
444 i++;
445 stop = SP_STOP(ochild);
446 }
447 }
449 if (i < 1) {
450 gchar c[64];
451 sp_svg_write_color (c, 64, 0x00000000);
453 Inkscape::CSSOStringStream os;
454 os << "stop-color:" << c << ";stop-opacity:" << 1.0 << ";";
456 Inkscape::XML::Node *child;
458 child = sp_repr_new ("svg:stop");
459 sp_repr_set_css_double(child, "offset", 0.0);
460 child->setAttribute("style", os.str().c_str());
461 SP_OBJECT_REPR (gradient)->addChild(child, NULL);
463 child = sp_repr_new ("svg:stop");
464 sp_repr_set_css_double(child, "offset", 1.0);
465 child->setAttribute("style", os.str().c_str());
466 SP_OBJECT_REPR (gradient)->addChild(child, NULL);
467 }
468 if (i < 2) {
469 sp_repr_set_css_double(SP_OBJECT_REPR(stop), "offset", 0.0);
470 Inkscape::XML::Node *child = SP_OBJECT_REPR(stop)->duplicate();
471 sp_repr_set_css_double(child, "offset", 1.0);
472 SP_OBJECT_REPR(gradient)->addChild(child, SP_OBJECT_REPR (stop));
473 }
474 }
476 static void
477 select_stop_in_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_stop)
478 {
479 int i = 0;
480 for ( SPObject *ochild = sp_object_first_child(SP_OBJECT(gradient)) ; ochild != NULL ; ochild = SP_OBJECT_NEXT(ochild) ) {
481 if (SP_IS_STOP (ochild)) {
482 if (SP_OBJECT (ochild) == SP_OBJECT(new_stop)) {
483 gtk_option_menu_set_history (GTK_OPTION_MENU (mnu), i);
484 break;
485 }
486 i++;
487 }
488 }
489 }
491 static void
492 update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_stop)
493 {
495 if (!SP_IS_GRADIENT (gradient))
496 return;
498 blocked = TRUE;
500 /* Clear old menu, if there is any */
501 if (gtk_option_menu_get_menu (GTK_OPTION_MENU (mnu))) {
502 gtk_option_menu_remove_menu (GTK_OPTION_MENU (mnu));
503 }
505 /* Create new menu widget */
506 GtkWidget *m = gtk_menu_new ();
507 gtk_widget_show (m);
508 GSList *sl = NULL;
509 if (gradient->has_stops) {
510 for ( SPObject *ochild = sp_object_first_child (SP_OBJECT(gradient)) ; ochild != NULL ; ochild = SP_OBJECT_NEXT(ochild) ) {
511 if (SP_IS_STOP (ochild)) {
512 sl = g_slist_append (sl, ochild);
513 }
514 }
515 }
516 if (!sl) {
517 GtkWidget *i = gtk_menu_item_new_with_label (_("No stops in gradient"));
518 gtk_widget_show (i);
519 gtk_menu_append (GTK_MENU (m), i);
520 gtk_widget_set_sensitive (mnu, FALSE);
521 } else {
523 for (; sl != NULL; sl = sl->next){
524 SPStop *stop;
525 GtkWidget *i;
526 if (SP_IS_STOP(sl->data)){
527 stop = SP_STOP (sl->data);
528 i = gtk_menu_item_new ();
529 gtk_widget_show (i);
530 g_object_set_data (G_OBJECT (i), "stop", stop);
531 GtkWidget *hb = gtk_hbox_new (FALSE, 4);
532 GtkWidget *cpv = sp_color_preview_new(sp_stop_get_rgba32(stop));
533 gtk_widget_show (cpv);
534 gtk_container_add ( GTK_CONTAINER (hb), cpv );
535 g_object_set_data ( G_OBJECT (i), "preview", cpv );
536 Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) sl->data);
537 GtkWidget *l = gtk_label_new (repr->attribute("id"));
538 gtk_widget_show (l);
539 gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
540 gtk_box_pack_start (GTK_BOX (hb), l, TRUE, TRUE, 0);
541 gtk_widget_show (hb);
542 gtk_container_add (GTK_CONTAINER (i), hb);
543 gtk_menu_append (GTK_MENU (m), i);
544 }
545 }
547 gtk_widget_set_sensitive (mnu, TRUE);
548 }
549 gtk_option_menu_set_menu (GTK_OPTION_MENU (mnu), m);
551 /* Set history */
552 if (new_stop == NULL) {
553 gtk_option_menu_set_history (GTK_OPTION_MENU (mnu), 0);
554 } else {
555 select_stop_in_list (mnu, gradient, new_stop);
556 }
558 blocked = FALSE;
559 }
562 /*user selected existing stop from list*/
563 static void
564 sp_grad_edit_select (GtkOptionMenu *mnu, GtkWidget *tbl)
565 {
566 SPGradient *gradient = (SPGradient *)g_object_get_data (G_OBJECT(tbl), "gradient");
568 GObject *item = G_OBJECT(gtk_menu_get_active (GTK_MENU(gtk_option_menu_get_menu (mnu))));
569 SPStop *stop = SP_STOP (g_object_get_data (item, "stop"));
570 if (!stop) return;
572 blocked = TRUE;
574 SPColorSelector *csel = (SPColorSelector*)g_object_get_data (G_OBJECT (tbl), "cselector");
575 guint32 const c = sp_stop_get_rgba32(stop);
576 csel->base->setAlpha(SP_RGBA32_A_F (c));
577 SPColor color;
578 sp_color_set_rgb_float (&color, SP_RGBA32_R_F (c), SP_RGBA32_G_F (c), SP_RGBA32_B_F (c));
579 // set its color, from the stored array
580 csel->base->setColor( color );
581 GtkWidget *offspin = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "offspn"));
582 GtkWidget *offslide =GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "offslide"));
584 GtkAdjustment *adj = (GtkAdjustment*)gtk_object_get_data (GTK_OBJECT (tbl), "offset");
586 bool isEndStop = false;
588 SPStop *prev = NULL;
589 prev = sp_prev_stop(stop, gradient);
590 if (prev != NULL ) {
591 adj->lower = prev->offset;
592 } else {
593 isEndStop = true;
594 adj->lower = 0;
595 }
597 SPStop *next = NULL;
598 next = sp_next_stop(stop);
599 if (next != NULL ) {
600 adj->upper = next->offset;
601 } else {
602 isEndStop = true;
603 adj->upper = 1.0;
604 }
606 //fixme: does this work on all possible input gradients?
607 if (!isEndStop) {
608 gtk_widget_set_sensitive (offslide, TRUE);
609 gtk_widget_set_sensitive (GTK_WIDGET (offspin), TRUE);
610 } else {
611 gtk_widget_set_sensitive (offslide, FALSE);
612 gtk_widget_set_sensitive (GTK_WIDGET (offspin), FALSE);
613 }
615 gtk_adjustment_set_value (adj, stop->offset);
617 gtk_adjustment_changed (adj);
619 blocked = FALSE;
620 }
625 static void
626 offadjustmentChanged( GtkAdjustment *adjustment, GtkWidget *vb)
627 {
628 if (blocked)
629 return;
631 blocked = TRUE;
633 GtkOptionMenu *mnu = (GtkOptionMenu *)g_object_get_data (G_OBJECT(vb), "stopmenu");
634 if (!g_object_get_data (G_OBJECT(gtk_menu_get_active (GTK_MENU(gtk_option_menu_get_menu (mnu)))), "stop")) return;
635 SPStop *stop = SP_STOP(g_object_get_data (G_OBJECT(gtk_menu_get_active (GTK_MENU(gtk_option_menu_get_menu (mnu)))), "stop"));
637 stop->offset = adjustment->value;
638 sp_repr_set_css_double(SP_OBJECT_REPR(stop), "offset", stop->offset);
640 sp_document_done (SP_OBJECT_DOCUMENT (stop));
642 blocked = FALSE;
643 }
645 guint32
646 sp_average_color (guint32 c1, guint32 c2, gdouble p = 0.5)
647 {
648 guint32 r = (guint32) (SP_RGBA32_R_U (c1) * p + SP_RGBA32_R_U (c2) * (1 - p));
649 guint32 g = (guint32) (SP_RGBA32_G_U (c1) * p + SP_RGBA32_G_U (c2) * (1 - p));
650 guint32 b = (guint32) (SP_RGBA32_B_U (c1) * p + SP_RGBA32_B_U (c2) * (1 - p));
651 guint32 a = (guint32) (SP_RGBA32_A_U (c1) * p + SP_RGBA32_A_U (c2) * (1 - p));
653 return SP_RGBA32_U_COMPOSE (r, g, b, a);
654 }
657 static void
658 sp_grd_ed_add_stop (GtkWidget *widget, GtkWidget *vb)
659 {
660 SPGradient *gradient = (SPGradient *) g_object_get_data (G_OBJECT(vb), "gradient");
661 verify_grad (gradient);
662 GtkOptionMenu *mnu = (GtkOptionMenu *)g_object_get_data (G_OBJECT(vb), "stopmenu");
664 SPStop *stop = (SPStop *) g_object_get_data (G_OBJECT(gtk_menu_get_active (GTK_MENU(gtk_option_menu_get_menu (mnu)))), "stop");
666 if (stop == NULL)
667 return;
669 Inkscape::XML::Node *new_stop_repr = NULL;
671 SPStop *next = sp_next_stop (stop);
673 if (next == NULL) {
674 SPStop *prev = sp_prev_stop (stop, gradient);
675 if (prev != NULL) {
676 next = stop;
677 stop = prev;
678 }
679 }
681 if (next != NULL) {
682 new_stop_repr = SP_OBJECT_REPR(stop)->duplicate();
683 SP_OBJECT_REPR(gradient)->addChild(new_stop_repr, SP_OBJECT_REPR(stop));
684 } else {
685 next = stop;
686 new_stop_repr = SP_OBJECT_REPR(sp_prev_stop(stop, gradient))->duplicate();
687 SP_OBJECT_REPR(gradient)->addChild(new_stop_repr, SP_OBJECT_REPR(sp_prev_stop(stop, gradient)));
688 }
690 SPStop *newstop = (SPStop *) SP_OBJECT_DOCUMENT(gradient)->getObjectByRepr(new_stop_repr);
692 newstop->offset = (stop->offset + next->offset) * 0.5 ;
694 guint32 const c1 = sp_stop_get_rgba32(stop);
695 guint32 const c2 = sp_stop_get_rgba32(next);
696 guint32 cnew = sp_average_color (c1, c2);
698 Inkscape::CSSOStringStream os;
699 gchar c[64];
700 sp_svg_write_color (c, 64, cnew);
701 gdouble opacity = (gdouble) SP_RGBA32_A_F (cnew);
702 os << "stop-color:" << c << ";stop-opacity:" << opacity <<";";
703 SP_OBJECT_REPR (newstop)->setAttribute("style", os.str().c_str());
705 sp_gradient_vector_widget_load_gradient (vb, gradient);
706 Inkscape::GC::release(new_stop_repr);
707 update_stop_list(GTK_WIDGET(mnu), gradient, newstop);
708 GtkWidget *offspin = GTK_WIDGET (g_object_get_data (G_OBJECT (vb), "offspn"));
709 GtkWidget *offslide =GTK_WIDGET (g_object_get_data (G_OBJECT (vb), "offslide"));
710 gtk_widget_set_sensitive (offslide, TRUE);
711 gtk_widget_set_sensitive (GTK_WIDGET (offspin), TRUE);
712 sp_document_done (SP_OBJECT_DOCUMENT (gradient));
713 }
715 static void
716 sp_grd_ed_del_stop (GtkWidget *widget, GtkWidget *vb)
717 {
718 SPGradient *gradient = (SPGradient *)g_object_get_data (G_OBJECT(vb), "gradient");
720 GtkOptionMenu *mnu = (GtkOptionMenu *)g_object_get_data (G_OBJECT(vb), "stopmenu");
721 if (!g_object_get_data (G_OBJECT(gtk_menu_get_active (GTK_MENU(gtk_option_menu_get_menu (mnu)))), "stop")) return;
722 SPStop *stop = SP_STOP(g_object_get_data (G_OBJECT(gtk_menu_get_active (GTK_MENU(gtk_option_menu_get_menu (mnu)))), "stop"));
723 if (gradient->vector.stops.size() > 2) { // 2 is the minimum
725 // if we delete first or last stop, move the next/previous to the edge
726 if (stop->offset == 0) {
727 SPStop *next = sp_next_stop (stop);
728 if (next) {
729 next->offset = 0;
730 sp_repr_set_css_double (SP_OBJECT_REPR (next), "offset", 0);
731 }
732 } else if (stop->offset == 1) {
733 SPStop *prev = sp_prev_stop (stop, gradient);
734 if (prev) {
735 prev->offset = 1;
736 sp_repr_set_css_double (SP_OBJECT_REPR (prev), "offset", 1);
737 }
738 }
740 SP_OBJECT_REPR(gradient)->removeChild(SP_OBJECT_REPR(stop));
741 sp_gradient_vector_widget_load_gradient (vb, gradient);
742 update_stop_list(GTK_WIDGET(mnu), gradient, NULL);
743 sp_document_done (SP_OBJECT_DOCUMENT (gradient));
744 }
746 }
748 static GtkWidget *
749 sp_gradient_vector_widget_new (SPGradient *gradient, SPStop *select_stop)
750 {
751 GtkWidget *vb, *w, *f, *csel;
753 g_return_val_if_fail (!gradient || SP_IS_GRADIENT (gradient), NULL);
755 vb = gtk_vbox_new (FALSE, PAD);
756 g_signal_connect (G_OBJECT (vb), "destroy", G_CALLBACK (sp_gradient_vector_widget_destroy), NULL);
758 w = sp_gradient_image_new (gradient);
759 g_object_set_data (G_OBJECT (vb), "preview", w);
760 gtk_widget_show (w);
761 gtk_box_pack_start (GTK_BOX (vb), w, TRUE, TRUE, PAD);
763 gtk_object_set_data (GTK_OBJECT (vb), "gradient", gradient);
764 sp_repr_add_listener (SP_OBJECT_REPR(gradient), &grad_edit_dia_repr_events, vb);
765 GtkTooltips *tt = gtk_tooltips_new ();
767 /* Stop list */
768 GtkWidget *mnu = gtk_option_menu_new ();
769 /* Create new menu widget */
770 update_stop_list (GTK_WIDGET(mnu), gradient, NULL);
771 gtk_signal_connect (GTK_OBJECT (mnu), "changed", GTK_SIGNAL_FUNC (sp_grad_edit_select), vb);
772 gtk_widget_show (mnu);
773 gtk_object_set_data (GTK_OBJECT (vb), "stopmenu", mnu);
774 gtk_box_pack_start (GTK_BOX (vb), mnu, FALSE, FALSE, 0);
776 /* Add and Remove buttons */
777 GtkWidget *hb = gtk_hbox_new (FALSE, 1);
778 // TRANSLATORS: "Stop" means: a "phase" of a gradient
779 GtkWidget *b = gtk_button_new_with_label (_("Add stop"));
780 gtk_widget_show (b);
781 gtk_container_add (GTK_CONTAINER (hb), b);
782 gtk_tooltips_set_tip (tt, b, _("Add another control stop to gradient"), NULL);
783 gtk_signal_connect (GTK_OBJECT (b), "clicked", GTK_SIGNAL_FUNC (sp_grd_ed_add_stop), vb);
784 b = gtk_button_new_with_label (_("Delete stop"));
785 gtk_widget_show (b);
786 gtk_container_add (GTK_CONTAINER (hb), b);
787 gtk_tooltips_set_tip (tt, b, _("Delete current control stop from gradient"), NULL);
788 gtk_signal_connect (GTK_OBJECT (b), "clicked", GTK_SIGNAL_FUNC (sp_grd_ed_del_stop), vb);
790 gtk_widget_show (hb);
791 gtk_box_pack_start (GTK_BOX (vb),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
794 /* Offset Slider and stuff */
795 hb = gtk_hbox_new (FALSE, 0);
797 /* Label */
798 GtkWidget *l = gtk_label_new (_("Offset:"));
799 gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
800 gtk_box_pack_start (GTK_BOX (hb),l, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
801 gtk_widget_show (l);
803 /* Adjustment */
804 GtkAdjustment *Offset_adj = NULL;
805 Offset_adj= (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 1.0, 0.01, 0.01, 0.0);
806 gtk_object_set_data (GTK_OBJECT (vb), "offset", Offset_adj);
807 GtkMenu *m = GTK_MENU(gtk_option_menu_get_menu (GTK_OPTION_MENU(mnu)));
808 SPStop *stop = SP_STOP (g_object_get_data (G_OBJECT (gtk_menu_get_active (m)), "stop"));
809 gtk_adjustment_set_value (Offset_adj, stop->offset);
811 /* Slider */
812 GtkWidget *slider = gtk_hscale_new(Offset_adj);
813 gtk_scale_set_draw_value( GTK_SCALE(slider), FALSE );
814 gtk_widget_show (slider);
815 gtk_box_pack_start (GTK_BOX (hb),slider, TRUE, TRUE, AUX_BETWEEN_BUTTON_GROUPS);
816 gtk_object_set_data (GTK_OBJECT (vb), "offslide", slider);
818 /* Spinbutton */
819 GtkWidget *sbtn = gtk_spin_button_new (GTK_ADJUSTMENT (Offset_adj), 0.01, 2);
820 sp_dialog_defocus_on_enter (sbtn);
821 gtk_widget_show (sbtn);
822 gtk_box_pack_start (GTK_BOX (hb),sbtn, FALSE, TRUE, AUX_BETWEEN_BUTTON_GROUPS);
823 gtk_object_set_data (GTK_OBJECT (vb), "offspn", sbtn);
825 if (stop->offset>0 && stop->offset<1) {
826 gtk_widget_set_sensitive (slider, TRUE);
827 gtk_widget_set_sensitive (GTK_WIDGET (sbtn), TRUE);
828 } else {
829 gtk_widget_set_sensitive (slider, FALSE);
830 gtk_widget_set_sensitive (GTK_WIDGET (sbtn), FALSE);
831 }
834 /* Signals */
835 gtk_signal_connect (GTK_OBJECT (Offset_adj), "value_changed",
836 GTK_SIGNAL_FUNC (offadjustmentChanged), vb);
838 // gtk_signal_connect (GTK_OBJECT (slider), "changed", GTK_SIGNAL_FUNC (offsliderChanged), vb);
839 gtk_widget_show (hb);
840 gtk_box_pack_start (GTK_BOX (vb), hb, FALSE, FALSE, PAD);
842 // TRANSLATORS: "Stop" means: a "phase" of a gradient
843 f = gtk_frame_new (_("Stop Color"));
844 gtk_widget_show (f);
845 gtk_box_pack_start (GTK_BOX (vb), f, TRUE, TRUE, PAD);
846 csel = (GtkWidget*)sp_color_selector_new (SP_TYPE_COLOR_NOTEBOOK, SP_COLORSPACE_TYPE_NONE);
847 g_object_set_data (G_OBJECT (vb), "cselector", csel);
848 gtk_widget_show (csel);
849 gtk_container_add (GTK_CONTAINER (f), csel);
850 g_signal_connect (G_OBJECT (csel), "dragged", G_CALLBACK (sp_gradient_vector_color_dragged), vb);
851 g_signal_connect (G_OBJECT (csel), "changed", G_CALLBACK (sp_gradient_vector_color_changed), vb);
853 gtk_widget_show (vb);
855 sp_gradient_vector_widget_load_gradient (vb, gradient);
857 if (select_stop)
858 select_stop_in_list (GTK_WIDGET(mnu), gradient, select_stop);
860 return vb;
861 }
865 GtkWidget *
866 sp_gradient_vector_editor_new (SPGradient *gradient, SPStop *stop)
867 {
868 GtkWidget *wid;
870 if (dlg == NULL) {
872 dlg = sp_window_new (_("Gradient editor"), TRUE);
873 if (x == -1000 || y == -1000) {
874 x = prefs_get_int_attribute (prefs_path, "x", 0);
875 y = prefs_get_int_attribute (prefs_path, "y", 0);
876 }
877 if (w ==0 || h == 0) {
878 w = prefs_get_int_attribute (prefs_path, "w", 0);
879 h = prefs_get_int_attribute (prefs_path, "h", 0);
880 }
882 if (x<0) x=0;
883 if (y<0) y=0;
885 if (x != 0 || y != 0)
886 gtk_window_move ((GtkWindow *) dlg, x, y);
887 else
888 gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
889 if (w && h) gtk_window_resize ((GtkWindow *) dlg, w, h);
890 sp_transientize (dlg);
891 wd.win = dlg;
892 wd.stop = 0;
893 g_signal_connect (G_OBJECT (INKSCAPE), "activate_desktop", G_CALLBACK (sp_transientize_callback), &wd);
894 gtk_signal_connect (GTK_OBJECT (dlg), "event", GTK_SIGNAL_FUNC (sp_dialog_event_handler), dlg);
895 gtk_signal_connect (GTK_OBJECT (dlg), "destroy", G_CALLBACK (sp_gradient_vector_dialog_destroy), dlg);
896 gtk_signal_connect (GTK_OBJECT (dlg), "delete_event", G_CALLBACK (sp_gradient_vector_dialog_delete), dlg);
897 g_signal_connect (G_OBJECT (INKSCAPE), "shut_down", G_CALLBACK (sp_gradient_vector_dialog_delete), dlg);
898 g_signal_connect ( G_OBJECT (INKSCAPE), "dialogs_hide", G_CALLBACK (sp_dialog_hide), dlg );
899 g_signal_connect ( G_OBJECT (INKSCAPE), "dialogs_unhide", G_CALLBACK (sp_dialog_unhide), dlg );
901 gtk_container_set_border_width (GTK_CONTAINER (dlg), PAD);
903 wid = (GtkWidget*)sp_gradient_vector_widget_new (gradient, stop);
904 g_object_set_data (G_OBJECT (dlg), "gradient-vector-widget", wid);
905 /* Connect signals */
906 gtk_widget_show (wid);
907 gtk_container_add (GTK_CONTAINER (dlg), wid);
908 } else {
909 // FIXME: temp fix for 0.38
910 // Simply load_gradient into the editor does not work for multi-stop gradients,
911 // as the stop list and other widgets are in a wrong state and crash readily.
912 // Instead we just delete the window (by sending the delete signal)
913 // and call sp_gradient_vector_editor_new again, so it creates the window anew.
915 GdkEventAny event;
916 GtkWidget *widget = (GtkWidget *) dlg;
917 event.type = GDK_DELETE;
918 event.window = widget->window;
919 event.send_event = TRUE;
920 g_object_ref (G_OBJECT (event.window));
921 gtk_main_do_event ((GdkEvent*)&event);
922 g_object_unref (G_OBJECT (event.window));
924 g_assert (dlg == NULL);
925 sp_gradient_vector_editor_new (gradient, stop);
926 }
928 return dlg;
929 }
931 static void
932 sp_gradient_vector_widget_load_gradient (GtkWidget *widget, SPGradient *gradient)
933 {
934 blocked = TRUE;
936 SPGradient *old;
938 old = (SPGradient*)g_object_get_data (G_OBJECT (widget), "gradient");
939 if (old != gradient) {
940 if (old) {
941 sp_signal_disconnect_by_data (old, widget);
942 }
943 if (gradient) {
944 g_signal_connect (G_OBJECT (gradient), "release", G_CALLBACK (sp_gradient_vector_gradient_release), widget);
945 g_signal_connect (G_OBJECT (gradient), "modified", G_CALLBACK (sp_gradient_vector_gradient_modified), widget);
946 }
947 }
949 g_object_set_data (G_OBJECT (widget), "gradient", gradient);
951 if (gradient) {
952 sp_gradient_ensure_vector (gradient);
954 GtkOptionMenu *mnu = (GtkOptionMenu *)g_object_get_data (G_OBJECT(widget), "stopmenu");
955 SPStop *stop = SP_STOP(g_object_get_data (G_OBJECT(gtk_menu_get_active (GTK_MENU(gtk_option_menu_get_menu (mnu)))), "stop"));
956 guint32 const c = sp_stop_get_rgba32(stop);
958 /// get the color selector
959 SPColorSelector *csel = SP_COLOR_SELECTOR(g_object_get_data (G_OBJECT (widget), "cselector"));
960 // set alpha
961 csel->base->setAlpha(SP_RGBA32_A_F (c));
962 SPColor color;
963 sp_color_set_rgb_float (&color, SP_RGBA32_R_F (c), SP_RGBA32_G_F (c), SP_RGBA32_B_F (c));
964 // set color
965 csel->base->setColor( color );
966 }
968 /* Fill preview */
969 GtkWidget *w = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(widget), "preview"));
970 sp_gradient_image_set_gradient (SP_GRADIENT_IMAGE (w), gradient);
972 GtkWidget *mnu = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(widget), "stopmenu"));
973 update_stop_list (GTK_WIDGET(mnu), gradient, NULL);
975 // Once the user edits a gradient, it stops being auto-collectable
976 if (SP_OBJECT_REPR(gradient)->attribute("inkscape:collect")) {
977 SPDocument *document = SP_OBJECT_DOCUMENT (gradient);
978 gboolean saved = sp_document_get_undo_sensitive(document);
979 sp_document_set_undo_sensitive (document, FALSE);
980 SP_OBJECT_REPR(gradient)->setAttribute("inkscape:collect", NULL);
981 sp_document_set_undo_sensitive (document, saved);
982 }
984 blocked = FALSE;
985 }
987 static void
988 sp_gradient_vector_dialog_destroy (GtkObject *object, gpointer data)
989 {
990 sp_signal_disconnect_by_data (INKSCAPE, dlg);
991 wd.win = dlg = NULL;
992 wd.stop = 0;
993 }
995 static gboolean
996 sp_gradient_vector_dialog_delete (GtkWidget *widget, GdkEvent *event, GtkWidget *dialog)
997 {
998 gtk_window_get_position ((GtkWindow *) dlg, &x, &y);
999 gtk_window_get_size ((GtkWindow *) dlg, &w, &h);
1001 if (x<0) x=0;
1002 if (y<0) y=0;
1004 prefs_set_int_attribute (prefs_path, "x", x);
1005 prefs_set_int_attribute (prefs_path, "y", y);
1006 prefs_set_int_attribute (prefs_path, "w", w);
1007 prefs_set_int_attribute (prefs_path, "h", h);
1009 return FALSE; // which means, go ahead and destroy it
1010 }
1012 /* Widget destroy handler */
1014 static void
1015 sp_gradient_vector_widget_destroy (GtkObject *object, gpointer data)
1016 {
1017 GObject *gradient;
1019 gradient = (GObject*)g_object_get_data (G_OBJECT (object), "gradient");
1021 if (gradient && SP_OBJECT_REPR(gradient)) {
1022 /* Remove signals connected to us */
1023 /* fixme: may use _connect_while_alive as well */
1024 sp_signal_disconnect_by_data (gradient, object);
1025 sp_repr_remove_listener_by_data (SP_OBJECT_REPR(gradient), object);
1026 }
1027 }
1029 static void
1030 sp_gradient_vector_gradient_release (SPGradient *gradient, GtkWidget *widget)
1031 {
1032 sp_gradient_vector_widget_load_gradient (widget, NULL);
1033 }
1035 static void
1036 sp_gradient_vector_gradient_modified (SPGradient *gradient, guint flags, GtkWidget *widget)
1037 {
1038 if (!blocked) {
1039 blocked = TRUE;
1040 sp_gradient_vector_widget_load_gradient (widget, gradient);
1041 blocked = FALSE;
1042 }
1043 }
1045 static void sp_gradient_vector_color_dragged(SPColorSelector *csel, GtkObject *object)
1046 {
1047 SPGradient *gradient, *ngr;
1049 if (blocked) return;
1051 gradient = (SPGradient*)g_object_get_data (G_OBJECT (object), "gradient");
1052 if (!gradient) return;
1054 blocked = TRUE;
1056 ngr = sp_gradient_ensure_vector_normalized (gradient);
1057 if (ngr != gradient) {
1058 /* Our master gradient has changed */
1059 sp_gradient_vector_widget_load_gradient (GTK_WIDGET (object), ngr);
1060 }
1062 sp_gradient_ensure_vector (ngr);
1064 GtkOptionMenu *mnu = (GtkOptionMenu *)g_object_get_data (G_OBJECT(object), "stopmenu");
1065 SPStop *stop = SP_STOP(g_object_get_data (G_OBJECT(gtk_menu_get_active (GTK_MENU(gtk_option_menu_get_menu (mnu)))), "stop"));
1068 csel->base->getColorAlpha(stop->specified_color, &stop->opacity);
1069 stop->currentColor = false;
1071 blocked = FALSE;
1072 SPColorPreview *cpv = (SPColorPreview *)g_object_get_data (G_OBJECT(gtk_menu_get_active (GTK_MENU(gtk_option_menu_get_menu (mnu)))), "preview");
1073 sp_color_preview_set_rgba32(cpv, sp_stop_get_rgba32(stop));
1075 }
1077 static void
1078 sp_gradient_vector_color_changed (SPColorSelector *csel, GtkObject *object)
1079 {
1080 SPColor color;
1081 float alpha;
1082 guint32 rgb;
1084 if (blocked) return;
1086 SPGradient *gradient = (SPGradient*)g_object_get_data (G_OBJECT (object), "gradient");
1087 if (!gradient) return;
1089 blocked = TRUE;
1091 SPGradient *ngr = sp_gradient_ensure_vector_normalized (gradient);
1092 if (ngr != gradient) {
1093 /* Our master gradient has changed */
1094 sp_gradient_vector_widget_load_gradient (GTK_WIDGET (object), ngr);
1095 }
1097 sp_gradient_ensure_vector (ngr);
1099 /* Set start parameters */
1100 /* We rely on normalized vector, i.e. stops HAVE to exist */
1101 g_return_if_fail (sp_first_stop(ngr) != NULL);
1103 GtkOptionMenu *mnu = (GtkOptionMenu *)g_object_get_data (G_OBJECT(object), "stopmenu");
1104 SPStop *stop = SP_STOP(g_object_get_data (G_OBJECT(gtk_menu_get_active (GTK_MENU(gtk_option_menu_get_menu (mnu)))), "stop"));
1106 csel = (SPColorSelector*)g_object_get_data (G_OBJECT (object), "cselector");
1107 csel->base->getColorAlpha( color, &alpha );
1108 rgb = sp_color_get_rgba32_ualpha (&color, 0x00);
1110 sp_repr_set_css_double (SP_OBJECT_REPR (stop), "offset", stop->offset);
1111 Inkscape::CSSOStringStream os;
1112 gchar c[64];
1113 sp_svg_write_color (c, 64, rgb);
1114 os << "stop-color:" << c << ";stop-opacity:" << (gdouble) alpha <<";";
1115 SP_OBJECT_REPR (stop)->setAttribute("style", os.str().c_str());
1116 // g_snprintf (c, 256, "stop-color:#%06x;stop-opacity:%g;", rgb >> 8, (gdouble) alpha);
1117 //SP_OBJECT_REPR (stop)->setAttribute("style", c);
1119 sp_document_done (SP_OBJECT_DOCUMENT (ngr));
1121 blocked = FALSE;
1122 }