Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
connector-toolbar.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
5/* Authors:
6 * MenTaLguY <mental@rydia.net>
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 * bulia byak <buliabyak@users.sf.net>
9 * Frank Felfe <innerspace@iname.com>
10 * John Cliff <simarilius@yahoo.com>
11 * David Turner <novalis@gnu.org>
12 * Josh Andler <scislac@scislac.com>
13 * Jon A. Cruz <jon@joncruz.org>
14 * Maximilian Albert <maximilian.albert@gmail.com>
15 * Tavmjong Bah <tavmjong@free.fr>
16 * Abhishek Sharma
17 * Kris De Gussem <Kris.DeGussem@gmail.com>
18 * Vaibhav Malik <vaibhavmalik2018@gmail.com>
19 *
20 * Copyright (C) 2004 David Turner
21 * Copyright (C) 2003 MenTaLguY
22 * Copyright (C) 1999-2011 authors
23 * Copyright (C) 2001-2002 Ximian, Inc.
24 *
25 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
26 */
27
28#include "connector-toolbar.h"
29
30#include <glibmm/i18n.h>
31#include <gtkmm/adjustment.h>
32#include <gtkmm/builder.h>
33#include <gtkmm/togglebutton.h>
34
35#include "conn-avoid-ref.h"
36#include "desktop.h"
37#include "document-undo.h"
38#include "enums.h"
39#include "layer-manager.h"
41#include "object/sp-namedview.h"
42#include "object/sp-path.h"
43#include "selection.h"
44#include "ui/builder-utils.h"
45#include "ui/icon-names.h"
48
50
51namespace Inkscape::UI::Toolbar {
52
56
57ConnectorToolbar::ConnectorToolbar(Glib::RefPtr<Gtk::Builder> const &builder)
58 : Toolbar{get_widget<Gtk::Box>(builder, "connector-toolbar")}
59 , _orthogonal_btn{get_widget<Gtk::ToggleButton> (builder, "_orthogonal_btn")}
60 , _curvature_item{get_derived_widget<UI::Widget::SpinButton>(builder, "_curvature_item")}
61 , _spacing_item {get_derived_widget<UI::Widget::SpinButton>(builder, "_spacing_item")}
62 , _length_item {get_derived_widget<UI::Widget::SpinButton>(builder, "_length_item")}
63 , _directed_btn {get_widget<Gtk::ToggleButton> (builder, "_directed_btn")}
64 , _overlap_btn {get_widget<Gtk::ToggleButton> (builder, "_overlap_btn")}
65{
66 auto prefs = Preferences::get();
67
71
72 // Values auto-calculated.
76
77 // Orthogonal connectors toggle button
78 _orthogonal_btn.set_active(prefs->getBool("/tools/connector/orthogonal"));
79
80 // Directed edges toggle button
81 _directed_btn.set_active(prefs->getBool("/tools/connector/directedlayout"));
82
83 // Avoid overlaps toggle button
84 _overlap_btn.set_active(prefs->getBool("/tools/connector/avoidoverlaplayout"));
85
86 // Signals.
87 get_widget<Gtk::Button>(builder, "avoid_btn")
88 .signal_clicked()
89 .connect(sigc::mem_fun(*this, &ConnectorToolbar::path_set_avoid));
90 get_widget<Gtk::Button>(builder, "ignore_btn")
91 .signal_clicked()
92 .connect(sigc::mem_fun(*this, &ConnectorToolbar::path_set_ignore));
93 get_widget<Gtk::Button>(builder, "graph_btn")
94 .signal_clicked()
95 .connect(sigc::mem_fun(*this, &ConnectorToolbar::graph_layout));
96
97 _orthogonal_btn.signal_toggled().connect(sigc::mem_fun(*this, &ConnectorToolbar::orthogonal_toggled));
98 _directed_btn.signal_toggled().connect(sigc::mem_fun(*this, &ConnectorToolbar::directed_graph_layout_toggled));
99 _overlap_btn.signal_toggled().connect(sigc::mem_fun(*this, &ConnectorToolbar::nooverlaps_graph_layout_toggled));
100
102}
103
105{
106 if (_desktop) {
107 _repr->removeObserver(*this);
109 _repr = nullptr;
110
111 _selection_changed_conn.disconnect();
112 }
113
115
116 if (_desktop) {
118
119 // Watch for changes to the connector-spacing attribute in the XML.
122 _repr->addObserver(*this);
123 // _repr->synthesizeEvents(*this); // BAD
124 }
125}
126
128 double default_value, ValueChangedMemFun value_changed_mem_fun)
129{
130 auto const adj = btn.get_adjustment();
131 auto const path = "/tools/connector/" + name;
132 auto const val = Preferences::get()->getDouble(path, default_value);
133 adj->set_value(val);
134 adj->signal_value_changed().connect(sigc::mem_fun(*this, value_changed_mem_fun));
135 btn.setDefocusTarget(this);
136}
137
142
147
149{
150 auto doc = _desktop->getDocument();
151
153 return;
154 }
155
156 // quit if run by the _changed callbacks
157 if (_blocker.pending()) {
158 return;
159 }
160
161 // in turn, prevent callbacks from responding
162 auto guard = _blocker.block();
163
164 bool is_orthog = _orthogonal_btn.get_active();
165 auto value = is_orthog ? "orthogonal" : "polyline";
166
167 bool modified = false;
168 for (auto item : _desktop->getSelection()->items()) {
170 item->setAttribute( "inkscape:connector-type", value);
172 modified = true;
173 }
174 }
175
176 if (!modified) {
177 Preferences::get()->setBool("/tools/connector/orthogonal", is_orthog);
178 } else {
179 DocumentUndo::done(doc, is_orthog ? _("Set connector type: orthogonal"): _("Set connector type: polyline"), INKSCAPE_ICON("draw-connector"));
180 }
181}
182
184{
185 auto doc = _desktop->getDocument();
186
188 return;
189 }
190
191 // quit if run by the _changed callbacks
192 if (_blocker.pending()) {
193 return;
194 }
195
196 // in turn, prevent callbacks from responding
197 auto guard = _blocker.block();
198
199 auto newValue = _curvature_item.get_adjustment()->get_value();
200 char value[G_ASCII_DTOSTR_BUF_SIZE];
201 g_ascii_dtostr(value, G_ASCII_DTOSTR_BUF_SIZE, newValue);
202
203 bool modified = false;
204 for (auto item : _desktop->getSelection()->items()) {
206 item->setAttribute( "inkscape:connector-curvature", value);
208 modified = true;
209 }
210 }
211
212 if (!modified) {
213 Preferences::get()->setDouble(Glib::ustring("/tools/connector/curvature"), newValue);
214 } else {
215 DocumentUndo::done(doc, _("Change connector curvature"), INKSCAPE_ICON("draw-connector"));
216 }
217}
218
220{
221 auto doc = _desktop->getDocument();
222
224 return;
225 }
226
227 auto repr = _desktop->getNamedView()->getRepr();
228
229 if (!repr->attribute("inkscape:connector-spacing") &&
230 _spacing_item.get_adjustment()->get_value() == defaultConnSpacing) {
231 // Don't need to update the repr if the attribute doesn't
232 // exist and it is being set to the default value -- as will
233 // happen at startup.
234 return;
235 }
236
237 // quit if run by the attr_changed listener
238 if (_blocker.pending()) {
239 return;
240 }
241
242 // in turn, prevent listener from responding
243 auto guard = _blocker.block();
244
245 repr->setAttributeCssDouble("inkscape:connector-spacing", _spacing_item.get_adjustment()->get_value());
247
248 bool modified = false;
250 auto m = Geom::identity();
252 modified = true;
253 }
254
255 if (modified) {
256 DocumentUndo::done(doc, _("Change connector spacing"), INKSCAPE_ICON("draw-connector"));
257 }
258}
259
261{
262 auto prefs = Preferences::get();
263
264 // hack for clones, see comment in align-and-distribute.cpp
265 int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
266 prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
267
268 auto tmp = _desktop->getSelection()->items();
269 auto vec = std::vector<SPItem *>{tmp.begin(), tmp.end()};
270 graphlayout(vec);
271
272 prefs->setInt("/options/clonecompensation/value", saved_compensation);
273
274 DocumentUndo::done(_desktop->getDocument(), _("Arrange connector network"), INKSCAPE_ICON("dialog-align-and-distribute"));
275}
276
278{
279 Preferences::get()->setDouble("/tools/connector/length", _length_item.get_adjustment()->get_value());
280}
281
283{
284 Preferences::get()->setBool("/tools/connector/directedlayout", _directed_btn.get_active());
285}
286
288{
289 if (auto path = cast<SPPath>(selection->singleItem())) {
290 _orthogonal_btn.set_active(path->connEndPair.isOrthogonal());
291 _curvature_item.get_adjustment()->set_value(path->connEndPair.getCurvature());
292 }
293}
294
296{
297 Preferences::get()->setBool("/tools/connector/avoidoverlaplayout", _overlap_btn.get_active());
298}
299
301{
302 if (_blocker.pending()) {
303 return;
304 }
305
306 static auto const connector_spacing_quark = g_quark_from_static_string("inkscape:connector-spacing");
307 if (name == connector_spacing_quark) {
308 _spacing_item.get_adjustment()->set_value(_desktop->getNamedView()->connector_spacing);
309 }
310}
311
312} // namespace Inkscape::UI::Toolbar
313
314/*
315 Local Variables:
316 mode:c++
317 c-file-style:"stroustrup"
318 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
319 indent-tabs-mode:nil
320 fill-column:99
321 End:
322*/
323// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Gtk builder utilities.
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
static bool getUndoSensitive(SPDocument const *document)
SPGroup * currentRoot() const
Returns current root (=bottom) layer.
SPItemRange items()
Returns a range of selected SPItems.
Definition object-set.h:255
SPItem * singleItem()
Returns a single selected item.
double getDouble(Glib::ustring const &pref_path, double def=0.0, Glib::ustring const &unit="")
Retrieve a floating point value.
static Preferences * get()
Access the singleton Preferences object.
void setDouble(Glib::ustring const &pref_path, double value)
Set a floating point value.
void setBool(Glib::ustring const &pref_path, bool value)
Set a Boolean value.
The set of selected SPObjects for a given document and layer model.
Definition selection.h:80
sigc::connection connectChanged(sigc::slot< void(Selection *)> slot)
Connects a slot to be notified of selection changes.
Definition selection.h:179
void(ConnectorToolbar::*)() ValueChangedMemFun
void setup_derived_spin_button(UI::Widget::SpinButton &btn, Glib::ustring const &name, double default_value, ValueChangedMemFun value_changed_mem_fun)
void setDesktop(SPDesktop *desktop) override
void notifyAttributeChanged(XML::Node &node, GQuark name, Util::ptr_shared old_value, Util::ptr_shared new_value) override
Attribute change callback.
Base class for all tool toolbars.
Definition toolbar.h:72
virtual void setDesktop(SPDesktop *desktop)
Definition toolbar.h:76
SpinButton widget, that allows entry of simple math expressions (also units, when linked with UnitMen...
Definition spinbutton.h:52
void setDefocusTarget(decltype(_defocus_target) target)
Definition spinbutton.h:127
void set_custom_numeric_menu_data(NumericMenuData &&custom_menu_data)
Interface for refcounted XML nodes.
Definition node.h:80
virtual void addObserver(NodeObserver &observer)=0
Add an object that will be notified of the changes to this node.
virtual void removeObserver(NodeObserver &observer)=0
Remove an object from the list of observers.
scoped_block block()
void handleSettingChange()
To do: update description of desktop.
Definition desktop.h:149
SPDocument * getDocument() const
Definition desktop.h:189
SPNamedView * getNamedView() const
Definition desktop.h:191
Inkscape::Selection * getSelection() const
Definition desktop.h:188
Inkscape::LayerManager & layerManager()
Definition desktop.h:287
SPAvoidRef & getAvoidRef()
Definition sp-item.cpp:202
double connector_spacing
void setAttribute(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
Inkscape::XML::Node * updateRepr(unsigned int flags=SP_OBJECT_WRITE_EXT)
Updates the object's repr based on the object's state.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
void avoid_item_move(Geom::Affine const *, SPItem *moved_item)
std::vector< SPItem * > get_avoided_items(SPObject *from, SPDesktop *desktop, bool initialised)
A class for handling shape interaction with libavoid.
static const double defaultConnSpacing
static const double defaultConnCurvature
Editable view implementation.
TODO: insert short description here.
@ SP_CLONE_COMPENSATION_UNMOVED
Definition enums.h:90
void graphlayout(std::vector< SPItem * > const &items)
Takes a list of inkscape items, extracts the graph defined by connectors between them,...
graph layout functions.
Macro for icon names used in Inkscape.
SPItem * item
Affine identity()
Create an identity matrix.
Definition affine.h:210
Definition desktop.h:50
static R & anchor(R &r)
Increments the reference count of a anchored object.
Definition gc-anchored.h:92
static R & release(R &r)
Decrements the reference count of a anchored object.
bool cc_item_is_connector(SPItem *item)
void cc_selection_set_avoid(SPDesktop *desktop, bool const set_avoid)
W & get_widget(const Glib::RefPtr< Gtk::Builder > &builder, const char *id)
W & get_derived_widget(const Glib::RefPtr< Gtk::Builder > &builder, const char *id, Args &&... args)
Glib::RefPtr< Gtk::Builder > create_builder(const char *filename)
guint32 GQuark
SPDesktop * desktop
Glib::ustring name
Definition toolbars.cpp:55
Glib::RefPtr< Gtk::Builder > builder