Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
lpe-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 "lpe-toolbar.h"
29
30#include <gtkmm/togglebutton.h>
31
33#include "selection.h"
34#include "ui/builder-utils.h"
36#include "ui/tools/lpe-tool.h"
37#include "ui/util.h"
40
47
48namespace Inkscape::UI::Toolbar {
49
51 : LPEToolbar{create_builder("toolbar-lpe.ui")}
52{}
53
54LPEToolbar::LPEToolbar(Glib::RefPtr<Gtk::Builder> const &builder)
55 : Toolbar{get_widget<Gtk::Box>(builder, "lpe-toolbar")}
56 , _show_bbox_btn(get_widget<Gtk::ToggleButton>(builder, "_show_bbox_btn"))
57 , _bbox_from_selection_btn(get_widget<Gtk::ToggleButton>(builder, "_bbox_from_selection_btn"))
58 , _measuring_btn(get_widget<Gtk::ToggleButton>(builder, "_measuring_btn"))
59 , _open_lpe_dialog_btn(get_widget<Gtk::ToggleButton>(builder, "_open_lpe_dialog_btn"))
60 , _tracker{std::make_unique<UnitTracker>(Util::UNIT_TYPE_LINEAR)}
61{
62 auto prefs = Preferences::get();
63
64 // Combo box to choose line segment type
66 auto store = Gtk::ListStore::create(columns);
67
68 for (auto item : {_("Closed"), _("Open start"), _("Open end"), _("Open both")}) {
69 auto row = *store->append();
70 row[columns.col_label ] = item;
71 row[columns.col_sensitive] = true;
72 }
73
74 _line_segment_combo = Gtk::manage(UI::Widget::ComboToolItem::create(_("Line Type"), _("Choose a line segment type"), "Not Used", store));
78 get_widget<Gtk::Box>(builder, "line_segment_box").append(*_line_segment_combo);
79
80 // Configure mode buttons
81 int btn_index = 0;
82 for_each_child(get_widget<Gtk::Box>(builder, "mode_buttons_box"), [&](Gtk::Widget &item){
83 auto &btn = dynamic_cast<Gtk::ToggleButton &>(item);
84 _mode_buttons.push_back(&btn);
85 btn.signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &LPEToolbar::mode_changed), btn_index++));
87 });
88
89 int mode = prefs->getInt("/tools/lpetool/mode", 0);
90 _mode_buttons[mode]->set_active();
91
92 // Add the units menu
93 _units_item = _tracker->create_tool_item(_("Units"), "");
94 _units_item->signal_changed_after().connect(sigc::mem_fun(*this, &LPEToolbar::unit_changed));
95 _units_item->set_sensitive(prefs->getBool("/tools/lpetool/show_measuring_info", true));
96 get_widget<Gtk::Box>(builder, "units_box").append(*_units_item);
97
98 // Set initial states
99 _show_bbox_btn.set_active(prefs->getBool("/tools/lpetool/show_bbox", true));
100 _bbox_from_selection_btn.set_active(false);
101 _measuring_btn.set_active(prefs->getBool("/tools/lpetool/show_measuring_info", true));
102 _open_lpe_dialog_btn.set_active(false);
103
104 // Signals.
105 _show_bbox_btn.signal_toggled().connect(sigc::mem_fun(*this, &LPEToolbar::toggle_show_bbox));
106 _bbox_from_selection_btn.signal_toggled().connect(sigc::mem_fun(*this, &LPEToolbar::toggle_set_bbox));
107 _measuring_btn.signal_toggled().connect(sigc::mem_fun(*this, &LPEToolbar::toggle_show_measuring_info));
108 _open_lpe_dialog_btn.signal_toggled().connect(sigc::mem_fun(*this, &LPEToolbar::open_lpe_dialog));
109
111}
112
113LPEToolbar::~LPEToolbar() = default;
114
116{
117 if (_desktop) {
118 c_selection_modified.disconnect();
119 c_selection_changed.disconnect();
120 }
121
123
124 if (_desktop) {
125 // Watch selection
129 }
130}
131
133{
134 _tracker->setActiveUnit(unit);
135}
136
138{
139 _mode_buttons[mode]->set_active();
140}
141
142// this is called when the mode is changed via the toolbar (i.e., one of the subtool buttons is pressed)
144{
145 using namespace LivePathEffect;
146
147 auto const tool = _desktop->getTool();
148 if (!SP_LPETOOL_CONTEXT(tool)) {
149 return;
150 }
151
152 // only take action if run by the attr_changed listener
153 if (_blocker.pending()) {
154 return;
155 }
156
157 // in turn, prevent listener from responding
158 auto guard = _blocker.block();
159
160 EffectType type = lpesubtools[mode].type;
161
162 auto const lc = SP_LPETOOL_CONTEXT(_desktop->getTool());
163 bool success = UI::Tools::lpetool_try_construction(lc->getDesktop(), type);
164 if (success) {
165 // since the construction was already performed, we set the state back to inactive
166 _mode_buttons[0]->set_active();
167 mode = 0;
168 } else {
169 // switch to the chosen subtool
170 SP_LPETOOL_CONTEXT(_desktop->getTool())->mode = type;
171 }
172
174 Preferences::get()->setInt("/tools/lpetool/mode", mode);
175 }
176}
177
179{
180 Preferences::get()->setBool("/tools/lpetool/show_bbox", _show_bbox_btn.get_active());
181
182 if (auto const lc = dynamic_cast<LpeTool *>(_desktop->getTool())) {
183 lc->reset_limiting_bbox();
184 }
185}
186
188{
189 auto selection = _desktop->getSelection();
190
191 auto bbox = selection->visualBounds();
192
193 if (bbox) {
194 Geom::Point A(bbox->min());
195 Geom::Point B(bbox->max());
196
197 A *= _desktop->doc2dt();
198 B *= _desktop->doc2dt();
199
200 // TODO: should we provide a way to store points in prefs?
201 auto prefs = Preferences::get();
202 prefs->setDouble("/tools/lpetool/bbox_upperleftx", A[Geom::X]);
203 prefs->setDouble("/tools/lpetool/bbox_upperlefty", A[Geom::Y]);
204 prefs->setDouble("/tools/lpetool/bbox_lowerrightx", B[Geom::X]);
205 prefs->setDouble("/tools/lpetool/bbox_lowerrighty", B[Geom::Y]);
206
207 SP_LPETOOL_CONTEXT(_desktop->getTool())->reset_limiting_bbox();
208 }
209
210 _bbox_from_selection_btn.set_active(false);
211}
212
214{
215 using namespace LivePathEffect;
216
217 // quit if run by the attr_changed listener
218 if (_blocker.pending()) {
219 return;
220 }
221
222 // in turn, prevent listener from responding
223 auto guard = _blocker.block();
224
225 auto line_seg = dynamic_cast<LPELineSegment *>(_currentlpe);
226
227 if (_currentlpeitem && line_seg) {
228 line_seg->end_type.param_set_value(static_cast<LivePathEffect::EndType>(mode));
230 }
231}
232
234{
235 auto const lc = dynamic_cast<LpeTool *>(_desktop->getTool());
236 if (!lc) {
237 return;
238 }
239
240 bool show = _measuring_btn.get_active();
241 Preferences::get()->setBool("/tools/lpetool/show_measuring_info", show);
242 lc->show_measuring_info(show);
243 _units_item->set_sensitive(show);
244}
245
247{
248 if (!_desktop) {
249 return;
250 }
251
252 Preferences::get()->setString("/tools/lpetool/unit", _tracker->getActiveUnit()->abbr);
253
254 if (auto const lc = SP_LPETOOL_CONTEXT(_desktop->getTool())) {
255 lc->delete_measuring_items();
256 lc->create_measuring_items();
257 }
258}
259
261{
262 if (dynamic_cast<LpeTool *>(_desktop->getTool())) {
263 _desktop->getContainer()->new_dialog("LivePathEffect");
264 } else {
265 std::cerr << "LPEToolbar::open_lpe_dialog: LPEToolbar active but current tool is not LPE tool!" << std::endl;
266 }
267 _open_lpe_dialog_btn.set_active(false);
268}
269
270void LPEToolbar::sel_modified(Selection *selection, guint /*flags*/)
271{
272 auto const tool = selection->desktop()->getTool();
273 if (auto const lc = SP_LPETOOL_CONTEXT(tool)) {
274 lc->update_measuring_items();
275 }
276}
277
279{
280 using namespace LivePathEffect;
281 auto const tool = selection->desktop()->getTool();
282 auto const lc = SP_LPETOOL_CONTEXT(tool);
283 if (!lc) {
284 return;
285 }
286
287 lc->delete_measuring_items();
288 lc->create_measuring_items(selection);
289
290 // activate line segment combo box if a single item with LPELineSegment is selected
291 auto lpeitem = cast<SPLPEItem>(selection->singleItem());
292 if (lpeitem && UI::Tools::lpetool_item_has_construction(lpeitem)) {
293
294 auto lpe = lpeitem->getCurrentLPE();
295 if (lpe && lpe->effectType() == LINE_SEGMENT) {
296 auto lpels = static_cast<LPELineSegment *>(lpe);
297 _currentlpe = lpe;
298 _currentlpeitem = lpeitem;
299 _line_segment_combo->set_sensitive(true);
300 _line_segment_combo->set_active( lpels->end_type.get_value() );
301 } else {
302 _currentlpe = nullptr;
303 _currentlpeitem = nullptr;
304 _line_segment_combo->set_sensitive(false);
305 }
306
307 } else {
308 _currentlpe = nullptr;
309 _currentlpeitem = nullptr;
310 _line_segment_combo->set_sensitive(false);
311 }
312}
313
314} // namespace Inkscape::UI::Toolbar
315
316/*
317 Local Variables:
318 mode:c++
319 c-file-style:"stroustrup"
320 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
321 indent-tabs-mode:nil
322 fill-column:99
323 End:
324*/
325// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
Gtk builder utilities.
Fragment store
Definition canvas.cpp:155
Two-dimensional point that doubles as a vector.
Definition point.h:66
static bool getUndoSensitive(SPDocument const *document)
SPDesktop * desktop()
Returns the desktop the selection is bound to.
Definition object-set.h:390
SPItem * singleItem()
Returns a single selected item.
Geom::OptRect visualBounds() const
static Preferences * get()
Access the singleton Preferences object.
void setString(Glib::ustring const &pref_path, Glib::ustring const &value)
Set an UTF-8 string value.
void setInt(Glib::ustring const &pref_path, int value)
Set an integer 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
sigc::connection connectModified(sigc::slot< void(Selection *, unsigned)> slot)
Connects a slot to be notified of selected object modifications.
Definition selection.h:232
void new_dialog(const Glib::ustring &dialog_type)
Add new dialog to the current container or in a floating window, based on preferences.
LivePathEffect::Effect * _currentlpe
Definition lpe-toolbar.h:81
void sel_changed(Inkscape::Selection *selection)
Gtk::ToggleButton & _show_bbox_btn
Definition lpe-toolbar.h:72
void sel_modified(Inkscape::Selection *selection, guint flags)
std::unique_ptr< UI::Widget::UnitTracker > _tracker
Definition lpe-toolbar.h:69
void setActiveUnit(Util::Unit const *unit) override
std::vector< Gtk::ToggleButton * > _mode_buttons
Definition lpe-toolbar.h:71
sigc::connection c_selection_modified
Definition lpe-toolbar.h:84
Gtk::ToggleButton & _bbox_from_selection_btn
Definition lpe-toolbar.h:73
UI::Widget::ComboToolItem * _line_segment_combo
Definition lpe-toolbar.h:76
Gtk::ToggleButton & _measuring_btn
Definition lpe-toolbar.h:74
UI::Widget::ComboToolItem * _units_item
Definition lpe-toolbar.h:77
void setDesktop(SPDesktop *desktop) override
Gtk::ToggleButton & _open_lpe_dialog_btn
Definition lpe-toolbar.h:75
sigc::connection c_selection_changed
Definition lpe-toolbar.h:85
Base class for all tool toolbars.
Definition toolbar.h:72
virtual void setDesktop(SPDesktop *desktop)
Definition toolbar.h:76
Base class for Event processors.
Definition tool-base.h:107
Gtk::TreeModelColumn< bool > col_sensitive
Gtk::TreeModelColumn< Glib::ustring > col_label
void use_group_label(bool use_group_label)
sigc::signal< void(int)> signal_changed_after()
static ComboToolItem * create(const Glib::ustring &label, const Glib::ustring &tooltip, const Glib::ustring &stock_id, Glib::RefPtr< Gtk::ListStore > store, bool has_entry=false)
sigc::signal< void(int)> signal_changed()
scoped_block block()
To do: update description of desktop.
Definition desktop.h:149
SPDocument * getDocument() const
Definition desktop.h:189
Inkscape::UI::Dialog::DialogContainer * getContainer()
Definition desktop.cpp:335
Inkscape::Selection * getSelection() const
Definition desktop.h:188
Inkscape::UI::Tools::ToolBase * getTool() const
Definition desktop.h:187
Geom::Affine const & doc2dt() const
Definition desktop.cpp:1337
A combobox that can be displayed in a toolbar.
A widget that manages DialogNotebook's and other widgets inside a horizontal DialogMultipaned.
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
SPItem * item
LPE <line_segment> implementation.
SubtoolEntry const lpesubtools[]
Definition lpe-tool.cpp:49
LPETool: a generic tool composed of subtools that are given by LPEs.
auto SP_LPETOOL_CONTEXT(Inkscape::UI::Tools::ToolBase *tool)
Definition lpe-tool.h:83
Definition desktop.h:50
int lpetool_item_has_construction(SPItem *item)
Definition lpe-tool.cpp:192
bool lpetool_try_construction(SPDesktop *desktop, LivePathEffect::EffectType const type)
Definition lpe-tool.cpp:210
W & get_widget(const Glib::RefPtr< Gtk::Builder > &builder, const char *id)
Gtk::Widget * for_each_child(Gtk::Widget &widget, Func &&func, bool const plus_self=false, bool const recurse=false, int const level=0)
Call Func with a reference to each child of parent, until it returns _break.
Definition util.h:103
Glib::RefPtr< Gtk::Builder > create_builder(const char *filename)
Miscellaneous supporting code.
Definition document.h:93
STL namespace.
int mode
void sp_lpe_item_update_patheffect(SPLPEItem *lpeitem, bool wholetree, bool write, bool with_satellites)
Calls any registered handlers for the update_patheffect action.
Inkscape::LivePathEffect::EffectType type
Definition lpe-tool.h:29
SPDesktop * desktop
Glib::RefPtr< Gtk::Builder > builder