Code

Upgraded gradient tool =)
[inkscape.git] / src / widgets / gradient-toolbar.cpp
1 /*
2  * Gradient aux toolbar
3  *
4  * Authors:
5  *   bulia byak <bulia@dr.com>
6  *
7  * Copyright (C) 2005 authors
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #ifdef HAVE_CONFIG_H
13 # include "config.h"
14 #endif
16 #include <gtk/gtk.h>
18 #include "macros.h"
19 #include "widgets/button.h"
20 #include "widgets/widget-sizes.h"
21 #include "widgets/spw-utilities.h"
22 #include "widgets/spinbutton-events.h"
23 #include "widgets/gradient-vector.h"
24 #include "widgets/gradient-image.h"
25 #include "style.h"
27 #include "prefs-utils.h"
28 #include "document-private.h"
29 #include "desktop.h"
30 #include "desktop-handles.h"
31 #include <glibmm/i18n.h>
33 #include "gradient-context.h"
34 #include "gradient-drag.h"
35 #include "sp-linear-gradient.h"
36 #include "sp-radial-gradient.h"
37 #include "gradient-chemistry.h"
38 #include "selection.h"
40 #include "toolbox.h"
43 //########################
44 //##       Gradient     ##
45 //########################
47 static void gr_toggle_type (GtkWidget *button, gpointer data) {
48     GtkWidget *linear = (GtkWidget *) g_object_get_data (G_OBJECT(data), "linear");
49     GtkWidget *radial = (GtkWidget *) g_object_get_data (G_OBJECT(data), "radial");
50     if (button == linear && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (linear))) {
51         prefs_set_int_attribute ("tools.gradient", "newgradient", SP_GRADIENT_TYPE_LINEAR);
52         if (radial) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radial), FALSE);
53     } else if (button == radial && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radial))) {
54         prefs_set_int_attribute ("tools.gradient", "newgradient", SP_GRADIENT_TYPE_RADIAL);
55         if (linear) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linear), FALSE);
56     }
57 }
59 static void gr_toggle_fillstroke (GtkWidget *button, gpointer data) {
60     GtkWidget *fill = (GtkWidget *) g_object_get_data (G_OBJECT(data), "fill");
61     GtkWidget *stroke = (GtkWidget *) g_object_get_data (G_OBJECT(data), "stroke");
62     if (button == fill && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fill))) {
63         prefs_set_int_attribute ("tools.gradient", "newfillorstroke", 1);
64         if (stroke) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (stroke), FALSE);
65     } else if (button == stroke && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (stroke))) {
66         prefs_set_int_attribute ("tools.gradient", "newfillorstroke", 0);
67         if (fill) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fill), FALSE);
68     }
69 }
71 void
72 gr_apply_gradient_to_item (SPItem *item, SPGradient *gr, SPGradientType new_type, guint new_fill, bool do_fill, bool do_stroke)
73 {
74     SPStyle *style = SP_OBJECT_STYLE (item);
76     if (do_fill) {
77         if (style && (style->fill.type == SP_PAINT_TYPE_PAINTSERVER) && 
78             SP_IS_GRADIENT (SP_OBJECT_STYLE_FILL_SERVER (item))) {
79             SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item);
80             if (SP_IS_LINEARGRADIENT (server)) {
81                 sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_LINEAR, true);
82             } else if (SP_IS_RADIALGRADIENT (server)) {
83                 sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_RADIAL, true);
84             } 
85         } else if (new_fill) {
86             sp_item_set_gradient(item, gr, new_type, true);
87         }
88     } 
90     if (do_stroke) {
91         if (style && (style->stroke.type == SP_PAINT_TYPE_PAINTSERVER) && 
92             SP_IS_GRADIENT (SP_OBJECT_STYLE_STROKE_SERVER (item))) {
93             SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item);
94             if (SP_IS_LINEARGRADIENT (server)) {
95                 sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_LINEAR, false);
96             } else if (SP_IS_RADIALGRADIENT (server)) {
97                 sp_item_set_gradient(item, gr, SP_GRADIENT_TYPE_RADIAL, false);
98             } 
99         } else if (!new_fill) {
100             sp_item_set_gradient(item, gr, new_type, false);
101         }
102     }
105 /**
106 Applies gradient vector gr to the gradients attached to the selected dragger of drag, or if none,
107 to all objects in selection. If there was no previous gradient on an item, uses gradient type and
108 fill/stroke setting from preferences to create new default (linear: left/right; radial: centered)
109 gradient.
110 */
111 void
112 gr_apply_gradient (Inkscape::Selection *selection, GrDrag *drag, SPGradient *gr)
114     SPGradientType new_type = (SPGradientType) prefs_get_int_attribute ("tools.gradient", "newgradient", SP_GRADIENT_TYPE_LINEAR);
115     guint new_fill = prefs_get_int_attribute ("tools.gradient", "newfillorstroke", 1);
118     // GRADIENTFIXME: make this work for multiple selected draggers.
119     
120     // First try selected dragger
121     if (drag && drag->selected) {
122         GrDragger *dragger = (GrDragger*) drag->selected->data;
123         for (GSList const* i = dragger->draggables; i != NULL; i = i->next) { // for all draggables of dragger
124             GrDraggable *draggable = (GrDraggable *) i->data;
125             gr_apply_gradient_to_item (draggable->item, gr, new_type, new_fill, draggable->fill_or_stroke, !draggable->fill_or_stroke);
126         }
127         return;
128     }
130    // If no drag or no dragger selected, act on selection
131    for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
132        gr_apply_gradient_to_item (SP_ITEM(i->data), gr, new_type, new_fill, new_fill, !new_fill);
133    }
136 void
137 gr_item_activate (GtkMenuItem *menuitem, gpointer data)
139     SPGradient *gr = (SPGradient *) g_object_get_data (G_OBJECT (menuitem), "gradient");
140     gr = sp_gradient_ensure_vector_normalized(gr);
142     SPDesktop *desktop = (SPDesktop *) data;
143     Inkscape::Selection *selection = sp_desktop_selection (desktop);
144     SPEventContext *ev = sp_desktop_event_context (desktop);
146     gr_apply_gradient (selection, ev? ev->get_drag() : NULL, gr);
148     sp_document_done (sp_desktop_document (desktop), SP_VERB_CONTEXT_GRADIENT,
149                       _("Assign gradient to object"));
152 gchar *
153 gr_prepare_label (SPObject *obj)
155     const gchar *id = obj->defaultLabel();
156     if (strlen(id) > 15 && (!strncmp (id, "#linearGradient", 15) || !strncmp (id, "#radialGradient", 15))) 
157         return g_strdup_printf ("<small>#%s</small>", id+15);
158     return g_strdup_printf ("<small>%s</small>", id);
161 GtkWidget *
162 gr_vector_list (SPDesktop *desktop, bool selection_empty, SPGradient *gr_selected, bool gr_multi)
164     SPDocument *document = sp_desktop_document (desktop);
166     GtkWidget *om = gtk_option_menu_new ();
167     GtkWidget *m = gtk_menu_new ();
169     GSList *gl = NULL;
170     const GSList *gradients = sp_document_get_resource_list (document, "gradient");
171                 for (const GSList *i = gradients; i != NULL; i = i->next) {
172         if (SP_GRADIENT_HAS_STOPS (i->data)) {
173             gl = g_slist_prepend (gl, i->data);
174         }
175                 }
176     gl = g_slist_reverse (gl);
178     guint pos = 0;
179     guint idx = 0;
181     if (!gl) {
182         GtkWidget *l = gtk_label_new("");
183         gtk_label_set_markup (GTK_LABEL(l), _("<small>No gradients</small>"));
184         GtkWidget *i = gtk_menu_item_new ();
185         gtk_container_add (GTK_CONTAINER (i), l);
187         gtk_widget_show (i);
188         gtk_menu_append (GTK_MENU (m), i);
189         gtk_widget_set_sensitive (om, FALSE);
190     } else if (selection_empty) {
191         GtkWidget *l = gtk_label_new("");
192         gtk_label_set_markup (GTK_LABEL(l), _("<small>Nothing selected</small>"));
193         GtkWidget *i = gtk_menu_item_new ();
194         gtk_container_add (GTK_CONTAINER (i), l);
196         gtk_widget_show (i);
197         gtk_menu_append (GTK_MENU (m), i);
198         gtk_widget_set_sensitive (om, FALSE);
199     } else {
201         if (gr_selected == NULL) {
202             GtkWidget *l = gtk_label_new("");
203             gtk_label_set_markup (GTK_LABEL(l), _("<small>No gradients in selection</small>"));
204             GtkWidget *i = gtk_menu_item_new ();
205             gtk_container_add (GTK_CONTAINER (i), l);
207             gtk_widget_show (i);
208             gtk_menu_append (GTK_MENU (m), i);
209         }
211         if (gr_multi) {
212             GtkWidget *l = gtk_label_new("");
213             gtk_label_set_markup (GTK_LABEL(l), _("<small>Multiple gradients</small>"));
214             GtkWidget *i = gtk_menu_item_new ();
215             gtk_container_add (GTK_CONTAINER (i), l);
217             gtk_widget_show (i);
218             gtk_menu_append (GTK_MENU (m), i);
219         }
221         while (gl) {
222             SPGradient *gradient = SP_GRADIENT (gl->data);
223             gl = g_slist_remove (gl, gradient);
225             GtkWidget *i = gtk_menu_item_new ();
226             g_object_set_data (G_OBJECT (i), "gradient", gradient);
227             g_signal_connect (G_OBJECT (i), "activate", G_CALLBACK (gr_item_activate), desktop);
229             GtkWidget *image = sp_gradient_image_new (gradient);
231             GtkWidget *hb = gtk_hbox_new (FALSE, 4);
232             GtkWidget *l = gtk_label_new ("");
233             gchar *label = gr_prepare_label (SP_OBJECT(gradient));
234             gtk_label_set_markup (GTK_LABEL(l), label);
235             g_free (label);
236             gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
237             gtk_box_pack_start (GTK_BOX (hb), l, TRUE, TRUE, 0);
238             gtk_box_pack_start (GTK_BOX (hb), image, FALSE, FALSE, 0);
240             gtk_widget_show_all (i);
242             gtk_container_add (GTK_CONTAINER (i), hb);
244             gtk_menu_append (GTK_MENU (m), i);
246             if (gradient == gr_selected) {
247                 pos = idx;
248             }
249             idx ++;
250         }
251         gtk_widget_set_sensitive (om, TRUE);
252     }
254     gtk_option_menu_set_menu (GTK_OPTION_MENU (om), m);
255     /* Select the current gradient, or the Multi/Nothing line */
256     if (gr_multi || gr_selected == NULL)
257         gtk_option_menu_set_history (GTK_OPTION_MENU (om), 0);
258     else 
259         gtk_option_menu_set_history (GTK_OPTION_MENU (om), pos);
261     return om;
265 void
266 gr_read_selection (Inkscape::Selection *selection, GrDrag *drag, SPGradient **gr_selected, bool *gr_multi, SPGradientSpread *spr_selected, bool *spr_multi) 
268     if (drag && drag->selected) {
269         // GRADIENTFIXME: make this work for more than one selected dragger?
270         GrDragger *dragger = (GrDragger*) drag->selected->data;
271         for (GSList const* i = dragger->draggables; i != NULL; i = i->next) { // for all draggables of dragger
272             GrDraggable *draggable = (GrDraggable *) i->data;
273             SPGradient *gradient = sp_item_gradient_get_vector (draggable->item, draggable->fill_or_stroke);
274             SPGradientSpread spread = sp_item_gradient_get_spread (draggable->item, draggable->fill_or_stroke);
276             if (gradient != *gr_selected) {
277                 if (*gr_selected != NULL) {
278                     *gr_multi = true;
279                 } else {
280                     *gr_selected = gradient;
281                 }
282             }
283             if (spread != *spr_selected) {
284                 if (*spr_selected != INT_MAX) {
285                     *spr_multi = true;
286                 } else {
287                     *spr_selected = spread;
288                 }
289             }
290          }
291         return;
292     } 
294    // If no selected dragger, read desktop selection
295    for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
296         SPItem *item = SP_ITEM(i->data);
297         SPStyle *style = SP_OBJECT_STYLE (item);
299         if (style && (style->fill.type == SP_PAINT_TYPE_PAINTSERVER)) { 
300             SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item);
301             if (SP_IS_GRADIENT (server)) {
302                 SPGradient *gradient = sp_gradient_get_vector (SP_GRADIENT (server), false);
303                 SPGradientSpread spread = sp_gradient_get_spread (SP_GRADIENT (server));
304                 if (gradient != *gr_selected) {
305                     if (*gr_selected != NULL) {
306                         *gr_multi = true;
307                     } else {
308                         *gr_selected = gradient;
309                     }
310                 }
311                 if (spread != *spr_selected) {
312                     if (*spr_selected != INT_MAX) {
313                         *spr_multi = true;
314                     } else {
315                         *spr_selected = spread;
316                     }
317                 }
318             }
319         }
320         if (style && (style->stroke.type == SP_PAINT_TYPE_PAINTSERVER)) { 
321             SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item);
322             if (SP_IS_GRADIENT (server)) {
323                 SPGradient *gradient = sp_gradient_get_vector (SP_GRADIENT (server), false);
324                 SPGradientSpread spread = sp_gradient_get_spread (SP_GRADIENT (server));
325                 if (gradient != *gr_selected) {
326                     if (*gr_selected != NULL) {
327                         *gr_multi = true;
328                     } else {
329                         *gr_selected = gradient;
330                     }
331                 }
332                 if (spread != *spr_selected) {
333                     if (*spr_selected != INT_MAX) {
334                         *spr_multi = true;
335                     } else {
336                         *spr_selected = spread;
337                     }
338                 }
339             }
340         }
341     }
342  }
344 static void 
345 gr_tb_selection_changed (Inkscape::Selection *, gpointer data)
347     GtkWidget *widget = (GtkWidget *) data;
349     SPDesktop *desktop = (SPDesktop *) g_object_get_data (G_OBJECT(widget), "desktop");
350     if (!desktop)
351         return;
353     Inkscape::Selection *selection = sp_desktop_selection (desktop); // take from desktop, not from args
354     if (!selection) 
355         return;
356     
357     SPEventContext *ev = sp_desktop_event_context (desktop);
359     GtkWidget *om = (GtkWidget *) g_object_get_data (G_OBJECT (widget), "menu");
360     if (om) gtk_widget_destroy (om);
362     SPGradient *gr_selected = NULL;
363     bool gr_multi = false;
365     SPGradientSpread spr_selected = (SPGradientSpread) INT_MAX; // meaning undefined
366     bool spr_multi = false;
368     gr_read_selection (selection, ev? ev->get_drag() : NULL, &gr_selected, &gr_multi, &spr_selected, &spr_multi);
370     om = gr_vector_list (desktop, selection->isEmpty(), gr_selected, gr_multi);
371     g_object_set_data (G_OBJECT (widget), "menu", om);
373     GtkWidget *buttons = (GtkWidget *) g_object_get_data (G_OBJECT(widget), "buttons");
374     gtk_widget_set_sensitive (buttons, (gr_selected && !gr_multi));
375   
376     gtk_box_pack_start (GTK_BOX (widget), om, TRUE, TRUE, 0);
378     gtk_widget_show_all (widget);
381 static void
382 gr_tb_selection_modified (Inkscape::Selection *selection, guint flags, gpointer data)
384     gr_tb_selection_changed (selection, data);
387 static void
388 gr_drag_selection_changed (gpointer dragger, gpointer data)
390     gr_tb_selection_changed (NULL, data);
393 static void
394 gr_defs_release (SPObject *defs, GtkWidget *widget)
396     gr_tb_selection_changed (NULL, (gpointer) widget);
399 static void
400 gr_defs_modified (SPObject *defs, guint flags, GtkWidget *widget)
402     gr_tb_selection_changed (NULL, (gpointer) widget);
405 static void
406 gr_fork (GtkWidget *button, GtkWidget *widget)
408     SPDesktop *desktop = (SPDesktop *) g_object_get_data (G_OBJECT(widget), "desktop");
409     SPDocument *document = sp_desktop_document (desktop);
410     Inkscape::Selection *selection = sp_desktop_selection (desktop);
411     SPEventContext *ev = sp_desktop_event_context (desktop);
412     GtkWidget *om = (GtkWidget *) g_object_get_data (G_OBJECT(widget), "menu");
414     if (om && document) {
415         GtkWidget *i = gtk_menu_get_active (GTK_MENU (gtk_option_menu_get_menu (GTK_OPTION_MENU (om))));
416         SPGradient *gr = (SPGradient *) g_object_get_data (G_OBJECT(i), "gradient");
418         if (gr) {
419             SPGradient *gr_new = sp_gradient_fork_vector_if_necessary (gr);
420             if (gr_new != gr) {
421                 gr_apply_gradient (selection, ev? ev->get_drag() : NULL, gr_new);
422                 sp_document_done (document, SP_VERB_CONTEXT_GRADIENT,
423                                   _("Duplicate gradient"));
424             }
425         }
426     }
428     spinbutton_defocus(GTK_OBJECT(widget));
431 static void gr_disconnect_sigc (GObject *obj, sigc::connection *connection) {
432     connection->disconnect();
433     delete connection;
436 static void
437 gr_edit (GtkWidget *button, GtkWidget *widget)
439     GtkWidget *om = (GtkWidget *) g_object_get_data (G_OBJECT(widget), "menu");
441     spinbutton_defocus(GTK_OBJECT(widget));
443     if (om) {
444         GtkWidget *i = gtk_menu_get_active (GTK_MENU (gtk_option_menu_get_menu (GTK_OPTION_MENU (om))));
445         SPGradient *gr = (SPGradient *) g_object_get_data (G_OBJECT(i), "gradient");
447         if (gr) {
448             GtkWidget *dialog = sp_gradient_vector_editor_new (gr);
449             gtk_widget_show (dialog);
450         }
451     }
454 GtkWidget *
455 gr_change_widget (SPDesktop *desktop)
457     Inkscape::Selection *selection = sp_desktop_selection (desktop);
458     SPDocument *document = sp_desktop_document (desktop);
459     SPEventContext *ev = sp_desktop_event_context (desktop);
461     SPGradient *gr_selected = NULL;
462     bool gr_multi = false;
464     SPGradientSpread spr_selected = (SPGradientSpread) INT_MAX; // meaning undefined
465     bool spr_multi = false;
467     GtkTooltips *tt = gtk_tooltips_new();
469     gr_read_selection (selection, ev? ev->get_drag() : NULL, &gr_selected, &gr_multi, &spr_selected, &spr_multi);
470  
471     GtkWidget *widget = gtk_hbox_new(FALSE, FALSE);
472     gtk_object_set_data(GTK_OBJECT(widget), "dtw", desktop->canvas);
473     g_object_set_data (G_OBJECT (widget), "desktop", desktop);
475     GtkWidget *om = gr_vector_list (desktop, selection->isEmpty(), gr_selected, gr_multi);
476     g_object_set_data (G_OBJECT (widget), "menu", om);
477   
478     gtk_box_pack_start (GTK_BOX (widget), om, TRUE, TRUE, 0);
480     {
481     GtkWidget *buttons = gtk_hbox_new(FALSE, 1);
483     /* Fork */
484     {
485         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
486         GtkWidget *b = gtk_button_new_with_label(_("Duplicate"));
487         gtk_tooltips_set_tip(tt, b, _("If the gradient is used by more than one object, create a copy of it for the selected object(s)"), NULL);
488         gtk_widget_show(b);
489         gtk_container_add(GTK_CONTAINER(hb), b);
490         gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(gr_fork), widget);
491         gtk_box_pack_start (GTK_BOX(buttons), hb, FALSE, FALSE, 0);
492     }
494     /* Edit... */
495     {
496         GtkWidget *hb = gtk_hbox_new(FALSE, 1);
497         GtkWidget *b = gtk_button_new_with_label(_("Edit..."));
498         gtk_tooltips_set_tip(tt, b, _("Edit the stops of the gradient"), NULL);
499         gtk_widget_show(b);
500         gtk_container_add(GTK_CONTAINER(hb), b);
501         gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(gr_edit), widget);
502         gtk_box_pack_start (GTK_BOX(buttons), hb, FALSE, FALSE, 0);
503     }
505     gtk_box_pack_end (GTK_BOX(widget), buttons, FALSE, FALSE, 0);
506     g_object_set_data (G_OBJECT(widget), "buttons", buttons);
507     gtk_widget_set_sensitive (buttons, (gr_selected && !gr_multi));
508     }
510     // connect to selection modified and changed signals
511     sigc::connection *conn1 = new sigc::connection (selection->connectChanged(
512         sigc::bind (
513             sigc::ptr_fun(&gr_tb_selection_changed),
514             (gpointer)widget )
515     ));
516     sigc::connection *conn2 = new sigc::connection (selection->connectModified(
517         sigc::bind (
518             sigc::ptr_fun(&gr_tb_selection_modified),
519             (gpointer)widget )
520     ));
522     sigc::connection *conn3 = new sigc::connection (desktop->connectToolSubselectionChanged(
523         sigc::bind (
524             sigc::ptr_fun(&gr_drag_selection_changed),
525             (gpointer)widget )
526     ));
528     // when widget is destroyed, disconnect
529     g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gr_disconnect_sigc), conn1);
530     g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gr_disconnect_sigc), conn2);
531     g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gr_disconnect_sigc), conn3);
533     // connect to release and modified signals of the defs (i.e. when someone changes gradient)
534     sigc::connection *release_connection = new sigc::connection();
535     *release_connection = SP_DOCUMENT_DEFS(document)->connectRelease(sigc::bind<1>(sigc::ptr_fun(&gr_defs_release), widget));
536     sigc::connection *modified_connection = new sigc::connection();
537     *modified_connection = SP_DOCUMENT_DEFS(document)->connectModified(sigc::bind<2>(sigc::ptr_fun(&gr_defs_modified), widget));
539     // when widget is destroyed, disconnect
540     g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gr_disconnect_sigc), release_connection);
541     g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gr_disconnect_sigc), modified_connection);
543     gtk_widget_show_all (widget);
544     return widget;
547 GtkWidget *
548 sp_gradient_toolbox_new(SPDesktop *desktop)
550     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
552     gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
553     gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
555     GtkTooltips *tt = gtk_tooltips_new();
557     sp_toolbox_add_label(tbl, _("<b>New:</b>"));
559     aux_toolbox_space(tbl, AUX_SPACING);
561     {
562     GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
563     GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
565     {
566     GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
567                                               SP_BUTTON_TYPE_TOGGLE,
568                                               NULL,
569                                               "fill_gradient",
570                                               _("Create linear gradient"),
571                                               tt);
572     g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (gr_toggle_type), tbl);
573     g_object_set_data(G_OBJECT(tbl), "linear", button);
574     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), 
575               prefs_get_int_attribute ("tools.gradient", "newgradient", SP_GRADIENT_TYPE_LINEAR) == SP_GRADIENT_TYPE_LINEAR);
576     gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
577     }
579     {
580     GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
581                                               SP_BUTTON_TYPE_TOGGLE,
582                                               NULL,
583                                               "fill_radial",
584                                               _("Create radial (elliptic or circular) gradient"),
585                                               tt);
586     g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (gr_toggle_type), tbl);
587     g_object_set_data(G_OBJECT(tbl), "radial", button);
588     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), 
589               prefs_get_int_attribute ("tools.gradient", "newgradient", SP_GRADIENT_TYPE_LINEAR) == SP_GRADIENT_TYPE_RADIAL);
590     gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
591     }
593     gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0);
594     gtk_box_pack_start(GTK_BOX(tbl), cvbox, FALSE, FALSE, 0);
595     }
597     aux_toolbox_space(tbl, AUX_SPACING);
599     sp_toolbox_add_label(tbl, _("on"), false);
601     aux_toolbox_space(tbl, AUX_SPACING);
603     {
604         GtkWidget *cvbox = gtk_vbox_new (FALSE, 0);
605     GtkWidget *cbox = gtk_hbox_new (FALSE, 0);
607     {
608     GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
609                                               SP_BUTTON_TYPE_TOGGLE,
610                                               NULL,
611                                               "controls_fill",
612                                               _("Create gradient in the fill"),
613                                               tt);
614     g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (gr_toggle_fillstroke), tbl);
615     g_object_set_data(G_OBJECT(tbl), "fill", button);
616     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), 
617                                   prefs_get_int_attribute ("tools.gradient", "newfillorstroke", 1) == 1);
618     gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
619     }
621     {
622     GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION,
623                                               SP_BUTTON_TYPE_TOGGLE,
624                                               NULL,
625                                               "controls_stroke",
626                                               _("Create gradient in the stroke"),
627                                               tt);
628     g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (gr_toggle_fillstroke), tbl);
629     g_object_set_data(G_OBJECT(tbl), "stroke", button);
630     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), 
631                                   prefs_get_int_attribute ("tools.gradient", "newfillorstroke", 1) == 0);
632     gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0);
633     }
635     gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, TRUE, 3);
636     gtk_box_pack_start(GTK_BOX(tbl), cvbox, FALSE, FALSE, 0);
637     }
640     sp_toolbox_add_label(tbl, _("<b>Change:</b>"));
642     aux_toolbox_space(tbl, AUX_SPACING);
644     {
645         GtkWidget *vectors = gr_change_widget (desktop);
646         gtk_box_pack_start (GTK_BOX (tbl), vectors, FALSE, FALSE, 0);
647     }
649     gtk_widget_show_all(tbl);
650     sp_set_font_size_smaller (tbl);
652     return tbl;
658 /*
659   Local Variables:
660   mode:c++
661   c-file-style:"stroustrup"
662   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
663   indent-tabs-mode:nil
664   fill-column:99
665   End:
666 */
667 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :