diff options
Diffstat (limited to 'src/widgets/gradient-toolbar.cpp')
| -rw-r--r-- | src/widgets/gradient-toolbar.cpp | 1214 |
1 files changed, 597 insertions, 617 deletions
diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp index 6f2f6a06c..70d4d359e 100644 --- a/src/widgets/gradient-toolbar.cpp +++ b/src/widgets/gradient-toolbar.cpp @@ -23,7 +23,6 @@ #include "document-undo.h" #include "document.h" #include "widgets/ege-adjustment-action.h" -#include "widgets/ege-select-one-action.h" #include "gradient-chemistry.h" #include "gradient-drag.h" #include "gradient-toolbar.h" @@ -41,6 +40,7 @@ #include "ui/icon-names.h" #include "ui/util.h" #include "ui/tools/gradient-tool.h" +#include "ui/widget/ink-select-one-action.h" #include "verbs.h" #include "widgets/gradient-image.h" #include "widgets/gradient-vector.h" @@ -49,24 +49,7 @@ using Inkscape::DocumentUndo; using Inkscape::UI::ToolboxFactory; using Inkscape::UI::Tools::ToolBase; -void gr_apply_gradient_to_item( SPItem *item, SPGradient *gr, SPGradientType initialType, Inkscape::PaintTarget initialMode, Inkscape::PaintTarget mode ); -void gr_apply_gradient(Inkscape::Selection *selection, GrDrag *drag, SPGradient *gr); -gboolean gr_vector_list(GtkWidget *combo_box, SPDesktop *desktop, bool selection_empty, SPGradient *gr_selected, bool gr_multi); -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 gboolean 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, ToolBase *ev, GtkWidget *data); -static void select_drag_by_stop( GtkWidget *combo_box, SPGradient *gradient, ToolBase *ev); -static SPGradient *gr_get_selected_gradient(GtkWidget *widget); -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); -void check_renderer(GtkWidget *combo); -static void gr_tb_selection_changed(Inkscape::Selection *selection, gpointer data); - -static gboolean blocked = FALSE; +static bool blocked = false; //######################## //## Gradient ## @@ -124,23 +107,17 @@ void gr_apply_gradient(Inkscape::Selection *selection, GrDrag *drag, SPGradient } } -gboolean gr_vector_list(GtkWidget *combo_box, SPDesktop *desktop, bool selection_empty, SPGradient *gr_selected, bool gr_multi) +int gr_vector_list(Glib::RefPtr<Gtk::ListStore> store, SPDesktop *desktop, + bool selection_empty, SPGradient *gr_selected, bool gr_multi) { - gboolean sensitive = FALSE; - if (blocked) { - return sensitive; + int selected = -1; + + if (!blocked) { + std::cerr << "gr_vector_list: should be blocked!" << std::endl; } + // Get list of gradients in document. SPDocument *document = desktop->getDocument(); - - GtkTreeIter iter; - 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); - std::vector<SPObject *> gl; std::vector<SPObject *> gradients = document->getResourceList( "gradient" ); for (std::vector<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) { @@ -150,64 +127,78 @@ gboolean gr_vector_list(GtkWidget *combo_box, SPDesktop *desktop, bool selection } } - guint pos = 0; + store->clear(); + + InkSelectOneActionColumns columns; + Gtk::TreeModel::Row row; if (gl.empty()) { // The document has no gradients - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, _("No gradient"), 1, NULL, 2, NULL, -1); - sensitive = FALSE; + + row = *(store->append()); + row[columns.col_label ] = _("No gradient"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_data ] = nullptr; + row[columns.col_sensitive] = true; } 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, _("Nothing selected"), 1, NULL, 2, NULL, -1); - sensitive = FALSE; + + row = *(store->append()); + row[columns.col_label ] = _("Nothing Selected"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_data ] = nullptr; + row[columns.col_sensitive] = true; } else { if (gr_selected == NULL) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, _("No gradient"), 1, NULL, 2, NULL, -1); - // Dead assignment: Value stored to 'sensitive' is never read - //sensitive = FALSE; + row = *(store->append()); + row[columns.col_label ] = _("No gradient"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_data ] = nullptr; + row[columns.col_sensitive] = true; } if (gr_multi) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, _("Multiple gradients"), 1, NULL, 2, NULL, -1); - // Dead assignment: Value stored to 'sensitive' is never read - //sensitive = FALSE; + row = *(store->append()); + row[columns.col_label ] = _("Multiple gradients"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_data ] = nullptr; + row[columns.col_sensitive] = true; } - guint idx = 0; + int idx = 0; for (std::vector<SPObject *>::const_iterator it = gl.begin(); it != gl.end(); ++it) { SPGradient *gradient = SP_GRADIENT(*it); Glib::ustring label = gr_prepare_label(gradient); - GdkPixbuf *pixb = sp_gradient_to_pixbuf(gradient, 64, 16); - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, label.c_str(), 1, pixb, 2, gradient, -1); + Glib::RefPtr<Gdk::Pixbuf> pixbuf = sp_gradient_to_pixbuf_ref(gradient, 64, 16); + + row = *(store->append()); + row[columns.col_label ] = label; + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_pixbuf ] = pixbuf; + row[columns.col_data ] = gradient; + row[columns.col_sensitive] = true; if (gradient == gr_selected) { - pos = idx; + selected = idx; } idx ++; } - sensitive = TRUE; - - } - /* Select the current gradient, or the Multi/Nothing line */ - if (gr_multi || gr_selected == NULL) { - gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box) , 0); - } - else { - gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box) , pos); + if (gr_multi) { + selected = 0; // This will show "Multiple Gradients" + } } - blocked = FALSE; - return sensitive; + return selected; } /* @@ -346,221 +337,27 @@ void gr_read_selection( Inkscape::Selection *selection, } } -/* - * Core function, setup all the widgets whenever something changes on the desktop - */ -static void gr_tb_selection_changed(Inkscape::Selection * /*selection*/, gpointer data) -{ - if (blocked) - return; - - GtkWidget *widget = GTK_WIDGET(data); - - SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(G_OBJECT(widget), "desktop")); - if (!desktop) { - return; - } - - Inkscape::Selection *selection = desktop->getSelection(); // take from desktop, not from args - if (selection) { - ToolBase *ev = desktop->getEventContext(); - GrDrag *drag = NULL; - if (ev) { - drag = ev->get_drag(); - } - - SPGradient *gr_selected = 0; - SPGradientSpread spr_selected = SP_GRADIENT_SPREAD_UNDEFINED; - bool gr_multi = false; - bool spr_multi = false; - - gr_read_selection(selection, drag, 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 ) { - check_renderer(gradient_combo); - gboolean sensitive = 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), sensitive ); - } - - EgeSelectOneAction* spread = (EgeSelectOneAction *) g_object_get_data(G_OBJECT(widget), "gradient_select_repeat_action"); - gtk_action_set_sensitive( GTK_ACTION(spread), (gr_selected && !gr_multi) ); - if (gr_selected) { - blocked = TRUE; - ege_select_one_action_set_active( spread, spr_selected); - blocked = FALSE; - } - - 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 && drag && !drag->selected.empty())); - - 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.empty())); - - InkAction *reverse = (InkAction *) g_object_get_data(G_OBJECT(widget), "gradient_stops_reverse_action"); - gtk_action_set_sensitive(GTK_ACTION(reverse), (gr_selected!= NULL)); - - 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) ); - - GtkWidget *stops_combo = gr_ege_select_one_get_combo(widget, "gradient_stops_combo_action"); - if ( stops_combo ) { - - check_renderer(stops_combo); - update_stop_list(stops_combo, gr_selected, NULL, widget, gr_multi); - select_stop_by_drag(stops_combo, gr_selected, ev, widget); - } - - //sp_gradient_vector_widget_load_gradient(widget, gr_selected); - - } - -} - -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 gr_tb_selection_modified(Inkscape::Selection *selection, guint /*flags*/, gpointer data) +/* Get stop selected by menu */ +static SPStop *get_selected_stop( GObject *data) { - gr_tb_selection_changed(selection, data); -} + InkSelectOneAction *act = + static_cast<InkSelectOneAction *>(g_object_get_data(data, "gradient_stop_action")); -static void gr_drag_selection_changed(gpointer /*dragger*/, gpointer data) -{ - gr_tb_selection_changed(NULL, data); - -} + int active = act->get_active(); -static void gr_defs_release(SPObject * /*defs*/, GtkWidget *widget) -{ - gr_tb_selection_changed(NULL, (gpointer) widget); -} - -static void gr_defs_modified(SPObject * /*defs*/, guint /*flags*/, GtkWidget *widget) -{ - gr_tb_selection_changed(NULL, (gpointer) widget); -} - -static SPStop *get_selected_stop( GtkWidget *vb) -{ - SPStop *stop = NULL; - - 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); - } - } + Glib::RefPtr<Gtk::ListStore> store = act->get_store(); + Gtk::TreeModel::Row row = store->children()[active]; + InkSelectOneActionColumns columns; + void* pointer = row[columns.col_data]; + SPStop *stop = static_cast<SPStop *>(pointer); 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 = gr_get_selected_gradient(widget); - - if (old != gradient) { - - g_message("Load 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); - } - - 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) +/* Add stop to gradient */ +static void gr_add_stop(GtkWidget * /*button*/, GObject *data) { - SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(G_OBJECT(vb), "desktop")); + SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(data, "desktop")); if (!desktop) { return; } @@ -579,10 +376,11 @@ static void gr_add_stop(GtkWidget * /*button*/, GtkWidget *vb) } -static void gr_remove_stop(GtkWidget * /*button*/, GtkWidget *vb) +/* Remove stop from vector */ +static void gr_remove_stop(GtkWidget * /*button*/, GObject *data) { - SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(G_OBJECT(vb), "desktop")); + SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(data, "desktop")); if (!desktop) { return; } @@ -604,6 +402,7 @@ static void gr_remove_stop(GtkWidget * /*button*/, GtkWidget *vb) } +/* Lock or unlock links */ static void gr_linked_changed(GtkToggleAction *act, gpointer /*data*/) { gboolean active = gtk_toggle_action_get_active( act ); @@ -617,6 +416,7 @@ static void gr_linked_changed(GtkToggleAction *act, gpointer /*data*/) prefs->setBool("/options/forkgradientvectors/value", !active); } +/* Reverse vector */ static void gr_reverse(GtkWidget * /*button*/, gpointer data) { SPDesktop *desktop = static_cast<SPDesktop *>(data); @@ -624,534 +424,622 @@ static void gr_reverse(GtkWidget * /*button*/, gpointer data) } /* - * Change desktop drag selection to this stop + * Change desktop dragger selection to this stop */ -static void select_drag_by_stop( GtkWidget *data, SPGradient *gradient, ToolBase *ev) +/* Set the offset widget value (based on which stop is selected). */ +static void gr_stop_set_offset (GObject *data) { - if (blocked || !ev || !gradient) - return; - - GrDrag *drag = ev->get_drag(); - if (!drag) { - return; + if (!blocked) { + std::cerr << "gr_stop_set_offset: should be blocked!" << std::endl; } SPStop *stop = get_selected_stop(data); - - drag->selectByStop(stop, false, true); - blocked = FALSE; -} - -static void select_stop_by_drag(GtkWidget *combo_box, SPGradient *gradient, ToolBase *ev, GtkWidget *data) -{ - if (blocked || !ev || !gradient) + if (!stop) { + // std::cerr << "gr_stop_set_offset: no stop!" << std::endl; return; + } - GrDrag *drag = ev->get_drag(); - - if (!drag || drag->selected.empty()) { - 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; + EgeAdjustmentAction* act = (EgeAdjustmentAction *)g_object_get_data( data, "offset_action"); + if (!act) { return; } + GtkAdjustment *adj = ege_adjustment_action_get_adjustment(act); - gint n = 0; + bool isEndStop = false; - // for all selected draggers - for(std::set<GrDragger *>::const_iterator i = drag->selected.begin(); i != drag->selected.end(); ++i) { //for all draggables of dragger - GrDragger *dragger = *i; - for(std::vector<GrDraggable *>::const_iterator j = dragger->draggables.begin(); j != dragger->draggables.end(); ++j) { //for all draggables of dragger - GrDraggable *draggable = *j; + 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); + } - if (draggable->point_type != POINT_RG_FOCUS) { - n++; - } - if (n > 1) { + 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); + } - // Multiple stops selected - GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box)); - if (!store) { - return; - } - GtkTreeIter iter; - gtk_list_store_prepend(store, &iter); - gtk_list_store_set(store, &iter, 0, _("Multiple stops"), 1, NULL, 2, NULL, -1); - gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box) , 0); - - EgeAdjustmentAction* act = (EgeAdjustmentAction *)g_object_get_data( G_OBJECT(data), "offset_action"); - if (act) { - gtk_action_set_sensitive( GTK_ACTION(act), FALSE); - } + gtk_adjustment_set_value(adj, stop->offset); + gtk_action_set_sensitive( GTK_ACTION(act), !isEndStop ); + gtk_adjustment_changed(adj); +} - return; - } +static void select_dragger_by_stop( GObject *data, SPGradient *gradient, ToolBase *ev) +{ + if (!blocked) { + std::cerr << "select_dragger_by_stop: should be blocked!" << std::endl; + } + if (!ev || !gradient) { + return; + } - SPGradient *vector = gradient->getVector(); - if (!vector) - return; + GrDrag *drag = ev->get_drag(); + if (!drag) { + return; + } - SPStop *stop = vector->getFirstStop(); + SPStop *stop = get_selected_stop(data); - 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; - } + drag->selectByStop(stop, false, true); - select_stop_in_list( combo_box, gradient, stop, data, TRUE); - } - } + gr_stop_set_offset(data); } -static void select_stop_in_list( GtkWidget *combo_box, SPGradient *gradient, SPStop *new_stop, GtkWidget *data, gboolean block) +/* Find position of new_stop in menu. */ +static int select_stop_in_list (SPGradient *gradient, SPStop *new_stop, GObject *data) { int i = 0; for (auto& ochild: gradient->children) { 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; + return i; } i++; } } + return -1; } -static gboolean update_stop_list( GtkWidget *stop_combo, SPGradient *gradient, SPStop *new_stop, GtkWidget *widget, bool gr_multi) +/* Construct stop list */ +static int update_stop_list( SPGradient *gradient, SPStop *new_stop, GObject *data, bool gr_multi) { - gboolean sensitive = FALSE; - - if (!stop_combo) { - return sensitive; + if (!blocked) { + std::cerr << "update_stop_list should be blocked!" << std::endl; } - GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model(GTK_COMBO_BOX(stop_combo)); + int selected = -1; + + auto act = static_cast<InkSelectOneAction*>(g_object_get_data(data, "gradient_stop_action")); + Glib::RefPtr<Gtk::ListStore> store = act->get_store(); + if (!store) { - return sensitive; + return selected; } - blocked = TRUE; + store->clear(); - /* Clear old list, if there is any */ - gtk_list_store_clear(store); - GtkTreeIter iter; + InkSelectOneActionColumns columns; + Gtk::TreeModel::Row row; if (!SP_IS_GRADIENT(gradient)) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, _("No gradient"), 1, NULL, 2, NULL, -1); - gtk_combo_box_set_active(GTK_COMBO_BOX(stop_combo) , 0); - sensitive = FALSE; - blocked = FALSE; - return sensitive; - } + // No valid gradient + + row = *(store->append()); + row[columns.col_label ] = _("No gradient"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_data ] = nullptr; + row[columns.col_sensitive] = true; + + } else if (!gradient->hasStops()) { + // Has gradient but it has no stops + + row = *(store->append()); + row[columns.col_label ] = _("No stops in gradient"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_data ] = nullptr; + row[columns.col_sensitive] = true; + + } else { + // Gradient has stops - /* Populate the combobox store */ - std::vector<SPObject *> sl; - if ( gradient->hasStops() ) { + // Get list of stops for (auto& ochild: gradient->children) { if (SP_IS_STOP(&ochild)) { - sl.push_back(&ochild); - } - } - } - if (sl.empty()) { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, _("No stops in gradient"), 1, NULL, 2, NULL, -1); - sensitive = FALSE; - } else { + SPStop *stop = SP_STOP(&ochild); + Glib::RefPtr<Gdk::Pixbuf> pixbuf = sp_gradstop_to_pixbuf_ref (stop, 32, 16); - for (std::vector<SPObject *>::const_iterator it = sl.begin(); it != sl.end(); ++it) { - if (SP_IS_STOP(*it)){ - SPStop *stop = SP_STOP(*it); - Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(*it)->getRepr(); - Inkscape::UI::Widget::ColorPreview *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(stop->get_rgba32())); - GdkPixbuf *pb = cpv->toPixbuf(32, 16); + Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(&ochild)->getRepr(); Glib::ustring label = gr_ellipsize_text(repr->attribute("id"), 25); - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, label.c_str(), 1, pb, 2, stop, -1); - // Dead assignment: Value stored to 'sensitive' is never read - //sensitive = FALSE; + row = *(store->append()); + row[columns.col_label ] = label; + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_pixbuf ] = pixbuf; + row[columns.col_data ] = stop; + row[columns.col_sensitive] = true; } } - - sensitive = TRUE; } - if (gr_multi) { - sensitive = FALSE; + if (new_stop != nullptr) { + selected = select_stop_in_list (gradient, new_stop, data); } - 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; - - return sensitive; + return selected; } -static SPGradient *gr_get_selected_gradient(GtkWidget *widget) +/* Set stop in menu to match stops selected by draggers. */ +static void select_stop_by_draggers(SPGradient *gradient, ToolBase *ev, GObject *data) { - 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)) { - gtk_tree_model_get(model, &iter, 2, &gr, -1); - return gr; - } + if (!blocked) { + std::cerr << "select_stop_by_draggers should be blocked!" << std::endl; } - return gr; -} + if (!ev || !gradient) + return; -/* -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); - } -} -*/ + SPGradient *vector = gradient->getVector(); + if (!vector) + return; -static void gr_stop_set_offset(GtkComboBox * /*widget*/, GtkWidget *data) -{ - SPStop *stop = get_selected_stop(data); - if (!stop) { + InkSelectOneAction *act = + static_cast<InkSelectOneAction *>(g_object_get_data(data, "gradient_stop_action")); + + GrDrag *drag = ev->get_drag(); + + if (!drag || drag->selected.empty()) { + act->set_active(0); + gr_stop_set_offset(data); return; } - EgeAdjustmentAction* act = (EgeAdjustmentAction *)g_object_get_data( G_OBJECT(data), "offset_action"); - if (!act) { - return; + gint n = 0; + SPStop *stop = nullptr; + int selected = -1; + + // For all selected draggers + for(auto i = drag->selected.begin(); i != drag->selected.end(); ++i) { + + GrDragger *dragger = *i; + + // For all draggables of dragger + for(auto j = dragger->draggables.begin(); j != dragger->draggables.end(); ++j) { + + GrDraggable *draggable = *j; + + if (draggable->point_type != POINT_RG_FOCUS) { + n++; + if (n > 1) break; + } + + 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; + } + } + if (n > 1) break; } - GtkAdjustment *adj = ege_adjustment_action_get_adjustment(act); + if (n > 1) { + // Multiple stops selected - bool isEndStop = false; + EgeAdjustmentAction* offset = (EgeAdjustmentAction *)g_object_get_data( G_OBJECT(data), "offset_action"); + if (offset) { + gtk_action_set_sensitive( GTK_ACTION(offset), FALSE); + } + + // Stop list always updated first... reinsert "Multiple stops" as first entry. + InkSelectOneActionColumns columns; + Glib::RefPtr<Gtk::ListStore> store = act->get_store(); + + Gtk::TreeModel::Row row = *(store->prepend()); + row[columns.col_label ] = _("Multiple stops"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_sensitive] = true; + selected = 0; - 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); + selected = select_stop_in_list( gradient, stop, data); } - SPStop *next = NULL; - next = stop->getNextStop(); - if (next != NULL ) { - gtk_adjustment_set_upper(adj, next->offset); + if (selected < 0) { + act->set_active (0); + act->set_sensitive (false); } else { - isEndStop = true; - gtk_adjustment_set_upper(adj, 1.0); + act->set_active (selected); + act->set_sensitive (true); + gr_stop_set_offset(data); } +} - blocked = TRUE; - gtk_adjustment_set_value(adj, stop->offset); - gtk_action_set_sensitive( GTK_ACTION(act), !isEndStop ); - gtk_adjustment_changed(adj); - blocked = FALSE; +/* Return gradient selected in menu. */ +static SPGradient *gr_get_selected_gradient(GObject *data) +{ + InkSelectOneAction *act = + static_cast<InkSelectOneAction *>(g_object_get_data(data, "gradient_select_action")); -} + int active = act->get_active(); + + Glib::RefPtr<Gtk::ListStore> store = act->get_store(); + Gtk::TreeModel::Row row = store->children()[active]; + InkSelectOneActionColumns columns; + void* pointer = row[columns.col_data]; + SPGradient *gr = static_cast<SPGradient *>(pointer); + + return gr; +} /* * Callback functions for user actions */ -static void gr_new_type_changed( EgeSelectOneAction *act, GObject * /*tbl*/ ) +static void gr_new_type_changed( GObject * /*data*/, int mode ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - gint typemode = ege_select_one_action_get_active( act ) == 0 ? SP_GRADIENT_TYPE_LINEAR : SP_GRADIENT_TYPE_RADIAL; - prefs->setInt("/tools/gradient/newgradient", typemode); + prefs->setInt("/tools/gradient/newgradient", + mode == 0 ? SP_GRADIENT_TYPE_LINEAR : SP_GRADIENT_TYPE_RADIAL); } -static void gr_new_fillstroke_changed( EgeSelectOneAction *act, GObject * /*tbl*/ ) +static void gr_new_fillstroke_changed( GObject * /*data*/, int mode ) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Inkscape::PaintTarget fsmode = (ege_select_one_action_get_active( act ) == 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; + Inkscape::PaintTarget fsmode = (mode == 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; prefs->setInt("/tools/gradient/newfillorstroke", (fsmode == Inkscape::FOR_FILL) ? 1 : 0); } /* * User selected a gradient from the combobox */ -static void gr_gradient_combo_changed(EgeSelectOneAction *act, gpointer data) +static void gr_gradient_changed( GObject *data, int active ) { 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_tree_model_iter_nth_child(model, &iter, NULL, n)) { - gtk_tree_model_get(model, &iter, 2, &gr, -1); + if (active < 0) { + return; } + blocked = true; + + SPGradient *gr = gr_get_selected_gradient (data); + if (gr) { gr = sp_gradient_ensure_vector_normalized(gr); - SPDesktop *desktop = static_cast<SPDesktop *>(data); + SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(data, "desktop")); Inkscape::Selection *selection = desktop->getSelection(); ToolBase *ev = desktop->getEventContext(); - gr_apply_gradient(selection, ev? ev->get_drag() : NULL, gr); + gr_apply_gradient(selection, ev ? ev->get_drag() : NULL, gr); DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_GRADIENT, _("Assign gradient to object")); } + blocked = false; } -static void gr_spread_change(EgeSelectOneAction *act, GtkWidget *widget) +/* + * User selected a spread method from the combobox + */ +static void gr_spread_changed( GObject *data, int active ) { if (blocked) { return; } - SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(G_OBJECT(widget), "desktop")); + blocked = true; + + SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(data, "desktop")); Inkscape::Selection *selection = desktop->getSelection(); SPGradient *gradient = 0; gr_get_dt_selected_gradient(selection, gradient); if (gradient) { - SPGradientSpread spread = (SPGradientSpread) ege_select_one_action_get_active(act); + SPGradientSpread spread = (SPGradientSpread) active; gradient->setSpread(spread); gradient->updateRepr(); DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_GRADIENT, _("Set gradient repeat")); } -} + blocked = false; +} /* * User selected a stop from the combobox */ -static void gr_stop_combo_changed(GtkComboBox * /*widget*/, GtkWidget *data) +static void gr_stop_changed( GObject *data, int active ) { if (blocked) { return; } + blocked = true; + SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(G_OBJECT(data), "desktop")); ToolBase *ev = desktop->getEventContext(); SPGradient *gr = gr_get_selected_gradient(data); - select_drag_by_stop(data, gr, ev); + select_dragger_by_stop(data, gr, ev); + + blocked = false; } /* - * User changed the offset + * User selected a stop from the combobox */ -static void gr_stop_offset_adjustment_changed(GtkAdjustment *adj, GObject *tbl) +static void gr_stop_combo_changed(GtkComboBox * /*widget*/, GObject *data) { 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); + blocked = true; - DocumentUndo::maybeDone(stop->document, "gradient:stop:offset", SP_VERB_CONTEXT_GRADIENT, - _("Change gradient stop offset")); + SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(G_OBJECT(data), "desktop")); + ToolBase *ev = desktop->getEventContext(); + SPGradient *gr = gr_get_selected_gradient(data); - } + select_dragger_by_stop(data, gr, ev); - blocked = FALSE; + blocked = false; } /* - * Change the combobox to show the icon/image on the left of the text + * User changed the offset */ -void check_renderer(GtkWidget *combo) +static void gr_stop_offset_adjustment_changed(GtkAdjustment *adj, GObject *data) { - gpointer rendered = g_object_get_data( G_OBJECT(combo), "renderers" ); - if (!rendered) { + if (blocked) { + return; + } - gtk_cell_layout_clear(GTK_CELL_LAYOUT(combo)); + blocked = true; - GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, FALSE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer, "pixbuf", 1, NULL); - gtk_cell_renderer_set_padding(renderer, 5, 0); + SPStop *stop = get_selected_stop(data); + if (stop) { + stop->offset = gtk_adjustment_get_value(adj); + sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset); - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer, "text", 0, NULL); + DocumentUndo::maybeDone(stop->document, "gradient:stop:offset", SP_VERB_CONTEXT_GRADIENT, + _("Change gradient stop offset")); - g_object_set_data(G_OBJECT(combo), "renderers", renderer); } + + blocked = false; } -static void gradient_toolbox_check_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder); + +static void gradient_toolbox_check_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* data); /** * Gradient auxiliary toolbar construction and setup. * */ -void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObject* holder) +void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObject* data) { GtkIconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + /* New gradient linear or radial */ { - 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 ); - - 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 ); + InkSelectOneActionColumns columns; + + Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); + + Gtk::TreeModel::Row row; + + row = *(store->append()); + row[columns.col_label ] = _("linear"); + row[columns.col_tooltip ] = _("Create linear gradient"); + row[columns.col_icon ] = INKSCAPE_ICON("paint-gradient-linear"); + row[columns.col_sensitive] = true; + + row = *(store->append()); + row[columns.col_label ] = _("radial"); + row[columns.col_tooltip ] = _("Create radial (elliptic or circular) gradient"); + row[columns.col_icon ] = INKSCAPE_ICON("paint-gradient-radial"); + row[columns.col_sensitive] = true; + + InkSelectOneAction* act = + InkSelectOneAction::create( "GradientNewTypeAction", // Name + _("New"), // Label + "", // Tooltip + "Not Used", // Icon + store ); // Tree store + + act->use_radio( true ); + act->use_group_label( true ); + gint mode = prefs->getInt("/tools/gradient/newgradient", SP_MESH_GEOMETRY_NORMAL); + act->set_active( mode ); + + gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); + g_object_set_data( data, "gradient_new_type_mode", act ); + + act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_new_type_changed), data)); } /* New gradient on fill or stroke*/ { - GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); + InkSelectOneActionColumns columns; - 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 ); + Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); - 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 ); + Gtk::TreeModel::Row row; - 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 ); + row = *(store->append()); + row[columns.col_label ] = _("fill"); + row[columns.col_tooltip ] = _("Create gradient in the fill"); + row[columns.col_icon ] = INKSCAPE_ICON("object-fill"); + row[columns.col_sensitive] = true; - 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 ); + row = *(store->append()); + row[columns.col_label ] = _("stroke"); + row[columns.col_tooltip ] = _("Create gradient in the stroke"); + row[columns.col_icon ] = INKSCAPE_ICON("object-stroke"); + row[columns.col_sensitive] = true; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + InkSelectOneAction* act = + InkSelectOneAction::create( "GradientNewFillStrokeAction", // Name + _(""), // Label + "", // Tooltip + "Not Used", // Icon + store ); // Tree store + + act->use_radio( true ); + act->use_group_label( false ); Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; - ege_select_one_action_set_active( act, (fsmode == Inkscape::FOR_FILL) ? 0 : 1 ); - g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(gr_new_fillstroke_changed), holder ); - } + act->set_active( fsmode == Inkscape::FOR_FILL ? 0 : 1 ); + gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); + g_object_set_data( data, "gradient_new_fillstroke_action", act ); + + act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_new_fillstroke_changed), data)); + } /* Gradient Select list*/ { - GtkListStore *store = gtk_list_store_new(3, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER); + InkSelectOneActionColumns columns; + + Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); - GtkTreeIter iter; - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, _("No gradient"), 1, NULL, 2, NULL, -1); + Gtk::TreeModel::Row row; - 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 ); + row = *(store->append()); + row[columns.col_label ] = _("No gradient"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_sensitive] = true; + InkSelectOneAction* act = + InkSelectOneAction::create( "GradientSelectGradientAction", // Name + _("Select"), // Label + "", // Tooltip + "Not Used", // Icon + store ); // Tree store + + act->use_radio( false ); + act->use_icon( false ); + act->use_pixbuf( true ); + act->use_group_label( true ); + act->set_active( 0 ); + act->set_sensitive( false ); + + gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); + g_object_set_data( data, "gradient_select_action", act ); + + act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_gradient_changed), data)); } - // Gradient Repeat type + // Gradient Spread type (how a gradient is drawn outside it's nominal area) { - 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, C_("Gradient repeat type", "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 ); + InkSelectOneActionColumns columns; + + Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); + + Gtk::TreeModel::Row row; + + row = *(store->append()); + row[columns.col_label ] = C_("Gradient repeat type", "None"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_sensitive] = true; + + row = *(store->append()); + row[columns.col_label ] = _("Reflected"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_sensitive] = true; + + row = *(store->append()); + row[columns.col_label ] = _("Direct"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_sensitive] = true; + + InkSelectOneAction* act = + InkSelectOneAction::create( "GradientSelectSpreadAction", // Name + _("Repeat"), // Label + // 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\")"), // Tooltip + "Not Used", // Icon + store ); // Tree store + + act->use_radio( false ); + act->use_icon( false ); + act->use_group_label( true ); + act->set_sensitive( false ); + + gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); + g_object_set_data( data, "gradient_spread_action", act ); + + act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_spread_changed), data)); } - /* Gradient Stop list */ + /* Gradidnt 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, 0, _("No stops"), 1, NULL, 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", _("Stops:"), 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 ); + InkSelectOneActionColumns columns; + + Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); + + Gtk::TreeModel::Row row; + + row = *(store->append()); + row[columns.col_label ] = _("No stops"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_sensitive] = true; + + InkSelectOneAction* act = + InkSelectOneAction::create( "GradientStopAction", // Name + _("Stops" ), // Label + "", // Tooltip + "Not Used", // Icon + store ); // Tree store + + act->use_radio( false ); + act->use_icon( false ); + act->use_pixbuf( true ); + act->use_group_label( true ); + act->set_active( 0 ); + act->set_sensitive( false ); + + gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); + g_object_set_data( data, "gradient_stop_action", act ); + + act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_stop_changed), data)); } /* Offset */ @@ -1160,7 +1048,7 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, eact = create_adjustment_action( "GradientEditOffsetAction", _("Offset"), C_("Gradient", "Offset:"), _("Offset of selected stop"), "/tools/gradient/stopoffset", 0, - GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, + GTK_WIDGET(desktop->canvas), data, FALSE, NULL, 0.0, 1.0, 0.01, 0.1, 0, 0, 0, gr_stop_offset_adjustment_changed, @@ -1168,7 +1056,7 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, 0.01, 2, 1.0); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); - g_object_set_data( holder, "offset_action", eact ); + g_object_set_data( data, "offset_action", eact ); gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); } @@ -1181,10 +1069,10 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, 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 ); + g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(gr_add_stop), data ); 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 ); + g_object_set_data( data, "gradient_stops_add_action", inky ); } /* Delete stop */ @@ -1195,10 +1083,10 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, 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 ); + g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(gr_remove_stop), data ); 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 ); + g_object_set_data( data, "gradient_stops_delete_action", inky ); } /* Reverse */ @@ -1212,7 +1100,7 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, 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 ); + g_object_set_data( data, "gradient_stops_reverse_action", inky ); } @@ -1227,14 +1115,106 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, g_signal_connect_after( G_OBJECT(itact), "toggled", G_CALLBACK(gr_linked_changed), desktop) ; gtk_action_group_add_action( mainActions, GTK_ACTION(itact) ); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool linkedmode = prefs->getBool("/options/forkgradientvectors/value", true); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(itact), !linkedmode ); } - g_object_set_data(holder, "desktop", desktop); + g_object_set_data(data, "desktop", desktop); + + desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(&gradient_toolbox_check_ec), data)); +} + + +// =================== Selection Changed Callbacks ======================= // + +/* + * Core function, setup all the widgets whenever something changes on the desktop + */ +static void gr_tb_selection_changed(Inkscape::Selection * /*selection*/, GObject* data) +{ + if (blocked) + return; + + blocked = true; - desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(&gradient_toolbox_check_ec), holder)); + SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(data, "desktop")); + if (!desktop) { + return; + } + + Inkscape::Selection *selection = desktop->getSelection(); // take from desktop, not from args + if (selection) { + + ToolBase *ev = desktop->getEventContext(); + GrDrag *drag = NULL; + if (ev) { + drag = ev->get_drag(); + } + + SPGradient *gr_selected = 0; + SPGradientSpread spr_selected = SP_GRADIENT_SPREAD_UNDEFINED; + bool gr_multi = false; + bool spr_multi = false; + + gr_read_selection(selection, drag, gr_selected, gr_multi, spr_selected, spr_multi); + + // Gradient selection menu + auto sel = static_cast<InkSelectOneAction*>(g_object_get_data(data, "gradient_select_action")); + Glib::RefPtr<Gtk::ListStore> store = sel->get_store(); + int gradient = gr_vector_list (store, desktop, selection->isEmpty(), gr_selected, gr_multi); + + if (gradient < 0) { + // No selection or no gradients + sel->set_active( 0 ); + sel->set_sensitive (false); + } else { + // Single gradient or multiple gradients + sel->set_active( gradient ); + sel->set_sensitive (true); + } + + // Spread menu + auto spread = static_cast<InkSelectOneAction*>(g_object_get_data(data, "gradient_spread_action")); + spread->set_sensitive( gr_selected && !gr_multi ); + spread->set_active( gr_selected ? (int)spr_selected : 0 ); + + InkAction *add = (InkAction *) g_object_get_data(data, "gradient_stops_add_action"); + gtk_action_set_sensitive(GTK_ACTION(add), (gr_selected && !gr_multi && drag && !drag->selected.empty())); + + InkAction *del = (InkAction *) g_object_get_data(data, "gradient_stops_delete_action"); + gtk_action_set_sensitive(GTK_ACTION(del), (gr_selected && !gr_multi && drag && !drag->selected.empty())); + + InkAction *reverse = (InkAction *) g_object_get_data(data, "gradient_stops_reverse_action"); + gtk_action_set_sensitive(GTK_ACTION(reverse), (gr_selected!= NULL)); + + InkSelectOneAction *stops_action = (InkSelectOneAction *) g_object_get_data(data, "gradient_stop_action"); + stops_action->set_sensitive( gr_selected && !gr_multi); + + int stop = update_stop_list (gr_selected, nullptr, data, gr_multi); + select_stop_by_draggers(gr_selected, ev, data); + } + + blocked = false; +} + +static void gr_tb_selection_modified(Inkscape::Selection *selection, guint /*flags*/, GObject* data) +{ + gr_tb_selection_changed(selection, data); +} + +static void gr_drag_selection_changed(gpointer /*dragger*/, GObject* data) +{ + gr_tb_selection_changed(NULL, data); +} + +static void gr_defs_release(SPObject * /*defs*/, GObject* data) +{ + gr_tb_selection_changed(NULL, data); +} + +static void gr_defs_modified(SPObject * /*defs*/, guint /*flags*/, GObject* data) +{ + gr_tb_selection_changed(NULL, data); } // lp:1327267 @@ -1242,7 +1222,7 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, * Checks the current tool and connects gradient aux toolbox signals if it happens to be the gradient tool. * Called every time the current tool changes by signal emission. */ -static void gradient_toolbox_check_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder) +static void gradient_toolbox_check_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* data) { static sigc::connection connChanged; static sigc::connection connModified; @@ -1255,16 +1235,16 @@ static void gradient_toolbox_check_ec(SPDesktop* desktop, Inkscape::UI::Tools::T SPDocument *document = desktop->getDocument(); // connect to selection modified and changed signals - connChanged = selection->connectChanged(sigc::bind(sigc::ptr_fun(&gr_tb_selection_changed), holder)); - connModified = selection->connectModified(sigc::bind(sigc::ptr_fun(&gr_tb_selection_modified), holder)); - connSubselectionChanged = desktop->connectToolSubselectionChanged(sigc::bind(sigc::ptr_fun(&gr_drag_selection_changed), holder)); + connChanged = selection->connectChanged(sigc::bind(sigc::ptr_fun(&gr_tb_selection_changed), data)); + connModified = selection->connectModified(sigc::bind(sigc::ptr_fun(&gr_tb_selection_modified), data)); + connSubselectionChanged = desktop->connectToolSubselectionChanged(sigc::bind(sigc::ptr_fun(&gr_drag_selection_changed), data)); // Is this necessary? Couldn't hurt. - gr_tb_selection_changed(selection, holder); + gr_tb_selection_changed(selection, data); // connect to release and modified signals of the defs (i.e. when someone changes gradient) - connDefsRelease = document->getDefs()->connectRelease(sigc::bind<1>(sigc::ptr_fun(&gr_defs_release), GTK_WIDGET(holder))); - connDefsModified = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&gr_defs_modified), GTK_WIDGET(holder))); + connDefsRelease = document->getDefs()->connectRelease( sigc::bind<1>(sigc::ptr_fun(&gr_defs_release), data)); + connDefsModified = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&gr_defs_modified), data)); } else { if (connChanged) connChanged.disconnect(); |
