diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2017-03-13 14:22:22 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2017-03-13 14:22:22 +0000 |
| commit | 014489163050d8abe9e5c4949fb80f3c21b1c17b (patch) | |
| tree | 7cbeb87aa023d563986b32f65fd500c6072ee86a /src | |
| parent | Two Extensions for converting objects to paths before exporting. (Bug 1662531) (diff) | |
| download | inkscape-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.cpp | 544 | ||||
| -rw-r--r-- | src/desktop.h | 129 | ||||
| -rw-r--r-- | src/display/canvas-grid.cpp | 4 | ||||
| -rw-r--r-- | src/display/sp-canvas.cpp | 8 | ||||
| -rw-r--r-- | src/display/sp-canvas.h | 4 | ||||
| -rw-r--r-- | src/file.cpp | 2 | ||||
| -rw-r--r-- | src/selection-chemistry.cpp | 4 | ||||
| -rw-r--r-- | src/sp-namedview.cpp | 10 | ||||
| -rw-r--r-- | src/ui/tools/tool-base.cpp | 26 | ||||
| -rw-r--r-- | src/verbs.cpp | 20 | ||||
| -rw-r--r-- | src/viewbox.cpp | 2 | ||||
| -rw-r--r-- | src/widgets/desktop-widget.cpp | 20 |
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); } |
