From e77e650354daef5ced80adddf6d5a334bb6216d3 Mon Sep 17 00:00:00 2001 From: Alexander Valavanis Date: Sat, 19 Jan 2019 13:58:46 +0000 Subject: derive all toolbars from Inkscape::Toolbar --- src/ui/toolbar/gradient-toolbar.cpp | 1341 +++++++++++++++++------------------ 1 file changed, 661 insertions(+), 680 deletions(-) (limited to 'src/ui/toolbar/gradient-toolbar.cpp') 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,511 +336,18 @@ void gr_read_selection( Inkscape::Selection *selection, } } -/* Get stop selected by menu */ -static SPStop *get_selected_stop( GObject *data) -{ - InkSelectOneAction *act = - static_cast(g_object_get_data(data, "gradient_stop_action")); - - int active = act->get_active(); - - Glib::RefPtr store = act->get_store(); - Gtk::TreeModel::Row row = store->children()[active]; - InkSelectOneActionColumns columns; - void* pointer = row[columns.col_data]; - SPStop *stop = static_cast(pointer); - - return stop; -} - -/* Add stop to gradient */ -static void gr_add_stop(GtkWidget * /*button*/, GObject *data) -{ - SPDesktop *desktop = static_cast(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); - } - -} - -/* Remove stop from vector */ -static void gr_remove_stop(GtkWidget * /*button*/, GObject *data) -{ - - SPDesktop *desktop = static_cast(g_object_get_data(data, "desktop")); - if (!desktop) { - return; - } - - Inkscape::Selection *selection = desktop->getSelection(); // take from desktop, not from args - if (!selection) { - return; - } - - ToolBase *ev = desktop->getEventContext(); - GrDrag *drag = nullptr; - if (ev) { - drag = ev->get_drag(); - } - - if (drag) { - drag->deleteSelected(); - } - -} - -/* 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 ); - } - - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setBool("/options/forkgradientvectors/value", !active); -} - -/* Reverse vector */ -static void gr_reverse(GtkWidget * /*button*/, gpointer data) -{ - SPDesktop *desktop = static_cast(data); - sp_gradient_reverse_selected_gradients(desktop); -} - -/* - * 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; - } - - SPStop *stop = get_selected_stop(data); - if (!stop) { - // std::cerr << "gr_stop_set_offset: no stop!" << std::endl; - return; - } - - EgeAdjustmentAction* act = (EgeAdjustmentAction *)g_object_get_data( data, "offset_action"); - if (!act) { - return; - } - GtkAdjustment *adj = ege_adjustment_action_get_adjustment(act); - - bool isEndStop = false; - - 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); - } - - 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); - } - - gtk_adjustment_set_value(adj, stop->offset); - gtk_action_set_sensitive( GTK_ACTION(act), !isEndStop ); - gtk_adjustment_changed(adj); -} - -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; - } - - GrDrag *drag = ev->get_drag(); - if (!drag) { - return; - } - - SPStop *stop = get_selected_stop(data); - - drag->selectByStop(stop, false, true); - - gr_stop_set_offset(data); -} - -/* 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; -} - -/* 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; - } - - int selected = -1; - - auto act = static_cast(g_object_get_data(data, "gradient_stop_action")); - Glib::RefPtr store = act->get_store(); - - if (!store) { - return selected; - } - - store->clear(); - - InkSelectOneActionColumns columns; - Gtk::TreeModel::Row row; - - if (!SP_IS_GRADIENT(gradient)) { - // 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 - - // Get list of stops - for (auto& ochild: gradient->children) { - if (SP_IS_STOP(&ochild)) { - - SPStop *stop = SP_STOP(&ochild); - Glib::RefPtr pixbuf = sp_gradstop_to_pixbuf_ref (stop, 32, 16); - - Inkscape::XML::Node *repr = reinterpret_cast(&ochild)->getRepr(); - Glib::ustring label = gr_ellipsize_text(repr->attribute("id"), 25); - - 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; - } - } - } - - if (new_stop != nullptr) { - selected = select_stop_in_list (gradient, new_stop, data); - } - - return selected; -} - -/* 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; - } - - if (!ev || !gradient) - return; - - SPGradient *vector = gradient->getVector(); - if (!vector) - return; - - InkSelectOneAction *act = - static_cast(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; - } - - 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; - } - - 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 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); - } - - 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); - } -} - -/* Return gradient selected in menu. */ -static SPGradient *gr_get_selected_gradient(GObject *data) -{ - InkSelectOneAction *act = - static_cast(g_object_get_data(data, "gradient_select_action")); - - int active = act->get_active(); - - Glib::RefPtr store = act->get_store(); - Gtk::TreeModel::Row row = store->children()[active]; - InkSelectOneActionColumns columns; - - void* pointer = row[columns.col_data]; - SPGradient *gr = static_cast(pointer); - - return gr; -} - -/* - * Callback functions for user actions - */ - -static void gr_new_type_changed( GObject * /*data*/, 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 ) -{ - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - 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_changed( GObject *data, int active ) -{ - if (blocked) { - return; - } - - 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(g_object_get_data(data, "desktop")); - 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, - _("Assign gradient to object")); - } - - blocked = false; -} - -/* - * User selected a spread method from the combobox - */ -static void gr_spread_changed( GObject *data, int active ) -{ - if (blocked) { - return; - } - - blocked = true; - - SPDesktop *desktop = static_cast(g_object_get_data(data, "desktop")); - Inkscape::Selection *selection = desktop->getSelection(); - SPGradient *gradient = nullptr; - gr_get_dt_selected_gradient(selection, gradient); - - if (gradient) { - 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_changed( GObject *data, int active ) -{ - if (blocked) { - return; - } - - blocked = true; - - SPDesktop *desktop = static_cast(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; -} - -/* - * User selected a stop from the combobox - */ -static void gr_stop_combo_changed(GtkComboBox * /*widget*/, GObject *data) -{ - if (blocked) { - return; - } - - blocked = true; - - SPDesktop *desktop = static_cast(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; -} - -/* - * User changed the offset - */ -static void gr_stop_offset_adjustment_changed(GtkAdjustment *adj, GObject *data) -{ - if (blocked) { - return; - } - - blocked = true; - - 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); - - DocumentUndo::maybeDone(stop->document, "gradient:stop:offset", SP_VERB_CONTEXT_GRADIENT, - _("Change gradient stop offset")); - - } - - blocked = false; -} - - -static void gradient_toolbox_check_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* data); +namespace Inkscape { +namespace UI { +namespace Toolbar { /** * Gradient auxiliary toolbar construction and setup. * */ -void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObject* data) +GtkWidget * +GradientToolbar::prep(SPDesktop * desktop, GtkActionGroup* mainActions) { + auto toolbar = new GradientToolbar(desktop); GtkIconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -865,22 +372,21 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, row[columns.col_icon ] = INKSCAPE_ICON("paint-gradient-radial"); row[columns.col_sensitive] = true; - InkSelectOneAction* act = + toolbar->_new_type_mode = InkSelectOneAction::create( "GradientNewTypeAction", // Name _("New"), // Label "", // Tooltip "Not Used", // Icon store ); // Tree store - act->use_radio( true ); - act->use_group_label( true ); + 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); - act->set_active( mode == SP_GRADIENT_TYPE_LINEAR ? 0 : 1 ); // linear == 1, radial == 2 + toolbar->_new_type_mode->set_active( mode == SP_GRADIENT_TYPE_LINEAR ? 0 : 1 ); // linear == 1, radial == 2 - gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); - g_object_set_data( data, "gradient_new_type_mode", act ); + gtk_action_group_add_action( mainActions, GTK_ACTION( toolbar->_new_type_mode->gobj() )); - act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_new_type_changed), data)); + toolbar->_new_type_mode->signal_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::new_type_changed)); } /* New gradient on fill or stroke*/ @@ -903,22 +409,21 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, row[columns.col_icon ] = INKSCAPE_ICON("object-stroke"); row[columns.col_sensitive] = true; - InkSelectOneAction* act = + toolbar->_new_fillstroke_action = InkSelectOneAction::create( "GradientNewFillStrokeAction", // Name "", // Label "", // Tooltip "Not Used", // Icon store ); // Tree store - act->use_radio( true ); - act->use_group_label( false ); + 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; - act->set_active( fsmode == Inkscape::FOR_FILL ? 0 : 1 ); + toolbar->_new_fillstroke_action->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 ); + gtk_action_group_add_action( mainActions, GTK_ACTION( toolbar->_new_fillstroke_action->gobj() )); - act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_new_fillstroke_changed), data)); + toolbar->_new_fillstroke_action->signal_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::new_fillstroke_changed)); } /* Gradient Select list*/ @@ -935,24 +440,23 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, row[columns.col_icon ] = "NotUsed"; row[columns.col_sensitive] = true; - InkSelectOneAction* act = + toolbar->_select_action = 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 ); + 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 ); - gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); - g_object_set_data( data, "gradient_select_action", act ); + gtk_action_group_add_action( mainActions, GTK_ACTION( toolbar->_select_action->gobj() )); - act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_gradient_changed), data)); + toolbar->_select_action->signal_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::gradient_changed)); } // Gradient Spread type (how a gradient is drawn outside it's nominal area) @@ -981,7 +485,7 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, row[columns.col_icon ] = "NotUsed"; row[columns.col_sensitive] = true; - InkSelectOneAction* act = + 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 @@ -992,15 +496,14 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, "Not Used", // Icon store ); // Tree store - act->use_radio( false ); - act->use_icon( false ); - act->use_group_label( true ); - act->set_sensitive( false ); + 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 ); - gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); - g_object_set_data( data, "gradient_spread_action", act ); + gtk_action_group_add_action( mainActions, GTK_ACTION( toolbar->_spread_action->gobj() )); - act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_spread_changed), data)); + toolbar->_spread_action->signal_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::spread_changed)); } /* Gradidnt Stop list */ @@ -1017,130 +520,468 @@ void sp_gradient_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, row[columns.col_icon ] = "NotUsed"; row[columns.col_sensitive] = true; - InkSelectOneAction* act = + toolbar->_stop_action = 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 ); + 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 ); + + gtk_action_group_add_action( mainActions, GTK_ACTION( toolbar->_stop_action->gobj() )); + + toolbar->_stop_action->signal_changed().connect(sigc::mem_fun(*toolbar, &GradientToolbar::stop_changed)); + } + + /* 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 ); + } + + /* 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 ); + } + + /* 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 ); + } + + /* 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 ); + } + + // 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) ); + + bool linkedmode = prefs->getBool("/options/forkgradientvectors/value", true); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(itact), !linkedmode ); + } + + desktop->connectEventContextChanged(sigc::mem_fun(*toolbar, &GradientToolbar::check_ec)); + + return GTK_WIDGET(toolbar->gobj()); +} + +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); +} + +void +GradientToolbar::new_fillstroke_changed(int mode) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + 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 + */ +void +GradientToolbar::gradient_changed(int active) +{ + if (blocked) { + return; + } + + if (active < 0) { + return; + } + + blocked = true; + + SPGradient *gr = get_selected_gradient(); + + if (gr) { + gr = sp_gradient_ensure_vector_normalized(gr); + + 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, + _("Assign gradient to object")); + } + + blocked = false; +} + +/** + * \brief Return gradient selected in menu + */ +SPGradient * +GradientToolbar::get_selected_gradient() +{ + int active = _select_action->get_active(); + + Glib::RefPtr store = _select_action->get_store(); + Gtk::TreeModel::Row row = store->children()[active]; + InkSelectOneActionColumns columns; + + void* pointer = row[columns.col_data]; + SPGradient *gr = static_cast(pointer); + + return gr; +} + +/** + * \brief User selected a spread method from the combobox + */ +void +GradientToolbar::spread_changed(int active) +{ + if (blocked) { + return; + } + + blocked = true; + + Inkscape::Selection *selection = _desktop->getSelection(); + SPGradient *gradient = nullptr; + gr_get_dt_selected_gradient(selection, gradient); + + if (gradient) { + SPGradientSpread spread = (SPGradientSpread) active; + gradient->setSpread(spread); + gradient->updateRepr(); + + DocumentUndo::done(_desktop->getDocument(), SP_VERB_CONTEXT_GRADIENT, + _("Set gradient repeat")); + } + + blocked = false; +} + +/** + * \brief User selected a stop from the combobox + */ +void +GradientToolbar::stop_changed(int active) +{ + if (blocked) { + return; + } + + blocked = true; + + ToolBase *ev = _desktop->getEventContext(); + SPGradient *gr = get_selected_gradient(); + + select_dragger_by_stop(gr, ev); + + blocked = false; +} + +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 + */ +SPStop * +GradientToolbar::get_selected_stop() +{ + int active = _stop_action->get_active(); + + Glib::RefPtr store = _stop_action->get_store(); + Gtk::TreeModel::Row row = store->children()[active]; + InkSelectOneActionColumns columns; + void* pointer = row[columns.col_data]; + SPStop *stop = static_cast(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; + } + + if (!_offset_action) { + return; + } + bool isEndStop = false; + + SPStop *prev = nullptr; + prev = stop->getPrevStop(); + if (prev != nullptr ) { + _offset_adj->set_lower(prev->offset); + } else { + isEndStop = true; + _offset_adj->set_lower(0); + } + + SPStop *next = nullptr; + next = stop->getNextStop(); + if (next != nullptr ) { + _offset_adj->set_upper(next->offset); + } else { + isEndStop = true; + _offset_adj->set_upper(1.0); + } + + _offset_adj->set_value(stop->offset); + gtk_action_set_sensitive( GTK_ACTION(_offset_action), !isEndStop ); + _offset_adj->changed(); +} + +/** + * \brief User changed the offset + */ +void +GradientToolbar::stop_offset_adjustment_changed() +{ + if (blocked) { + return; + } + + blocked = true; + + SPStop *stop = get_selected_stop(); + if (stop) { + 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, + _("Change gradient stop offset")); + + } + + blocked = false; +} - gtk_action_group_add_action( mainActions, GTK_ACTION( act->gobj() )); - g_object_set_data( data, "gradient_stop_action", act ); +/** + * \brief Add stop to gradient + */ +void +GradientToolbar::add_stop(GtkWidget * /*button*/, gpointer data) +{ + auto toolbar = reinterpret_cast(data); + if (!toolbar->_desktop) { + return; + } - act->signal_changed().connect(sigc::bind<0>(sigc::ptr_fun(&gr_stop_changed), data)); + Inkscape::Selection *selection = toolbar->_desktop->getSelection(); + if (!selection) { + return; } - /* 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 ); + ToolBase *ev = toolbar->_desktop->getEventContext(); + Inkscape::UI::Tools::GradientTool *rc = SP_GRADIENT_CONTEXT(ev); + if (rc) { + sp_gradient_context_add_stops_between_selected_stops(rc); } +} - /* 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 ); +/** + * \brief Remove stop from vector + */ +void +GradientToolbar::remove_stop(GtkWidget * /*button*/, gpointer data) +{ + auto toolbar = reinterpret_cast(data); + + if (!toolbar->_desktop) { + return; } - /* 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 ); + Inkscape::Selection *selection = toolbar->_desktop->getSelection(); // take from desktop, not from args + if (!selection) { + return; } - /* 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 ); + ToolBase *ev = toolbar->_desktop->getEventContext(); + GrDrag *drag = nullptr; + if (ev) { + drag = ev->get_drag(); + } + if (drag) { + drag->deleteSelected(); } +} - // 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) ); +/** + * \brief Reverse vector + */ +void +GradientToolbar::reverse(GtkWidget * /*button*/, gpointer data) +{ + SPDesktop *desktop = static_cast(data); + sp_gradient_reverse_selected_gradients(desktop); +} - bool linkedmode = prefs->getBool("/options/forkgradientvectors/value", true); - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(itact), !linkedmode ); +/** + * \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 ); } - g_object_set_data(data, "desktop", desktop); - - desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(&gradient_toolbox_check_ec), data)); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setBool("/options/forkgradientvectors/value", !active); } +// 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(); + + // 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)); -// =================== Selection Changed Callbacks ======================= // + // Is this necessary? Couldn't hurt. + selection_changed(selection); -/* + // 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(); + } +} + +/** * Core function, setup all the widgets whenever something changes on the desktop */ -static void gr_tb_selection_changed(Inkscape::Selection * /*selection*/, GObject* data) +void +GradientToolbar::selection_changed(Inkscape::Selection * /*selection*/) { if (blocked) return; blocked = true; - SPDesktop *desktop = static_cast(g_object_get_data(data, "desktop")); - if (!desktop) { + if (!_desktop) { return; } - Inkscape::Selection *selection = desktop->getSelection(); // take from desktop, not from args + Inkscape::Selection *selection = _desktop->getSelection(); // take from desktop, not from args if (selection) { - ToolBase *ev = desktop->getEventContext(); + ToolBase *ev = _desktop->getEventContext(); GrDrag *drag = nullptr; if (ev) { drag = ev->get_drag(); @@ -1154,106 +995,246 @@ static void gr_tb_selection_changed(Inkscape::Selection * /*selection*/, GObject gr_read_selection(selection, drag, gr_selected, gr_multi, spr_selected, spr_multi); // Gradient selection menu - auto sel = static_cast(g_object_get_data(data, "gradient_select_action")); - Glib::RefPtr store = sel->get_store(); - int gradient = gr_vector_list (store, desktop, selection->isEmpty(), gr_selected, gr_multi); + auto store = _select_action->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); + _select_action->set_active( 0 ); + _select_action->set_sensitive (false); } else { // Single gradient or multiple gradients - sel->set_active( gradient ); - sel->set_sensitive (true); + _select_action->set_active( gradient ); + _select_action->set_sensitive (true); } // Spread menu - auto spread = static_cast(g_object_get_data(data, "gradient_spread_action")); - spread->set_sensitive( gr_selected && !gr_multi ); - spread->set_active( gr_selected ? (int)spr_selected : 0 ); + _spread_action->set_sensitive( gr_selected && !gr_multi ); + _spread_action->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())); + 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)); - 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())); + _stop_action->set_sensitive( gr_selected && !gr_multi); - InkAction *reverse = (InkAction *) g_object_get_data(data, "gradient_stops_reverse_action"); - gtk_action_set_sensitive(GTK_ACTION(reverse), (gr_selected!= nullptr)); - - 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); + int stop = update_stop_list (gr_selected, nullptr, gr_multi); + select_stop_by_draggers(gr_selected, ev); } blocked = false; } -static void gr_tb_selection_modified(Inkscape::Selection *selection, guint /*flags*/, GObject* data) +/** + * \brief Construct stop list + */ +int +GradientToolbar::update_stop_list( SPGradient *gradient, SPStop *new_stop, bool gr_multi) { - gr_tb_selection_changed(selection, data); -} + if (!blocked) { + std::cerr << "update_stop_list should be blocked!" << std::endl; + } -static void gr_drag_selection_changed(gpointer /*dragger*/, GObject* data) -{ - gr_tb_selection_changed(nullptr, data); -} + int selected = -1; -static void gr_defs_release(SPObject * /*defs*/, GObject* data) -{ - gr_tb_selection_changed(nullptr, data); + auto store = _stop_action->get_store(); + + if (!store) { + return selected; + } + + store->clear(); + + InkSelectOneActionColumns columns; + Gtk::TreeModel::Row row; + + if (!SP_IS_GRADIENT(gradient)) { + // 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 + + // Get list of stops + for (auto& ochild: gradient->children) { + if (SP_IS_STOP(&ochild)) { + + SPStop *stop = SP_STOP(&ochild); + Glib::RefPtr pixbuf = sp_gradstop_to_pixbuf_ref (stop, 32, 16); + + Inkscape::XML::Node *repr = reinterpret_cast(&ochild)->getRepr(); + Glib::ustring label = gr_ellipsize_text(repr->attribute("id"), 25); + + 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; + } + } + } + + if (new_stop != nullptr) { + selected = select_stop_in_list (gradient, new_stop); + } + + return selected; } -static void gr_defs_modified(SPObject * /*defs*/, guint /*flags*/, GObject* data) +/** + * \brief Find position of new_stop in menu. + */ +int +GradientToolbar::select_stop_in_list(SPGradient *gradient, SPStop *new_stop) { - gr_tb_selection_changed(nullptr, data); + int i = 0; + for (auto& ochild: gradient->children) { + if (SP_IS_STOP(&ochild)) { + if (&ochild == new_stop) { + return i; + } + i++; + } + } + return -1; } -// 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. + * \brief Set stop in menu to match stops selected by draggers */ -static void gradient_toolbox_check_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* data) +void +GradientToolbar::select_stop_by_draggers(SPGradient *gradient, ToolBase *ev) { - static sigc::connection connChanged; - static sigc::connection connModified; - static sigc::connection connSubselectionChanged; - static sigc::connection connDefsRelease; - static sigc::connection connDefsModified; + if (!blocked) { + std::cerr << "select_stop_by_draggers should be blocked!" << std::endl; + } - if (SP_IS_GRADIENT_CONTEXT(ec)) { - Inkscape::Selection *selection = desktop->getSelection(); - SPDocument *document = desktop->getDocument(); + if (!ev || !gradient) + return; - // 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)); + SPGradient *vector = gradient->getVector(); + if (!vector) + return; - // Is this necessary? Couldn't hurt. - gr_tb_selection_changed(selection, data); + GrDrag *drag = ev->get_drag(); - // 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)); + if (!drag || drag->selected.empty()) { + _stop_action->set_active(0); + stop_set_offset(); + return; + } + + 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; + } + + if (n > 1) { + // Multiple stops selected + if (_offset_action) { + gtk_action_set_sensitive( GTK_ACTION(_offset_action), FALSE); + } + + // Stop list always updated first... reinsert "Multiple stops" as first entry. + InkSelectOneActionColumns columns; + Glib::RefPtr store = _stop_action->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); + } + + if (selected < 0) { + _stop_action->set_active (0); + _stop_action->set_sensitive (false); } else { - if (connChanged) - connChanged.disconnect(); - if (connModified) - connModified.disconnect(); - if (connSubselectionChanged) - connSubselectionChanged.disconnect(); - if (connDefsRelease) - connDefsRelease.disconnect(); - if (connDefsModified) - connDefsModified.disconnect(); + _stop_action->set_active (selected); + _stop_action->set_sensitive (true); + stop_set_offset(); } } +void +GradientToolbar::selection_modified(Inkscape::Selection *selection, guint /*flags*/) +{ + selection_changed(selection); +} + +void +GradientToolbar::drag_selection_changed(gpointer /*dragger*/) +{ + selection_changed(nullptr); +} + +void +GradientToolbar::defs_release(SPObject * /*defs*/) +{ + selection_changed(nullptr); +} + +void +GradientToolbar::defs_modified(SPObject * /*defs*/, guint /*flags*/) +{ + selection_changed(nullptr); +} + +} +} +} /* Local Variables: mode:c++ -- cgit v1.2.3