=== modified file 'src/ege-select-one-action.cpp' --- src/ege-select-one-action.cpp 2012-02-22 18:49:11 +0000 +++ src/ege-select-one-action.cpp 2012-03-27 12:47:54 +0000 @@ -826,6 +826,7 @@ g_signal_connect( G_OBJECT(normal), "changed", G_CALLBACK(combo_changed_cb), action ); g_object_set_data( G_OBJECT(holder), "ege-combo-box", normal ); + g_object_set_data( G_OBJECT(act), "ege-combo-box", normal ); if (act->private_data->appearanceMode == APPEARANCE_COMPACT) { gchar* sss = 0; @@ -1002,7 +1003,7 @@ void combo_changed_cb( GtkComboBox* widget, gpointer user_data ) { EgeSelectOneAction *act = EGE_SELECT_ONE_ACTION(user_data); - gchar *text; + gchar *text = 0; GtkComboBox *cb = GTK_COMBO_BOX (widget); gint newActive = gtk_combo_box_get_active(widget); @@ -1029,6 +1030,11 @@ text = gtk_combo_box_get_active_text (cb); #endif + if (!text) { + /* User probably deleted the data in the model */ + return; + } + if (newActive == -1) { /* indicates the user is entering text for a custom aka "open" value */ if (act->private_data->pendingText && text && (strcmp(act->private_data->pendingText, text) == 0) ) { === modified file 'src/widgets/gradient-toolbar.cpp' --- src/widgets/gradient-toolbar.cpp 2012-03-15 12:43:34 +0000 +++ src/widgets/gradient-toolbar.cpp 2012-03-27 12:49:08 +0000 @@ -40,41 +40,65 @@ #include "sp-linear-gradient.h" #include "sp-radial-gradient.h" #include "gradient-chemistry.h" +#include "gradient-selector.h" #include "selection.h" #include "ui/icon-names.h" +#include "../ege-adjustment-action.h" +#include "../ege-output-action.h" +#include "../ege-select-one-action.h" +#include "../ink-action.h" +#include "../ink-comboboxentry-action.h" + +#include "sp-stop.h" +#include "ui/widget/color-preview.h" +#include "svg/css-ostringstream.h" +#include "svg/svg-color.h" +#include "desktop-style.h" + #include "toolbox.h" +/* + * TODO + * Reselect node on offset change + * Put gradient icon before text in combobox + * move renderers + */ + using Inkscape::DocumentUndo; +using Inkscape::UI::ToolboxFactory; + +static void update_stop_list( GtkWidget *stop_combo, SPGradient *gradient, SPStop *new_stop, GtkWidget *widget, bool gr_multi); +static void sp_gradient_vector_widget_load_gradient(GtkWidget *widget, SPGradient *gradient); +static void select_stop_in_list( GtkWidget *combo_box, SPGradient *gradient, SPStop *new_stop, GtkWidget *data, gboolean block); +static void select_stop_by_drag( GtkWidget *combo_box, SPGradient *gradient, SPEventContext *ev, GtkWidget *data); +static void select_drag_by_stop( GtkWidget *combo_box, SPGradient *gradient, SPEventContext *ev); +static SPGradient *gr_get_selected_gradient (GtkWidget *widget); +void gr_get_dt_selected_gradient (Inkscape::Selection *selection, SPGradient *&gr_selected); +void gr_read_selection( Inkscape::Selection *selection, GrDrag *drag, SPGradient *&gr_selected, bool &gr_multi, SPGradientSpread &spr_selected, bool &spr_multi ); + +static void gr_stop_set_offset (GtkComboBox *widget, GtkWidget *data); +void add_toolbar_widget(GtkWidget *tbl, GtkWidget *widget); +static GtkWidget * gr_ege_select_one_get_combo(GtkWidget *widget, const gchar *name); + +static gboolean blocked = FALSE; //######################## //## Gradient ## //######################## -static void gr_toggle_type (GtkWidget *button, gpointer data) { +static void gr_new_type_changed( EgeSelectOneAction *act, GObject *tbl ) +{ Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - GtkWidget *linear = (GtkWidget *) g_object_get_data (G_OBJECT(data), "linear"); - GtkWidget *radial = (GtkWidget *) g_object_get_data (G_OBJECT(data), "radial"); - if (button == linear && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (linear))) { - prefs->setInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_LINEAR); - if (radial) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radial), FALSE); - } else if (button == radial && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radial))) { - prefs->setInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_RADIAL); - if (linear) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linear), FALSE); - } + gint typemode = ege_select_one_action_get_active( act ) == 0 ? SP_GRADIENT_TYPE_LINEAR : SP_GRADIENT_TYPE_RADIAL; + prefs->setInt("/tools/gradient/newgradient", typemode); } -static void gr_toggle_fillstroke (GtkWidget *button, gpointer data) { +static void gr_new_fillstroke_changed( EgeSelectOneAction *act, GObject *tbl ) +{ Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - GtkWidget *fill = (GtkWidget *) g_object_get_data (G_OBJECT(data), "fill"); - GtkWidget *stroke = (GtkWidget *) g_object_get_data (G_OBJECT(data), "stroke"); - if (button == fill && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fill))) { - prefs->setBool("/tools/gradient/newfillorstroke", true); - if (stroke) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (stroke), FALSE); - } else if (button == stroke && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (stroke))) { - prefs->setBool("/tools/gradient/newfillorstroke", false); - if (fill) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fill), FALSE); - } + bool fillmode = ege_select_one_action_get_active( act ) == 0; + prefs->setBool("/tools/gradient/newfillorstroke", fillmode); } void gr_apply_gradient_to_item( SPItem *item, SPGradient *gr, SPGradientType new_type, guint new_fill, bool do_fill, bool do_stroke ) @@ -141,17 +165,42 @@ } } -void gr_combo_box_changed (GtkComboBox *widget, gpointer data) -{ + +void gr_spread_change (EgeSelectOneAction *act, GtkWidget *widget) +{ + if (blocked) { + return; + } + + SPDesktop *desktop = static_cast(g_object_get_data(G_OBJECT(widget), "desktop")); + Inkscape::Selection *selection = sp_desktop_selection (desktop); + SPGradient *gradient = 0; + gr_get_dt_selected_gradient(selection, gradient); + + if (gradient) { + SPGradientSpread spread = (SPGradientSpread) ege_select_one_action_get_active (act); + gradient->setSpread(spread); + gradient->updateRepr(); + + DocumentUndo::done(sp_desktop_document (desktop), SP_VERB_CONTEXT_GRADIENT, + _("Set gradient repeat")); + } +} + +void gr_gradient_combo_changed (EgeSelectOneAction *act, gpointer data) +{ + if (blocked) { + return; + } + + SPGradient *gr = NULL; + gint n = ege_select_one_action_get_active(act); + GtkTreeModel *model = ege_select_one_action_get_model(act); GtkTreeIter iter; - if (!gtk_combo_box_get_active_iter (widget, &iter)) { - return; + if (gtk_tree_model_iter_nth_child (model ,&iter, NULL, n)) { + gtk_tree_model_get (model, &iter, 2, &gr, -1); } - GtkTreeModel *model = gtk_combo_box_get_model (widget); - SPGradient *gr = NULL; - gtk_tree_model_get (model, &iter, 2, &gr, -1); - if (gr) { gr = sp_gradient_ensure_vector_normalized(gr); @@ -169,26 +218,21 @@ -GtkWidget *gr_vector_list(SPDesktop *desktop, bool selection_empty, SPGradient *gr_selected, bool gr_multi) +void gr_vector_list(GtkWidget *combo_box, SPDesktop *desktop, bool selection_empty, SPGradient *gr_selected, bool gr_multi) { + if (blocked) + return; + SPDocument *document = sp_desktop_document (desktop); - GtkListStore *store; GtkTreeIter iter; - GtkCellRenderer *renderer; - GtkWidget *combo_box; - - store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER); - combo_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)); - - renderer = gtk_cell_renderer_pixbuf_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, FALSE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer, "pixbuf", 0, NULL); - gtk_cell_renderer_set_padding(renderer, 5, 0); - - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer, "text", 1, NULL); + + GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model (GTK_COMBO_BOX(combo_box)); + + blocked = TRUE; + + /* Clear old list, if there is any */ + gtk_list_store_clear(store); GSList *gl = NULL; const GSList *gradients = document->getResourceList("gradient"); @@ -206,13 +250,13 @@ if (!gl) { // The document has no gradients gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, NULL, 1, _("No gradients"), 2, NULL, -1); + gtk_list_store_set (store, &iter, 1, NULL, 0, _("No gradient"), 2, NULL, -1); gtk_widget_set_sensitive (combo_box, FALSE); } else if (selection_empty) { // Document has gradients, but nothing is currently selected. gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, NULL, 1, _("Nothing selected"), 2, NULL, -1); + gtk_list_store_set (store, &iter, 1, NULL, 0, _("Nothing selected"), 2, NULL, -1); gtk_widget_set_sensitive (combo_box, FALSE); } else { @@ -220,7 +264,7 @@ if (gr_selected == NULL) { gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, NULL, 1, _("No gradient"), 2, NULL, -1); + gtk_list_store_set (store, &iter, 1, NULL, 0, _("No gradient"), 2, NULL, -1); gtk_widget_set_sensitive (combo_box, FALSE); } @@ -228,7 +272,7 @@ if (gr_multi) { gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, NULL, 1, _("Multiple gradients"), 2, NULL, -1); + gtk_list_store_set (store, &iter, 1, NULL, 0, _("Multiple gradients"), 2, NULL, -1); gtk_widget_set_sensitive (combo_box, FALSE); } @@ -238,9 +282,9 @@ gl = g_slist_remove (gl, gradient); gchar *label = gr_prepare_label(gradient); - GdkPixbuf *pixb = sp_gradient_to_pixbuf (gradient, 64, 18); + GdkPixbuf *pixb = sp_gradient_to_pixbuf (gradient, 64, 16); gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, pixb, 1, label, 2, gradient, -1); + gtk_list_store_set (store, &iter, 1, pixb, 0, label, 2, gradient, -1); g_free (label); if (gradient == gr_selected) { @@ -249,6 +293,7 @@ idx ++; } gtk_widget_set_sensitive (combo_box, TRUE); + } /* Select the current gradient, or the Multi/Nothing line */ @@ -259,13 +304,48 @@ gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , pos); } - sp_set_font_size_smaller(combo_box); - - g_signal_connect (G_OBJECT (combo_box), "changed", G_CALLBACK (gr_combo_box_changed), desktop); - - return combo_box; -} - + + + //g_signal_connect (G_OBJECT (combo_box), "changed", G_CALLBACK (gr_gradient_combo_changed), desktop); + + blocked = FALSE; + + //return combo_box; +} + +/* + * Get the gradient of the selected item + * this is different to the "getVector" version after all the href resolution. + */ +void gr_get_dt_selected_gradient (Inkscape::Selection *selection, SPGradient *&gr_selected) +{ + SPGradient *gradient = 0; + + for (GSList const* i = selection->itemList(); i; i = i->next) { + SPItem *item = SP_ITEM(i->data); + SPStyle *style = item->style; + SPPaintServer *server = 0; + + if (style && (style->fill.isPaintserver())) { + server = item->style->getFillPaintServer(); + } + if (style && (style->stroke.isPaintserver())) { + server = item->style->getStrokePaintServer(); + } + + if ( SP_IS_GRADIENT(server) ) { + gradient = SP_GRADIENT(server); + } + } + + if (gradient && gradient->isSolid()) { + gradient = 0; + } + + if (gradient) { + gr_selected = gradient; + } +} void gr_read_selection( Inkscape::Selection *selection, GrDrag *drag, @@ -364,8 +444,14 @@ } } + static void gr_tb_selection_changed(Inkscape::Selection * /*selection*/, gpointer data) { + if (blocked) + return; + + //g_message("gr_tb_selection_changed"); + GtkWidget *widget = GTK_WIDGET(data); SPDesktop *desktop = static_cast(g_object_get_data(G_OBJECT(widget), "desktop")); @@ -373,11 +459,9 @@ Inkscape::Selection *selection = sp_desktop_selection(desktop); // take from desktop, not from args if (selection) { SPEventContext *ev = sp_desktop_event_context(desktop); - - GtkWidget *combo_box = (GtkWidget *) g_object_get_data(G_OBJECT(widget), "combobox"); - if (combo_box) { - gtk_widget_destroy(combo_box); - combo_box = 0; + GrDrag *drag = NULL; + if (ev) { + drag = ev->get_drag(); } SPGradient *gr_selected = 0; @@ -386,19 +470,95 @@ SPGradientSpread spr_selected = static_cast(INT_MAX); // meaning undefined bool spr_multi = false; - gr_read_selection(selection, ev ? ev->get_drag() : 0, gr_selected, gr_multi, spr_selected, spr_multi); - - combo_box = gr_vector_list(desktop, selection->isEmpty(), gr_selected, gr_multi); - g_object_set_data(G_OBJECT(widget), "combobox", combo_box); - - GtkWidget *buttons = (GtkWidget *) g_object_get_data(G_OBJECT(widget), "buttons"); - gtk_widget_set_sensitive(buttons, (gr_selected && !gr_multi)); - - gtk_box_pack_start(GTK_BOX(widget), combo_box, TRUE, TRUE, 0); - - gtk_widget_show_all(widget); - } - } + gr_read_selection(selection, ev ? drag : 0, gr_selected, gr_multi, spr_selected, spr_multi); + + GtkWidget *gradient_combo = gr_ege_select_one_get_combo(widget, "gradient_select_combo_action"); + if ( gradient_combo ) { + + gpointer rendered = g_object_get_data( G_OBJECT(gradient_combo), "renderers" ); + if (!rendered) { + + GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (gradient_combo), renderer, FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (gradient_combo), renderer, "pixbuf", 1, NULL); + gtk_cell_renderer_set_padding(renderer, 5, 0); + + /* + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb), renderer, "text", 0, NULL); + */ + + g_object_set_data(G_OBJECT(gradient_combo), "renderers", renderer); + } + gr_vector_list(gradient_combo, desktop, selection->isEmpty(), gr_selected, gr_multi); + + EgeSelectOneAction *gradient_action = (EgeSelectOneAction *) g_object_get_data(G_OBJECT(widget), "gradient_select_combo_action"); + gtk_action_set_sensitive( GTK_ACTION(gradient_action), (selection != NULL) ); + } + + EgeSelectOneAction* spread = (EgeSelectOneAction *) g_object_get_data(G_OBJECT(widget), "gradient_select_repeat_action"); + if (gr_selected) { + blocked = TRUE; + ege_select_one_action_set_active( spread, spr_selected); + blocked = FALSE; + } + gtk_action_set_sensitive( GTK_ACTION(spread), (gr_selected && !gr_multi) ); + + InkAction *add = (InkAction *) g_object_get_data(G_OBJECT(widget), "gradient_stops_add_action"); + gtk_action_set_sensitive(GTK_ACTION(add), (gr_selected && !gr_multi)); + + InkAction *del = (InkAction *) g_object_get_data(G_OBJECT(widget), "gradient_stops_delete_action"); + gtk_action_set_sensitive(GTK_ACTION(del), (gr_selected && !gr_multi && drag && drag->selected)); + + InkAction *reverse = (InkAction *) g_object_get_data(G_OBJECT(widget), "gradient_stops_reverse_action"); + gtk_action_set_sensitive(GTK_ACTION(reverse), (gr_selected && !gr_multi)); + + GtkWidget *stops_combo = gr_ege_select_one_get_combo(widget, "gradient_stops_combo_action"); + if ( stops_combo ) { + gpointer rendered = g_object_get_data( G_OBJECT(stops_combo), "renderers" ); + if (!rendered) { + + GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (stops_combo), renderer, FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (stops_combo), renderer, "pixbuf", 1, NULL); + gtk_cell_renderer_set_padding(renderer, 5, 0); + + /* + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb), renderer, "text", 0, NULL); +*/ + + g_object_set_data(G_OBJECT(stops_combo), "renderers", renderer); + } + + update_stop_list(stops_combo, gr_selected, NULL, widget, gr_multi); + + EgeSelectOneAction *stops_action = (EgeSelectOneAction *) g_object_get_data(G_OBJECT(widget), "gradient_stops_combo_action"); + gtk_action_set_sensitive( GTK_ACTION(stops_action), (gr_selected && !gr_multi) ); + + select_stop_by_drag(stops_combo, gr_selected, ev, widget); + + } + + sp_gradient_vector_widget_load_gradient(widget, gr_selected); + //gtk_widget_show_all(widget); + } + } +} + +static GtkWidget * gr_ege_select_one_get_combo(GtkWidget *widget, const gchar *name) +{ + GtkWidget *combo_box = 0; + EgeSelectOneAction *act1 = (EgeSelectOneAction *)g_object_get_data( G_OBJECT(widget), name); + if (act1) { + gpointer combodata = g_object_get_data( G_OBJECT(act1), "ege-combo-box" ); + if ( GTK_IS_COMBO_BOX(combodata) ) { + combo_box = GTK_WIDGET(combodata); + } + } + return combo_box; } static void @@ -411,6 +571,7 @@ gr_drag_selection_changed (gpointer /*dragger*/, gpointer data) { gr_tb_selection_changed (NULL, data); + } static void @@ -430,220 +591,810 @@ delete connection; } -static void -gr_edit (GtkWidget */*button*/, GtkWidget *widget) -{ - GtkWidget *combo_box = (GtkWidget *) g_object_get_data (G_OBJECT(widget), "combobox"); - - spinbutton_defocus(GTK_OBJECT(widget)); - +static void verify_grad(SPGradient *gradient) +{ + int i = 0; + SPStop *stop = NULL; + /* count stops */ + for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) { + if (SP_IS_STOP(ochild)) { + i++; + stop = SP_STOP(ochild); + } + } + + Inkscape::XML::Document *xml_doc; + xml_doc = gradient->getRepr()->document(); + + if (i < 1) { + Inkscape::CSSOStringStream os; + os << "stop-color: #000000;stop-opacity:" << 1.0 << ";"; + + Inkscape::XML::Node *child; + + child = xml_doc->createElement("svg:stop"); + sp_repr_set_css_double(child, "offset", 0.0); + child->setAttribute("style", os.str().c_str()); + gradient->getRepr()->addChild(child, NULL); + Inkscape::GC::release(child); + + child = xml_doc->createElement("svg:stop"); + sp_repr_set_css_double(child, "offset", 1.0); + child->setAttribute("style", os.str().c_str()); + gradient->getRepr()->addChild(child, NULL); + Inkscape::GC::release(child); + } + if (i < 2) { + sp_repr_set_css_double(stop->getRepr(), "offset", 0.0); + Inkscape::XML::Node *child = stop->getRepr()->duplicate(gradient->getRepr()->document()); + sp_repr_set_css_double(child, "offset", 1.0); + gradient->getRepr()->addChild(child, stop->getRepr()); + Inkscape::GC::release(child); + } +} + + +static SPStop *get_selected_stop( GtkWidget *vb) +{ + SPStop *stop = NULL; +/* + GtkWidget *combo_box = static_cast(g_object_get_data(G_OBJECT(vb), "stop_combo_box")); if (combo_box) { GtkTreeIter iter; - if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX(combo_box), &iter)) { - return; - } - - GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(combo_box)); - SPGradient *gr = NULL; - gtk_tree_model_get (model, &iter, 2, &gr, -1); - - if (gr) { - GtkWidget *dialog = sp_gradient_vector_editor_new (gr); - gtk_widget_show (dialog); - } - } -} - -GtkWidget * gr_change_widget(SPDesktop *desktop) -{ + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(combo_box), &iter)) { + GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model (GTK_COMBO_BOX(combo_box)); + gtk_tree_model_get (GTK_TREE_MODEL(store), &iter, 2, &stop, -1); + } + } +*/ + + GtkWidget *cb = gr_ege_select_one_get_combo(vb, "gradient_stops_combo_action"); + if ( cb ) { + GtkTreeIter iter; + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(cb), &iter)) { + GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model (GTK_COMBO_BOX(cb)); + gtk_tree_model_get (GTK_TREE_MODEL(store), &iter, 2, &stop, -1); + } + } + + return stop; +} + + +static void sp_gradient_vector_gradient_release(SPObject */*object*/, GtkWidget *widget) +{ + sp_gradient_vector_widget_load_gradient(widget, NULL); +} + +static void sp_gradient_vector_gradient_modified(SPObject *object, guint /*flags*/, GtkWidget *widget) +{ + SPGradient *gradient=SP_GRADIENT(object); + if (!blocked) { + blocked = TRUE; + sp_gradient_vector_widget_load_gradient(widget, gradient); + blocked = FALSE; + } +} + +static void sp_gradient_vector_widget_load_gradient(GtkWidget *widget, SPGradient *gradient) +{ + blocked = TRUE; + + SPGradient *old; + + //old = (SPGradient*)g_object_get_data(G_OBJECT(widget), "gradient"); + old = gr_get_selected_gradient(widget); + + if (old != gradient) { + sigc::connection *release_connection; + sigc::connection *modified_connection; + + release_connection = (sigc::connection *)g_object_get_data(G_OBJECT(widget), "gradient_release_connection"); + modified_connection = (sigc::connection *)g_object_get_data(G_OBJECT(widget), "gradient_modified_connection"); + + if (old) { + g_assert( release_connection != NULL ); + g_assert( modified_connection != NULL ); + release_connection->disconnect(); + modified_connection->disconnect(); + sp_signal_disconnect_by_data(old, widget); + } + + if (gradient) { + if (!release_connection) { + release_connection = new sigc::connection(); + } + if (!modified_connection) { + modified_connection = new sigc::connection(); + } + *release_connection = gradient->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_gradient_vector_gradient_release), widget)); + *modified_connection = gradient->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_gradient_vector_gradient_modified), widget)); + } else { + if (release_connection) { + delete release_connection; + release_connection = NULL; + } + if (modified_connection) { + delete modified_connection; + modified_connection = NULL; + } + } + + g_object_set_data(G_OBJECT(widget), "gradient_release_connection", release_connection); + g_object_set_data(G_OBJECT(widget), "gradient_modified_connection", modified_connection); + } + + //g_object_set_data(G_OBJECT(widget), "gradient", gradient); + + if (gradient) { + gtk_widget_set_sensitive(widget, TRUE); + + gradient->ensureVector(); + + SPStop *stop = get_selected_stop(widget); + if (!stop) { + return; + } + + // Once the user edits a gradient, it stops being auto-collectable + if (gradient->getRepr()->attribute("inkscape:collect")) { + SPDocument *document = gradient->document; + bool saved = DocumentUndo::getUndoSensitive(document); + DocumentUndo::setUndoSensitive(document, false); + gradient->getRepr()->setAttribute("inkscape:collect", NULL); + DocumentUndo::setUndoSensitive(document, saved); + } + } else { // no gradient, disable everything + gtk_widget_set_sensitive(widget, FALSE); + } + + blocked = FALSE; +} + +static void +gr_add_stop (GtkWidget */*button*/,GtkWidget *vb) +{ + //SPGradient *gradient = static_cast(g_object_get_data(G_OBJECT(vb), "gradient")); + SPGradient *gradient = gr_get_selected_gradient(vb); + + verify_grad(gradient); + + SPStop *stop = get_selected_stop(vb); + if (!stop) { + return; + } + + Inkscape::XML::Node *new_stop_repr = NULL; + + SPStop *next = stop->getNextStop(); + + if (next == NULL) { + SPStop *prev = stop->getPrevStop(); + if (prev != NULL) { + next = stop; + stop = prev; + } + } + + if (next != NULL) { + new_stop_repr = stop->getRepr()->duplicate(gradient->getRepr()->document()); + gradient->getRepr()->addChild(new_stop_repr, stop->getRepr()); + } else { + next = stop; + new_stop_repr = stop->getPrevStop()->getRepr()->duplicate(gradient->getRepr()->document()); + gradient->getRepr()->addChild(new_stop_repr, stop->getPrevStop()->getRepr()); + } + + SPStop *newstop = reinterpret_cast(gradient->document->getObjectByRepr(new_stop_repr)); + + newstop->offset = (stop->offset + next->offset) * 0.5 ; + + guint32 const c1 = sp_stop_get_rgba32(stop); + guint32 const c2 = sp_stop_get_rgba32(next); + guint32 cnew = sp_average_color(c1, c2); + + Inkscape::CSSOStringStream os; + gchar c[64]; + sp_svg_write_color(c, sizeof(c), cnew); + gdouble opacity = static_cast(SP_RGBA32_A_F(cnew)); + os << "stop-color:" << c << ";stop-opacity:" << opacity <<";"; + newstop->getRepr()->setAttribute("style", os.str().c_str()); + sp_repr_set_css_double( newstop->getRepr(), "offset", (double)newstop->offset); + + sp_gradient_vector_widget_load_gradient(vb, gradient); + Inkscape::GC::release(new_stop_repr); + + DocumentUndo::done(gradient->document, SP_VERB_CONTEXT_GRADIENT, + _("Add gradient stop")); +} + +static void +gr_remove_stop (GtkWidget */*button*/, GtkWidget *vb) +{ + //SPGradient *gradient = static_cast(g_object_get_data(G_OBJECT(vb), "gradient")); + SPGradient *gradient = gr_get_selected_gradient(vb); + if (!gradient) { + return; + } + + SPStop *stop = get_selected_stop(vb); + if (!stop) { + return; + } + + if (gradient->vector.stops.size() > 2) { // 2 is the minimum + + // if we delete first or last stop, move the next/previous to the edge + if (stop->offset == 0) { + SPStop *next = stop->getNextStop(); + if (next) { + next->offset = 0; + sp_repr_set_css_double(next->getRepr(), "offset", 0); + } + } else if (stop->offset == 1) { + SPStop *prev = stop->getPrevStop(); + if (prev) { + prev->offset = 1; + sp_repr_set_css_double(prev->getRepr(), "offset", 1); + } + } + + gradient->getRepr()->removeChild(stop->getRepr()); + sp_gradient_vector_widget_load_gradient(vb, gradient); + //GtkWidget *stop_combo = (GtkWidget *) g_object_get_data(G_OBJECT(vb), "stop_combo_box"); + GtkWidget *stop_combo = gr_ege_select_one_get_combo(vb, "gradient_stops_combo_action"); + update_stop_list(stop_combo, gradient, NULL, vb, FALSE); + DocumentUndo::done(gradient->document, SP_VERB_CONTEXT_GRADIENT, + _("Delete gradient stop")); + } + +} + +static void +gr_reverse (GtkWidget */*button*/, gpointer data) +{ + SPDesktop *desktop = static_cast(data); + Inkscape::Selection *selection = sp_desktop_selection (desktop); + SPEventContext *ev = sp_desktop_event_context (desktop); + + if (!ev) { + return; + } + + GrDrag *drag = ev->get_drag(); + + // First try selected dragger + if (drag && drag->selected) { + drag->selected_reverse_vector(); + } else { // If no drag or no dragger selected, act on selection (both fill and stroke gradients) + for (GSList const* i = selection->itemList(); i != NULL; i = i->next) { + sp_item_gradient_reverse_vector (SP_ITEM(i->data), true); + sp_item_gradient_reverse_vector (SP_ITEM(i->data), false); + } + } + // we did an undoable action + DocumentUndo::done(sp_desktop_document (desktop), SP_VERB_CONTEXT_GRADIENT, + _("Invert gradient")); +} + +/* + * Change desktop drag selection to this stop + */ +static void select_drag_by_stop( GtkWidget *data, SPGradient *gradient, SPEventContext *ev) +{ + if (blocked || !ev || !gradient) + return; + + GrDrag *drag = ev->get_drag(); + if (!drag) { + return; + } + + SPStop *stop = get_selected_stop(data); + + + SPStop *stop_iter; + GList *i; + + // Walk thru the draggers and the gradient stops at the same time + for (i = drag->draggers, stop_iter = gradient->getFirstStop(); + i != NULL && stop_iter && SP_IS_STOP(stop_iter); + i = i->next, stop_iter = SP_STOP(stop_iter->getNext())) { + + if (stop == stop_iter) { + GrDragger *d = (GrDragger *) i->data; + drag->setSelected(d, false, true); + blocked = FALSE; + return; + } + } +} + +static void select_stop_by_drag( GtkWidget *combo_box, SPGradient *gradient, SPEventContext *ev, GtkWidget *data) +{ + if (blocked || !ev || !gradient) + return; + + GrDrag *drag = ev->get_drag(); + + if (!drag || !drag->selected) { + blocked = TRUE; + gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , 0); + gr_stop_set_offset(GTK_COMBO_BOX(combo_box), data); + blocked = FALSE; + return; + } + + // for all selected draggers + for (GList *i = drag->selected; i != NULL; i = i->next) { + + // TODO How to handle multiple selection ? + GrDragger *dragger = (GrDragger *) i->data; + + // The first draggable + GSList const* j = dragger->draggables; + GrDraggable *draggable = (GrDraggable *) j->data; + + SPGradient *vector = gradient->getVector(); + if (!vector) + return; + + SPStop *stop = vector->getFirstStop(); + + switch (draggable->point_type) { + case POINT_LG_MID: + case POINT_RG_MID1: + case POINT_RG_MID2: + { + stop = sp_get_stop_i(vector, draggable->point_i); + } + break; + case POINT_LG_END: + case POINT_RG_R1: + case POINT_RG_R2: + { + stop = sp_last_stop(vector); + } + break; + default: + break; + } + + select_stop_in_list( combo_box, gradient, stop, data, TRUE); + + return; + } +} + +static void select_stop_in_list( GtkWidget *combo_box, SPGradient *gradient, SPStop *new_stop, GtkWidget *data, gboolean block) +{ + //if (blocked) + // return; + + int i = 0; + for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) { + if (SP_IS_STOP(ochild)) { + if (ochild == new_stop) { + blocked = block; + gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , i); + gr_stop_set_offset(GTK_COMBO_BOX(combo_box), data); + blocked = FALSE; + return; + } + i++; + } + } +} + + +static void update_stop_list( GtkWidget *stop_combo, SPGradient *gradient, SPStop *new_stop, GtkWidget *widget, bool gr_multi) +{ + if (!stop_combo) { + return; + } + + GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model (GTK_COMBO_BOX(stop_combo)); + if (!store) { + return; + } + + blocked = TRUE; + + /* Clear old list, if there is any */ + gtk_list_store_clear(store); + GtkTreeIter iter; + + + if (!SP_IS_GRADIENT(gradient)) { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 1, NULL, 0, _("No gradient"), 2, NULL, -1); + gtk_combo_box_set_active (GTK_COMBO_BOX(stop_combo) , 0); + gtk_widget_set_sensitive (stop_combo, FALSE); + blocked = FALSE; + return; + } + + /* Populate the combobox store */ + GSList *sl = NULL; + if ( gradient->hasStops() ) { + for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) { + if (SP_IS_STOP(ochild)) { + sl = g_slist_append(sl, ochild); + } + } + } + if (!sl) { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 1, NULL, 0, _("No stops in gradient"), 2, NULL, -1); + gtk_widget_set_sensitive (stop_combo, FALSE); + + } else { + + for (; sl != NULL; sl = sl->next){ + if (SP_IS_STOP(sl->data)){ + SPStop *stop = SP_STOP(sl->data); + Inkscape::XML::Node *repr = reinterpret_cast(sl->data)->getRepr(); + Inkscape::UI::Widget::ColorPreview *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(sp_stop_get_rgba32(stop))); + GdkPixbuf *pb = cpv->toPixbuf(32, 16); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 1, pb, 0, repr->attribute("id"), 2, stop, -1); + gtk_widget_set_sensitive (stop_combo, FALSE); + } + } + + gtk_widget_set_sensitive(stop_combo, TRUE); + } + + + if (gr_multi) { + gtk_widget_set_sensitive (stop_combo, FALSE); + } + + /* Set history */ + if (new_stop == NULL) { + gtk_combo_box_set_active (GTK_COMBO_BOX(stop_combo) , 0); + } else { + select_stop_in_list(stop_combo, gradient, new_stop, widget, TRUE); + } + + blocked = FALSE; +} + +static SPGradient *gr_get_selected_gradient (GtkWidget *widget) +{ + SPGradient *gr = NULL; + EgeSelectOneAction* act1 = (EgeSelectOneAction *)g_object_get_data( G_OBJECT(widget), "gradient_select_combo_action"); + if (act1) { + gint n = ege_select_one_action_get_active(act1); + GtkTreeModel *model = ege_select_one_action_get_model(act1); + GtkTreeIter iter; + if (gtk_tree_model_iter_nth_child (model ,&iter, NULL, n)) { + SPGradient *gr = NULL; + gtk_tree_model_get (model, &iter, 2, &gr, -1); + return gr; + } + } + + return gr; +} + +/*static void +gr_edit (GtkWidget *button, GtkWidget *widget) +{ + SPGradient *gr = gr_get_selected_gradient(widget); + if (gr) { + GtkWidget *dialog = sp_gradient_vector_editor_new (gr); + gtk_widget_show (dialog); + } +}*/ + +static void gr_stop_set_offset (GtkComboBox */*widget*/, GtkWidget *data) +{ + SPStop *stop = get_selected_stop(data); + if (!stop) { + return; + } + + EgeAdjustmentAction* act = (EgeAdjustmentAction *)g_object_get_data( G_OBJECT(data), "offset_action"); + if (!act) { + return; + } + + GtkAdjustment *adj = ege_adjustment_action_get_adjustment(act); + + bool isEndStop = false; + + SPStop *prev = NULL; + prev = stop->getPrevStop(); + if (prev != NULL ) { + gtk_adjustment_set_lower (adj, prev->offset); + } else { + isEndStop = true; + gtk_adjustment_set_lower (adj, 0); + } + + SPStop *next = NULL; + next = stop->getNextStop(); + if (next != NULL ) { + gtk_adjustment_set_upper (adj, next->offset); + } else { + isEndStop = true; + gtk_adjustment_set_upper (adj, 1.0); + } + + + blocked = TRUE; + gtk_adjustment_set_value(adj, stop->offset); + gtk_action_set_sensitive( GTK_ACTION(act), !isEndStop ); + gtk_adjustment_changed(adj); + blocked = FALSE; + + InkAction *del = (InkAction *) g_object_get_data(G_OBJECT(data), "gradient_stops_delete_action"); + gtk_action_set_sensitive(GTK_ACTION(del), !isEndStop); + +} + +static void gr_stop_combo_changed (GtkComboBox *widget, GtkWidget *data) +{ + if (blocked) { + return; + } + + SPDesktop *desktop = static_cast(g_object_get_data(G_OBJECT(data), "desktop")); + SPEventContext *ev = sp_desktop_event_context (desktop); + SPGradient *gr = gr_get_selected_gradient(data); + + select_drag_by_stop(data, gr, ev); +} + +static void gr_stop_offset_adjustment_changed(GtkAdjustment *adj, GObject *tbl) +{ + if (blocked) { + return; + } + + blocked = TRUE; + + SPStop *stop = get_selected_stop(GTK_WIDGET(tbl)); + if (stop) { + stop->offset = gtk_adjustment_get_value (adj); + sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset); + + DocumentUndo::maybeDone(stop->document, "gradient:stop:offset", SP_VERB_CONTEXT_GRADIENT, + _("Change gradient stop offset")); + + } + + blocked = FALSE; +} + +/** + * Gradient auxiliary toolbar construction and setup. + * + */ +void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObject* holder) +{ + Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1); + + /* New gradient type*/ + { + GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); + + GtkTreeIter iter; + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, + 0, _("linear"), 1, _("Create linear gradient"), 2, INKSCAPE_ICON("paint-gradient-linear"), -1 ); + + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, + 0, _("radial"), 1, _("Create radial (elliptic or circular) gradient"), 2, INKSCAPE_ICON("paint-gradient-radial"), -1 ); + + EgeSelectOneAction* act = ege_select_one_action_new( "GradientNewTypeAction", (""), (""), NULL, GTK_TREE_MODEL(model) ); + g_object_set( act, "short_label", _("New:"), NULL ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + g_object_set_data( holder, "gradient_new_type_action", act ); + + ege_select_one_action_set_appearance( act, "full" ); + ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE ); + g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL ); + ege_select_one_action_set_icon_column( act, 2 ); + ege_select_one_action_set_tooltip_column( act, 1 ); + + /// @todo Convert to boolean? + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gint mode = prefs->getInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_LINEAR) != SP_GRADIENT_TYPE_LINEAR; + ege_select_one_action_set_active( act, mode ); + g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(gr_new_type_changed), holder ); + } + + /* New gradient on fill or stroke*/ + { + GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); + + GtkTreeIter iter; + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, + 0, _("fill"), 1, _("Create gradient in the fill"), 2, INKSCAPE_ICON("object-fill"), -1 ); + + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, + 0, _("stroke"), 1, _("Create gradient in the stroke"), 2, INKSCAPE_ICON("object-stroke"), -1 ); + + EgeSelectOneAction* act = ege_select_one_action_new( "GradientNewFillStrokeAction", (""), (""), NULL, GTK_TREE_MODEL(model) ); + g_object_set( act, "short_label", _("on:"), NULL ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + g_object_set_data( holder, "gradient_new_fillstroke_action", act ); + + ege_select_one_action_set_appearance( act, "full" ); + ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE ); + g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL ); + ege_select_one_action_set_icon_column( act, 2 ); + ege_select_one_action_set_tooltip_column( act, 1 ); + + /// @todo Convert to boolean? + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool fillstrokemode = !prefs->getBool("/tools/gradient/newfillorstroke", true); + ege_select_one_action_set_active( act, fillstrokemode ); + g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(gr_new_fillstroke_changed), holder ); + } + + + /* Gradient Select list*/ + { + GtkListStore *store = gtk_list_store_new (3, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER); + + GtkTreeIter iter; + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 1, NULL, 0, _("No gradient"), 2, NULL, -1); + + EgeSelectOneAction* act1 = ege_select_one_action_new( "GradientSelectGradientAction", _("Select:"), ("Choose a gradient"), NULL, GTK_TREE_MODEL(store) ); + g_object_set( act1, "short_label", _("Select:"), NULL ); + ege_select_one_action_set_appearance( act1, "compact" ); + gtk_action_set_sensitive( GTK_ACTION(act1), FALSE ); + g_signal_connect( G_OBJECT(act1), "changed", G_CALLBACK(gr_gradient_combo_changed), desktop ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act1) ); + g_object_set_data( holder, "gradient_select_combo_action", act1 ); + + } + + // Gradient Repeat type + { + GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT ); + + GtkTreeIter iter; + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, 0, _("none"), 1, SP_GRADIENT_SPREAD_PAD, -1 ); + + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, 0, _("reflected"), 1, SP_GRADIENT_SPREAD_REFLECT, -1 ); + + gtk_list_store_append( model, &iter ); + gtk_list_store_set( model, &iter, 0, _("direct"), 1, SP_GRADIENT_SPREAD_REPEAT, -1 ); + + EgeSelectOneAction* act1 = ege_select_one_action_new( "GradientSelectRepeatAction", _("Repeat"), + (// TRANSLATORS: for info, see http://www.w3.org/TR/2000/CR-SVG-20000802/pservers.html#LinearGradientSpreadMethodAttribute + _("Whether to fill with flat color beyond the ends of the gradient vector " + "(spreadMethod=\"pad\"), or repeat the gradient in the same direction " + "(spreadMethod=\"repeat\"), or repeat the gradient in alternating opposite " + "directions (spreadMethod=\"reflect\")")), + NULL, GTK_TREE_MODEL(model) ); + g_object_set( act1, "short_label", _("Repeat:"), NULL ); + ege_select_one_action_set_appearance( act1, "compact" ); + gtk_action_set_sensitive( GTK_ACTION(act1), FALSE ); + g_signal_connect( G_OBJECT(act1), "changed", G_CALLBACK(gr_spread_change), holder ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act1) ); + g_object_set_data( holder, "gradient_select_repeat_action", act1 ); + } + + /* Gradient Stop list */ + { + GtkListStore *store = gtk_list_store_new (3, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER); + + GtkTreeIter iter; + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 1, NULL, 0, _("No gradient"), 2, NULL, -1); + + EgeSelectOneAction* act1 = ege_select_one_action_new( "GradientEditStopsAction", _("Stops"), _("Select a stop for the current gradient"), NULL, GTK_TREE_MODEL(store) ); + g_object_set( act1, "short_label", _("Edit:"), NULL ); + ege_select_one_action_set_appearance( act1, "compact" ); + gtk_action_set_sensitive( GTK_ACTION(act1), FALSE ); + g_signal_connect( G_OBJECT(act1), "changed", G_CALLBACK(gr_stop_combo_changed), holder ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act1) ); + g_object_set_data( holder, "gradient_stops_combo_action", act1 ); + } + + /* Offset */ + { + EgeAdjustmentAction* eact = 0; + gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + gdouble values[] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; + eact = create_adjustment_action( "GradientEditOffsetAction", + _("Offset"), _("Offset:"), _("Offset of selected stop"), + "/tools/gradient/stopoffset", 0, + GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, FALSE, NULL, + 0.0, 1.0, 0.01, 0.1, + labels, values, G_N_ELEMENTS(labels), + gr_stop_offset_adjustment_changed + , 0.01, 2, 1.0); + + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + g_object_set_data( holder, "offset_action", eact ); + gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); + + } + /* Add stop*/ + { + InkAction* inky = ink_action_new( "GradientEditAddAction", + _("Insert new stop"), + _("Insert new stop"), + INKSCAPE_ICON("node-add"), + secondarySize ); + g_object_set( inky, "short_label", _("Delete"), NULL ); + g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(gr_add_stop), holder ); + gtk_action_group_add_action( mainActions, GTK_ACTION(inky) ); + gtk_action_set_sensitive( GTK_ACTION(inky), FALSE ); + g_object_set_data( holder, "gradient_stops_add_action", inky ); + } + + /* Delete stop*/ + { + InkAction* inky = ink_action_new( "GradientEditDeleteAction", + _("Delete stop"), + _("Delete stop"), + INKSCAPE_ICON("node-delete"), + secondarySize ); + g_object_set( inky, "short_label", _("Delete"), NULL ); + g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(gr_remove_stop), holder ); + gtk_action_group_add_action( mainActions, GTK_ACTION(inky) ); + gtk_action_set_sensitive( GTK_ACTION(inky), FALSE ); + g_object_set_data( holder, "gradient_stops_delete_action", inky ); + } + + /* Reverse */ + { + InkAction* inky = ink_action_new( "GradientEditReverseAction", + _("Reverse"), + _("Reverse the direction of the gradient"), + INKSCAPE_ICON("object-flip-horizontal"), + secondarySize ); + g_object_set( inky, "short_label", _("Delete"), NULL ); + g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(gr_reverse), desktop ); + gtk_action_group_add_action( mainActions, GTK_ACTION(inky) ); + gtk_action_set_sensitive( GTK_ACTION(inky), FALSE ); + g_object_set_data( holder, "gradient_stops_reverse_action", inky ); + + } + Inkscape::Selection *selection = sp_desktop_selection (desktop); SPDocument *document = sp_desktop_document (desktop); - SPEventContext *ev = sp_desktop_event_context (desktop); - - SPGradient *gr_selected = NULL; - bool gr_multi = false; - - SPGradientSpread spr_selected = (SPGradientSpread) INT_MAX; // meaning undefined - bool spr_multi = false; - - gr_read_selection (selection, ev? ev->get_drag() : 0, gr_selected, gr_multi, spr_selected, spr_multi); - - GtkWidget *widget = gtk_hbox_new(FALSE, FALSE); - g_object_set_data(G_OBJECT(widget), "dtw", desktop->canvas); - g_object_set_data (G_OBJECT (widget), "desktop", desktop); - - GtkWidget *combo_box = gr_vector_list(desktop, selection->isEmpty(), gr_selected, gr_multi); - g_object_set_data(G_OBJECT(widget), "combobox", combo_box); - - gtk_box_pack_start (GTK_BOX (widget), combo_box, TRUE, TRUE, 0); - - { - GtkWidget *buttons = gtk_hbox_new(FALSE, 1); - - /* Edit... */ - { - GtkWidget *hb = gtk_hbox_new(FALSE, 1); - GtkWidget *b = gtk_button_new_with_label(_("Edit...")); - gtk_widget_set_tooltip_text(b, _("Edit the stops of the gradient")); - gtk_widget_show(b); - gtk_container_add(GTK_CONTAINER(hb), b); - g_signal_connect(G_OBJECT(b), "clicked", G_CALLBACK(gr_edit), widget); - gtk_box_pack_start (GTK_BOX(buttons), hb, FALSE, FALSE, 0); - } - - gtk_box_pack_end (GTK_BOX(widget), buttons, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT(widget), "buttons", buttons); - gtk_widget_set_sensitive (buttons, (gr_selected && !gr_multi)); - } + + g_object_set_data(holder, "desktop", desktop); // connect to selection modified and changed signals - sigc::connection *conn1 = new sigc::connection (selection->connectChanged( - sigc::bind ( - sigc::ptr_fun(&gr_tb_selection_changed), - (gpointer)widget ) - )); - sigc::connection *conn2 = new sigc::connection (selection->connectModified( - sigc::bind ( - sigc::ptr_fun(&gr_tb_selection_modified), - (gpointer)widget ) - )); - - sigc::connection *conn3 = new sigc::connection (desktop->connectToolSubselectionChanged( - sigc::bind ( - sigc::ptr_fun(&gr_drag_selection_changed), - (gpointer)widget ) - )); - - // when widget is destroyed, disconnect - g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gr_disconnect_sigc), conn1); - g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gr_disconnect_sigc), conn2); - g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gr_disconnect_sigc), conn3); - - // connect to release and modified signals of the defs (i.e. when someone changes gradient) + sigc::connection *conn1 = new sigc::connection( + selection->connectChanged(sigc::bind(sigc::ptr_fun(&gr_tb_selection_changed), (gpointer) holder))); + sigc::connection *conn2 = new sigc::connection( + selection->connectModified(sigc::bind(sigc::ptr_fun(&gr_tb_selection_modified), (gpointer) holder))); + sigc::connection *conn3 = new sigc::connection( + desktop->connectToolSubselectionChanged( sigc::bind(sigc::ptr_fun(&gr_drag_selection_changed), (gpointer) holder))); + + // when holder is destroyed, disconnect + g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(gr_disconnect_sigc), conn1); + g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(gr_disconnect_sigc), conn2); + g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(gr_disconnect_sigc), conn3); + + // connect to release and modified signals of the defs (i.e. when someone changes gradient) sigc::connection *release_connection = new sigc::connection(); - *release_connection = document->getDefs()->connectRelease(sigc::bind<1>(sigc::ptr_fun(&gr_defs_release), widget)); + *release_connection = document->getDefs()->connectRelease(sigc::bind<1>(sigc::ptr_fun(&gr_defs_release), GTK_WIDGET(holder))); sigc::connection *modified_connection = new sigc::connection(); - *modified_connection = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&gr_defs_modified), widget)); - - // when widget is destroyed, disconnect - g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gr_disconnect_sigc), release_connection); - g_signal_connect(G_OBJECT(widget), "destroy", G_CALLBACK(gr_disconnect_sigc), modified_connection); - - gtk_widget_show_all (widget); - return widget; -} - -GtkWidget * -sp_gradient_toolbox_new(SPDesktop *desktop) -{ - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - GtkWidget *tbl = gtk_toolbar_new(); - - g_object_set_data(G_OBJECT(tbl), "dtw", desktop->canvas); - g_object_set_data(G_OBJECT(tbl), "desktop", desktop); - - sp_toolbox_add_label(tbl, _("New:")); - - // TODO replace aux_toolbox_space(tbl, AUX_SPACING); - - { - GtkWidget *cvbox = gtk_vbox_new (FALSE, 0); - GtkWidget *cbox = gtk_hbox_new (FALSE, 0); - - { - GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION, - SP_BUTTON_TYPE_TOGGLE, - NULL, - INKSCAPE_ICON("paint-gradient-linear"), - _("Create linear gradient") ); - g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (gr_toggle_type), tbl); - g_object_set_data(G_OBJECT(tbl), "linear", button); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), - prefs->getInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_LINEAR) == SP_GRADIENT_TYPE_LINEAR); - gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0); - } - - { - GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION, - SP_BUTTON_TYPE_TOGGLE, - NULL, - INKSCAPE_ICON("paint-gradient-radial"), - _("Create radial (elliptic or circular) gradient")); - g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (gr_toggle_type), tbl); - g_object_set_data(G_OBJECT(tbl), "radial", button); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), - prefs->getInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_LINEAR) == SP_GRADIENT_TYPE_RADIAL); - gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0); - } - - gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0); - GtkToolItem *cvbox_toolitem = gtk_tool_item_new(); - gtk_container_add(GTK_CONTAINER(cvbox_toolitem), cvbox); - gtk_toolbar_insert(GTK_TOOLBAR(tbl), cvbox_toolitem, -1); - } - - // TODO replace aux_toolbox_space(tbl, AUX_SPACING); - - sp_toolbox_add_label(tbl, _("on"), false); - - // TODO replace aux_toolbox_space(tbl, AUX_SPACING); - - { - GtkWidget *cvbox = gtk_vbox_new (FALSE, 0); - GtkWidget *cbox = gtk_hbox_new (FALSE, 0); - - { - GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION, - SP_BUTTON_TYPE_TOGGLE, - NULL, - INKSCAPE_ICON("object-fill"), - _("Create gradient in the fill")); - g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (gr_toggle_fillstroke), tbl); - g_object_set_data(G_OBJECT(tbl), "fill", button); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), - prefs->getBool("/tools/gradient/newfillorstroke", true)); - gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0); - } - - { - GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION, - SP_BUTTON_TYPE_TOGGLE, - NULL, - INKSCAPE_ICON("object-stroke"), - _("Create gradient in the stroke")); - g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (gr_toggle_fillstroke), tbl); - g_object_set_data(G_OBJECT(tbl), "stroke", button); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), - !prefs->getBool("/tools/gradient/newfillorstroke", true)); - gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0); - } - - gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, TRUE, 3); - GtkToolItem *cvbox_toolitem = gtk_tool_item_new(); - gtk_container_add(GTK_CONTAINER(cvbox_toolitem), cvbox); - gtk_toolbar_insert(GTK_TOOLBAR(tbl), cvbox_toolitem, -1); - } - - - sp_toolbox_add_label(tbl, _("Change:")); - - // TODO replace aux_toolbox_space(tbl, AUX_SPACING); - - { - GtkWidget *vectors = gr_change_widget (desktop); - GtkToolItem *vectors_toolitem = gtk_tool_item_new(); - gtk_container_add(GTK_CONTAINER(vectors_toolitem), vectors); - gtk_toolbar_insert(GTK_TOOLBAR(tbl), vectors_toolitem, -1); - } - - gtk_widget_show_all(tbl); - sp_set_font_size_smaller (tbl); - - return tbl; -} - - - + *modified_connection = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&gr_defs_modified), GTK_WIDGET(holder))); + + // when holder is destroyed, disconnect + g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(gr_disconnect_sigc), release_connection); + g_signal_connect(G_OBJECT(holder), "destroy", G_CALLBACK(gr_disconnect_sigc), modified_connection); + +} /* Local Variables: === modified file 'src/widgets/gradient-toolbar.h' --- src/widgets/gradient-toolbar.h 2011-06-03 10:44:52 +0000 +++ src/widgets/gradient-toolbar.h 2012-03-26 02:32:22 +0000 @@ -16,6 +16,6 @@ struct SPDesktop; GtkWidget *sp_gradient_toolbox_new (SPDesktop *desktop); - +void sp_gradient_toolbox_prep(SPDesktop * /*desktop*/, GtkActionGroup* mainActions, GObject* holder); #endif /* !SEEN_SELECT_TOOLBAR_H */ === modified file 'src/widgets/gradient-vector.cpp' --- src/widgets/gradient-vector.cpp 2012-03-15 12:43:34 +0000 +++ src/widgets/gradient-vector.cpp 2012-03-25 14:22:36 +0000 @@ -682,7 +682,7 @@ } } -guint32 sp_average_color(guint32 c1, guint32 c2, gdouble p = 0.5) +guint32 sp_average_color(guint32 c1, guint32 c2, gdouble p/* = 0.5*/) { guint32 r = (guint32) (SP_RGBA32_R_U(c1) * p + SP_RGBA32_R_U(c2) * (1 - p)); guint32 g = (guint32) (SP_RGBA32_G_U(c1) * p + SP_RGBA32_G_U(c2) * (1 - p)); === modified file 'src/widgets/gradient-vector.h' --- src/widgets/gradient-vector.h 2012-03-15 12:43:34 +0000 +++ src/widgets/gradient-vector.h 2012-03-25 14:22:36 +0000 @@ -75,6 +75,8 @@ /* fixme: rethink this (Lauris) */ GtkWidget *sp_gradient_vector_editor_new (SPGradient *gradient, SPStop *stop = NULL); +guint32 sp_average_color(guint32 c1, guint32 c2, gdouble p = 0.5); + gchar *gr_prepare_label (SPObject *obj); === modified file 'src/widgets/toolbox.cpp' --- src/widgets/toolbox.cpp 2012-03-12 00:31:09 +0000 +++ src/widgets/toolbox.cpp 2012-03-27 12:57:17 +0000 @@ -243,10 +243,12 @@ SP_VERB_INVALID, 0, 0}, { "SPDropperContext", "dropper_toolbox", 0, sp_dropper_toolbox_prep, "DropperToolbar", SP_VERB_INVALID, 0, 0}, - { "SPGradientContext", "gradient_toolbox", sp_gradient_toolbox_new, 0, 0, - SP_VERB_INVALID, 0, 0}, +/* { "SPGradientContext", "gradient_toolbox", sp_gradient_toolbox_new, 0, 0, + SP_VERB_INVALID, 0, 0},*/ { "SPConnectorContext", "connector_toolbox", 0, sp_connector_toolbox_prep, "ConnectorToolbar", SP_VERB_INVALID, 0, 0}, + { "SPGradientContext", "gradient_toolbox", 0, sp_gradient_toolbox_prep, "GradientToolbar", + SP_VERB_INVALID, 0, 0}, { "SPFloodContext", "paintbucket_toolbox", 0, sp_paintbucket_toolbox_prep, "PaintbucketToolbar", SP_VERB_CONTEXT_PAINTBUCKET_PREFS, "/tools/paintbucket", N_("Style of Paint Bucket fill objects")}, { NULL, NULL, NULL, NULL, NULL, SP_VERB_INVALID, NULL, NULL } @@ -529,6 +531,20 @@ " " " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " " " " " @@ -1082,7 +1098,7 @@ return widget; } -static EgeAdjustmentAction * create_adjustment_action( gchar const *name, +EgeAdjustmentAction * create_adjustment_action( gchar const *name, gchar const *label, gchar const *shortLabel, gchar const *tooltip, Glib::ustring const &path, gdouble def, GtkWidget *focusTarget, @@ -1092,7 +1108,7 @@ gdouble lower, gdouble upper, gdouble step, gdouble page, gchar const** descrLabels, gdouble const* descrValues, guint descrCount, void (*callback)(GtkAdjustment *, GObject *), - gdouble climb = 0.1, guint digits = 3, double factor = 1.0 ) + gdouble climb/* = 0.1*/, guint digits/* = 3*/, double factor/* = 1.0*/ ) { static bool init = false; if ( !init ) { @@ -3086,7 +3102,7 @@ gtk_box_pack_end(GTK_BOX(boxl), l, FALSE, FALSE, 0); if ( GTK_IS_TOOLBAR(tbl) ) { GtkToolItem *boxl_toolitem = gtk_tool_item_new(); - gtk_container_add(GTK_CONTAINER(boxl_toolitem), boxl); + gtk_container_add(GTK_CONTAINER(boxl_toolitem), boxl); gtk_toolbar_insert(GTK_TOOLBAR(tbl), boxl_toolitem, -1); } else { gtk_box_pack_start(GTK_BOX(tbl), boxl, FALSE, FALSE, 0); === modified file 'src/widgets/toolbox.h' --- src/widgets/toolbox.h 2011-10-23 08:01:33 +0000 +++ src/widgets/toolbox.h 2012-03-26 03:48:00 +0000 @@ -17,6 +17,7 @@ #include #include "icon-size.h" +#include "../ege-adjustment-action.h" class SPDesktop; class SPEventContext; @@ -39,6 +40,7 @@ static GtkWidget *createCommandsToolbox(); static GtkWidget *createSnapToolbox(); + static Glib::ustring getToolboxName(GtkWidget* toolbox); static void updateSnapToolbox(SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox); @@ -58,6 +60,17 @@ // TODO remove this: void sp_toolbox_add_label(GtkWidget *tbl, gchar const *title, bool wide = true); + EgeAdjustmentAction * create_adjustment_action( gchar const *name, + gchar const *label, gchar const *shortLabel, gchar const *tooltip, + Glib::ustring const &path, gdouble def, + GtkWidget *focusTarget, + GtkWidget *us, + GObject *dataKludge, + gboolean altx, gchar const *altx_mark, + gdouble lower, gdouble upper, gdouble step, gdouble page, + gchar const** descrLabels, gdouble const* descrValues, guint descrCount, + void (*callback)(GtkAdjustment *, GObject *), + gdouble climb = 0.1, guint digits = 3, double factor = 1.0 ); #endif /* !SEEN_TOOLBOX_H */