diff options
| author | Alexander Valavanis <valavanisalex@gmail.com> | 2018-06-17 16:00:04 +0000 |
|---|---|---|
| committer | Alexander Valavanis <valavanisalex@gmail.com> | 2018-06-17 16:00:04 +0000 |
| commit | 039408dbad2877c3b75d08f66dddaff17fe3dcf3 (patch) | |
| tree | 5f6072daaa0f4a406b3b0e2f04f81f3c4140f51e /src/ui/toolbar/connector-toolbar.cpp | |
| parent | Minor documentation changes. (diff) | |
| download | inkscape-039408dbad2877c3b75d08f66dddaff17fe3dcf3.tar.gz inkscape-039408dbad2877c3b75d08f66dddaff17fe3dcf3.zip | |
Move toolbars to ui/toolbar
Diffstat (limited to 'src/ui/toolbar/connector-toolbar.cpp')
| -rw-r--r-- | src/ui/toolbar/connector-toolbar.cpp | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/src/ui/toolbar/connector-toolbar.cpp b/src/ui/toolbar/connector-toolbar.cpp new file mode 100644 index 000000000..2709c700e --- /dev/null +++ b/src/ui/toolbar/connector-toolbar.cpp @@ -0,0 +1,450 @@ +/** + * @file + * Connector aux toolbar + */ +/* Authors: + * MenTaLguY <mental@rydia.net> + * Lauris Kaplinski <lauris@kaplinski.com> + * bulia byak <buliabyak@users.sf.net> + * Frank Felfe <innerspace@iname.com> + * John Cliff <simarilius@yahoo.com> + * David Turner <novalis@gnu.org> + * Josh Andler <scislac@scislac.com> + * Jon A. Cruz <jon@joncruz.org> + * Maximilian Albert <maximilian.albert@gmail.com> + * Tavmjong Bah <tavmjong@free.fr> + * Abhishek Sharma + * Kris De Gussem <Kris.DeGussem@gmail.com> + * + * Copyright (C) 2004 David Turner + * Copyright (C) 2003 MenTaLguY + * Copyright (C) 1999-2011 authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glibmm/i18n.h> + +#include "connector-toolbar.h" +#include "conn-avoid-ref.h" + +#include "desktop.h" +#include "document-undo.h" +#include "enums.h" +#include "graphlayout.h" +#include "widgets/ink-action.h" +#include "widgets/ink-toggle-action.h" +#include "widgets/toolbox.h" +#include "inkscape.h" +#include "verbs.h" + +#include "object/sp-namedview.h" +#include "object/sp-path.h" + +#include "ui/icon-names.h" +#include "ui/tools/connector-tool.h" +#include "ui/uxmanager.h" + +#include "widgets/ege-adjustment-action.h" +#include "widgets/spinbutton-events.h" + +#include "xml/node-event-vector.h" + +using Inkscape::UI::UXManager; +using Inkscape::DocumentUndo; +using Inkscape::UI::ToolboxFactory; +using Inkscape::UI::PrefPusher; + +//######################### +//## Connector ## +//######################### + +static void sp_connector_path_set_avoid(void) +{ + Inkscape::UI::Tools::cc_selection_set_avoid(true); +} + + +static void sp_connector_path_set_ignore(void) +{ + Inkscape::UI::Tools::cc_selection_set_avoid(false); +} + +static void sp_connector_orthogonal_toggled( GtkToggleAction* act, GObject *tbl ) +{ + SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data( tbl, "desktop" )); + SPDocument *doc = desktop->getDocument(); + + if (!DocumentUndo::getUndoSensitive(doc)) { + return; + } + + + // quit if run by the _changed callbacks + if (g_object_get_data( tbl, "freeze" )) { + return; + } + + // in turn, prevent callbacks from responding + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); + + bool is_orthog = gtk_toggle_action_get_active( act ); + gchar orthog_str[] = "orthogonal"; + gchar polyline_str[] = "polyline"; + gchar *value = is_orthog ? orthog_str : polyline_str ; + + bool modmade = false; + auto itemlist= desktop->getSelection()->items(); + for(auto i=itemlist.begin();i!=itemlist.end();++i){ + SPItem *item = *i; + + if (Inkscape::UI::Tools::cc_item_is_connector(item)) { + item->setAttribute( "inkscape:connector-type", + value, NULL); + item->avoidRef->handleSettingChange(); + modmade = true; + } + } + + if (!modmade) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setBool("/tools/connector/orthogonal", is_orthog); + } else { + + DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR, + is_orthog ? _("Set connector type: orthogonal"): _("Set connector type: polyline")); + } + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); +} + +static void connector_curvature_changed(GtkAdjustment *adj, GObject* tbl) +{ + SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data( tbl, "desktop" )); + SPDocument *doc = desktop->getDocument(); + + if (!DocumentUndo::getUndoSensitive(doc)) { + return; + } + + + // quit if run by the _changed callbacks + if (g_object_get_data( tbl, "freeze" )) { + return; + } + + // in turn, prevent callbacks from responding + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); + + gdouble newValue = gtk_adjustment_get_value(adj); + gchar value[G_ASCII_DTOSTR_BUF_SIZE]; + g_ascii_dtostr(value, G_ASCII_DTOSTR_BUF_SIZE, newValue); + + bool modmade = false; + auto itemlist= desktop->getSelection()->items(); + for(auto i=itemlist.begin();i!=itemlist.end();++i){ + SPItem *item = *i; + + if (Inkscape::UI::Tools::cc_item_is_connector(item)) { + item->setAttribute( "inkscape:connector-curvature", + value, NULL); + item->avoidRef->handleSettingChange(); + modmade = true; + } + } + + if (!modmade) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setDouble(Glib::ustring("/tools/connector/curvature"), newValue); + } + else { + DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR, + _("Change connector curvature")); + } + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); +} + + +static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl) +{ + SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data( tbl, "desktop" )); + SPDocument *doc = desktop->getDocument(); + + if (!DocumentUndo::getUndoSensitive(doc)) { + return; + } + + Inkscape::XML::Node *repr = desktop->namedview->getRepr(); + + if ( !repr->attribute("inkscape:connector-spacing") && + ( gtk_adjustment_get_value(adj) == defaultConnSpacing )) { + // Don't need to update the repr if the attribute doesn't + // exist and it is being set to the default value -- as will + // happen at startup. + return; + } + + // quit if run by the attr_changed listener + if (g_object_get_data( tbl, "freeze" )) { + return; + } + + // in turn, prevent listener from responding + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE)); + + sp_repr_set_css_double(repr, "inkscape:connector-spacing", gtk_adjustment_get_value(adj)); + desktop->namedview->updateRepr(); + bool modmade = false; + + std::vector<SPItem *> items; + items = get_avoided_items(items, desktop->currentRoot(), desktop); + for (std::vector<SPItem *>::const_iterator iter = items.begin(); iter != items.end(); ++iter ) { + SPItem *item = *iter; + Geom::Affine m = Geom::identity(); + avoid_item_move(&m, item); + modmade = true; + } + + if(modmade) { + DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR, + _("Change connector spacing")); + } + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); +} + +static void sp_connector_graph_layout(void) +{ + if (!SP_ACTIVE_DESKTOP) { + return; + } + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + // hack for clones, see comment in align-and-distribute.cpp + int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); + prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); + + auto tmp = SP_ACTIVE_DESKTOP->getSelection()->items(); + std::vector<SPItem *> vec(tmp.begin(), tmp.end()); + graphlayout(vec); + + prefs->setInt("/options/clonecompensation/value", saved_compensation); + + DocumentUndo::done(SP_ACTIVE_DESKTOP->getDocument(), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, _("Arrange connector network")); +} + +static void sp_directed_graph_layout_toggled( GtkToggleAction* act, GObject * /*tbl*/ ) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setBool("/tools/connector/directedlayout", + gtk_toggle_action_get_active( act )); +} + +static void sp_nooverlaps_graph_layout_toggled( GtkToggleAction* act, GObject * /*tbl*/ ) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setBool("/tools/connector/avoidoverlaplayout", + gtk_toggle_action_get_active( act )); +} + + +static void connector_length_changed(GtkAdjustment *adj, GObject* /*tbl*/) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setDouble("/tools/connector/length", gtk_adjustment_get_value(adj)); +} + +static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr, + gchar const *name, gchar const * /*old_value*/, gchar const * /*new_value*/, + bool /*is_interactive*/, gpointer data) +{ + GtkWidget *tbl = GTK_WIDGET(data); + + if ( !g_object_get_data(G_OBJECT(tbl), "freeze") + && (strcmp(name, "inkscape:connector-spacing") == 0) ) { + GtkAdjustment *adj = static_cast<GtkAdjustment*>(g_object_get_data(G_OBJECT(tbl), "spacing")); + gdouble spacing = defaultConnSpacing; + sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing); + + gtk_adjustment_set_value(adj, spacing); + +#if !GTK_CHECK_VERSION(3,18,0) + gtk_adjustment_value_changed(adj); +#endif + + spinbutton_defocus(tbl); + } +} + +static Inkscape::XML::NodeEventVector connector_tb_repr_events = { + NULL, /* child_added */ + NULL, /* child_removed */ + connector_tb_event_attr_changed, + NULL, /* content_changed */ + NULL /* order_changed */ +}; + +static void sp_connector_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) +{ + GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "curvature" ) ); + GtkToggleAction *act = GTK_TOGGLE_ACTION( g_object_get_data( tbl, "orthogonal" ) ); + SPItem *item = selection->singleItem(); + if (SP_IS_PATH(item)) + { + gdouble curvature = SP_PATH(item)->connEndPair.getCurvature(); + bool is_orthog = SP_PATH(item)->connEndPair.isOrthogonal(); + gtk_toggle_action_set_active(act, is_orthog); + gtk_adjustment_set_value(adj, curvature); + } + +} + +void sp_connector_toolbox_prep( SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder ) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + GtkIconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1); + + { + InkAction* inky = ink_action_new( "ConnectorAvoidAction", + _("Avoid"), + _("Make connectors avoid selected objects"), + INKSCAPE_ICON("connector-avoid"), + secondarySize ); + g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_connector_path_set_avoid), holder ); + gtk_action_group_add_action( mainActions, GTK_ACTION(inky) ); + } + + { + InkAction* inky = ink_action_new( "ConnectorIgnoreAction", + _("Ignore"), + _("Make connectors ignore selected objects"), + INKSCAPE_ICON("connector-ignore"), + secondarySize ); + g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_connector_path_set_ignore), holder ); + gtk_action_group_add_action( mainActions, GTK_ACTION(inky) ); + } + + // Orthogonal connectors toggle button + { + InkToggleAction* act = ink_toggle_action_new( "ConnectorOrthogonalAction", + _("Orthogonal"), + _("Make connector orthogonal or polyline"), + INKSCAPE_ICON("connector-orthogonal"), + GTK_ICON_SIZE_MENU ); + gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); + + bool tbuttonstate = prefs->getBool("/tools/connector/orthogonal"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), ( tbuttonstate ? TRUE : FALSE )); + g_object_set_data( holder, "orthogonal", act ); + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_connector_orthogonal_toggled), holder ); + } + + EgeAdjustmentAction* eact = 0; + // Curvature spinbox + eact = create_adjustment_action( "ConnectorCurvatureAction", + _("Connector Curvature"), _("Curvature:"), + _("The amount of connectors curvature"), + "/tools/connector/curvature", defaultConnCurvature, + GTK_WIDGET(desktop->canvas), holder, TRUE, "inkscape:connector-curvature", + 0, 100, 1.0, 10.0, + 0, 0, 0, + connector_curvature_changed, NULL /*unit tracker*/, 1, 0 ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + + // Spacing spinbox + eact = create_adjustment_action( "ConnectorSpacingAction", + _("Connector Spacing"), _("Spacing:"), + _("The amount of space left around objects by auto-routing connectors"), + "/tools/connector/spacing", defaultConnSpacing, + GTK_WIDGET(desktop->canvas), holder, TRUE, "inkscape:connector-spacing", + 0, 100, 1.0, 10.0, + 0, 0, 0, + connector_spacing_changed, NULL /*unit tracker*/, 1, 0 ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + + // Graph (connector network) layout + { + InkAction* inky = ink_action_new( "ConnectorGraphAction", + _("Graph"), + _("Nicely arrange selected connector network"), + INKSCAPE_ICON("distribute-graph"), + secondarySize ); + g_signal_connect_after( G_OBJECT(inky), "activate", G_CALLBACK(sp_connector_graph_layout), holder ); + gtk_action_group_add_action( mainActions, GTK_ACTION(inky) ); + } + + // Default connector length spinbox + eact = create_adjustment_action( "ConnectorLengthAction", + _("Connector Length"), _("Length:"), + _("Ideal length for connectors when layout is applied"), + "/tools/connector/length", 100, + GTK_WIDGET(desktop->canvas), holder, TRUE, "inkscape:connector-length", + 10, 1000, 10.0, 100.0, + 0, 0, 0, + connector_length_changed, NULL /*unit tracker*/, 1, 0 ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + + + // Directed edges toggle button + { + InkToggleAction* act = ink_toggle_action_new( "ConnectorDirectedAction", + _("Downwards"), + _("Make connectors with end-markers (arrows) point downwards"), + INKSCAPE_ICON("distribute-graph-directed"), + GTK_ICON_SIZE_MENU ); + gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); + + bool tbuttonstate = prefs->getBool("/tools/connector/directedlayout"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), ( tbuttonstate ? TRUE : FALSE )); + + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_directed_graph_layout_toggled), holder ); + desktop->getSelection()->connectChanged(sigc::bind(sigc::ptr_fun(sp_connector_toolbox_selection_changed), holder)); + } + + // Avoid overlaps toggle button + { + InkToggleAction* act = ink_toggle_action_new( "ConnectorOverlapAction", + _("Remove overlaps"), + _("Do not allow overlapping shapes"), + INKSCAPE_ICON("distribute-remove-overlaps"), + GTK_ICON_SIZE_MENU ); + gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); + + bool tbuttonstate = prefs->getBool("/tools/connector/avoidoverlaplayout"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), (tbuttonstate ? TRUE : FALSE )); + + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_nooverlaps_graph_layout_toggled), holder ); + } + + + // Code to watch for changes to the connector-spacing attribute in + // the XML. + Inkscape::XML::Node *repr = desktop->namedview->getRepr(); + g_assert(repr != NULL); + + purge_repr_listener( holder, holder ); + + if (repr) { + g_object_set_data( holder, "repr", repr ); + Inkscape::GC::anchor(repr); + sp_repr_add_listener( repr, &connector_tb_repr_events, holder ); + sp_repr_synthesize_events( repr, &connector_tb_repr_events, holder ); + } +} // end of sp_connector_toolbox_prep() + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |
