Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
actions-canvas-transform.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Gio::Actions for transforming the canvas view. Tied to a particular InkscapeWindow.
4 *
5 * Copyright (C) 2020 Tavmjong Bah
6 *
7 * The contents of this file may be used under the GNU General Public License Version 2 or later.
8 *
9 */
10
11#include <iostream>
12
13#include <giomm.h> // Not <gtkmm.h>! To eventually allow a headless version!
14#include <glibmm/i18n.h>
15
16#include <2geom/angle.h> // rad_from_deg
17
19#include "actions-helper.h"
21#include "inkscape-window.h"
22#include "desktop.h"
23
24#include "object/sp-namedview.h"
25#include "page-manager.h"
26
27#include "ui/tools/freehand-base.h" // SP_DRAW_CONTEXT
28#include "ui/tools/pen-tool.h"
30
31#include "ui/widget/canvas.h" // Canvas area
32
33enum {
46
53};
54
55static void
56canvas_zoom_helper(SPDesktop* dt, const Geom::Point& midpoint, double zoom_factor)
57{
58 if (auto const * const tool = dt->getTool();
59 tool && (dynamic_cast<Inkscape::UI::Tools::PencilTool const *>(tool) ||
60 dynamic_cast<Inkscape::UI::Tools::PenTool const *>(tool)))
61 {
62 // Zoom around end of unfinished path.
63 auto const &freehand_base = dynamic_cast<Inkscape::UI::Tools::FreehandBase const &>(*tool);
64 if (auto const zoom_to = freehand_base.red_curve_get_last_point()) {
65 dt->zoom_relative(*zoom_to, zoom_factor);
66 return;
67 }
68 }
69
70 dt->zoom_relative(midpoint, zoom_factor, false);
71}
72
73void
75{
76 SPDesktop* dt = win->get_desktop();
77 SPDocument *doc = dt->getDocument();
78
79 // The following might be better done elsewhere:
80
81 // Get preference dependent parameters
83 double zoom_inc =
84 prefs->getDoubleLimited("/options/zoomincrement/value", M_SQRT2, 1.01, 10);
85 double rotate_inc =
86 prefs->getDoubleLimited("/options/rotateincrement/value", 15, 1, 90, "°");
87 rotate_inc *= M_PI/180.0;
88
89 // Get document dependent parameters
90 Geom::Rect const canvas = dt->getCanvas()->get_area_world();
91 Geom::Point midpoint = dt->w2d(canvas.midpoint()); // Midpoint of drawing on canvas.
92
93 switch (option) {
95 canvas_zoom_helper( dt, midpoint, zoom_inc);
96 break;
97
99 canvas_zoom_helper( dt, midpoint, 1.0 / zoom_inc); // zoom_inc > 1
100 break;
101
103 dt->zoom_realworld( midpoint, 1.0 );
104 break;
105
107 dt->zoom_realworld( midpoint, 0.5 );
108 break;
109
111 dt->zoom_realworld( midpoint, 2.0 );
112 break;
113
115 dt->zoom_selection();
116 break;
117
119 dt->zoom_drawing();
120 break;
121
123 doc->getPageManager().zoomToSelectedPage(dt, false);
124 break;
125
127 doc->getPageManager().zoomToSelectedPage(dt, true);
128 break;
129
132 break;
133
135 dt->prev_transform();
136 break;
137
139 dt->next_transform(); // Is this only zoom? Yes!
140 break;
141
143 dt->rotate_relative_center_point (midpoint, rotate_inc);
144 break;
145
147 dt->rotate_relative_center_point (midpoint, -rotate_inc);
148 break;
149
151 dt->rotate_absolute_center_point (midpoint, 0);
152 break;
153
156 break;
157
160 break;
161
164 break;
165
166 default:
167 show_output("canvas_zoom: unhandled action value!");
168 }
169}
170
171// Zoom to an arbitrary value
172void
173canvas_zoom_absolute(Glib::VariantBase const &value, InkscapeWindow *win)
174{
175 auto d = Glib::VariantBase::cast_dynamic<Glib::Variant<double> >(value);
176
177 SPDesktop* dt = win->get_desktop();
178
180 if (prefs->getDouble("/options/zoomcorrection/shown", true)) {
181 dt->zoom_realworld(dt->current_center(), d.get());
182 } else {
183 dt->zoom_absolute(dt->current_center(), d.get(), false);
184 }
185}
186
187// Zoom a relative amount
188void
189canvas_zoom_relative(Glib::VariantBase const &value, InkscapeWindow *win)
190{
191 auto d = Glib::VariantBase::cast_dynamic<Glib::Variant<double> >(value);
192
193 SPDesktop* dt = win->get_desktop();
194 dt->zoom_relative(dt->current_center(), d.get());
195}
196
197// Rotate to an arbitrary value
198void
199canvas_rotate_absolute_radians(Glib::VariantBase const &value, InkscapeWindow *win)
200{
201 auto d = Glib::VariantBase::cast_dynamic<Glib::Variant<double> >(value);
202
203 SPDesktop* dt = win->get_desktop();
204 dt->rotate_absolute_center_point(dt->current_center(), d.get());
205}
206
207void
208canvas_rotate_absolute_degrees(Glib::VariantBase const &value, InkscapeWindow *win)
209{
210 auto d = Glib::VariantBase::cast_dynamic<Glib::Variant<double> >(value);
211
212 SPDesktop* dt = win->get_desktop();
213 dt->rotate_absolute_center_point(dt->current_center(), Geom::rad_from_deg(d.get()));
214}
215
216// Rotate a relative amount
217void
218canvas_rotate_relative_radians(Glib::VariantBase const &value, InkscapeWindow *win)
219{
220 auto d = Glib::VariantBase::cast_dynamic<Glib::Variant<double> >(value);
221
222 SPDesktop* dt = win->get_desktop();
223 dt->rotate_relative_center_point(dt->current_center(), d.get());
224}
225
226void
227canvas_rotate_relative_degrees(Glib::VariantBase const &value, InkscapeWindow *win)
228{
229 auto d = Glib::VariantBase::cast_dynamic<Glib::Variant<double> >(value);
230
231 SPDesktop* dt = win->get_desktop();
232 dt->rotate_relative_center_point(dt->current_center(), Geom::rad_from_deg(d.get()));
233}
234
238void
240{
241 auto action = win->lookup_action("canvas-rotate-lock");
242 if (!action) {
243 show_output("canvas_rotate_lock: action missing!");
244 return;
245 }
246
247 auto saction = std::dynamic_pointer_cast<Gio::SimpleAction>(action);
248 if (!saction) {
249 show_output("canvas_rotate_lock: action not SimpleAction!");
250 return;
251 }
252
253 bool state = false;
254 saction->get_state(state);
255 state = !state;
256 saction->change_state(state);
257
258 // Save value as a preference
260 pref->setBool("/options/rotationlock", state);
261
262 SPDesktop* dt = win->get_desktop();
263 dt->set_rotation_lock(state);
264}
265
266const Glib::ustring SECTION = NC_("Action Section", "Canvas Geometry");
267
268std::vector<std::vector<Glib::ustring>> raw_data_canvas_transform =
269{
270 // clang-format off
271 {"win.canvas-zoom-in", N_("Zoom In"), SECTION, N_("Zoom in") },
272 {"win.canvas-zoom-out", N_("Zoom Out"), SECTION, N_("Zoom out") },
273 {"win.canvas-zoom-1-1", N_("Zoom 1:1"), SECTION, N_("Zoom to 1:1") },
274 {"win.canvas-zoom-1-2", N_("Zoom 1:2"), SECTION, N_("Zoom to 1:2") },
275 {"win.canvas-zoom-2-1", N_("Zoom 2:1"), SECTION, N_("Zoom to 2:1") },
276 {"win.canvas-zoom-selection", N_("Zoom Selection"), SECTION, N_("Zoom to fit selection in window") },
277 {"win.canvas-zoom-drawing", N_("Zoom Drawing"), SECTION, N_("Zoom to fit drawing in window") },
278 {"win.canvas-zoom-page", N_("Zoom Page"), SECTION, N_("Zoom to fit page in window") },
279 {"win.canvas-zoom-page-width", N_("Zoom Page Width"), SECTION, N_("Zoom to fit page width in window") },
280 {"win.canvas-zoom-center-page", N_("Zoom Center Page"), SECTION, N_("Center page in window") },
281 {"win.canvas-zoom-prev", N_("Zoom Prev"), SECTION, N_("Go back to previous zoom (from the history of zooms)")},
282 {"win.canvas-zoom-next", N_("Zoom Next"), SECTION, N_("Go to next zoom (from the history of zooms)")},
283
284 {"win.canvas-rotate-cw", N_("Rotate Clockwise"), SECTION, N_("Rotate canvas clockwise") },
285 {"win.canvas-rotate-ccw", N_("Rotate Counter-CW"), SECTION, N_("Rotate canvas counter-clockwise") },
286 {"win.canvas-rotate-reset", N_("Reset Rotation"), SECTION, N_("Reset canvas rotation") },
287
288 {"win.canvas-flip-horizontal", N_("Flip Horizontal"), SECTION, N_("Flip canvas horizontally") },
289 {"win.canvas-flip-vertical", N_("Flip Vertical"), SECTION, N_("Flip canvas vertically") },
290 {"win.canvas-flip-reset", N_("Reset Flipping"), SECTION, N_("Reset canvas flipping") },
291
292 {"win.canvas-zoom-absolute", N_("Zoom Absolute"), SECTION, N_("Zoom to an absolute value") },
293 {"win.canvas-zoom-relative", N_("Zoom Relative"), SECTION, N_("Zoom by a relative amount") },
294
295 {"win.canvas-rotate-absolute-radians", N_("Rotate Absolute (Radians)"), SECTION, N_("Rotate to an absolute value (radians)") },
296 {"win.canvas-rotate-relative-radians", N_("Rotate Relative (Radians)"), SECTION, N_("Rotate by a relative amount (radians)") },
297 {"win.canvas-rotate-absolute-degrees", N_("Rotate Absolute (Degrees)"), SECTION, N_("Rotate to an absolute value (degrees)") },
298 {"win.canvas-rotate-relative-degrees", N_("Rotate Relative (Degrees)"), SECTION, N_("Rotate by a relative amount (degrees)") },
299
300 {"win.canvas-rotate-lock", N_("Lock Rotation"), SECTION, N_("Lock canvas rotation") },
301 // clang-format on
302};
303
304void
306{
307 auto prefs = Inkscape::Preferences::get();
308
309 bool rotate_lock = prefs->getBool("/options/rotationlock");
310
311 Glib::VariantType Double(Glib::VARIANT_TYPE_DOUBLE);
312
313 // clang-format off
314 win->add_action( "canvas-zoom-in", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_IN));
315 win->add_action( "canvas-zoom-out", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_OUT));
316 win->add_action( "canvas-zoom-1-1", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_1_1));
317 win->add_action( "canvas-zoom-1-2", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_1_2));
318 win->add_action( "canvas-zoom-2-1", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_2_1));
319 win->add_action( "canvas-zoom-selection", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_SELECTION));
320 win->add_action( "canvas-zoom-drawing", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_DRAWING));
321 win->add_action( "canvas-zoom-page", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_PAGE));
322 win->add_action( "canvas-zoom-page-width", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_PAGE_WIDTH));
323 win->add_action( "canvas-zoom-center-page",sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_CENTER_PAGE));
324 win->add_action( "canvas-zoom-prev", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_PREV));
325 win->add_action( "canvas-zoom-next", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ZOOM_NEXT));
326
327 win->add_action( "canvas-rotate-cw", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ROTATE_CW));
328 win->add_action( "canvas-rotate-ccw", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ROTATE_CCW));
329 win->add_action( "canvas-rotate-reset", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_ROTATE_RESET));
330
331 win->add_action( "canvas-flip-horizontal", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_FLIP_HORIZONTAL));
332 win->add_action( "canvas-flip-vertical", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_FLIP_VERTICAL));
333 win->add_action( "canvas-flip-reset", sigc::bind(sigc::ptr_fun(&canvas_transform), win, INK_CANVAS_FLIP_RESET));
334
335 win->add_action_with_parameter( "canvas-zoom-absolute", Double, sigc::bind(sigc::ptr_fun(&canvas_zoom_absolute), win));
336 win->add_action_with_parameter( "canvas-zoom-relative", Double, sigc::bind(sigc::ptr_fun(&canvas_zoom_relative), win));
337
338 win->add_action_with_parameter( "canvas-rotate-absolute-radians", Double, sigc::bind(sigc::ptr_fun(&canvas_rotate_absolute_radians), win));
339 win->add_action_with_parameter( "canvas-rotate-relative-radians", Double, sigc::bind(sigc::ptr_fun(&canvas_rotate_relative_radians), win));
340 win->add_action_with_parameter( "canvas-rotate-absolute-degrees", Double, sigc::bind(sigc::ptr_fun(&canvas_rotate_absolute_degrees), win));
341 win->add_action_with_parameter( "canvas-rotate-relative-degrees", Double, sigc::bind(sigc::ptr_fun(&canvas_rotate_relative_degrees), win));
342
343 win->add_action_bool( "canvas-rotate-lock",sigc::bind(sigc::ptr_fun(&canvas_rotate_lock), win), rotate_lock);
344 // clang-format on
345
347 if (!app) {
348 show_output("add_actions_canvas_transform: no app!");
349 return;
350 }
351 app->get_action_extra_data().add_data(raw_data_canvas_transform);
352}
353
355{
356 auto prefs = Inkscape::Preferences::get();
357
358 bool rotate_lock = prefs->getBool("/options/rotationlock");
359
360 dt->set_rotation_lock(rotate_lock);
361}
362
363/*
364 Local Variables:
365 mode:c++
366 c-file-style:"stroustrup"
367 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
368 indent-tabs-mode:nil
369 fill-column:99
370 End:
371*/
372// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
SimpleSnap option
const Glib::ustring SECTION
void apply_preferences_canvas_transform(SPDesktop *dt)
void canvas_rotate_absolute_degrees(Glib::VariantBase const &value, InkscapeWindow *win)
void canvas_zoom_absolute(Glib::VariantBase const &value, InkscapeWindow *win)
void canvas_transform(InkscapeWindow *win, const int &option)
void canvas_rotate_relative_radians(Glib::VariantBase const &value, InkscapeWindow *win)
void canvas_rotate_relative_degrees(Glib::VariantBase const &value, InkscapeWindow *win)
void canvas_rotate_absolute_radians(Glib::VariantBase const &value, InkscapeWindow *win)
void add_actions_canvas_transform(InkscapeWindow *win)
std::vector< std::vector< Glib::ustring > > raw_data_canvas_transform
void canvas_zoom_relative(Glib::VariantBase const &value, InkscapeWindow *win)
@ INK_CANVAS_ZOOM_CENTER_PAGE
@ INK_CANVAS_ZOOM_SELECTION
@ INK_CANVAS_ZOOM_PAGE_WIDTH
@ INK_CANVAS_FLIP_VERTICAL
@ INK_CANVAS_ROTATE_RESET
@ INK_CANVAS_ZOOM_DRAWING
@ INK_CANVAS_FLIP_HORIZONTAL
void canvas_rotate_lock(InkscapeWindow *win)
Toggle rotate lock.
static void canvas_zoom_helper(SPDesktop *dt, const Geom::Point &midpoint, double zoom_factor)
void show_output(Glib::ustring const &data, bool const is_cerr)
Various trigoniometric helper functions.
Inkscape canvas widget.
CPoint midpoint() const
Get the point in the geometric center of the rectangle.
Two-dimensional point that doubles as a vector.
Definition point.h:66
Axis aligned, non-empty rectangle.
Definition rect.h:92
static InkscapeApplication * instance()
Singleton instance.
SPDesktop * get_desktop()
void zoomToSelectedPage(SPDesktop *desktop, bool width_only=false)
void centerToSelectedPage(SPDesktop *desktop)
Preference storage class.
Definition preferences.h:61
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 setBool(Glib::ustring const &pref_path, bool value)
Set a Boolean value.
double getDoubleLimited(Glib::ustring const &pref_path, double def=0.0, double min=DBL_MIN, double max=DBL_MAX, Glib::ustring const &unit="")
Retrieve a limited floating point value.
PenTool: a context for pen tool events.
Definition pen-tool.h:41
PencilTool: a context for pencil tool events.
Definition pencil-tool.h:49
Geom::IntRect get_area_world() const
Return the area shown in the canvas in world coordinates.
Definition canvas.cpp:1560
To do: update description of desktop.
Definition desktop.h:149
Inkscape::UI::Widget::Canvas * getCanvas() const
Definition desktop.h:190
SPDocument * getDocument() const
Definition desktop.h:189
void rotate_relative_center_point(Geom::Point const &c, double rotate)
Rotate aligning the point 'c' to the center of desktop window.
Definition desktop.cpp:781
void flip_relative_center_point(Geom::Point const &c, CanvasFlip flip)
Flip direction, aligning the point 'c' to the center of desktop window.
Definition desktop.cpp:837
void set_rotation_lock(bool lock)
Definition desktop.h:344
void rotate_absolute_center_point(Geom::Point const &c, double rotate)
Set new rotation, aligning the point 'c' to the center of desktop window.
Definition desktop.cpp:768
void prev_transform()
Revert back to previous transform if possible.
Definition desktop.cpp:390
void zoom_realworld(Geom::Point const &c, double ratio)
Zoom in to an absolute realworld ratio, e.g.
Definition desktop.cpp:570
Inkscape::UI::Tools::ToolBase * getTool() const
Definition desktop.h:187
void zoom_selection()
Zoom to selection.
Definition desktop.cpp:625
@ FLIP_HORIZONTAL
Definition desktop.h:357
@ FLIP_NONE
Definition desktop.h:356
@ FLIP_VERTICAL
Definition desktop.h:358
void flip_absolute_center_point(Geom::Point const &c, CanvasFlip flip)
Set new flip direction, aligning the point 'c' to the center of desktop window.
Definition desktop.cpp:823
void zoom_relative(Geom::Point const &c, double zoom, bool keep_point=true)
Zoom in or out relatively to the current zoom.
Definition desktop.cpp:557
void next_transform()
Set transform to next in list.
Definition desktop.cpp:416
void zoom_drawing()
Zoom to whole drawing.
Definition desktop.cpp:602
Geom::Affine const & w2d() const
Transformation from window to desktop coordinates (zoom/rotate).
Definition desktop.h:416
Typed SVG document implementation.
Definition document.h:101
Inkscape::PageManager & getPageManager()
Definition document.h:162
Editable view implementation.
Inkscape - An SVG editor.
PenTool: a context for pen tool events.
PencilTool: a context for pencil tool events.