diff options
Diffstat (limited to 'src/ui/toolbar/gradient-toolbar.cpp')
| -rw-r--r-- | src/ui/toolbar/gradient-toolbar.cpp | 1271 |
1 files changed, 626 insertions, 645 deletions
diff --git a/src/ui/toolbar/gradient-toolbar.cpp b/src/ui/toolbar/gradient-toolbar.cpp index cf14be7c3..4d1b16c6e 100644 --- a/src/ui/toolbar/gradient-toolbar.cpp +++ b/src/ui/toolbar/gradient-toolbar.cpp @@ -336,371 +336,300 @@ void gr_read_selection( Inkscape::Selection *selection, } } -/* Get stop selected by menu */ -static SPStop *get_selected_stop( GObject *data) -{ - InkSelectOneAction *act = - static_cast<InkSelectOneAction *>(g_object_get_data(data, "gradient_stop_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]; - SPStop *stop = static_cast<SPStop *>(pointer); +namespace Inkscape { +namespace UI { +namespace Toolbar { - return stop; -} - -/* Add stop to gradient */ -static void gr_add_stop(GtkWidget * /*button*/, GObject *data) +/** + * Gradient auxiliary toolbar construction and setup. + * + */ +GtkWidget * +GradientToolbar::prep(SPDesktop * desktop, GtkActionGroup* mainActions) { - SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(data, "desktop")); - if (!desktop) { - return; - } - - Inkscape::Selection *selection = desktop->getSelection(); - if (!selection) { - return; - } - - ToolBase *ev = desktop->getEventContext(); - Inkscape::UI::Tools::GradientTool *rc = SP_GRADIENT_CONTEXT(ev); - - if (rc) { - sp_gradient_context_add_stops_between_selected_stops(rc); - } - -} + auto toolbar = new GradientToolbar(desktop); + GtkIconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1); -/* Remove stop from vector */ -static void gr_remove_stop(GtkWidget * /*button*/, GObject *data) -{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(data, "desktop")); - if (!desktop) { - return; - } + /* New gradient linear or radial */ + { + InkSelectOneActionColumns columns; - Inkscape::Selection *selection = desktop->getSelection(); // take from desktop, not from args - if (!selection) { - return; - } + Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); - ToolBase *ev = desktop->getEventContext(); - GrDrag *drag = nullptr; - if (ev) { - drag = ev->get_drag(); - } + Gtk::TreeModel::Row row; - if (drag) { - drag->deleteSelected(); - } + 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; -/* Lock or unlock links */ -static void gr_linked_changed(GtkToggleAction *act, gpointer /*data*/) -{ - gboolean active = gtk_toggle_action_get_active( act ); - if ( active ) { - g_object_set( G_OBJECT(act), "iconId", INKSCAPE_ICON("object-locked"), NULL ); - } else { - g_object_set( G_OBJECT(act), "iconId", INKSCAPE_ICON("object-unlocked"), NULL ); - } + toolbar->_new_type_mode = + InkSelectOneAction::create( "GradientNewTypeAction", // Name + _("New"), // Label + "", // Tooltip + "Not Used", // Icon + store ); // Tree store - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setBool("/options/forkgradientvectors/value", !active); -} + toolbar->_new_type_mode->use_radio( true ); + toolbar->_new_type_mode->use_group_label( true ); + gint mode = prefs->getInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_LINEAR); + toolbar->_new_type_mode->set_active( mode == SP_GRADIENT_TYPE_LINEAR ? 0 : 1 ); // linear == 1, radial == 2 -/* Reverse vector */ -static void gr_reverse(GtkWidget * /*button*/, gpointer data) -{ - SPDesktop *desktop = static_cast<SPDesktop *>(data); - sp_gradient_reverse_selected_gradients(desktop); -} + gtk_action_group_add_action( mainActions, GTK_ACTION( toolbar->_new_type_mode->gobj() )); -/* - * Change desktop dragger selection to this stop - */ -/* Set the offset widget value (based on which stop is selected). */ -static void gr_stop_set_offset (GObject *data) -{ - if (!blocked) { - std::cerr << "gr_stop_set_offset: should be blocked!" << std::endl; + toolbar->_new_type_mode->signal_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::new_type_changed)); } - SPStop *stop = get_selected_stop(data); - if (!stop) { - // std::cerr << "gr_stop_set_offset: no stop!" << std::endl; - return; - } + /* New gradient on fill or stroke*/ + { + InkSelectOneActionColumns columns; - EgeAdjustmentAction* act = (EgeAdjustmentAction *)g_object_get_data( data, "offset_action"); - if (!act) { - return; - } - GtkAdjustment *adj = ege_adjustment_action_get_adjustment(act); + Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); - bool isEndStop = false; + Gtk::TreeModel::Row row; - SPStop *prev = nullptr; - prev = stop->getPrevStop(); - if (prev != nullptr ) { - gtk_adjustment_set_lower(adj, prev->offset); - } else { - isEndStop = true; - gtk_adjustment_set_lower(adj, 0); - } + 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; - SPStop *next = nullptr; - next = stop->getNextStop(); - if (next != nullptr ) { - gtk_adjustment_set_upper(adj, next->offset); - } else { - isEndStop = true; - gtk_adjustment_set_upper(adj, 1.0); - } + 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; - gtk_adjustment_set_value(adj, stop->offset); - gtk_action_set_sensitive( GTK_ACTION(act), !isEndStop ); - gtk_adjustment_changed(adj); -} + toolbar->_new_fillstroke_action = + InkSelectOneAction::create( "GradientNewFillStrokeAction", // Name + "", // Label + "", // Tooltip + "Not Used", // Icon + store ); // Tree store -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; - } + toolbar->_new_fillstroke_action->use_radio( true ); + toolbar->_new_fillstroke_action->use_group_label( false ); + Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; + toolbar->_new_fillstroke_action->set_active( fsmode == Inkscape::FOR_FILL ? 0 : 1 ); - if (!ev || !gradient) { - return; - } + gtk_action_group_add_action( mainActions, GTK_ACTION( toolbar->_new_fillstroke_action->gobj() )); - GrDrag *drag = ev->get_drag(); - if (!drag) { - return; + toolbar->_new_fillstroke_action->signal_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::new_fillstroke_changed)); } - SPStop *stop = get_selected_stop(data); + /* Gradient Select list*/ + { + InkSelectOneActionColumns columns; - drag->selectByStop(stop, false, true); + Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); - gr_stop_set_offset(data); -} + Gtk::TreeModel::Row row; -/* 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) { - return i; - } - i++; - } - } - return -1; -} + row = *(store->append()); + row[columns.col_label ] = _("No gradient"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_sensitive] = true; -/* Construct stop list */ -static int update_stop_list( SPGradient *gradient, SPStop *new_stop, GObject *data, bool gr_multi) -{ - if (!blocked) { - std::cerr << "update_stop_list should be blocked!" << std::endl; - } + toolbar->_select_action = + InkSelectOneAction::create( "GradientSelectGradientAction", // Name + _("Select"), // Label + "", // Tooltip + "Not Used", // Icon + store ); // Tree store - int selected = -1; + toolbar->_select_action->use_radio( false ); + toolbar->_select_action->use_icon( false ); + toolbar->_select_action->use_pixbuf( true ); + toolbar->_select_action->use_group_label( true ); + toolbar->_select_action->set_active( 0 ); + toolbar->_select_action->set_sensitive( false ); - auto act = static_cast<InkSelectOneAction*>(g_object_get_data(data, "gradient_stop_action")); - Glib::RefPtr<Gtk::ListStore> store = act->get_store(); + gtk_action_group_add_action( mainActions, GTK_ACTION( toolbar->_select_action->gobj() )); - if (!store) { - return selected; + toolbar->_select_action->signal_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::gradient_changed)); } - store->clear(); + // Gradient Spread type (how a gradient is drawn outside it's nominal area) + { + InkSelectOneActionColumns columns; - InkSelectOneActionColumns columns; - Gtk::TreeModel::Row row; + Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); - if (!SP_IS_GRADIENT(gradient)) { - // No valid gradient + Gtk::TreeModel::Row row; row = *(store->append()); - row[columns.col_label ] = _("No gradient"); + row[columns.col_label ] = C_("Gradient repeat type", "None"); 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_label ] = _("Reflected"); row[columns.col_tooltip ] = ""; row[columns.col_icon ] = "NotUsed"; - row[columns.col_data ] = nullptr; row[columns.col_sensitive] = true; - } else { - // Gradient has stops + row = *(store->append()); + row[columns.col_label ] = _("Direct"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_sensitive] = true; - // Get list of stops - for (auto& ochild: gradient->children) { - if (SP_IS_STOP(&ochild)) { + toolbar->_spread_action = + 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 - SPStop *stop = SP_STOP(&ochild); - Glib::RefPtr<Gdk::Pixbuf> pixbuf = sp_gradstop_to_pixbuf_ref (stop, 32, 16); + toolbar->_spread_action->use_radio( false ); + toolbar->_spread_action->use_icon( false ); + toolbar->_spread_action->use_group_label( true ); + toolbar->_spread_action->set_sensitive( false ); - Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(&ochild)->getRepr(); - Glib::ustring label = gr_ellipsize_text(repr->attribute("id"), 25); + gtk_action_group_add_action( mainActions, GTK_ACTION( toolbar->_spread_action->gobj() )); - 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; - } - } + toolbar->_spread_action->signal_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::spread_changed)); } - if (new_stop != nullptr) { - selected = select_stop_in_list (gradient, new_stop, data); - } + /* Gradidnt Stop list */ + { + InkSelectOneActionColumns columns; - return selected; -} + Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); -/* Set stop in menu to match stops selected by draggers. */ -static void select_stop_by_draggers(SPGradient *gradient, ToolBase *ev, GObject *data) -{ - if (!blocked) { - std::cerr << "select_stop_by_draggers should be blocked!" << std::endl; - } + Gtk::TreeModel::Row row; - if (!ev || !gradient) - return; + row = *(store->append()); + row[columns.col_label ] = _("No stops"); + row[columns.col_tooltip ] = ""; + row[columns.col_icon ] = "NotUsed"; + row[columns.col_sensitive] = true; - SPGradient *vector = gradient->getVector(); - if (!vector) - return; + toolbar->_stop_action = + InkSelectOneAction::create( "GradientStopAction", // Name + _("Stops" ), // Label + "", // Tooltip + "Not Used", // Icon + store ); // Tree store - InkSelectOneAction *act = - static_cast<InkSelectOneAction *>(g_object_get_data(data, "gradient_stop_action")); + toolbar->_stop_action->use_radio( false ); + toolbar->_stop_action->use_icon( false ); + toolbar->_stop_action->use_pixbuf( true ); + toolbar->_stop_action->use_group_label( true ); + toolbar->_stop_action->set_active( 0 ); + toolbar->_stop_action->set_sensitive( false ); - GrDrag *drag = ev->get_drag(); + gtk_action_group_add_action( mainActions, GTK_ACTION( toolbar->_stop_action->gobj() )); - if (!drag || drag->selected.empty()) { - act->set_active(0); - gr_stop_set_offset(data); - return; + toolbar->_stop_action->signal_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::stop_changed)); } - gint n = 0; - SPStop *stop = nullptr; - int selected = -1; - - // For all selected draggers - for(auto dragger : drag->selected) { - - // For all draggables of dragger - for(auto draggable : dragger->draggables) { - - 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; + /* Offset */ + { + toolbar->_offset_action = create_adjustment_action( "GradientEditOffsetAction", + _("Offset"), C_("Gradient", "Offset:"), _("Offset of selected stop"), + "/tools/gradient/stopoffset", 0, + GTK_WIDGET(desktop->canvas), + nullptr, // dataKludge + FALSE, nullptr, + 0.0, 1.0, 0.01, 0.1, + nullptr, nullptr, 0, + nullptr, // callback + nullptr /*unit tracker*/, + 0.01, 2, 1.0); + + toolbar->_offset_adj = Glib::wrap(ege_adjustment_action_get_adjustment(toolbar->_offset_action)); + toolbar->_offset_adj->signal_value_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::stop_offset_adjustment_changed)); + gtk_action_group_add_action( mainActions, GTK_ACTION(toolbar->_offset_action) ); + gtk_action_set_sensitive( GTK_ACTION(toolbar->_offset_action), FALSE ); } - if (n > 1) { - // Multiple stops selected - - 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; - - } else { - selected = select_stop_in_list( gradient, stop, data); + /* Add stop */ + { + toolbar->_stops_add_action = ink_action_new( "GradientEditAddAction", + _("Insert new stop"), + _("Insert new stop"), + INKSCAPE_ICON("node-add"), + secondarySize ); + gtk_action_set_short_label(GTK_ACTION(toolbar->_stops_add_action), _("Delete")); + g_signal_connect_after( G_OBJECT(toolbar->_stops_add_action), "activate", G_CALLBACK(add_stop), (gpointer)toolbar); + gtk_action_group_add_action( mainActions, GTK_ACTION(toolbar->_stops_add_action) ); + gtk_action_set_sensitive( GTK_ACTION(toolbar->_stops_add_action), FALSE ); } - if (selected < 0) { - act->set_active (0); - act->set_sensitive (false); - } else { - act->set_active (selected); - act->set_sensitive (true); - gr_stop_set_offset(data); + /* Delete stop */ + { + toolbar->_stops_delete_action = ink_action_new( "GradientEditDeleteAction", + _("Delete stop"), + _("Delete stop"), + INKSCAPE_ICON("node-delete"), + secondarySize ); + gtk_action_set_short_label(GTK_ACTION(toolbar->_stops_delete_action), _("Delete")); + g_signal_connect_after( G_OBJECT(toolbar->_stops_delete_action), "activate", G_CALLBACK(remove_stop), (gpointer)toolbar ); + gtk_action_group_add_action( mainActions, GTK_ACTION(toolbar->_stops_delete_action) ); + gtk_action_set_sensitive( GTK_ACTION(toolbar->_stops_delete_action), 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")); + /* Reverse */ + { + toolbar->_stops_reverse_action = ink_action_new( "GradientEditReverseAction", + _("Reverse"), + _("Reverse the direction of the gradient"), + INKSCAPE_ICON("object-flip-horizontal"), + secondarySize ); + // TODO: Is this label correct? + gtk_action_set_short_label(GTK_ACTION(toolbar->_stops_reverse_action), _("Delete")); + g_signal_connect_after( G_OBJECT(toolbar->_stops_reverse_action), "activate", G_CALLBACK(reverse), desktop ); + gtk_action_group_add_action( mainActions, GTK_ACTION(toolbar->_stops_reverse_action) ); + gtk_action_set_sensitive( GTK_ACTION(toolbar->_stops_reverse_action), FALSE ); + } - int active = act->get_active(); + // Gradients Linked toggle + { + InkToggleAction* itact = ink_toggle_action_new( "GradientEditLinkAction", + _("Link gradients"), + _("Link gradients to change all related gradients"), + INKSCAPE_ICON("object-unlocked"), + GTK_ICON_SIZE_MENU ); + // TODO: Shouldn't this be translatable? + gtk_action_set_short_label( GTK_ACTION(itact), "Lock"); + g_signal_connect_after( G_OBJECT(itact), "toggled", G_CALLBACK(linked_changed), desktop) ; + gtk_action_group_add_action( mainActions, GTK_ACTION(itact) ); - Glib::RefPtr<Gtk::ListStore> store = act->get_store(); - Gtk::TreeModel::Row row = store->children()[active]; - InkSelectOneActionColumns columns; + bool linkedmode = prefs->getBool("/options/forkgradientvectors/value", true); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(itact), !linkedmode ); + } - void* pointer = row[columns.col_data]; - SPGradient *gr = static_cast<SPGradient *>(pointer); + desktop->connectEventContextChanged(sigc::mem_fun(*toolbar, &GradientToolbar::check_ec)); - return gr; + return GTK_WIDGET(toolbar->gobj()); } -/* - * Callback functions for user actions - */ - -static void gr_new_type_changed( GObject * /*data*/, int mode ) +void +GradientToolbar::new_type_changed(int mode) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setInt("/tools/gradient/newgradient", mode == 0 ? SP_GRADIENT_TYPE_LINEAR : SP_GRADIENT_TYPE_RADIAL); } -static void gr_new_fillstroke_changed( GObject * /*data*/, int mode ) +void +GradientToolbar::new_fillstroke_changed(int mode) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); Inkscape::PaintTarget fsmode = (mode == 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; @@ -710,7 +639,8 @@ static void gr_new_fillstroke_changed( GObject * /*data*/, int mode ) /* * User selected a gradient from the combobox */ -static void gr_gradient_changed( GObject *data, int active ) +void +GradientToolbar::gradient_changed(int active) { if (blocked) { return; @@ -722,28 +652,46 @@ static void gr_gradient_changed( GObject *data, int active ) blocked = true; - SPGradient *gr = gr_get_selected_gradient (data); + SPGradient *gr = get_selected_gradient(); if (gr) { gr = sp_gradient_ensure_vector_normalized(gr); - SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(data, "desktop")); - Inkscape::Selection *selection = desktop->getSelection(); - ToolBase *ev = desktop->getEventContext(); + Inkscape::Selection *selection = _desktop->getSelection(); + ToolBase *ev = _desktop->getEventContext(); gr_apply_gradient(selection, ev ? ev->get_drag() : nullptr, gr); - DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_GRADIENT, + DocumentUndo::done(_desktop->getDocument(), SP_VERB_CONTEXT_GRADIENT, _("Assign gradient to object")); } blocked = false; } -/* - * User selected a spread method from the combobox +/** + * \brief Return gradient selected in menu */ -static void gr_spread_changed( GObject *data, int active ) +SPGradient * +GradientToolbar::get_selected_gradient() +{ + int active = _select_action->get_active(); + + Glib::RefPtr<Gtk::ListStore> store = _select_action->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; +} + +/** + * \brief User selected a spread method from the combobox + */ +void +GradientToolbar::spread_changed(int active) { if (blocked) { return; @@ -751,8 +699,7 @@ static void gr_spread_changed( GObject *data, int active ) blocked = true; - SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(data, "desktop")); - Inkscape::Selection *selection = desktop->getSelection(); + Inkscape::Selection *selection = _desktop->getSelection(); SPGradient *gradient = nullptr; gr_get_dt_selected_gradient(selection, gradient); @@ -761,17 +708,18 @@ static void gr_spread_changed( GObject *data, int active ) gradient->setSpread(spread); gradient->updateRepr(); - DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_GRADIENT, + DocumentUndo::done(_desktop->getDocument(), SP_VERB_CONTEXT_GRADIENT, _("Set gradient repeat")); } blocked = false; } -/* - * User selected a stop from the combobox +/** + * \brief User selected a stop from the combobox */ -static void gr_stop_changed( GObject *data, int active ) +void +GradientToolbar::stop_changed(int active) { if (blocked) { return; @@ -779,39 +727,106 @@ static void gr_stop_changed( GObject *data, int active ) 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); + ToolBase *ev = _desktop->getEventContext(); + SPGradient *gr = get_selected_gradient(); - select_dragger_by_stop(data, gr, ev); + select_dragger_by_stop(gr, ev); blocked = false; } -/* - * User selected a stop from the combobox +void +GradientToolbar::select_dragger_by_stop(SPGradient *gradient, + ToolBase *ev) +{ + if (!blocked) { + std::cerr << "select_dragger_by_stop: should be blocked!" << std::endl; + } + + if (!ev || !gradient) { + return; + } + + GrDrag *drag = ev->get_drag(); + if (!drag) { + return; + } + + SPStop *stop = get_selected_stop(); + + drag->selectByStop(stop, false, true); + + stop_set_offset(); +} + +/** + * \brief Get stop selected by menu */ -static void gr_stop_combo_changed(GtkComboBox * /*widget*/, GObject *data) +SPStop * +GradientToolbar::get_selected_stop() { - if (blocked) { + int active = _stop_action->get_active(); + + Glib::RefPtr<Gtk::ListStore> store = _stop_action->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; +} + +/** + * Change desktop dragger selection to this stop + * + * Set the offset widget value (based on which stop is selected) + */ +void +GradientToolbar::stop_set_offset() +{ + if (!blocked) { + std::cerr << "gr_stop_set_offset: should be blocked!" << std::endl; + } + + SPStop *stop = get_selected_stop(); + if (!stop) { + // std::cerr << "gr_stop_set_offset: no stop!" << std::endl; return; } - blocked = true; + if (!_offset_action) { + return; + } + bool isEndStop = false; - SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(G_OBJECT(data), "desktop")); - ToolBase *ev = desktop->getEventContext(); - SPGradient *gr = gr_get_selected_gradient(data); + SPStop *prev = nullptr; + prev = stop->getPrevStop(); + if (prev != nullptr ) { + _offset_adj->set_lower(prev->offset); + } else { + isEndStop = true; + _offset_adj->set_lower(0); + } - select_dragger_by_stop(data, gr, ev); + SPStop *next = nullptr; + next = stop->getNextStop(); + if (next != nullptr ) { + _offset_adj->set_upper(next->offset); + } else { + isEndStop = true; + _offset_adj->set_upper(1.0); + } - blocked = false; + _offset_adj->set_value(stop->offset); + gtk_action_set_sensitive( GTK_ACTION(_offset_action), !isEndStop ); + _offset_adj->changed(); } -/* - * User changed the offset +/** + * \brief User changed the offset */ -static void gr_stop_offset_adjustment_changed(GtkAdjustment *adj, GObject *data) +void +GradientToolbar::stop_offset_adjustment_changed() { if (blocked) { return; @@ -819,9 +834,9 @@ static void gr_stop_offset_adjustment_changed(GtkAdjustment *adj, GObject *data) blocked = true; - SPStop *stop = get_selected_stop(data); + SPStop *stop = get_selected_stop(); if (stop) { - stop->offset = gtk_adjustment_get_value(adj); + stop->offset = _offset_adj->get_value(); sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset); DocumentUndo::maybeDone(stop->document, "gradient:stop:offset", SP_VERB_CONTEXT_GRADIENT, @@ -832,428 +847,394 @@ static void gr_stop_offset_adjustment_changed(GtkAdjustment *adj, GObject *data) blocked = false; } - -static void gradient_toolbox_check_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* data); - /** - * Gradient auxiliary toolbar construction and setup. - * + * \brief Add stop to gradient */ -void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObject* data) +void +GradientToolbar::add_stop(GtkWidget * /*button*/, gpointer data) { - GtkIconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1); - - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - /* New gradient linear or radial */ - { - InkSelectOneActionColumns columns; - - Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); - - Gtk::TreeModel::Row row; + auto toolbar = reinterpret_cast<GradientToolbar *>(data); + if (!toolbar->_desktop) { + return; + } - 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; + Inkscape::Selection *selection = toolbar->_desktop->getSelection(); + if (!selection) { + return; + } - 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; + ToolBase *ev = toolbar->_desktop->getEventContext(); + Inkscape::UI::Tools::GradientTool *rc = SP_GRADIENT_CONTEXT(ev); - InkSelectOneAction* act = - InkSelectOneAction::create( "GradientNewTypeAction", // Name - _("New"), // Label - "", // Tooltip - "Not Used", // Icon - store ); // Tree store + if (rc) { + sp_gradient_context_add_stops_between_selected_stops(rc); + } +} - act->use_radio( true ); - act->use_group_label( true ); - gint mode = prefs->getInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_LINEAR); - act->set_active( mode == SP_GRADIENT_TYPE_LINEAR ? 0 : 1 ); // linear == 1, radial == 2 +/** + * \brief Remove stop from vector + */ +void +GradientToolbar::remove_stop(GtkWidget * /*button*/, gpointer data) +{ + auto toolbar = reinterpret_cast<GradientToolbar *>(data); - gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); - g_object_set_data( data, "gradient_new_type_mode", act ); + if (!toolbar->_desktop) { + return; + } - act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_new_type_changed), data)); + Inkscape::Selection *selection = toolbar->_desktop->getSelection(); // take from desktop, not from args + if (!selection) { + return; } - /* New gradient on fill or stroke*/ - { - InkSelectOneActionColumns columns; + ToolBase *ev = toolbar->_desktop->getEventContext(); + GrDrag *drag = nullptr; + if (ev) { + drag = ev->get_drag(); + } - Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); + if (drag) { + drag->deleteSelected(); + } +} - Gtk::TreeModel::Row row; +/** + * \brief Reverse vector + */ +void +GradientToolbar::reverse(GtkWidget * /*button*/, gpointer data) +{ + SPDesktop *desktop = static_cast<SPDesktop *>(data); + sp_gradient_reverse_selected_gradients(desktop); +} - 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; +/** + * \brief Lock or unlock links + */ +void +GradientToolbar::linked_changed(GtkToggleAction *act, gpointer /*data*/) +{ + gboolean active = gtk_toggle_action_get_active( act ); + if ( active ) { + g_object_set( G_OBJECT(act), "iconId", INKSCAPE_ICON("object-locked"), NULL ); + } else { + g_object_set( G_OBJECT(act), "iconId", INKSCAPE_ICON("object-unlocked"), NULL ); + } - 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(); + prefs->setBool("/options/forkgradientvectors/value", !active); +} - InkSelectOneAction* act = - InkSelectOneAction::create( "GradientNewFillStrokeAction", // Name - "", // Label - "", // Tooltip - "Not Used", // Icon - store ); // Tree store +// lp:1327267 +/** + * 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. + */ +void +GradientToolbar::check_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec) +{ + if (SP_IS_GRADIENT_CONTEXT(ec)) { + Inkscape::Selection *selection = desktop->getSelection(); + SPDocument *document = desktop->getDocument(); - 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; - act->set_active( fsmode == Inkscape::FOR_FILL ? 0 : 1 ); + // connect to selection modified and changed signals + _connection_changed = selection->connectChanged(sigc::mem_fun(*this, &GradientToolbar::selection_changed)); + _connection_modified = selection->connectModified(sigc::mem_fun(*this, &GradientToolbar::selection_modified)); + _connection_subselection_changed = desktop->connectToolSubselectionChanged(sigc::mem_fun(*this, &GradientToolbar::drag_selection_changed)); - gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); - g_object_set_data( data, "gradient_new_fillstroke_action", act ); + // Is this necessary? Couldn't hurt. + selection_changed(selection); - act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_new_fillstroke_changed), data)); + // connect to release and modified signals of the defs (i.e. when someone changes gradient) + _connection_defs_release = document->getDefs()->connectRelease(sigc::mem_fun(*this, &GradientToolbar::defs_release)); + _connection_defs_modified = document->getDefs()->connectModified(sigc::mem_fun(*this, &GradientToolbar::defs_modified)); + } else { + if (_connection_changed) + _connection_changed.disconnect(); + if (_connection_modified) + _connection_modified.disconnect(); + if (_connection_subselection_changed) + _connection_subselection_changed.disconnect(); + if (_connection_defs_release) + _connection_defs_release.disconnect(); + if (_connection_defs_modified) + _connection_defs_modified.disconnect(); } +} - /* Gradient Select list*/ - { - InkSelectOneActionColumns columns; +/** + * Core function, setup all the widgets whenever something changes on the desktop + */ +void +GradientToolbar::selection_changed(Inkscape::Selection * /*selection*/) +{ + if (blocked) + return; - Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); + blocked = true; - Gtk::TreeModel::Row row; + if (!_desktop) { + return; + } - row = *(store->append()); - row[columns.col_label ] = _("No gradient"); - row[columns.col_tooltip ] = ""; - row[columns.col_icon ] = "NotUsed"; - row[columns.col_sensitive] = true; + Inkscape::Selection *selection = _desktop->getSelection(); // take from desktop, not from args + if (selection) { - InkSelectOneAction* act = - InkSelectOneAction::create( "GradientSelectGradientAction", // Name - _("Select"), // Label - "", // Tooltip - "Not Used", // Icon - store ); // Tree store + ToolBase *ev = _desktop->getEventContext(); + GrDrag *drag = nullptr; + if (ev) { + drag = ev->get_drag(); + } - 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 ); + SPGradient *gr_selected = nullptr; + SPGradientSpread spr_selected = SP_GRADIENT_SPREAD_UNDEFINED; + bool gr_multi = false; + bool spr_multi = false; - gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); - g_object_set_data( data, "gradient_select_action", act ); + gr_read_selection(selection, drag, gr_selected, gr_multi, spr_selected, spr_multi); - act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_gradient_changed), data)); - } + // Gradient selection menu + auto store = _select_action->get_store(); + int gradient = gr_vector_list (store, _desktop, selection->isEmpty(), gr_selected, gr_multi); - // Gradient Spread type (how a gradient is drawn outside it's nominal area) - { - InkSelectOneActionColumns columns; + if (gradient < 0) { + // No selection or no gradients + _select_action->set_active( 0 ); + _select_action->set_sensitive (false); + } else { + // Single gradient or multiple gradients + _select_action->set_active( gradient ); + _select_action->set_sensitive (true); + } - Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); + // Spread menu + _spread_action->set_sensitive( gr_selected && !gr_multi ); + _spread_action->set_active( gr_selected ? (int)spr_selected : 0 ); - Gtk::TreeModel::Row row; + gtk_action_set_sensitive(GTK_ACTION(_stops_add_action), (gr_selected && !gr_multi && drag && !drag->selected.empty())); + gtk_action_set_sensitive(GTK_ACTION(_stops_delete_action), (gr_selected && !gr_multi && drag && !drag->selected.empty())); + gtk_action_set_sensitive(GTK_ACTION(_stops_reverse_action), (gr_selected!= nullptr)); - 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; + _stop_action->set_sensitive( gr_selected && !gr_multi); - row = *(store->append()); - row[columns.col_label ] = _("Reflected"); - row[columns.col_tooltip ] = ""; - row[columns.col_icon ] = "NotUsed"; - row[columns.col_sensitive] = true; + int stop = update_stop_list (gr_selected, nullptr, gr_multi); + select_stop_by_draggers(gr_selected, ev); + } - row = *(store->append()); - row[columns.col_label ] = _("Direct"); - row[columns.col_tooltip ] = ""; - row[columns.col_icon ] = "NotUsed"; - row[columns.col_sensitive] = true; + blocked = false; +} - 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 +/** + * \brief Construct stop list + */ +int +GradientToolbar::update_stop_list( SPGradient *gradient, SPStop *new_stop, bool gr_multi) +{ + if (!blocked) { + std::cerr << "update_stop_list should be blocked!" << std::endl; + } - act->use_radio( false ); - act->use_icon( false ); - act->use_group_label( true ); - act->set_sensitive( false ); + int selected = -1; - gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); - g_object_set_data( data, "gradient_spread_action", act ); + auto store = _stop_action->get_store(); - act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_spread_changed), data)); + if (!store) { + return selected; } - /* Gradidnt Stop list */ - { - InkSelectOneActionColumns columns; + store->clear(); - Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create(columns); + InkSelectOneActionColumns columns; + Gtk::TreeModel::Row row; - Gtk::TreeModel::Row row; + if (!SP_IS_GRADIENT(gradient)) { + // No valid gradient row = *(store->append()); - row[columns.col_label ] = _("No stops"); + 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; - 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 ); + } else if (!gradient->hasStops()) { + // Has gradient but it has no stops - gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); - g_object_set_data( data, "gradient_stop_action", act ); + 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; - act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_stop_changed), data)); - } + } else { + // Gradient has stops - /* Offset */ - { - EgeAdjustmentAction* eact = nullptr; - eact = create_adjustment_action( "GradientEditOffsetAction", - _("Offset"), C_("Gradient", "Offset:"), _("Offset of selected stop"), - "/tools/gradient/stopoffset", 0, - GTK_WIDGET(desktop->canvas), data, FALSE, nullptr, - 0.0, 1.0, 0.01, 0.1, - nullptr, nullptr, 0, - gr_stop_offset_adjustment_changed, - nullptr /*unit tracker*/, - 0.01, 2, 1.0); - - gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); - g_object_set_data( data, "offset_action", eact ); - gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); + // Get list of stops + for (auto& ochild: gradient->children) { + if (SP_IS_STOP(&ochild)) { - } + SPStop *stop = SP_STOP(&ochild); + Glib::RefPtr<Gdk::Pixbuf> pixbuf = sp_gradstop_to_pixbuf_ref (stop, 32, 16); - /* 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), data ); - gtk_action_group_add_action( mainActions, GTK_ACTION(inky) ); - gtk_action_set_sensitive( GTK_ACTION(inky), FALSE ); - g_object_set_data( data, "gradient_stops_add_action", inky ); - } + Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(&ochild)->getRepr(); + Glib::ustring label = gr_ellipsize_text(repr->attribute("id"), 25); - /* 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), data ); - gtk_action_group_add_action( mainActions, GTK_ACTION(inky) ); - gtk_action_set_sensitive( GTK_ACTION(inky), FALSE ); - g_object_set_data( data, "gradient_stops_delete_action", inky ); + 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; + } + } } - /* 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( data, "gradient_stops_reverse_action", inky ); - + if (new_stop != nullptr) { + selected = select_stop_in_list (gradient, new_stop); } - // Gradients Linked toggle - { - InkToggleAction* itact = ink_toggle_action_new( "GradientEditLinkAction", - _("Link gradients"), - _("Link gradients to change all related gradients"), - INKSCAPE_ICON("object-unlocked"), - GTK_ICON_SIZE_MENU ); - g_object_set( itact, "short_label", "Lock", NULL ); - g_signal_connect_after( G_OBJECT(itact), "toggled", G_CALLBACK(gr_linked_changed), desktop) ; - gtk_action_group_add_action( mainActions, GTK_ACTION(itact) ); + return selected; +} - bool linkedmode = prefs->getBool("/options/forkgradientvectors/value", true); - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(itact), !linkedmode ); +/** + * \brief Find position of new_stop in menu. + */ +int +GradientToolbar::select_stop_in_list(SPGradient *gradient, SPStop *new_stop) +{ + int i = 0; + for (auto& ochild: gradient->children) { + if (SP_IS_STOP(&ochild)) { + if (&ochild == new_stop) { + return i; + } + i++; + } } - - g_object_set_data(data, "desktop", desktop); - - desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(&gradient_toolbox_check_ec), data)); + return -1; } - -// =================== Selection Changed Callbacks ======================= // - -/* - * Core function, setup all the widgets whenever something changes on the desktop +/** + * \brief Set stop in menu to match stops selected by draggers */ -static void gr_tb_selection_changed(Inkscape::Selection * /*selection*/, GObject* data) +void +GradientToolbar::select_stop_by_draggers(SPGradient *gradient, ToolBase *ev) { - if (blocked) + if (!blocked) { + std::cerr << "select_stop_by_draggers should be blocked!" << std::endl; + } + + if (!ev || !gradient) return; - blocked = true; + SPGradient *vector = gradient->getVector(); + if (!vector) + return; - SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(data, "desktop")); - if (!desktop) { + GrDrag *drag = ev->get_drag(); + + if (!drag || drag->selected.empty()) { + _stop_action->set_active(0); + stop_set_offset(); return; } - Inkscape::Selection *selection = desktop->getSelection(); // take from desktop, not from args - if (selection) { + gint n = 0; + SPStop *stop = nullptr; + int selected = -1; - ToolBase *ev = desktop->getEventContext(); - GrDrag *drag = nullptr; - if (ev) { - drag = ev->get_drag(); - } + // For all selected draggers + for(auto dragger : drag->selected) { - SPGradient *gr_selected = nullptr; - SPGradientSpread spr_selected = SP_GRADIENT_SPREAD_UNDEFINED; - bool gr_multi = false; - bool spr_multi = false; + // For all draggables of dragger + for(auto draggable : dragger->draggables) { - gr_read_selection(selection, drag, gr_selected, gr_multi, spr_selected, spr_multi); + if (draggable->point_type != POINT_RG_FOCUS) { + n++; + if (n > 1) break; + } - // 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); + stop = vector->getFirstStop(); - 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); + 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; + } - // 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())); + if (n > 1) { + // Multiple stops selected + if (_offset_action) { + gtk_action_set_sensitive( GTK_ACTION(_offset_action), FALSE); + } - InkAction *reverse = (InkAction *) g_object_get_data(data, "gradient_stops_reverse_action"); - gtk_action_set_sensitive(GTK_ACTION(reverse), (gr_selected!= nullptr)); + // Stop list always updated first... reinsert "Multiple stops" as first entry. + InkSelectOneActionColumns columns; + Glib::RefPtr<Gtk::ListStore> store = _stop_action->get_store(); - InkSelectOneAction *stops_action = (InkSelectOneAction *) g_object_get_data(data, "gradient_stop_action"); - stops_action->set_sensitive( gr_selected && !gr_multi); + 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; - int stop = update_stop_list (gr_selected, nullptr, data, gr_multi); - select_stop_by_draggers(gr_selected, ev, data); + } else { + selected = select_stop_in_list(gradient, stop); } - blocked = false; + if (selected < 0) { + _stop_action->set_active (0); + _stop_action->set_sensitive (false); + } else { + _stop_action->set_active (selected); + _stop_action->set_sensitive (true); + stop_set_offset(); + } } -static void gr_tb_selection_modified(Inkscape::Selection *selection, guint /*flags*/, GObject* data) +void +GradientToolbar::selection_modified(Inkscape::Selection *selection, guint /*flags*/) { - gr_tb_selection_changed(selection, data); + selection_changed(selection); } -static void gr_drag_selection_changed(gpointer /*dragger*/, GObject* data) +void +GradientToolbar::drag_selection_changed(gpointer /*dragger*/) { - gr_tb_selection_changed(nullptr, data); + selection_changed(nullptr); } -static void gr_defs_release(SPObject * /*defs*/, GObject* data) +void +GradientToolbar::defs_release(SPObject * /*defs*/) { - gr_tb_selection_changed(nullptr, data); + selection_changed(nullptr); } -static void gr_defs_modified(SPObject * /*defs*/, guint /*flags*/, GObject* data) +void +GradientToolbar::defs_modified(SPObject * /*defs*/, guint /*flags*/) { - gr_tb_selection_changed(nullptr, data); + selection_changed(nullptr); } -// lp:1327267 -/** - * 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* data) -{ - static sigc::connection connChanged; - static sigc::connection connModified; - static sigc::connection connSubselectionChanged; - static sigc::connection connDefsRelease; - static sigc::connection connDefsModified; - - if (SP_IS_GRADIENT_CONTEXT(ec)) { - Inkscape::Selection *selection = desktop->getSelection(); - SPDocument *document = desktop->getDocument(); - - // connect to selection modified and changed signals - 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, 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), data)); - connDefsModified = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&gr_defs_modified), data)); - } else { - if (connChanged) - connChanged.disconnect(); - if (connModified) - connModified.disconnect(); - if (connSubselectionChanged) - connSubselectionChanged.disconnect(); - if (connDefsRelease) - connDefsRelease.disconnect(); - if (connDefsModified) - connDefsModified.disconnect(); - } } - +} +} /* Local Variables: mode:c++ |
