Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
guides.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
6/* Authors:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 * Andrius R. <knutux@gmail.com>
9 * Johan Engelen
10 * Abhishek Sharma
11 *
12 * Copyright (C) 1999-2007 Authors
13 *
14 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
15 */
16
17#include "guides.h"
18
19#include <glibmm/i18n.h>
20#include <gtkmm/button.h>
21
22#include "desktop.h"
23#include "document-undo.h"
24#include "document.h"
25#include "object/sp-guide.h"
26#include "object/sp-namedview.h"
27#include "page-manager.h"
28#include "preferences.h"
30
31namespace Inkscape::UI::Dialog {
32namespace {
33
34bool relative_toggle_status = false; // initialize relative checkbox status for when this dialog is opened for first time
35Glib::ustring angle_unit_status = DEG; // initialize angle unit status
36
37} // namespace
38
40 : _desktop(desktop)
41 , _guide(guide)
42 , _locked_toggle(_("Lo_cked"))
43 , _relative_toggle(_("Rela_tive change"))
44 , _spin_button_x(C_("Guides", "_X:"), Glib::ustring{}, UNIT_TYPE_LINEAR, Glib::ustring{}, &_unit_menu)
45 , _spin_button_y(C_("Guides", "_Y:"), Glib::ustring{}, UNIT_TYPE_LINEAR, Glib::ustring{}, &_unit_menu)
46 , _label_entry(_("_Label:"), _("Optionally give this guideline a name"))
47 , _spin_angle(_("_Angle:"), {}, UNIT_TYPE_RADIAL)
48{
49 set_name("GuidelinePropertiesDialog");
50 _locked_toggle.set_use_underline();
51 _locked_toggle.set_tooltip_text(_("Lock the movement of guides"));
52 _relative_toggle.set_use_underline();
53 _relative_toggle.set_tooltip_text(_("Move and/or rotate the guide relative to current settings"));
54 _setup();
55}
56
58{
59 // save current status
60 relative_toggle_status = _relative_toggle.get_active();
61 angle_unit_status = _spin_angle.getUnit()->abbr;
62}
63
65{
66 auto dialog = Gtk::manage(new GuidelinePropertiesDialog(guide, desktop));
67 dialog->present(); // will self-destruct
68}
69
71{
72 _mode = !_relative_toggle.get_active();
73 if (!_mode) {
74 // relative
76
79 } else {
80 // absolute
82
83 auto pos = _oldpos;
84
85 // Adjust position by the page position
87 auto &pm = _guide->document->getPageManager();
88 pos *= pm.getSelectedPageAffine().inverse();
89 }
90
93 }
94}
95
97{
98 _onOKimpl();
99 DocumentUndo::done(_guide->document, _("Set guide properties"), "");
100}
101
103{
104 double deg_angle = _spin_angle.getValue(DEG);
105 if (!_mode)
106 deg_angle += _oldangle;
107 Geom::Point normal;
108 if ( deg_angle == 90. || deg_angle == 270. || deg_angle == -90. || deg_angle == -270.) {
109 normal = Geom::Point(1.,0.);
110 } else if ( deg_angle == 0. || deg_angle == 180. || deg_angle == -180.) {
111 normal = Geom::Point(0.,1.);
112 } else {
113 double rad_angle = Geom::rad_from_deg( deg_angle );
114 normal = Geom::rot90(Geom::Point::polar(rad_angle, 1.0));
115 }
116 //To allow reposition from dialog
117 _guide->set_locked(false, false);
118
119 _guide->set_normal(normal, true);
120
121 double const points_x = _spin_button_x.getValue("px");
122 double const points_y = _spin_button_y.getValue("px");
123 Geom::Point newpos(points_x, points_y);
124
125 // Adjust position by either the relative position, or the page offset
126 if (!_mode) {
127 newpos += _oldpos;
128 }
130 auto &pm = _guide->document->getPageManager();
131 newpos *= pm.getSelectedPageAffine();
132 }
133
134 _guide->moveto(newpos, true);
135 _guide->set_label(_label_entry.getEntry()->get_text().c_str(), true);
136 _guide->set_locked(_locked_toggle.get_active(), true);
137
138 const auto c = _color.get_rgba();
139 unsigned r = c.get_red_u()/257, g = c.get_green_u()/257, b = c.get_blue_u()/257;
140 //TODO: why 257? verify this!
141 // don't know why, but introduced: 761f7da58cd6d625b88c24eee6fae1b7fa3bfcdd
142
143 _guide->set_color(r, g, b, true);
144}
145
147{
148 SPDocument *doc = _guide->document;
149 if (_guide->remove(true))
150 DocumentUndo::done(doc, _("Delete guide"), "");
151}
152
154{
156 _onOKimpl();
157 DocumentUndo::done(_guide->document, _("Duplicate guide"), "");
158}
159
161{
162 set_title(_("Guideline"));
163
164 auto vbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
165 set_child(*vbox);
166
167 _layout_table.set_row_spacing(4);
168 _layout_table.set_column_spacing(4);
169 _layout_table.set_margin(4);
170 _layout_table.set_expand();
171
172 vbox->append(_layout_table);
173
174 _label_name.set_label("foo0");
175 _label_name.set_halign(Gtk::Align::START);
176 _label_name.set_valign(Gtk::Align::CENTER);
177
178 _label_descr.set_label("foo1");
179 _label_descr.set_halign(Gtk::Align::START);
180 _label_descr.set_valign(Gtk::Align::CENTER);
181
182 _label_name.set_halign(Gtk::Align::FILL);
183 _label_name.set_valign(Gtk::Align::FILL);
184 _layout_table.attach(_label_name, 0, 0, 3, 1);
185
186 _label_descr.set_halign(Gtk::Align::FILL);
187 _label_descr.set_valign(Gtk::Align::FILL);
188 _layout_table.attach(_label_descr, 0, 1, 3, 1);
189
190 _label_entry.set_halign(Gtk::Align::FILL);
191 _label_entry.set_valign(Gtk::Align::FILL);
192 _label_entry.set_hexpand();
193 _layout_table.attach(_label_entry, 1, 2, 2, 1);
194
195 _color.set_halign(Gtk::Align::FILL);
196 _color.set_valign(Gtk::Align::FILL);
197 _color.set_hexpand();
198 _color.set_margin_end(6);
199 _layout_table.attach(_color, 1, 3, 2, 1);
200
201 // unitmenus
202 /* fixme: We should allow percents here too, as percents of the canvas size */
203 _unit_menu.setUnitType(UNIT_TYPE_LINEAR);
204 _unit_menu.setUnit("px");
207 }
208 _spin_angle.setUnit(angle_unit_status);
209
210 // position spinbuttons
212 size_t minimumexponent = std::min(std::abs(prefs->getInt("/options/svgoutput/minimumexponent", -8)), 5); //we limit to 5 to minimize rounding errors
213 _spin_button_x.setDigits(minimumexponent);
215 _spin_button_x.setIncrements(1.0, 10.0);
216 _spin_button_x.setRange(-1e6, 1e6);
217
218 _spin_button_y.setDigits(minimumexponent);
220 _spin_button_y.setIncrements(1.0, 10.0);
221 _spin_button_y.setRange(-1e6, 1e6);
222
226
227 _row_labels = Gtk::SizeGroup::create(Gtk::SizeGroup::Mode::HORIZONTAL);
229 _row_labels->add_widget(*label);
230 label->set_xalign(0);
231 }
232
233 _spin_button_x.set_halign(Gtk::Align::FILL);
234 _spin_button_x.set_valign(Gtk::Align::FILL);
235 _spin_button_x.set_hexpand();
236 _layout_table.attach(_spin_button_x, 1, 4, 1, 1);
237
238 _spin_button_y.set_halign(Gtk::Align::FILL);
239 _spin_button_y.set_valign(Gtk::Align::FILL);
240 _spin_button_y.set_hexpand();
241 _layout_table.attach(_spin_button_y, 1, 5, 1, 1);
242
243 _unit_menu.set_halign(Gtk::Align::FILL);
244 _unit_menu.set_valign(Gtk::Align::FILL);
245 _unit_menu.set_margin_end(6);
246 _layout_table.attach(_unit_menu, 2, 4, 1, 1);
247
248 // angle spinbutton
250 _spin_angle.setDigits(minimumexponent);
252 _spin_angle.setIncrements(1.0, 10.0);
253 _spin_angle.setRange(-3600., 3600.);
254
255 _spin_angle.set_halign(Gtk::Align::FILL);
256 _spin_angle.set_valign(Gtk::Align::FILL);
257 _spin_angle.set_hexpand();
258 _layout_table.attach(_spin_angle, 1, 6, 2, 1);
259
260 _spin_button_x.getSpinButton().set_activates_default();
261 _spin_button_y.getSpinButton().set_activates_default();
262 _spin_angle.getSpinButton().set_activates_default();
263
264 // mode radio button
265 _relative_toggle.set_halign(Gtk::Align::FILL);
266 _relative_toggle.set_valign(Gtk::Align::FILL);
267 _relative_toggle.set_hexpand();
268 _relative_toggle.set_margin_start(6);
269 _layout_table.attach(_relative_toggle, 1, 7, 2, 1);
270
271 // locked radio button
272 _locked_toggle.set_halign(Gtk::Align::FILL);
273 _locked_toggle.set_valign(Gtk::Align::FILL);
274 _locked_toggle.set_hexpand();
275 _locked_toggle.set_margin_start(6);
276 _layout_table.attach(_locked_toggle, 1, 8, 2, 1);
277
278 _relative_toggle.signal_toggled().connect(sigc::mem_fun(*this, &GuidelinePropertiesDialog::_modeChanged));
279 _relative_toggle.set_active(relative_toggle_status);
280
281 bool global_guides_lock = _desktop->getNamedView()->getLockGuides();
282 if(global_guides_lock){
283 _locked_toggle.set_sensitive(false);
284 }
285 _locked_toggle.set_active(_guide->getLocked());
286
287 // buttons
288 auto buttonbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL);
289 vbox->append(*buttonbox);
290 buttonbox->set_halign(Gtk::Align::END);
291 buttonbox->set_homogeneous();
292
293 auto add_button = [&] (Glib::ustring const &label, sigc::slot<void ()> &&slot) {
294 auto button = Gtk::make_managed<Gtk::Button>(label, true);
295 button->signal_clicked().connect(std::move(slot));
296 buttonbox->append(*button);
297 return button;
298 };
299
300 auto ok = add_button(_("_OK"), [this] { _onOK(); destroy(); });
301 add_button(_("_Duplicate"), [this] { _onDuplicate(); destroy(); });
302 add_button(_("_Delete"), [this] { _onDelete(); destroy(); });
303 add_button(_("_Cancel"), [this] { destroy(); });
304
305 // initialize dialog
307 if (_guide->isVertical()) {
308 _oldangle = 90;
309 } else if (_guide->isHorizontal()) {
310 _oldangle = 0;
311 } else {
312 _oldangle = Geom::deg_from_rad( std::atan2( - _guide->getNormal()[Geom::X], _guide->getNormal()[Geom::Y] ) );
313 }
314
315 {
316 gchar *label = g_strdup_printf(_("Guideline ID: %s"), _guide->getId());
317 _label_name.set_label(label);
318 g_free(label);
319 }
320 {
321 gchar *guide_description = _guide->description(false);
322 gchar *label = g_strdup_printf(_("Current: %s"), guide_description);
323 g_free(guide_description);
324 _label_descr.set_markup(label);
325 g_free(label);
326 }
327
328 // init name entry
329 _label_entry.getEntry()->set_text(_guide->getLabel() ? _guide->getLabel() : "");
330
331 Gdk::RGBA c;
332 c.set_rgba(((_guide->getColor()>>24)&0xff) / 255.0, ((_guide->getColor()>>16)&0xff) / 255.0, ((_guide->getColor()>>8)&0xff) / 255.0);
333 _color.set_rgba(c);
334
335 _modeChanged(); // sets values of spinboxes.
336
337 if ( _oldangle == 90. || _oldangle == 270. || _oldangle == -90. || _oldangle == -270.) {
339 } else if ( _oldangle == 0. || _oldangle == 180. || _oldangle == -180.) {
341 } else {
343 }
344
345 set_modal(true);
347
348 set_default_widget(*ok);
349}
350
351} // namespace Inkscape::UI::Dialog
352
353/*
354 Local Variables:
355 mode:c++
356 c-file-style:"stroustrup"
357 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
358 indent-tabs-mode:nil
359 fill-column:99
360 End:
361*/
362// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Affine inverse() const
Compute the inverse matrix.
Definition affine.cpp:388
Two-dimensional point that doubles as a vector.
Definition point.h:66
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
Geom::Affine getSelectedPageAffine() const
Preference storage class.
Definition preferences.h:66
static Preferences * get()
Access the singleton Preferences object.
int getInt(Glib::ustring const &pref_path, int def=0)
Retrieve an integer.
Dialog for modifying guidelines.
Definition guides.h:40
Glib::RefPtr< Gtk::SizeGroup > _row_labels
Definition guides.h:77
static void showDialog(SPGuide *guide, SPDesktop *desktop)
Definition guides.cpp:64
Inkscape::UI::Widget::Entry _label_entry
Definition guides.h:69
Inkscape::UI::Widget::ScalarUnit _spin_angle
Definition guides.h:72
Inkscape::UI::Widget::UnitMenu _unit_menu
Definition guides.h:66
Inkscape::UI::Widget::ScalarUnit _spin_button_x
Definition guides.h:67
Inkscape::UI::Widget::ScalarUnit _spin_button_y
Definition guides.h:68
GuidelinePropertiesDialog(SPGuide *guide, SPDesktop *desktop)
Definition guides.cpp:39
Gtk::Entry const * getEntry() const
Definition entry.h:31
Gtk::Label const * getLabel() const
Definition labelled.h:51
void setValue(double number, Glib::ustring const &units)
Sets the number and unit system.
void grabFocusAndSelectEntry()
Grab focus, and select the text that is in the entry field.
bool setUnit(Glib::ustring const &units)
Sets the unit for the ScalarUnit widget.
void setAlignment(double xalign)
allow align text in entry.
void setValueKeepUnit(double number, Glib::ustring const &units)
Convert and sets the number only and keeps the current unit.
Unit const * getUnit() const
Gets the object for the currently selected unit.
double getValue(Glib::ustring const &units) const
Returns the value in the given unit system.
void setIncrements(double step, double page)
Sets the step and page increments for the spin button.
Definition scalar.cpp:123
void setWidthChars(unsigned chars)
Sets the width of the spin button by number of characters.
Definition scalar.cpp:142
void setDigits(unsigned digits)
Sets the precision to be displayed by the spin button.
Definition scalar.cpp:94
void setRange(double min, double max)
Sets the minimum and maximum range allowed for the spin button.
Definition scalar.cpp:128
SpinButton const & getSpinButton() const
Definition scalar.cpp:178
bool setUnit(Glib::ustring const &unit)
Sets the dropdown widget to the given unit abbreviation.
Definition unit-menu.cpp:75
bool setUnitType(UnitType unit_type, bool svg_length=false)
Adds the unit type to the widget.
Definition unit-menu.cpp:33
Glib::ustring abbr
Definition units.h:76
To do: update description of desktop.
Definition desktop.h:149
SPNamedView * getNamedView() const
Definition desktop.h:191
void setWindowTransient(Gtk::Window &window, int transient_policy=1)
Definition desktop.cpp:970
Typed SVG document implementation.
Definition document.h:103
bool get_origin_follows_page()
Inkscape::PageManager & getPageManager()
Definition document.h:164
void set_locked(const bool locked, bool const commit)
Definition sp-guide.cpp:452
char * description(bool const verbose=true) const
Returns a human-readable description of the guideline for use in dialog boxes and status bar.
Definition sp-guide.cpp:482
Geom::Point getNormal() const
Definition sp-guide.h:55
bool isHorizontal() const
Definition sp-guide.h:79
void set_color(const unsigned r, const unsigned g, const unsigned b, bool const commit)
Definition sp-guide.cpp:436
void moveto(Geom::Point const point_on_line, bool const commit)
Definition sp-guide.cpp:367
bool isVertical() const
Definition sp-guide.h:80
void set_normal(Geom::Point const normal_to_line, bool const commit)
Definition sp-guide.cpp:412
guint32 getColor() const
Definition sp-guide.h:52
SPGuide * duplicate()
Definition sp-guide.cpp:257
Geom::Point getPoint() const
Definition sp-guide.h:54
bool getLocked() const
Definition sp-guide.h:64
bool remove(bool force=false)
Definition sp-guide.cpp:529
void set_label(const char *label, bool const commit)
Definition sp-guide.cpp:464
char const * getLabel() const
Definition sp-guide.h:61
Inkscape::Util::Unit const * display_units
bool getLockGuides()
SPDocument * document
Definition sp-object.h:188
char const * getId() const
Returns the objects current ID string.
double c[8][4]
Editable view implementation.
TODO: insert short description here.
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
static const unsigned int DEG
Glib::ustring label
D2< T > rot90(D2< T > const &a)
Definition d2.h:397
Dialog code.
Definition desktop.h:117
Singleton class to access the preferences file in a convenient way.
SPGuide – a guideline.
SPDesktop * desktop