summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2017-03-13 14:22:22 +0000
committertavmjong-free <tavmjong@free.fr>2017-03-13 14:22:22 +0000
commit014489163050d8abe9e5c4949fb80f3c21b1c17b (patch)
tree7cbeb87aa023d563986b32f65fd500c6072ee86a /src
parentTwo Extensions for converting objects to paths before exporting. (Bug 1662531) (diff)
downloadinkscape-014489163050d8abe9e5c4949fb80f3c21b1c17b.tar.gz
inkscape-014489163050d8abe9e5c4949fb80f3c21b1c17b.zip
Replace rectangle based zooming by affine based zooming.
This allows a rotation to be included in the drawing to window mapping. General code cleanup. Added documentation. Any change to zooming behavior is probably a bug. (bzr r15592)
Diffstat (limited to 'src')
-rw-r--r--src/desktop.cpp544
-rw-r--r--src/desktop.h129
-rw-r--r--src/display/canvas-grid.cpp4
-rw-r--r--src/display/sp-canvas.cpp8
-rw-r--r--src/display/sp-canvas.h4
-rw-r--r--src/file.cpp2
-rw-r--r--src/selection-chemistry.cpp4
-rw-r--r--src/sp-namedview.cpp10
-rw-r--r--src/ui/tools/tool-base.cpp26
-rw-r--r--src/verbs.cpp20
-rw-r--r--src/viewbox.cpp2
-rw-r--r--src/widgets/desktop-widget.cpp20
12 files changed, 425 insertions, 348 deletions
diff --git a/src/desktop.cpp b/src/desktop.cpp
index 2476b10bb..ddd5dfe83 100644
--- a/src/desktop.cpp
+++ b/src/desktop.cpp
@@ -120,20 +120,16 @@ SPDesktop::SPDesktop() :
_widget( NULL ),
_guides_message_context( NULL ),
_active( false ),
- _w2d(),
- _d2w(),
_doc2dt( Geom::Scale(1, -1) ),
_image_render_observer(this, "/options/rendering/imageinoutlinemode"),
grids_visible( false )
{
- _d2w.setIdentity();
- _w2d.setIdentity();
-
layers = new Inkscape::LayerModel();
layers->_layer_activated_signal.connect(sigc::bind(sigc::ptr_fun(_layer_activated), this));
layers->_layer_deactivated_signal.connect(sigc::bind(sigc::ptr_fun(_layer_deactivated), this));
layers->_layer_changed_signal.connect(sigc::bind(sigc::ptr_fun(_layer_hierarchy_changed), this));
selection = Inkscape::GC::release( new Inkscape::Selection(layers, this) );
+ // _current_affine.setRotate(M_PI/4); // To test zooming with rotation
}
void
@@ -479,7 +475,7 @@ SPDesktop::remove_temporary_canvasitem (Inkscape::Display::TemporaryItem * tempi
}
void SPDesktop::redrawDesktop() {
- sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw
+ sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _current_affine.d2w()); // redraw
}
void SPDesktop::_setDisplayMode(Inkscape::RenderMode mode) {
@@ -733,307 +729,223 @@ Geom::Point SPDesktop::point() const
{
Geom::Point p = _widget->getPointer();
Geom::Point pw = sp_canvas_window_to_world (canvas, p);
- p = w2d(pw);
-
Geom::Rect const r = canvas->getViewbox();
- Geom::Point r0 = w2d(r.min());
- Geom::Point r1 = w2d(r.max());
-
- if (p[Geom::X] >= r0[Geom::X] &&
- p[Geom::X] <= r1[Geom::X] &&
- p[Geom::Y] >= r1[Geom::Y] &&
- p[Geom::Y] <= r0[Geom::Y])
- {
+ if (r.interiorContains(pw)) {
+ p = w2d(pw);
return p;
- } else {
- return (r0 + r1) / 2;
}
-}
-
-/**
- * Put current zoom data in history list.
- */
-void
-SPDesktop::push_current_zoom (std::list<Geom::Rect> &history)
-{
- Geom::Rect area = get_display_area();
- if (history.empty() || history.front() != area) {
- history.push_front(area);
- }
+ // Shouldn't happen
+ std::cerr << "SPDesktop::point(): point outside of canvas!" << std::endl;
+ Geom::Point r0 = w2d(r.min());
+ Geom::Point r1 = w2d(r.max());
+ return (r0 + r1) / 2.0;
}
+
/**
- * Set viewbox (x0, x1, y0 and y1 are in document pixels. Border is in screen pixels).
+ * Revert back to previous transform if possible. Note: current transform is
+ * always at front of stack.
*/
void
-SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double border, bool log)
+SPDesktop::prev_transform()
{
- g_assert(_widget);
- bool zoomChanged = false;
-
- // save the zoom
- if (log) {
- push_current_zoom(zooms_past);
- // if we do a logged zoom, our zoom-forward list is invalidated, so delete it
- zooms_future.clear();
- }
-
- double const cx = 0.5 * (x0 + x1);
- double const cy = 0.5 * (y0 + y1);
-
- // FIXME: This 2geom idiom doesn't allow us to declare dbox const
- Geom::Rect viewbox = canvas->getViewbox();
- viewbox.expandBy(-border);
-
- double scale = _d2w.descrim();
- double newscale;
- if (((x1 - x0) * viewbox.dimensions()[Geom::Y]) > ((y1 - y0) * viewbox.dimensions()[Geom::X])) {
- newscale = viewbox.dimensions()[Geom::X] / (x1 - x0);
- } else {
- newscale = viewbox.dimensions()[Geom::Y] / (y1 - y0);
+ if (transforms_past.empty()) {
+ std::cerr << "SPDesktop::prev_transform: current transform missing!" << std::endl;
+ return;
}
- newscale = CLAMP(newscale, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); // unit: 'screen pixels' per 'document pixels'
-
- int clear = FALSE;
- if (!Geom::are_near(newscale, scale, Geom::EPSILON * scale)) {
- // zoom changed - set new zoom factors
- _d2w = Geom::Scale(newscale, -newscale);
- _w2d = Geom::Scale(1/newscale, 1/-newscale);
- redrawDesktop();
- clear = TRUE;
- zoomChanged = true;
+ if (transforms_past.size() == 1) {
+ messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No previous transform."));
+ return;
}
- /* Calculate top left corner (in document pixels) */
- x0 = cx - 0.5 * viewbox.dimensions()[Geom::X] / newscale;
- y1 = cy + 0.5 * viewbox.dimensions()[Geom::Y] / newscale;
-
- // Scroll
- canvas->scrollTo(x0 * newscale - border, y1 * -newscale - border, clear);
-
- /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */
- //sp_box3d_context_update_lines(event_context);
- if (SP_IS_BOX3D_CONTEXT(event_context)) {
- SP_BOX3D_CONTEXT(event_context)->_vpdrag->updateLines();
- }
+ // Push current transform into future transforms list.
+ transforms_future.push_front( _current_affine );
- _widget->updateRulers();
- _widget->updateScrollbars(_d2w.descrim());
- _widget->updateZoom();
+ // Remove the current transform from the past transforms list.
+ transforms_past.pop_front();
- if ( zoomChanged ) {
- signal_zoom_changed.emit(_d2w.descrim());
- }
-}
+ // restore previous transform
+ _current_affine = transforms_past.front();
+ set_display_area (false);
-void SPDesktop::set_display_area(Geom::Rect const &a, Geom::Coord b, bool log)
-{
- set_display_area(a.min()[Geom::X], a.min()[Geom::Y], a.max()[Geom::X], a.max()[Geom::Y], b, log);
}
-/**
- * Return viewbox dimensions.
- */
-Geom::Rect SPDesktop::get_display_area() const
-{
- Geom::Rect const viewbox = canvas->getViewbox();
-
- double const scale = _d2w[0];
-
- /// @fixme hardcoded desktop transform
- return Geom::Rect(Geom::Point(viewbox.min()[Geom::X] / scale, viewbox.max()[Geom::Y] / -scale),
- Geom::Point(viewbox.max()[Geom::X] / scale, viewbox.min()[Geom::Y] / -scale));
-}
/**
- * Revert back to previous zoom if possible.
+ * Set transform to next in list.
*/
-void
-SPDesktop::prev_zoom()
+void SPDesktop::next_transform()
{
- if (zooms_past.empty()) {
- messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No previous zoom."));
+ if (transforms_future.empty()) {
+ this->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No next transform."));
return;
}
- // push current zoom into forward zooms list
- push_current_zoom (zooms_future);
+ // restore next transform
+ _current_affine = transforms_future.front();
+ set_display_area (false);
- // restore previous zoom
- Geom::Rect past = zooms_past.front();
- set_display_area (past.left(), past.top(), past.right(), past.bottom(), 0, false);
+ // remove the just-used transform from the future transforms list
+ transforms_future.pop_front();
- // remove the just-added zoom from the past zooms list
- zooms_past.pop_front();
+ // push current transform into past transforms list
+ transforms_past.push_front( _current_affine );
}
+
/**
- * Set zoom to next in list.
+ * Clear transform lists.
*/
-void SPDesktop::next_zoom()
+void
+SPDesktop::clear_transform_history()
{
- if (zooms_future.empty()) {
- this->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No next zoom."));
- return;
- }
-
- // push current zoom into past zooms list
- push_current_zoom (zooms_past);
-
- // restore next zoom
- Geom::Rect future = zooms_future.front();
- set_display_area (future.left(), future.top(), future.right(), future.bottom(), 0, false);
-
- // remove the just-used zoom from the zooms_future list
- zooms_future.pop_front();
+ transforms_past.clear();
+ transforms_future.clear();
}
+
/**
- * Performs a quick zoom into what the user is working on.
- *
- * @param enable Whether we're going in or out of quick zoom.
+ * Does all the dirty work in setting the display area.
+ * _current_affine must already be full updated (including offset).
+ * log: if true, save transform in transform stack for reuse.
*/
-void SPDesktop::zoom_quick(bool enable)
+void
+SPDesktop::set_display_area (bool log)
{
- if (enable == _quick_zoom_enabled) {
- return;
+ // Save the transform
+ if (log) {
+ transforms_past.push_front( _current_affine );
+ // if we do a logged transform, our transform-forward list is invalidated, so delete it
+ transforms_future.clear();
}
- if (enable) {
- _quick_zoom_stored_area = get_display_area();
- bool zoomed = false;
-
- // TODO This needs to migrate into the node tool, but currently the design
- // of this method is sufficiently wrong to prevent this.
- if (!zoomed && INK_IS_NODE_TOOL(event_context)) {
- Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(event_context);
- if (!nt->_selected_nodes->empty()) {
- Geom::Rect nodes = *nt->_selected_nodes->bounds();
- double area = nodes.area();
- // do not zoom if a single cusp node is selected aand the bounds
- // have zero area.
- if (!Geom::are_near(area, 0) && area * 2.0 < _quick_zoom_stored_area.area()) {
- set_display_area(nodes, true);
- zoomed = true;
- }
- }
- }
+ redrawDesktop();
- if (!zoomed) {
- Geom::OptRect const d = selection->visualBounds();
- if (d && d->area() * 2.0 < _quick_zoom_stored_area.area()) {
- set_display_area(*d, true);
- zoomed = true;
- }
- }
+ // Scroll
+ Geom::Point offset = _current_affine.getOffset();
+ canvas->scrollTo(offset, true);
+ // To do: if transform unchanged call with 'false' (redraw only newly exposed areas).
- if (!zoomed) {
- zoom_relative(_quick_zoom_stored_area.midpoint()[Geom::X], _quick_zoom_stored_area.midpoint()[Geom::Y], 2.0);
- }
- } else {
- set_display_area(_quick_zoom_stored_area, false);
+ /* Update perspective lines if we are in the 3D box tool (so that infinite ones are shown
+ * correctly) */
+ if (SP_IS_BOX3D_CONTEXT(event_context)) {
+ SP_BOX3D_CONTEXT(event_context)->_vpdrag->updateLines();
}
- _quick_zoom_enabled = enable;
- return;
+ _widget->updateRulers();
+ _widget->updateScrollbars(_current_affine.getZoom());
+ _widget->updateZoom();
+
+ signal_zoom_changed.emit(_current_affine.getZoom());
}
+
/**
- * Zoom to point with absolute zoom factor.
+ * Map the drawing to the window so that 'c' lies at 'w' where where 'c'
+ * is a point on the canvas and 'w' is position in window in screen pixels.
*/
void
-SPDesktop::zoom_absolute_keep_point (double cx, double cy, double px, double py, double zoom)
+SPDesktop::set_display_area (Geom::Point const &c, Geom::Point const &w, bool log)
{
- zoom = CLAMP (zoom, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX);
-
- // maximum or minimum zoom reached, but there's no exact equality because of rounding errors;
- // this check prevents "sliding" when trying to zoom in at maximum zoom;
- /// \todo someone please fix calculations properly and remove this hack
- if (fabs(_d2w.descrim() - zoom) < 0.0001*zoom && (fabs(SP_DESKTOP_ZOOM_MAX - zoom) < 0.01 || fabs(SP_DESKTOP_ZOOM_MIN - zoom) < 0.000001))
- return;
-
- Geom::Rect const viewbox = canvas->getViewbox();
-
- double const width2 = viewbox.dimensions()[Geom::X] / zoom;
- double const height2 = viewbox.dimensions()[Geom::Y] / zoom;
-
- set_display_area(cx - px * width2,
- cy - py * height2,
- cx + (1 - px) * width2,
- cy + (1 - py) * height2,
- 0.0);
+ // The relative offset needed to keep c at w.
+ Geom::Point offset = d2w(c) - w;
+ _current_affine.addOffset( offset );
+ set_display_area( log );
}
+
/**
- * Apply the desktop's current style or the tool style to the object.
- */
-void SPDesktop::applyCurrentOrToolStyle(SPObject *obj, Glib::ustring const &tool_path, bool with_text)
+ * Map the center of rectangle 'r' (which specifies a non-rotated region of the
+ * drawing) to lie at the center of the window. The zoom factor is calculated such that
+ * the edges of 'r' closest to 'w' are 'border' length inside of the window (if
+ * there is no rotation). 'r' is in document pixel units, 'border' is in screen pixels.
+ */
+void
+SPDesktop::set_display_area( Geom::Rect const &r, double border, bool log)
{
- SPCSSAttr *css_current = sp_desktop_get_style(this, with_text);
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ // Create a rectangle the size of the window aligned with origin.
+ Geom::Rect w( Geom::Point(), canvas->getViewbox().dimensions() ); // Not the SVG 'viewBox'.
- if (prefs->getBool(tool_path + "/usecurrent") && css_current) {
- obj->setCSS(css_current,"style");
+ // Shrink window to account for border padding.
+ w.expandBy( -border );
+
+ double zoom = 1.0;
+ // Determine which direction limits scale:
+ // if (r.width/w.width > r.height/w.height) then zoom using width.
+ // Avoiding division in test:
+ if ( r.width()*w.height() > r.height()*w.width() ) {
+ zoom = w.width() / r.width();
} else {
- SPCSSAttr *css = prefs->getInheritedStyle(tool_path + "/style");
- obj->setCSS(css,"style");
- sp_repr_css_attr_unref(css);
- }
- if (css_current) {
- sp_repr_css_attr_unref(css_current);
+ zoom = w.height() / r.height();
}
+ _current_affine.setScale( zoom );
+
+ // Zero offset, actual offset calculated later.
+ _current_affine.setOffset( Geom::Point( 0, 0 ) );
+
+ set_display_area( r.midpoint(), w.midpoint(), log );
}
+
/**
- * Zoom to center with absolute zoom factor.
+ * Return viewbox dimensions. FixMe: Doesn't handle rotation. FixMe InvertedY
*/
-void
-SPDesktop::zoom_absolute (double cx, double cy, double zoom)
+Geom::Rect SPDesktop::get_display_area() const
{
- zoom_absolute_keep_point (cx, cy, 0.5, 0.5, zoom);
+ Geom::Rect const viewbox = canvas->getViewbox();
+ double const scale = _current_affine.getZoom();
+
+ /// @fixme hardcoded desktop transform
+ return Geom::Rect(Geom::Point(viewbox.min()[Geom::X] / scale, viewbox.max()[Geom::Y] / -scale),
+ Geom::Point(viewbox.max()[Geom::X] / scale, viewbox.min()[Geom::Y] / -scale));
}
+
/**
- * Zoom to point with relative zoom factor.
+ * Zoom keeping the point 'c' fixed in the desktop window.
*/
void
-SPDesktop::zoom_relative_keep_point (double cx, double cy, double zoom)
+SPDesktop::zoom_absolute_keep_point (Geom::Point const &c, double zoom)
{
- Geom::Rect const area = get_display_area();
-
- if (cx < area.min()[Geom::X]) {
- cx = area.min()[Geom::X];
- }
- if (cx > area.max()[Geom::X]) {
- cx = area.max()[Geom::X];
- }
- if (cy < area.min()[Geom::Y]) {
- cy = area.min()[Geom::Y];
- }
- if (cy > area.max()[Geom::Y]) {
- cy = area.max()[Geom::Y];
- }
+ zoom = CLAMP (zoom, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX);
+ Geom::Point w = d2w( c ); // Must be before zoom changed.
+ _current_affine.setScale( zoom );
+ set_display_area( c, w );
+}
- gdouble const scale = _d2w.descrim() * zoom;
- double const px = (cx - area.min()[Geom::X]) / area.dimensions()[Geom::X];
- double const py = (cy - area.min()[Geom::Y]) / area.dimensions()[Geom::Y];
- zoom_absolute_keep_point(cx, cy, px, py, scale);
+void
+SPDesktop::zoom_relative_keep_point (Geom::Point const &c, double zoom)
+{
+ double new_zoom = _current_affine.getZoom() * zoom;
+ zoom_absolute_keep_point( c, new_zoom );
}
+
/**
- * Zoom to center with relative zoom factor.
+ * Zoom aligning the point 'c' to the center of desktop window.
*/
-void
-SPDesktop::zoom_relative (double cx, double cy, double zoom)
+void
+SPDesktop::zoom_absolute_center_point (Geom::Point const &c, double zoom)
+{
+ zoom = CLAMP (zoom, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX);
+ _current_affine.setScale( zoom );
+ Geom::Rect viewbox = canvas->getViewbox();
+ set_display_area( c, viewbox.midpoint() );
+}
+
+
+void
+SPDesktop::zoom_relative_center_point (Geom::Point const &c, double zoom)
{
- gdouble scale = _d2w.descrim() * zoom;
- zoom_absolute (cx, cy, scale);
+ double new_zoom = _current_affine.getZoom() * zoom;
+ zoom_absolute_center_point( c, new_zoom );
}
+
/**
* Set display area to origin and current document dimensions.
*/
@@ -1068,14 +980,23 @@ SPDesktop::zoom_page_width()
set_display_area(d, 10);
}
+
/**
- * Zoom to selection.
+ * Zoom to whole drawing.
*/
void
-SPDesktop::zoom_selection()
+SPDesktop::zoom_drawing()
{
- Geom::OptRect const d = selection->visualBounds();
+ g_return_if_fail (doc() != NULL);
+ SPItem *docitem = doc()->getRoot();
+ g_return_if_fail (docitem != NULL);
+ docitem->bbox_valid = FALSE;
+ Geom::OptRect d = docitem->desktopVisualBounds();
+
+ /* Note that the second condition here indicates that
+ ** there are no items in the drawing.
+ */
if ( !d || d->minExtent() < 0.1 ) {
return;
}
@@ -1083,59 +1004,95 @@ SPDesktop::zoom_selection()
set_display_area(*d, 10);
}
+
/**
- * Tell widget to let zoom widget grab keyboard focus.
+ * Zoom to selection.
*/
void
-SPDesktop::zoom_grab_focus()
+SPDesktop::zoom_selection()
{
- _widget->letZoomGrabFocus();
+ Geom::OptRect const d = selection->visualBounds();
+
+ if ( !d || d->minExtent() < 0.1 ) {
+ return;
+ }
+
+ set_display_area(*d, 10);
}
+
/**
- * Zoom to whole drawing.
+ * Performs a quick zoom into what the user is working on.
+ *
+ * @param enable Whether we're going in or out of quick zoom.
*/
-void
-SPDesktop::zoom_drawing()
+void SPDesktop::zoom_quick(bool enable)
{
- g_return_if_fail (doc() != NULL);
- SPItem *docitem = doc()->getRoot();
- g_return_if_fail (docitem != NULL);
+ if (enable == _quick_zoom_enabled) {
+ return;
+ }
- docitem->bbox_valid = FALSE;
- Geom::OptRect d = docitem->desktopVisualBounds();
+ if (enable) {
+ _quick_zoom_affine = _current_affine;
+ bool zoomed = false;
- /* Note that the second condition here indicates that
- ** there are no items in the drawing.
- */
- if ( !d || d->minExtent() < 0.1 ) {
- return;
+ // TODO This needs to migrate into the node tool, but currently the design
+ // of this method is sufficiently wrong to prevent this.
+ if (!zoomed && INK_IS_NODE_TOOL(event_context)) {
+ Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(event_context);
+ if (!nt->_selected_nodes->empty()) {
+ Geom::Rect nodes = *nt->_selected_nodes->bounds();
+ double area = nodes.area();
+ // do not zoom if a single cusp node is selected aand the bounds
+ // have zero area.
+ if (!Geom::are_near(area, 0)) {
+ set_display_area(nodes, true);
+ zoomed = true;
+ }
+ }
+ }
+
+ if (!zoomed) {
+ Geom::OptRect const d = selection->visualBounds();
+ if (d) {
+ set_display_area(*d, true);
+ zoomed = true;
+ }
+ }
+
+ if (!zoomed) {
+ Geom::Rect const d_canvas = canvas->getViewbox(); // Not SVG 'viewBox'
+ Geom::Point midpoint = w2d(d_canvas.midpoint()); // Midpoint of drawing on canvas.
+ zoom_relative_center_point(midpoint, 2.0);
+ }
+ } else {
+ _current_affine = _quick_zoom_affine;
+ set_display_area( false );
}
- set_display_area(*d, 10);
+ _quick_zoom_enabled = enable;
+ return;
}
+
/**
- * Scroll canvas by specific coordinate amount in svg coordinates.
+ * Tell widget to let zoom widget grab keyboard focus.
*/
void
-SPDesktop::scroll_world_in_svg_coords (double dx, double dy, bool is_scrolling)
+SPDesktop::zoom_grab_focus()
{
- double scale = _d2w.descrim();
- scroll_world(dx*scale, dy*scale, is_scrolling);
+ _widget->letZoomGrabFocus();
}
+
/**
- * Scroll canvas by specific coordinate amount.
+ * Scroll canvas by to a particular point (window coordinates).
*/
void
-SPDesktop::scroll_world (double dx, double dy, bool is_scrolling)
+SPDesktop::scroll_absolute (Geom::Point const &point, bool is_scrolling)
{
- g_assert(_widget);
-
- Geom::Rect const viewbox = canvas->getViewbox();
-
- canvas->scrollTo(viewbox.min()[Geom::X] - dx, viewbox.min()[Geom::Y] - dy, FALSE, is_scrolling);
+ canvas->scrollTo(point, FALSE, is_scrolling);
+ _current_affine.setOffset( point );
/* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */
//sp_box3d_context_update_lines(event_context);
@@ -1144,9 +1101,36 @@ SPDesktop::scroll_world (double dx, double dy, bool is_scrolling)
}
_widget->updateRulers();
- _widget->updateScrollbars(_d2w.descrim());
+ _widget->updateScrollbars(_current_affine.getZoom());
}
+
+/**
+ * Scroll canvas by specific coordinate amount (window coordinates).
+ */
+void
+SPDesktop::scroll_relative (Geom::Point const &delta, bool is_scrolling)
+{
+ Geom::Rect const viewbox = canvas->getViewbox();
+ scroll_absolute( viewbox.min() - delta, is_scrolling );
+}
+
+
+/**
+ * Scroll canvas by specific coordinate amount in svg coordinates.
+ */
+void
+SPDesktop::scroll_relative_in_svg_coords (double dx, double dy, bool is_scrolling)
+{
+ double scale = _current_affine.getZoom();
+ scroll_relative(Geom::Point(dx*scale, dy*scale), is_scrolling);
+}
+
+
+/**
+ * Scroll screen so as to keep point 'p' visible in window. 'p' is in drawing coordinates.
+ * (Used, for example, when a node is being dragged.)
+ */
bool
SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed)
{
@@ -1157,7 +1141,7 @@ SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed)
gdouble autoscrolldistance = (gdouble) prefs->getIntLimited("/options/autoscrolldistance/value", 0, -1000, 10000);
// autoscrolldistance is in screen pixels, but the display area is in document units
- autoscrolldistance /= _d2w.descrim();
+ autoscrolldistance /= _current_affine.getZoom();
// FIXME: This 2geom idiom doesn't allow us to declare dbox const
Geom::Rect dbox = get_display_area();
dbox.expandBy(-autoscrolldistance);
@@ -1165,7 +1149,7 @@ SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed)
if (!(p[X] > dbox.min()[X] && p[X] < dbox.max()[X]) ||
!(p[Y] > dbox.min()[Y] && p[Y] < dbox.max()[Y]) ) {
- Geom::Point const s_w( p * (Geom::Affine)_d2w );
+ Geom::Point const s_w( p * _current_affine.d2w() );
gdouble x_to;
if (p[X] < dbox.min()[X])
@@ -1184,14 +1168,14 @@ SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed)
y_to = p[Y];
Geom::Point const d_dt(x_to, y_to);
- Geom::Point const d_w( d_dt * _d2w );
+ Geom::Point const d_w( d_dt * _current_affine.d2w() );
Geom::Point const moved_w( d_w - s_w );
if (autoscrollspeed == 0)
autoscrollspeed = prefs->getDoubleLimited("/options/autoscrollspeed/value", 1, 0, 10);
if (autoscrollspeed != 0)
- scroll_world (autoscrollspeed * moved_w);
+ scroll_relative (autoscrollspeed * moved_w);
return true;
}
@@ -1380,6 +1364,28 @@ SPDesktop::onWindowStateEvent (GdkEventWindowState* event)
return false;
}
+
+/**
+ * Apply the desktop's current style or the tool style to the object.
+ */
+void SPDesktop::applyCurrentOrToolStyle(SPObject *obj, Glib::ustring const &tool_path, bool with_text)
+{
+ SPCSSAttr *css_current = sp_desktop_get_style(this, with_text);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ if (prefs->getBool(tool_path + "/usecurrent") && css_current) {
+ obj->setCSS(css_current,"style");
+ } else {
+ SPCSSAttr *css = prefs->getInheritedStyle(tool_path + "/style");
+ obj->setCSS(css,"style");
+ sp_repr_css_attr_unref(css);
+ }
+ if (css_current) {
+ sp_repr_css_attr_unref(css_current);
+ }
+}
+
+
void
SPDesktop::setToolboxFocusTo (gchar const *label)
{
@@ -1623,7 +1629,7 @@ SPDesktop::_onSelectionModified
(Inkscape::Selection */*selection*/, guint /*flags*/, SPDesktop *dt)
{
if (!dt->_widget) return;
- dt->_widget->updateScrollbars (dt->_d2w.descrim());
+ dt->_widget->updateScrollbars (dt->_current_affine.getZoom());
}
static void
@@ -1765,17 +1771,17 @@ static void _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop)
Geom::Affine SPDesktop::w2d() const
{
- return _w2d;
+ return _current_affine.w2d();
}
Geom::Point SPDesktop::w2d(Geom::Point const &p) const
{
- return p * _w2d;
+ return p * _current_affine.w2d();
}
Geom::Point SPDesktop::d2w(Geom::Point const &p) const
{
- return p * _d2w;
+ return p * _current_affine.d2w();
}
Geom::Affine SPDesktop::doc2dt() const
diff --git a/src/desktop.h b/src/desktop.h
index 3652d4a97..2d2297c6b 100644
--- a/src/desktop.h
+++ b/src/desktop.h
@@ -29,6 +29,7 @@
#include <sigc++/sigc++.h>
#include <2geom/affine.h>
+#include <2geom/transforms.h>
#include <2geom/rect.h>
#include "ui/view/view.h"
@@ -179,11 +180,6 @@ public:
SPCSSAttr *current; ///< current style
bool _focusMode; ///< Whether we're focused working or general working
- std::list<Geom::Rect> zooms_past;
- std::list<Geom::Rect> zooms_future;
-
- bool _quick_zoom_enabled; ///< Signifies that currently we're in quick zoom mode
- Geom::Rect _quick_zoom_stored_area; ///< The area of the screen before quick zoom
unsigned int dkey;
unsigned int number;
guint window_state;
@@ -323,38 +319,37 @@ public:
SPItem *getGroupAtPoint(Geom::Point const &p) const;
Geom::Point point() const;
+ void prev_transform();
+ void next_transform();
+ void clear_transform_history();
+
+ void set_display_area (bool log = true);
+ void set_display_area (Geom::Point const &c, Geom::Point const &w, bool log = true);
+ void set_display_area (Geom::Rect const &a, Geom::Coord border, bool log = true);
Geom::Rect get_display_area() const;
- void set_display_area (double x0, double y0, double x1, double y1, double border, bool log = true);
- void set_display_area(Geom::Rect const &a, Geom::Coord border, bool log = true);
- void zoom_absolute (double cx, double cy, double zoom);
- void zoom_relative (double cx, double cy, double zoom);
- void zoom_absolute_keep_point (double cx, double cy, double px, double py, double zoom);
- void zoom_relative_keep_point (double cx, double cy, double zoom);
- void zoom_relative_keep_point (Geom::Point const &c, double const zoom)
- {
- zoom_relative_keep_point (c[Geom::X], c[Geom::Y], zoom);
- }
+
+ void zoom_absolute_keep_point (Geom::Point const &c, double const zoom);
+ void zoom_relative_keep_point (Geom::Point const &c, double const zoom);
+ void zoom_absolute_center_point (Geom::Point const &c, double const zoom);
+ void zoom_relative_center_point (Geom::Point const &c, double const zoom);
void zoom_page();
void zoom_page_width();
void zoom_drawing();
void zoom_selection();
- void zoom_grab_focus();
- double current_zoom() const { return _d2w.descrim(); }
- void prev_zoom();
- void next_zoom();
- void zoom_quick(bool enable = true);
+ double current_zoom() const { return _current_affine.getZoom(); }
+
+ void zoom_quick(bool enable = true);
/** \brief Returns whether the desktop is in quick zoom mode or not */
bool quick_zoomed(void) { return _quick_zoom_enabled; }
+ void zoom_grab_focus();
+
+ void scroll_absolute (Geom::Point const &point, bool is_scrolling = false);
+ void scroll_relative (Geom::Point const &delta, bool is_scrolling = false);
+ void scroll_relative_in_svg_coords (double dx, double dy, bool is_scrolling = false);
bool scroll_to_point (Geom::Point const &s_dt, gdouble autoscrollspeed = 0);
- void scroll_world (double dx, double dy, bool is_scrolling = false);
- void scroll_world (Geom::Point const &scroll, bool is_scrolling = false)
- {
- scroll_world(scroll[Geom::X], scroll[Geom::Y], is_scrolling);
- }
- void scroll_world_in_svg_coords (double dx, double dy, bool is_scrolling = false);
void getWindowGeometry (gint &x, gint &y, gint &w, gint &h);
void setWindowPosition (Geom::Point p);
@@ -407,7 +402,7 @@ public:
*/
void show_dialogs();
- Geom::Affine w2d() const; //transformation from window to desktop coordinates (used for zooming)
+ Geom::Affine w2d() const; //transformation from window to desktop coordinates (zoom/rotate).
Geom::Point w2d(Geom::Point const &p) const;
Geom::Point d2w(Geom::Point const &p) const;
Geom::Affine doc2dt() const;
@@ -430,8 +425,82 @@ private:
Inkscape::UI::View::EditWidgetInterface *_widget;
Inkscape::MessageContext *_guides_message_context;
bool _active;
- Geom::Affine _w2d;
- Geom::Affine _d2w;
+
+ // This simple class ensures that _w2d is always in sync with _rotation and _scale
+ // We keep rotation and scale separate to avoid having to extract them from the affine.
+ // With offset, this describes fully how to map the drawing to the window.
+ // Future: merge offset as a translation in w2d.
+ class DesktopAffine {
+ public:
+ Geom::Affine w2d() const { return _w2d; };
+ Geom::Affine d2w() const { return _d2w; };
+
+ void setScale( Geom::Scale scale ) {
+ _scale = scale;
+ _update();
+ }
+ void setScale( double scale ) {
+ _scale = Geom::Scale(scale, -scale); // Y flip
+ _update();
+ }
+ void addScale( Geom::Scale scale) {
+ _scale *= scale;
+ _update();
+ }
+ void addScale( double scale ) {
+ _scale *= Geom::Scale(scale, -scale); // Y flip?? Check
+ _update();
+ }
+
+ void setRotate( Geom::Rotate rotate ) {
+ _rotate = rotate;
+ _update();
+ }
+ void setRotate( double rotate ) {
+ _rotate = Geom::Rotate( rotate );
+ _update();
+ }
+ void addRotate( Geom::Rotate rotate ) {
+ _rotate *= rotate;
+ _update();
+ }
+ void addRotate( double rotate ) {
+ _rotate *= Geom::Rotate( rotate );
+ _update();
+ }
+
+ double getZoom() const {
+ return _d2w.descrim();
+ }
+
+ void setOffset( Geom::Point offset ) {
+ _offset = offset;
+ }
+ void addOffset( Geom::Point offset ) {
+ _offset += offset;
+ }
+ Geom::Point getOffset() {
+ return _offset;
+ }
+
+ private:
+ void _update() {
+ _d2w = _rotate * _scale;
+ _w2d = _d2w.inverse();
+ }
+ Geom::Affine _w2d; // Window to desktop
+ Geom::Affine _d2w; // Desktop to window
+ Geom::Rotate _rotate; // Rotate part of _w2d
+ Geom::Scale _scale; // Scale part of _w2d
+ Geom::Point _offset; // Point on canvas to align to (0,0) of window
+ };
+
+ DesktopAffine _current_affine;
+ std::list<DesktopAffine> transforms_past;
+ std::list<DesktopAffine> transforms_future;
+ bool _quick_zoom_enabled; ///< Signifies that currently we're in quick zoom mode
+ DesktopAffine _quick_zoom_affine; ///< The transform of the screen before quick zoom
+
Geom::Affine _doc2dt;
/*
@@ -457,8 +526,6 @@ private:
bool grids_visible; /* don't set this variable directly, use the method below */
void set_grids_visible(bool visible);
- void push_current_zoom(std::list<Geom::Rect> &);
-
sigc::signal<void, SPDesktop*> _destroy_signal;
sigc::signal<void,SPDesktop*,SPDocument*> _document_replaced_signal;
sigc::signal<void> _activate_signal;
diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp
index cf7d04555..2dadde336 100644
--- a/src/display/canvas-grid.cpp
+++ b/src/display/canvas-grid.cpp
@@ -841,7 +841,9 @@ void
CanvasXYGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/)
{
ow = origin * affine;
- sw = spacing * affine;
+ // Temp hack to insure grid doesn't collapse with rotation.
+ sw[0] = spacing[0] * sqrt(affine[0]*affine[0] + affine[1]*affine[1]);
+ sw[1] = spacing[1] * sqrt(affine[2]*affine[2] + affine[3]*affine[3]);
sw -= Geom::Point(affine[4], affine[5]);
for(int dim = 0; dim < 2; dim++) {
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index 9cc9e51a2..61602e880 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -1937,10 +1937,16 @@ double start_angle = 0;
bool started = false;
bool rotated = false;
-void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scrolling)
+/**
+ * Scroll screen to point 'c'. 'c' is measured in screen pixels.
+ */
+void SPCanvas::scrollTo( Geom::Point const &c, unsigned int clear, bool is_scrolling)
{
GtkAllocation allocation;
+ double cx = c[Geom::X];
+ double cy = c[Geom::Y];
+
int ix = (int) round(cx); // ix and iy are the new canvas coordinates (integer screen pixels)
int iy = (int) round(cy); // cx might be negative, so (int)(cx + 0.5) will not do!
int dx = ix - _x0; // dx and dy specify the displacement (scroll) of the
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index 21b6760f2..708653bdf 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -70,8 +70,8 @@ GType sp_canvas_get_type() G_GNUC_CONST;
* Port of GnomeCanvas for inkscape needs.
*/
struct SPCanvas {
- /// Scrolls canvas to specific position (cx and cy are measured in screen pixels).
- void scrollTo(double cx, double cy, unsigned int clear, bool is_scrolling = false);
+ /// Scrolls canvas to specific position (c is measured in screen pixels).
+ void scrollTo(Geom::Point const &c, unsigned int clear, bool is_scrolling = false);
void startRotateTo(double angle);
void rotateTo(double angle);
bool endRotateTo();
diff --git a/src/file.cpp b/src/file.cpp
index 6613b1e65..fc9ce6b19 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -908,7 +908,7 @@ void sp_file_revert_dialog()
reverted = sp_file_open(uri,NULL);
if (reverted) {
// restore zoom and view
- desktop->zoom_absolute(c[Geom::X], c[Geom::Y], zoom);
+ desktop->zoom_absolute_center_point(c, zoom);
}
} else {
reverted = false;
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index f2bdeba4e..5d585ab5d 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -2554,9 +2554,7 @@ void scroll_to_show_item(SPDesktop *desktop, SPItem *item)
Geom::Point const d_dt = dbox.midpoint();
Geom::Point const d_w = desktop->d2w(d_dt);
Geom::Point const moved_w( d_w - s_w );
- gint const dx = (gint) moved_w[X];
- gint const dy = (gint) moved_w[Y];
- desktop->scroll_world(dx, dy);
+ desktop->scroll_relative(moved_w);
}
}
diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp
index 166e90238..403b8a41b 100644
--- a/src/sp-namedview.cpp
+++ b/src/sp-namedview.cpp
@@ -839,18 +839,18 @@ void sp_namedview_window_from_document(SPDesktop *desktop)
}
}
+ // Cancel any history of transforms up to this point (must be before call to zoom).
+ desktop->clear_transform_history();
+
// restore zoom and view
if (nv->zoom != 0 && nv->zoom != HUGE_VAL && !IS_NAN(nv->zoom)
&& nv->cx != HUGE_VAL && !IS_NAN(nv->cx)
&& nv->cy != HUGE_VAL && !IS_NAN(nv->cy)) {
- desktop->zoom_absolute(nv->cx, nv->cy, nv->zoom);
+ desktop->zoom_absolute_center_point( Geom::Point(nv->cx, nv->cy), nv->zoom );
} else if (desktop->getDocument()) { // document without saved zoom, zoom to its page
desktop->zoom_page();
}
- // cancel any history of zooms up to this point
- desktop->zooms_past.clear();
-
if (show_dialogs) {
desktop->show_dialogs();
}
@@ -1280,7 +1280,7 @@ void SPNamedView::translateGrids(Geom::Translate const &tr) {
void SPNamedView::scrollAllDesktops(double dx, double dy, bool is_scrolling) {
for(std::vector<SPDesktop *>::iterator it=this->views.begin();it!=this->views.end();++it ) {
- (*it)->scroll_world_in_svg_coords(dx, dy, is_scrolling);
+ (*it)->scroll_relative_in_svg_coords(dx, dy, is_scrolling);
}
}
diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp
index aab256712..8c7f54d14 100644
--- a/src/ui/tools/tool-base.cpp
+++ b/src/ui/tools/tool-base.cpp
@@ -497,7 +497,7 @@ bool ToolBase::root_handler(GdkEvent* event) {
Geom::Point const motion_w(event->motion.x, event->motion.y);
Geom::Point const moved_w(motion_w - button_w);
- this->desktop->scroll_world(moved_w, true); // we're still scrolling, do not redraw
+ this->desktop->scroll_relative(moved_w, true); // we're still scrolling, do not redraw
ret = TRUE;
}
} else if (zoom_rb) {
@@ -575,7 +575,7 @@ bool ToolBase::root_handler(GdkEvent* event) {
Geom::Point const motion_w(event->button.x, event->button.y);
Geom::Point const moved_w(motion_w - button_w);
- this->desktop->scroll_world(moved_w);
+ this->desktop->scroll_relative(moved_w);
desktop->updateNow();
ret = TRUE;
} else if (zoom_rb == event->button.button) {
@@ -675,7 +675,7 @@ bool ToolBase::root_handler(GdkEvent* event) {
acceleration, desktop->getCanvas()));
gobble_key_events(get_group0_keyval(&event->key), GDK_CONTROL_MASK);
- this->desktop->scroll_world(i, 0);
+ this->desktop->scroll_relative(Geom::Point(i, 0));
ret = TRUE;
}
break;
@@ -688,7 +688,7 @@ bool ToolBase::root_handler(GdkEvent* event) {
acceleration, desktop->getCanvas()));
gobble_key_events(get_group0_keyval(&event->key), GDK_CONTROL_MASK);
- this->desktop->scroll_world(0, i);
+ this->desktop->scroll_relative(Geom::Point(0, i));
ret = TRUE;
}
break;
@@ -701,7 +701,7 @@ bool ToolBase::root_handler(GdkEvent* event) {
acceleration, desktop->getCanvas()));
gobble_key_events(get_group0_keyval(&event->key), GDK_CONTROL_MASK);
- this->desktop->scroll_world(-i, 0);
+ this->desktop->scroll_relative(Geom::Point(-i, 0));
ret = TRUE;
}
break;
@@ -714,7 +714,7 @@ bool ToolBase::root_handler(GdkEvent* event) {
acceleration, desktop->getCanvas()));
gobble_key_events(get_group0_keyval(&event->key), GDK_CONTROL_MASK);
- this->desktop->scroll_world(0, -i);
+ this->desktop->scroll_relative(Geom::Point(0, -i));
ret = TRUE;
}
break;
@@ -856,11 +856,11 @@ bool ToolBase::root_handler(GdkEvent* event) {
if (event->scroll.state & GDK_SHIFT_MASK) {
switch (event->scroll.direction) {
case GDK_SCROLL_UP:
- desktop->scroll_world(wheel_scroll, 0);
+ desktop->scroll_relative(Geom::Point(wheel_scroll, 0));
break;
case GDK_SCROLL_DOWN:
- desktop->scroll_world(-wheel_scroll, 0);
+ desktop->scroll_relative(Geom::Point(-wheel_scroll, 0));
break;
default:
@@ -896,24 +896,24 @@ bool ToolBase::root_handler(GdkEvent* event) {
} else {
switch (event->scroll.direction) {
case GDK_SCROLL_UP:
- desktop->scroll_world(0, wheel_scroll);
+ desktop->scroll_relative(Geom::Point(0, wheel_scroll));
break;
case GDK_SCROLL_DOWN:
- desktop->scroll_world(0, -wheel_scroll);
+ desktop->scroll_relative(Geom::Point(0, -wheel_scroll));
break;
case GDK_SCROLL_LEFT:
- desktop->scroll_world(wheel_scroll, 0);
+ desktop->scroll_relative(Geom::Point(wheel_scroll, 0));
break;
case GDK_SCROLL_RIGHT:
- desktop->scroll_world(-wheel_scroll, 0);
+ desktop->scroll_relative(Geom::Point(-wheel_scroll, 0));
break;
case GDK_SCROLL_SMOOTH:
gdk_event_get_scroll_deltas(event, &delta_x, &delta_y);
- desktop->scroll_world(delta_x, delta_y);
+ desktop->scroll_relative(Geom::Point(delta_x, delta_y));
break;
}
}
diff --git a/src/verbs.cpp b/src/verbs.cpp
index d67e68392..8b3d7a5a2 100644
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
@@ -1890,7 +1890,10 @@ void ZoomVerb::perform(SPAction *action, void *data)
zcorr = prefs->getDouble("/options/zoomcorrection/value", 1.0);
Geom::Rect const d = dt->get_display_area();
-
+
+ Geom::Rect const d_canvas = dt->getCanvas()->getViewbox(); // Not SVG 'viewBox'
+ Geom::Point midpoint = dt->w2d(d_canvas.midpoint()); // Midpoint of drawing on canvas.
+
switch (reinterpret_cast<std::size_t>(data)) {
case SP_VERB_ZOOM_IN:
{
@@ -1907,7 +1910,7 @@ void ZoomVerb::perform(SPAction *action, void *data)
}
}
- dt->zoom_relative( d.midpoint()[Geom::X], d.midpoint()[Geom::Y], mul*zoom_inc);
+ dt->zoom_relative_center_point( midpoint, mul*zoom_inc);
break;
}
case SP_VERB_ZOOM_OUT:
@@ -1924,17 +1927,17 @@ void ZoomVerb::perform(SPAction *action, void *data)
}
}
- dt->zoom_relative( d.midpoint()[Geom::X], d.midpoint()[Geom::Y], 1 / (mul*zoom_inc) );
+ dt->zoom_relative_center_point( midpoint, 1 / (mul*zoom_inc) );
break;
}
case SP_VERB_ZOOM_1_1:
- dt->zoom_absolute( d.midpoint()[Geom::X], d.midpoint()[Geom::Y], 1.0 * zcorr );
+ dt->zoom_absolute_center_point( midpoint, 1.0 * zcorr );
break;
case SP_VERB_ZOOM_1_2:
- dt->zoom_absolute( d.midpoint()[Geom::X], d.midpoint()[Geom::Y], 0.5 * zcorr );
+ dt->zoom_absolute_center_point( midpoint, 0.5 * zcorr );
break;
case SP_VERB_ZOOM_2_1:
- dt->zoom_absolute( d.midpoint()[Geom::X], d.midpoint()[Geom::Y], 2.0 * zcorr );
+ dt->zoom_absolute_center_point( midpoint, 2.0 * zcorr );
break;
case SP_VERB_ZOOM_PAGE:
dt->zoom_page();
@@ -1949,10 +1952,10 @@ void ZoomVerb::perform(SPAction *action, void *data)
dt->zoom_selection();
break;
case SP_VERB_ZOOM_NEXT:
- dt->next_zoom();
+ dt->next_transform();
break;
case SP_VERB_ZOOM_PREV:
- dt->prev_zoom();
+ dt->prev_transform();
break;
case SP_VERB_TOGGLE_RULERS:
dt->toggleRulers();
@@ -2895,6 +2898,7 @@ Verb *Verb::_base_verbs[] = {
// Zoom/View
new ZoomVerb(SP_VERB_ZOOM_IN, "ZoomIn", N_("Zoom In"), N_("Zoom in"), INKSCAPE_ICON("zoom-in")),
new ZoomVerb(SP_VERB_ZOOM_OUT, "ZoomOut", N_("Zoom Out"), N_("Zoom out"), INKSCAPE_ICON("zoom-out")),
+ // WHY ARE THE FOLLOWING ZoomVerbs???
new ZoomVerb(SP_VERB_TOGGLE_RULERS, "ToggleRulers", N_("_Rulers"), N_("Show or hide the canvas rulers"), NULL),
new ZoomVerb(SP_VERB_TOGGLE_SCROLLBARS, "ToggleScrollbars", N_("Scroll_bars"), N_("Show or hide the canvas scrollbars"), NULL),
new ZoomVerb(SP_VERB_TOGGLE_GRID, "ToggleGrid", N_("Page _Grid"), N_("Show or hide the page grid"), INKSCAPE_ICON("show-grid")),
diff --git a/src/viewbox.cpp b/src/viewbox.cpp
index ebfc04d8a..1fa33117a 100644
--- a/src/viewbox.cpp
+++ b/src/viewbox.cpp
@@ -268,7 +268,7 @@ void SPViewBox::apply_viewbox(const Geom::Rect& in, double scale_none) {
center_rotation *= Geom::Rotate(Geom::rad_from_deg(this->angle - this->previous_angle));
center_rotation *= Geom::Translate(page_center * vbt);
view_center = desktop->dt2doc(view_center * center_rotation);
- desktop->zoom_relative(view_center[Geom::X], view_center[Geom::Y], 1.0);
+ desktop->zoom_relative_center_point(view_center, 1.0);
this->rotated = false;
}
}
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 3f75a811e..135cdd96f 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -867,7 +867,7 @@ sp_desktop_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
double newshortside = MIN(newarea.width(), newarea.height());
zoom *= newshortside / oldshortside;
}
- dtw->desktop->zoom_absolute(area.midpoint()[Geom::X], area.midpoint()[Geom::Y], zoom);
+ dtw->desktop->zoom_absolute_center_point (area.midpoint(), zoom);
// TODO - Should call show_dialogs() from sp_namedview_window_from_document only.
// But delaying the call to here solves dock sizing issues on OS X, (see #171579)
@@ -897,7 +897,7 @@ sp_desktop_widget_realize (GtkWidget *widget)
if (d.width() < 1.0 || d.height() < 1.0) return;
- dtw->desktop->set_display_area (d.left(), d.top(), d.right(), d.bottom(), 10);
+ dtw->desktop->set_display_area (d, 10);
dtw->updateNamedview();
}
@@ -1787,15 +1787,9 @@ sp_desktop_widget_adjustment_value_changed (GtkAdjustment */*adj*/, SPDesktopWid
dtw->update = 1;
- dtw->canvas->scrollTo(gtk_adjustment_get_value(dtw->hadj),
- gtk_adjustment_get_value(dtw->vadj), FALSE);
- sp_desktop_widget_update_rulers (dtw);
-
- /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */
- //sp_box3d_context_update_lines(dtw->desktop->event_context);
- if (SP_IS_BOX3D_CONTEXT(dtw->desktop->event_context)) {
- SP_BOX3D_CONTEXT(dtw->desktop->event_context)->_vpdrag->updateLines();
- }
+ // Do not call canvas->scrollTo directly... messes up 'offset'.
+ dtw->desktop->scroll_absolute( Geom::Point(gtk_adjustment_get_value(dtw->hadj),
+ gtk_adjustment_get_value(dtw->vadj)), false);
dtw->update = 0;
}
@@ -1906,7 +1900,7 @@ sp_dtw_zoom_value_changed (GtkSpinButton *spin, gpointer data)
Geom::Rect const d = desktop->get_display_area();
g_signal_handler_block (spin, dtw->zoom_update);
- desktop->zoom_absolute (d.midpoint()[Geom::X], d.midpoint()[Geom::Y], zoom_factor);
+ desktop->zoom_absolute_center_point (d.midpoint(), zoom_factor);
g_signal_handler_unblock (spin, dtw->zoom_update);
spinbutton_defocus (GTK_WIDGET(spin));
@@ -2142,7 +2136,7 @@ static void
sp_dtw_zoom_menu_handler (SPDesktop *dt, gdouble factor)
{
Geom::Rect const d = dt->get_display_area();
- dt->zoom_absolute(d.midpoint()[Geom::X], d.midpoint()[Geom::Y], factor);
+ dt->zoom_absolute_center_point (d.midpoint(), factor);
}