diff options
author | Armin Le Grand <Armin.Le.Grand@cib.de> | 2018-10-12 11:13:09 +0200 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@cib.de> | 2018-11-27 11:33:10 +0100 |
commit | d464d505fbf6e53a38afdd3661d320fac8c760d6 (patch) | |
tree | 3bf7db8591172bf948198f19d36df5df886486bb /svx | |
parent | 3e1e2b6687b0259ae28441cc0d314de0d908776b (diff) |
Refactor calc non-linear ViewToDevice transform
This change solves the non-linear World-To-View trans-
formation that calc uses due to it's screen rendering
as good as currently possible (AFAIK).
Calcv view is layouted on pixel base (due to better
homogen distances and full pixel lines between cells),
but this leads to having a non-linear transformation
between discrete units (pixels, view) and model coordinates
(World). In principle, each cell has it's own (so called)
ViewTransformation -> the position on screen depends on
the mappings of all cells top/left from it. This is
obvioulsly non-linear and can sometimes be seen by
producing 'offset' errors when many cells (small and thin)
are shown in low zoom stages.
No better solution for this comes to mind easily. The
extremes are - on the one hand AntiAliasing the whole
calc edit view and accept 'unsharp/AAed' lines - on the
other hand what we have now.
Maybe a future solution could find a mapping that gets
close to linear mapping for the full view. On the long
run this state is hard to keep correct. Even with this
extended solution the mapping of SdrObjects spawning
mutiple cells is assumed 'linear' in that area - which
is in reality currently not the case (!)
Note: This is only true for the screen visualization,
print and/or PDF export do not do that pixel-based
layouting.
Note2: This mechanism is general in DrawingLayer (look
for '.*GridOffset.*'. If it is deactivated by providing
no offsets, the result is the unchanged, linear mapping.
First step: Add interfaces to get a possible GridOffset
at ViewObjectContact. There it belongs, we have a view-
dependent offset per object and view. Add mechanisms to
create on-demand and reach back to the view (aka calc's
derivation of it).
Second step: Implement the on-demand creation, adapt to
use it in ViewObjectContact::getPrimitive2DSequence, add
stuff to reset on zoom change, disable temporarily old
mechanism -> paint already works. Need to adapt the
places from old mechanism where the GridOffset was used,
but no longer the geometry creations.
Third step: Isolated and disabled old mechanism (by
already removing SetGridOffset). Marked all places that
possibly need change with '//Z' tag. Main work now will
be to adapt in the SdrView implementations in svx to know
about having a SdrObject-dependent ViewTransformation
at all (currently not known, was hard-coded at some places
from the old code, ViewTransformation set as MapMode at
a target OutputDevice, not member at SdrView at all...).
Fourth step: Adapt the Handles and OverlayObjects to
use an evtl. existing GridOffset. The mechanism is that
the SdrHdl(s) can be seen as 'Model-Objects', these get
converted to OverlayObjects in the ::CreateB2dIAObject()
implementations, for all SdrMarkView and SdrPageView,
so this is the place where the ObjectContact is known
(the SdrPageWindow *is* a ObjectContact) and the view-
dependent GridOffset can be calculated per SdrObject.
I modified OverlayObject to be able to work with a
set Offset that embeds the created visualization using
this additionally.
Handles get now correctly set and have a working HitTest
(due to that already using the primitives). Some inter-
action stuff already working, some will need more
adaption. We simply have no concept for this stuff...
Refactored to not get dependencies to SdrObject in
ObjectContact.
Fifth Step: Make HitTest work by adding the View-And-
Object dependent GridOffset in the View when HitTest
is triggered. This is in SdrMarkView::CheckSingleSdrObjectHit
where pObj->GetCurrentBoundRect() is used that gets the
view-independent form. To make HitTest work, add a possible
GridOffset.
Since this will be necessary more often in SdrView hierarchy,
added a tooling method (getPossibleGridOffsetForSdrObject)
at that level after checking that at that level will be
reachable at all potential spots.
Inside that method the correct ObjectContact will be identified
and the object-specific offset requested there.
Sixth Step: Adaptions and started some cleanups. Still some
adaptions needed:
- After creation of new object, need to relocate from
used GridOffset setting to WorldCoordinates
- Interactions, e.g. start with dragging handles or full
object/points
Seventh Step: React on EndCreateObj. Here, the created
SdrObject is in model coordinates and needs to be adapted
to evtl. GridOffset. This is 'tricky' due to calculating
the possible offset based on new coordinates 'close'
to the target position, but may be in the wrong cell.
Nonetheless this is the best we can do here.
Last (hopefully) missing are now all interaction
viszualizations. They already work and are applied
correctly, but wrong visualized.
Have taken the time to unify adding OverlayObjects for
selection visualization to OverlayManager, see
handleNewOverlayObject. This does all needed when adding
OverlayObjects in one place where the GridOffset can
also be handled. It makles things more safe - not possible
to forget one of the three steps for others.
Eighth Step: Do the same unification for creating the
OverlayGeometry, also rename methods to make usage more
clear. We now have
SdrHdl::insertNewlyCreatedOverlayObjectForSdrHdl
SdrDragMethod::insertNewlyCreatedOverlayObjectForSdrDragMethod
which can do the needed GridOffset changes centralized.
Needed to get a ObjectContact for this at SdrDragMethod,
so adapted ::CreateOverlayGeometry implementations
accordingly. Missing is now the implementation in
insertNewlyCreatedOverlayObjectForSdrDragMethod to add
the GridOffset - if used. This has no SdrObject at this
time, so we will need a fallback to do the same using a
Range (Rectangle). The stuff doing this for SdrObject
already has a fallback and is based on using the Rectangle
from the SdrObject anyways, so this will be possible.
Ninth Step: Cleanup of old stuff (no more //Z), adapted
some usages of OverlayObject creations to use
getViewIndependentPrimitive2DContainer instead of the
view dependent parts so that offset applied to
drag-overlays is correct and not already added. Adapted
insertNewlyCreatedOverlayObjectForSdrDragMethod to use
calculateGridOffsetForB2DRange. Use now that instead of
SdrObject-based approach in calc - is more generic.
Getting closer, but still not complete - there is an
error with dragging the grepped handle somehow - the
offset for drag is somehow wrong.
Tenth Step: Corrected that offset error. Of course at
interaction start and progress (move) the coordinates
are in GrifOffset coordinates and need to be corrected
to Model coordinates. Done that at ::BegDragObj and
::MovDragObj, works well.
Of course there are exceptions for the crop-handles, so
needed to add setting the correct parameters at SdrHdl
when these got created, then all works as expected.
The strategy is to *not* change the model data itself
in any way, instead do all changes/adaptions in the
view-only code. This has minimal impact and is needed
due to having a 1:n relationship between model and
views anyways.
There are two directions: All visualizations are adapted
to take the GridOffset into account (SdrObjects, overlay,
handles, InteractionObjects, ...). In the other direction
input like MousePosition is in principle in calc EditView
in 'GridOffset'-coordinates and needs to be mapped back
before usage.
Change-Id: I2ecdd409def96a7248a26a65a22e59eb962880a0
Reviewed-on: https://gerrit.libreoffice.org/64057
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Diffstat (limited to 'svx')
39 files changed, 623 insertions, 433 deletions
diff --git a/svx/inc/dragmt3d.hxx b/svx/inc/dragmt3d.hxx index 01d9cd6d6469..c5cd6db44878 100644 --- a/svx/inc/dragmt3d.hxx +++ b/svx/inc/dragmt3d.hxx @@ -77,7 +77,9 @@ public: virtual bool EndSdrDrag(bool bCopy) override; // for migration from XOR to overlay - virtual void CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager) override; + virtual void CreateOverlayGeometry( + sdr::overlay::OverlayManager& rOverlayManager, + const sdr::contact::ObjectContact& rObjectContact) override; }; // Derivative of SdrDragMethod for spinning 3D objects diff --git a/svx/inc/sdr/contact/objectcontactofpageview.hxx b/svx/inc/sdr/contact/objectcontactofpageview.hxx deleted file mode 100644 index 4fb0bef53898..000000000000 --- a/svx/inc/sdr/contact/objectcontactofpageview.hxx +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_SVX_INC_SDR_CONTACT_OBJECTCONTACTOFPAGEVIEW_HXX -#define INCLUDED_SVX_INC_SDR_CONTACT_OBJECTCONTACTOFPAGEVIEW_HXX - -#include <svx/sdr/contact/objectcontact.hxx> -#include <vcl/idle.hxx> - -class SdrPageWindow; -class SdrPage; - -namespace sdr -{ - namespace contact - { - class ObjectContactOfPageView final : public ObjectContact, public Idle - { - // the owner of this ObjectContactOfPageView. Set from constructor and not - // to be changed in any way. - SdrPageWindow& mrPageWindow; - - // Process the whole displaying, the real version - void DoProcessDisplay(DisplayInfo& rDisplayInfo); - - public: - // access to SdrPageWindow - SdrPageWindow& GetPageWindow() const { return mrPageWindow; } - - // access to SdrPage of PageView - SdrPage* GetSdrPage() const; - - // basic constructor, used from SdrPageView. - explicit ObjectContactOfPageView(SdrPageWindow& rPageWindow, - const sal_Char *pDebugName); - virtual ~ObjectContactOfPageView() override; - - // LazyInvalidate request. This is used from the VOCs to mark that they - // got invalidated by an ActionChanged() call. An active view needs to remember - // this and take action on it. Default implementation directly calls back - // triggerLazyInvalidate() which promptly handles the request - virtual void setLazyInvalidate(ViewObjectContact& rVOC) override; - - // call this to support evtl. preparations for repaint - virtual void PrepareProcessDisplay() override; - - // From baseclass Timer, the timeout call triggered by the LazyInvalidate mechanism - virtual void Invoke() final override; - - // Process the whole displaying - virtual void ProcessDisplay(DisplayInfo& rDisplayInfo) override; - - // test if visualizing of entered groups is switched on at all - virtual bool DoVisualizeEnteredGroup() const override; - - // get active group's (the entered group) ViewContact - virtual const ViewContact* getActiveViewContact() const override; - - // Invalidate given rectangle at the window/output which is represented by - // this ObjectContact. - virtual void InvalidatePartOfView(const basegfx::B2DRange& rRange) const override; - - // Get info about the need to visualize GluePoints. The default - // is that it is not necessary. - virtual bool AreGluePointsVisible() const override; - - // check if text animation is allowed. - virtual bool IsTextAnimationAllowed() const override; - - // check if graphic animation is allowed. - virtual bool IsGraphicAnimationAllowed() const override; - - // print? Default is false - virtual bool isOutputToPrinter() const override; - - // recording MetaFile? Default is false - virtual bool isOutputToRecordingMetaFile() const override; - - // pdf export? Default is false - virtual bool isOutputToPDFFile() const override; - - // gray display mode - virtual bool isDrawModeGray() const override; - - // high contrast display mode - virtual bool isDrawModeHighContrast() const override; - - // override access to SdrPageView - virtual SdrPageView* TryToGetSdrPageView() const override; - - // access to OutputDevice. May return 0L like the default implementations do. Override as needed. - virtual OutputDevice* TryToGetOutputDevice() const override; - - /** sets all UNO controls which are associated with this ObjectContact to - design or alive mode. - */ - void SetUNOControlsDesignMode( bool _bDesignMode ) const; - }; - } // end of namespace contact -} // end of namespace sdr - -#endif // INCLUDED_SVX_INC_SDR_CONTACT_OBJECTCONTACTOFPAGEVIEW_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/inc/sdr/contact/viewcontactofsdrole2obj.hxx b/svx/inc/sdr/contact/viewcontactofsdrole2obj.hxx index a00b95b1661d..8d94c6115aa6 100644 --- a/svx/inc/sdr/contact/viewcontactofsdrole2obj.hxx +++ b/svx/inc/sdr/contact/viewcontactofsdrole2obj.hxx @@ -33,8 +33,6 @@ class ViewContactOfSdrOle2Obj : public ViewContactOfSdrRectObj private: // #i123539# allow local buffering of chart data (if chart) drawinglayer::primitive2d::Primitive2DReference mxChartContent; - // used to check if we need to re-calc the transformation - Point maGridOffset; protected: // Create a Object-Specific ViewObjectContact, set ViewContact and diff --git a/svx/source/engine3d/dragmt3d.cxx b/svx/source/engine3d/dragmt3d.cxx index 94d2bd213fbd..36971d34bf6d 100644 --- a/svx/source/engine3d/dragmt3d.cxx +++ b/svx/source/engine3d/dragmt3d.cxx @@ -209,7 +209,9 @@ void E3dDragMethod::MoveSdrDrag(const Point& /*rPnt*/) // Draw the wire frame model // for migration from XOR to overlay -void E3dDragMethod::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager) +void E3dDragMethod::CreateOverlayGeometry( + sdr::overlay::OverlayManager& rOverlayManager, + const sdr::contact::ObjectContact& rObjectContact) { const sal_uInt32 nCnt(maGrp.size()); basegfx::B2DPolyPolygon aResult; @@ -249,10 +251,14 @@ void E3dDragMethod::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlay if(aResult.count()) { - std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled( - aResult)); - rOverlayManager.add(*pNew); - addToOverlayObjectList(std::move(pNew)); + std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew( + new sdr::overlay::OverlayPolyPolygonStripedAndFilled( + aResult)); + + insertNewlyCreatedOverlayObjectForSdrDragMethod( + std::move(pNew), + rObjectContact, + rOverlayManager); } } diff --git a/svx/source/engine3d/view3d.cxx b/svx/source/engine3d/view3d.cxx index 8a1b3852f8ae..e3def1a409f6 100644 --- a/svx/source/engine3d/view3d.cxx +++ b/svx/source/engine3d/view3d.cxx @@ -114,22 +114,16 @@ Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView& rView) if(pPV && pPV->PageWindowCount()) { - sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact(); - sdr::contact::DisplayInfo aDisplayInfo; - - // Do not use the last ViewPort set at the OC at the last ProcessDisplay() - rOC.resetViewPort(); - for(size_t a = 0; a < mnCount; ++a) { SdrObject* pObject = mrView.GetMarkedObjectByIndex(a); if(pObject) { - sdr::contact::ViewContact& rVC = pObject->GetViewContact(); - sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rOC); - - const drawinglayer::primitive2d::Primitive2DContainer aNewSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo)); + // use the view-independent primitive representation (without + // evtl. GridOffset, that may be applied to the DragEntry individually) + const drawinglayer::primitive2d::Primitive2DContainer aNewSequence( + pObject->GetViewContact().getViewIndependentPrimitive2DContainer()); maFullOverlay.append(aNewSequence); } } diff --git a/svx/source/sdr/contact/objectcontact.cxx b/svx/source/sdr/contact/objectcontact.cxx index a4d52073dfa1..33839d8c83f0 100644 --- a/svx/source/sdr/contact/objectcontact.cxx +++ b/svx/source/sdr/contact/objectcontact.cxx @@ -31,6 +31,26 @@ using namespace com::sun::star; namespace sdr { namespace contact { +bool ObjectContact::supportsGridOffsets() const +{ + // default does not support GridOffset + return false; +} + +void ObjectContact::calculateGridOffsetForViewOjectContact( + basegfx::B2DVector& /*rTarget*/, + const ViewObjectContact& /*rClient*/) const +{ + // default does not on-demand calculate GridOffset +} + +void ObjectContact::calculateGridOffsetForB2DRange( + basegfx::B2DVector& /*rTarget*/, + const basegfx::B2DRange& /*rB2DRange*/) const +{ + // default does not on-demand calculate GridOffset +} + ObjectContact::ObjectContact() : maViewObjectContactVector(), maPrimitiveAnimator(), @@ -209,6 +229,18 @@ void ObjectContact::resetViewPort() } } +void ObjectContact::resetAllGridOffsets() +{ + const sal_uInt32 nVOCCount(getViewObjectContactCount()); + + for(sal_uInt32 a(0); a < nVOCCount; a++) + { + ViewObjectContact* pVOC(getViewObjectContact(a)); + assert(pVOC && "ObjectContact: ViewObjectContact list Corrupt (!)"); + pVOC->resetGridOffset(); + } +} + }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sdr/contact/objectcontactofpageview.cxx b/svx/source/sdr/contact/objectcontactofpageview.cxx index 6a2247bcd6c2..0c6ecf0abc3a 100644 --- a/svx/source/sdr/contact/objectcontactofpageview.cxx +++ b/svx/source/sdr/contact/objectcontactofpageview.cxx @@ -19,7 +19,7 @@ #include <config_features.h> -#include <sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/contact/objectcontactofpageview.hxx> #include <sdr/contact/viewobjectcontactofunocontrol.hxx> #include <svx/svdpagv.hxx> #include <svx/svdpage.hxx> diff --git a/svx/source/sdr/contact/viewcontact.cxx b/svx/source/sdr/contact/viewcontact.cxx index 0567ff65c473..178c50f22bc1 100644 --- a/svx/source/sdr/contact/viewcontact.cxx +++ b/svx/source/sdr/contact/viewcontact.cxx @@ -25,7 +25,7 @@ #include <basegfx/color/bcolor.hxx> #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> -#include <sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/contact/objectcontactofpageview.hxx> #include <tools/debug.hxx> namespace sdr { namespace contact { diff --git a/svx/source/sdr/contact/viewcontactofe3dscene.cxx b/svx/source/sdr/contact/viewcontactofe3dscene.cxx index 591db03619fb..86ca5f0ed09c 100644 --- a/svx/source/sdr/contact/viewcontactofe3dscene.cxx +++ b/svx/source/sdr/contact/viewcontactofe3dscene.cxx @@ -244,11 +244,8 @@ void ViewContactOfE3dScene::createViewInformation3D(const basegfx::B3DRange& rCo void ViewContactOfE3dScene::createObjectTransformation() { // create 2d Object Transformation from relative point in 2d scene to world - tools::Rectangle aRectangle = GetE3dScene().GetSnapRect(); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - aRectangle += GetE3dScene().GetGridOffset(); + const tools::Rectangle aRectangle(GetE3dScene().GetSnapRect()); + maObjectTransformation.set(0, 0, aRectangle.getWidth()); maObjectTransformation.set(1, 1, aRectangle.getHeight()); maObjectTransformation.set(0, 2, aRectangle.Left()); diff --git a/svx/source/sdr/contact/viewcontactofgraphic.cxx b/svx/source/sdr/contact/viewcontactofgraphic.cxx index 15de4be75752..2892b3e63eff 100644 --- a/svx/source/sdr/contact/viewcontactofgraphic.cxx +++ b/svx/source/sdr/contact/viewcontactofgraphic.cxx @@ -310,14 +310,10 @@ namespace sdr // take unrotated snap rect for position and size. Directly use model data, not getBoundRect() or getSnapRect() // which will use the primitive data we just create in the near future - tools::Rectangle rRectangle = GetGrafObject().GetGeoRect(); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - rRectangle += GetGrafObject().GetGridOffset(); + const tools::Rectangle aRectangle(GetGrafObject().GetGeoRect()); const ::basegfx::B2DRange aObjectRange( - rRectangle.Left(), rRectangle.Top(), - rRectangle.Right(), rRectangle.Bottom()); + aRectangle.Left(), aRectangle.Top(), + aRectangle.Right(), aRectangle.Bottom()); // look for mirroring const GeoStat& rGeoStat(GetGrafObject().GetGeoStat()); diff --git a/svx/source/sdr/contact/viewcontactofgroup.cxx b/svx/source/sdr/contact/viewcontactofgroup.cxx index d6a0e98dfcfe..38afca26ff65 100644 --- a/svx/source/sdr/contact/viewcontactofgroup.cxx +++ b/svx/source/sdr/contact/viewcontactofgroup.cxx @@ -71,11 +71,7 @@ namespace sdr else { // append an invisible outline for the cases where no visible content exists - tools::Rectangle aCurrentBoundRect(GetSdrObjGroup().GetLastBoundRect()); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - aCurrentBoundRect += GetSdrObjGroup().GetGridOffset(); + const tools::Rectangle aCurrentBoundRect(GetSdrObjGroup().GetLastBoundRect()); const basegfx::B2DRange aCurrentRange( aCurrentBoundRect.Left(), aCurrentBoundRect.Top(), aCurrentBoundRect.Right(), aCurrentBoundRect.Bottom()); diff --git a/svx/source/sdr/contact/viewcontactofsdrcaptionobj.cxx b/svx/source/sdr/contact/viewcontactofsdrcaptionobj.cxx index 7fc5effd6cf3..8fe42c1fa6de 100644 --- a/svx/source/sdr/contact/viewcontactofsdrcaptionobj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrcaptionobj.cxx @@ -63,16 +63,10 @@ namespace sdr false)); // take unrotated snap rect (direct model data) for position and size - tools::Rectangle rRectangle = rCaptionObj.GetGeoRect(); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - Point aGridOff = rCaptionObj.GetGridOffset(); - rRectangle += aGridOff; - + const tools::Rectangle aRectangle(rCaptionObj.GetGeoRect()); const ::basegfx::B2DRange aObjectRange( - rRectangle.Left(), rRectangle.Top(), - rRectangle.Right(), rRectangle.Bottom()); + aRectangle.Left(), aRectangle.Top(), + aRectangle.Right(), aRectangle.Bottom()); const GeoStat& rGeoStat(rCaptionObj.GetGeoStat()); // fill object matrix @@ -87,11 +81,8 @@ namespace sdr double fCornerRadiusY; drawinglayer::primitive2d::calculateRelativeCornerRadius( rCaptionObj.GetEckenradius(), aObjectRange, fCornerRadiusX, fCornerRadiusY); - ::basegfx::B2DPolygon aTail = rCaptionObj.getTailPolygon(); - // Hack for calc, transform position of tail according - // to current zoom so as objects relative position to grid - // appears stable - aTail.transform( basegfx::utils::createTranslateB2DHomMatrix( aGridOff.X(), aGridOff.Y() ) ); + const basegfx::B2DPolygon aTail(rCaptionObj.getTailPolygon()); + // create primitive. Always create one (even if invisible) to let the decomposition // of SdrCaptionPrimitive2D create needed invisible elements for HitTest and BoundRect const drawinglayer::primitive2d::Primitive2DReference xReference( diff --git a/svx/source/sdr/contact/viewcontactofsdrcircobj.cxx b/svx/source/sdr/contact/viewcontactofsdrcircobj.cxx index 7104edcb227c..8d796643386d 100644 --- a/svx/source/sdr/contact/viewcontactofsdrcircobj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrcircobj.cxx @@ -50,11 +50,7 @@ namespace sdr false)); // take unrotated snap rect (direct model data) for position and size - tools::Rectangle aRectangle = GetCircObj().GetGeoRect(); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - aRectangle += GetRectObj().GetGridOffset(); + const tools::Rectangle aRectangle(GetCircObj().GetGeoRect()); const basegfx::B2DRange aObjectRange( aRectangle.Left(), aRectangle.Top(), aRectangle.Right(), aRectangle.Bottom() ); diff --git a/svx/source/sdr/contact/viewcontactofsdredgeobj.cxx b/svx/source/sdr/contact/viewcontactofsdredgeobj.cxx index c22d14e18fa0..37eb5267cd5f 100644 --- a/svx/source/sdr/contact/viewcontactofsdredgeobj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdredgeobj.cxx @@ -40,12 +40,7 @@ namespace sdr drawinglayer::primitive2d::Primitive2DContainer ViewContactOfSdrEdgeObj::createViewIndependentPrimitive2DSequence() const { - basegfx::B2DPolygon aEdgeTrack = GetEdgeObj().getEdgeTrack(); - Point aGridOff = GetEdgeObj().GetGridOffset(); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - aEdgeTrack.transform( basegfx::utils::createTranslateB2DHomMatrix( aGridOff.X(), aGridOff.Y() ) ); + const basegfx::B2DPolygon aEdgeTrack(GetEdgeObj().getEdgeTrack()); // what to do when no EdgeTrack is provided (HitTest and selectability) ? OSL_ENSURE(0 != aEdgeTrack.count(), "Connectors with no geometry are not allowed (!)"); diff --git a/svx/source/sdr/contact/viewcontactofsdrmediaobj.cxx b/svx/source/sdr/contact/viewcontactofsdrmediaobj.cxx index 90403799d53a..bda8a934109f 100644 --- a/svx/source/sdr/contact/viewcontactofsdrmediaobj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrmediaobj.cxx @@ -100,11 +100,7 @@ drawinglayer::primitive2d::Primitive2DContainer ViewContactOfSdrMediaObj::create { // create range using the model data directly. This is in SdrTextObj::aRect which i will access using // GetGeoRect() to not trigger any calculations. It's the unrotated geometry which is okay for MediaObjects ATM. - tools::Rectangle aRectangle(GetSdrMediaObj().GetGeoRect()); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - aRectangle += GetSdrMediaObj().GetGridOffset(); + const tools::Rectangle aRectangle(GetSdrMediaObj().GetGeoRect()); const basegfx::B2DRange aRange( aRectangle.Left(), aRectangle.Top(), aRectangle.Right(), aRectangle.Bottom()); diff --git a/svx/source/sdr/contact/viewcontactofsdrobj.cxx b/svx/source/sdr/contact/viewcontactofsdrobj.cxx index d042186c4d73..ca8abd63a8b4 100644 --- a/svx/source/sdr/contact/viewcontactofsdrobj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrobj.cxx @@ -29,7 +29,7 @@ #include <basegfx/color/bcolor.hxx> #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx> #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx> -#include <sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/contact/objectcontactofpageview.hxx> #include <svx/sdrpagewindow.hxx> #include <svx/sdrpaintwindow.hxx> #include <svx/svdhdl.hxx> diff --git a/svx/source/sdr/contact/viewcontactofsdrobjcustomshape.cxx b/svx/source/sdr/contact/viewcontactofsdrobjcustomshape.cxx index c3f8666ad1d9..5c4bb784c515 100644 --- a/svx/source/sdr/contact/viewcontactofsdrobjcustomshape.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrobjcustomshape.cxx @@ -45,13 +45,13 @@ namespace sdr basegfx::B2DRange ViewContactOfSdrObjCustomShape::getCorrectedTextBoundRect() const { - tools::Rectangle aObjectBound(GetCustomShapeObj().GetGeoRect()); - aObjectBound += GetCustomShapeObj().GetGridOffset(); + const tools::Rectangle aObjectBound(GetCustomShapeObj().GetGeoRect()); tools::Rectangle aTextBound(aObjectBound); GetCustomShapeObj().GetTextBounds(aTextBound); - aTextBound += GetCustomShapeObj().GetGridOffset(); basegfx::B2DRange aTextRange(aTextBound.Left(), aTextBound.Top(), aTextBound.Right(), aTextBound.Bottom()); - const basegfx::B2DRange aObjectRange(aObjectBound.Left(), aObjectBound.Top(), aObjectBound.Right(), aObjectBound.Bottom()); + const basegfx::B2DRange aObjectRange( + aObjectBound.Left(), aObjectBound.Top(), + aObjectBound.Right(), aObjectBound.Bottom()); // no need to correct if no extra text range if(aTextRange != aObjectRange) @@ -118,18 +118,8 @@ namespace sdr const SdrObject* pSdrObjRepresentation = GetCustomShapeObj().GetSdrObjectFromCustomShape(); bool b3DShape(false); - Point aGridOff = GetCustomShapeObj().GetGridOffset(); - if(pSdrObjRepresentation) { - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - // TTTT: Need to check what *exactly* this is doing - in it's current - // form it's indeed pretty much a 'hack' as mentioned above and massively - // in the way for future changes... - const_cast< SdrObject* >( pSdrObjRepresentation )->SetGridOffset( aGridOff ); - // tdf#118498 The processing of SdrObjListIter for SdrIterMode::DeepNoGroups // did change for 3D-Objects, it now correctly enters and iterates the // SdrObjects in the E3dScene (same as for SdrObjGroup). This is more correct @@ -160,10 +150,10 @@ namespace sdr { // take unrotated snap rect as default, then get the // unrotated text box. Rotation needs to be done centered - tools::Rectangle aObjectBound(GetCustomShapeObj().GetGeoRect()); - // hack for calc grid sync - aObjectBound += GetCustomShapeObj().GetGridOffset(); - const basegfx::B2DRange aObjectRange(aObjectBound.Left(), aObjectBound.Top(), aObjectBound.Right(), aObjectBound.Bottom()); + const tools::Rectangle aObjectBound(GetCustomShapeObj().GetGeoRect()); + const basegfx::B2DRange aObjectRange( + aObjectBound.Left(), aObjectBound.Top(), + aObjectBound.Right(), aObjectBound.Bottom()); // #i101684# get the text range unrotated and absolute to the object range const basegfx::B2DRange aTextRange(getCorrectedTextBoundRect()); diff --git a/svx/source/sdr/contact/viewcontactofsdrole2obj.cxx b/svx/source/sdr/contact/viewcontactofsdrole2obj.cxx index 9a538162779f..6a13aaef8682 100644 --- a/svx/source/sdr/contact/viewcontactofsdrole2obj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrole2obj.cxx @@ -60,12 +60,10 @@ ViewContactOfSdrOle2Obj::~ViewContactOfSdrOle2Obj() basegfx::B2DHomMatrix ViewContactOfSdrOle2Obj::createObjectTransform() const { // take unrotated snap rect (direct model data) for position and size - tools::Rectangle rRectangle = GetOle2Obj().GetGeoRect(); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - rRectangle += GetOle2Obj().GetGridOffset(); - const basegfx::B2DRange aObjectRange(rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom()); + const tools::Rectangle aRectangle(GetOle2Obj().GetGeoRect()); + const basegfx::B2DRange aObjectRange( + aRectangle.Left(), aRectangle.Top(), + aRectangle.Right(), aRectangle.Bottom()); // create object matrix const GeoStat& rGeoStat(GetOle2Obj().GetGeoStat()); @@ -100,17 +98,12 @@ drawinglayer::primitive2d::Primitive2DContainer ViewContactOfSdrOle2Obj::createP // #i123539# allow buffering and reuse of local chart data to not need to rebuild it // on every ViewObjectContact::getPrimitive2DSequence call. TTTT: Not needed for // aw080, there this mechanism already works differently - if(mxChartContent.is() - // check if we need to update the transformation primitive wrapping the chart - && maGridOffset == GetOle2Obj().GetGridOffset()) + if(mxChartContent.is()) { xContent = mxChartContent; } else { - // update grid offset - const_cast< ViewContactOfSdrOle2Obj* >(this)->maGridOffset = GetOle2Obj().GetGridOffset(); - // try to get chart primitives and chart range directly from xChartModel basegfx::B2DRange aChartContentRange; const drawinglayer::primitive2d::Primitive2DContainer aChartSequence( diff --git a/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx b/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx index 9005b67a3fb4..28942f7b04de 100644 --- a/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx @@ -74,11 +74,6 @@ namespace sdr GetPathObj().getText(0), false)); basegfx::B2DPolyPolygon aUnitPolyPolygon(GetPathObj().GetPathPoly()); - Point aGridOff = GetPathObj().GetGridOffset(); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - aUnitPolyPolygon.transform( basegfx::utils::createTranslateB2DHomMatrix( aGridOff.X(), aGridOff.Y() ) ); sal_uInt32 nPolyCount(ensureGeometry(aUnitPolyPolygon)); // prepare object transformation and unit polygon (direct model data) diff --git a/svx/source/sdr/contact/viewcontactofsdrrectobj.cxx b/svx/source/sdr/contact/viewcontactofsdrrectobj.cxx index f02ba917280c..34734f96e1cd 100644 --- a/svx/source/sdr/contact/viewcontactofsdrrectobj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrrectobj.cxx @@ -47,14 +47,10 @@ drawinglayer::primitive2d::Primitive2DContainer ViewContactOfSdrRectObj::createV false)); // take unrotated snap rect (direct model data) for position and size - tools::Rectangle rRectangle = GetRectObj().GetGeoRect(); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - rRectangle += GetRectObj().GetGridOffset(); + const tools::Rectangle aRectangle(GetRectObj().GetGeoRect()); const ::basegfx::B2DRange aObjectRange( - rRectangle.Left(), rRectangle.Top(), - rRectangle.Right(), rRectangle.Bottom() ); + aRectangle.Left(), aRectangle.Top(), + aRectangle.Right(), aRectangle.Bottom() ); const GeoStat& rGeoStat(GetRectObj().GetGeoStat()); diff --git a/svx/source/sdr/contact/viewcontactofunocontrol.cxx b/svx/source/sdr/contact/viewcontactofunocontrol.cxx index 547e2ebc5339..78bdce4d6c2e 100644 --- a/svx/source/sdr/contact/viewcontactofunocontrol.cxx +++ b/svx/source/sdr/contact/viewcontactofunocontrol.cxx @@ -21,7 +21,7 @@ #include <sdr/contact/viewcontactofunocontrol.hxx> #include <sdr/contact/viewobjectcontactofunocontrol.hxx> -#include <sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/contact/objectcontactofpageview.hxx> #include <svx/sdr/contact/displayinfo.hxx> #include <svx/svdouno.hxx> #include <svx/svdpagv.hxx> @@ -94,12 +94,7 @@ namespace sdr { namespace contact { // create range. Use model data directly, not getBoundRect()/getSnapRect; these will use // the primitive data themselves in the long run. Use SdrUnoObj's (which is a SdrRectObj) // call to GetGeoRect() to access SdrTextObj::aRect directly and without executing anything - tools::Rectangle aRectangle(GetSdrUnoObj().GetGeoRect()); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - Point aGridOffset = GetSdrUnoObj().GetGridOffset(); - aRectangle += aGridOffset; + const tools::Rectangle aRectangle(GetSdrUnoObj().GetGeoRect()); const basegfx::B2DRange aRange( aRectangle.Left(), aRectangle.Top(), aRectangle.Right(), aRectangle.Bottom()); diff --git a/svx/source/sdr/contact/viewobjectcontact.cxx b/svx/source/sdr/contact/viewobjectcontact.cxx index e300703bfd74..197113cda630 100644 --- a/svx/source/sdr/contact/viewobjectcontact.cxx +++ b/svx/source/sdr/contact/viewobjectcontact.cxx @@ -36,8 +36,8 @@ #include <drawinglayer/processor2d/baseprocessor2d.hxx> #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx> #include <svx/svdoole2.hxx> - #include <sdr/contact/viewcontactofsdrole2obj.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> using namespace com::sun::star; @@ -159,6 +159,7 @@ ViewObjectContact::ViewObjectContact(ObjectContact& rObjectContact, ViewContact& mrViewContact(rViewContact), maObjectRange(), mxPrimitive2DSequence(), + maGridOffset(0.0, 0.0), mbLazyInvalidate(false) { // make the ViewContact remember me @@ -363,8 +364,36 @@ drawinglayer::primitive2d::Primitive2DContainer const & ViewObjectContact::getPr // always update object range when PrimitiveSequence changes const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D()); - const_cast< ViewObjectContact* >(this)->maObjectRange = - mxPrimitive2DSequence.getB2DRange(rViewInformation2D); + const_cast< ViewObjectContact* >(this)->maObjectRange = mxPrimitive2DSequence.getB2DRange(rViewInformation2D); + + // check and eventually embed to GridOffset transform primitive + if(GetObjectContact().supportsGridOffsets()) + { + const basegfx::B2DVector& rGridOffset(getGridOffset()); + + if(0.0 != rGridOffset.getX() || 0.0 != rGridOffset.getY()) + { + const basegfx::B2DHomMatrix aTranslateGridOffset( + basegfx::utils::createTranslateB2DHomMatrix( + rGridOffset)); + const drawinglayer::primitive2d::Primitive2DReference aEmbed( + new drawinglayer::primitive2d::TransformPrimitive2D( + aTranslateGridOffset, + mxPrimitive2DSequence)); + + // Set values at local data. So for now, the mechanism is to reset some of the + // defining things (mxPrimitive2DSequence, maGridOffset) and re-create the + // buffered data (including maObjectRange). It *could* be changed to keep + // the unmodified PrimitiveSequence and only update the GridOffset, but this + // would require a 2nd instance of maObjectRange and mxPrimitive2DSequence. I + // started doing so, but it just makes the code more complicated. For now, + // just allow re-creation of the PrimitiveSequence (and removing buffered + // decomposed content of it). May be optimized, though. OTOH it only happens + // in calc which traditionally does not have a huge amout of DrawObjects anyways. + const_cast< ViewObjectContact* >(this)->mxPrimitive2DSequence = drawinglayer::primitive2d::Primitive2DContainer { aEmbed }; + const_cast< ViewObjectContact* >(this)->maObjectRange.transform(aTranslateGridOffset); + } + } } // return current Primitive2DContainer @@ -427,6 +456,30 @@ drawinglayer::primitive2d::Primitive2DContainer ViewObjectContact::getPrimitive2 return xSeqRetval; } +// Support getting a GridOffset per object and view for non-linear ViewToDevice +// transformation (calc). On-demand created by delegating to the ObjectContact +// (->View) that has then all needed information +const basegfx::B2DVector& ViewObjectContact::getGridOffset() const +{ + if(0.0 == maGridOffset.getX() && 0.0 == maGridOffset.getY() && GetObjectContact().supportsGridOffsets()) + { + // create on-demand + GetObjectContact().calculateGridOffsetForViewOjectContact(const_cast<ViewObjectContact*>(this)->maGridOffset, *this); + } + + return maGridOffset; +} + +void ViewObjectContact::resetGridOffset() +{ + // reset buffered GridOffset itself + maGridOffset.setX(0.0); + maGridOffset.setY(0.0); + + // also reset sequence to get a re-calculation when GridOffset changes + mxPrimitive2DSequence.clear(); +} + }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sdr/contact/viewobjectcontactofsdrobj.cxx b/svx/source/sdr/contact/viewobjectcontactofsdrobj.cxx index f0c545e7151b..c6183a2007ba 100644 --- a/svx/source/sdr/contact/viewobjectcontactofsdrobj.cxx +++ b/svx/source/sdr/contact/viewobjectcontactofsdrobj.cxx @@ -22,7 +22,7 @@ #include <svx/sdr/contact/viewcontactofsdrobj.hxx> #include <svx/sdr/contact/objectcontact.hxx> #include <svx/sdr/contact/displayinfo.hxx> -#include <sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/contact/objectcontactofpageview.hxx> #include <sdr/contact/viewcontactofsdrole2obj.hxx> #include <svx/sdrpagewindow.hxx> #include <svx/sdrpaintwindow.hxx> diff --git a/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx b/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx index c785a6cdad13..50dcbd25e71e 100644 --- a/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx +++ b/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx @@ -22,7 +22,7 @@ #include <sdr/contact/viewcontactofunocontrol.hxx> #include <svx/sdr/contact/displayinfo.hxx> #include <svx/sdr/properties/properties.hxx> -#include <sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/contact/objectcontactofpageview.hxx> #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx> #include <svx/svdouno.hxx> #include <svx/svdpagv.hxx> @@ -918,12 +918,7 @@ namespace sdr { namespace contact { SdrUnoObj* pUnoObject( nullptr ); if ( getUnoObject( pUnoObject ) ) { - Point aGridOffset = pUnoObject->GetGridOffset(); - tools::Rectangle aRect( pUnoObject->GetLogicRect() ); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - aRect += aGridOffset; + const tools::Rectangle aRect( pUnoObject->GetLogicRect() ); UnoControlContactHelper::adjustControlGeometry_throw( m_aControl, aRect, _rViewTransformation, m_aZoomLevelNormalization ); } else @@ -1086,12 +1081,7 @@ namespace sdr { namespace contact { // knit the model and the control _out_rControl.setModel( xControlModel ); - Point aGridOffset = _rUnoObject.GetGridOffset(); - tools::Rectangle aRect( _rUnoObject.GetLogicRect() ); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - aRect += aGridOffset; + const tools::Rectangle aRect( _rUnoObject.GetLogicRect() ); // proper geometry UnoControlContactHelper::adjustControlGeometry_throw( @@ -1488,12 +1478,7 @@ namespace sdr { namespace contact { // Do use model data directly to create the correct geometry. Do NOT // use getBoundRect()/getSnapRect() here; these will use the sequence of // primitives themselves in the long run. - tools::Rectangle aSdrGeoData( _rVOC.GetSdrUnoObj().GetGeoRect() ); - Point aGridOffset = _rVOC.GetSdrUnoObj().GetGridOffset(); - // Hack for calc, transform position of object according - // to current zoom so as objects relative position to grid - // appears stable - aSdrGeoData += aGridOffset; + const tools::Rectangle aSdrGeoData( _rVOC.GetSdrUnoObj().GetGeoRect() ); const basegfx::B2DRange aRange( aSdrGeoData.Left(), aSdrGeoData.Top(), diff --git a/svx/source/sdr/overlay/overlayobject.cxx b/svx/source/sdr/overlay/overlayobject.cxx index aae05f9f0b96..d480007d4852 100644 --- a/svx/source/sdr/overlay/overlayobject.cxx +++ b/svx/source/sdr/overlay/overlayobject.cxx @@ -26,8 +26,9 @@ #include <basegfx/polygon/b2dpolypolygon.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> #include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> - +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> namespace sdr { @@ -37,7 +38,8 @@ namespace sdr { const basegfx::B2DRange aPreviousRange(maBaseRange); maBaseRange.reset(); - setPrimitive2DSequence(drawinglayer::primitive2d::Primitive2DContainer()); + resetPrimitive2DSequence(); +// setPrimitive2DSequence(drawinglayer::primitive2d::Primitive2DContainer()); if(getOverlayManager() && !aPreviousRange.isEmpty()) { @@ -91,6 +93,8 @@ namespace sdr OverlayObject::OverlayObject(Color aBaseColor) : Event(), mpOverlayManager(nullptr), + maPrimitive2DSequence(), + maOffset(0.0, 0.0), maBaseColor(aBaseColor), mbIsVisible(true), mbIsHittable(true), @@ -109,8 +113,21 @@ namespace sdr if(getPrimitive2DSequence().empty()) { // no existing sequence; create one - const_cast< OverlayObject* >(this)->setPrimitive2DSequence( - const_cast< OverlayObject* >(this)->createOverlayObjectPrimitive2DSequence()); + const_cast< OverlayObject* >(this)->maPrimitive2DSequence = const_cast< OverlayObject* >(this)->createOverlayObjectPrimitive2DSequence(); + + if(!getOffset().equalZero()) + { + // embed to offset transformation + const basegfx::B2DHomMatrix aTranslateGridOffset( + basegfx::utils::createTranslateB2DHomMatrix( + getOffset())); + const drawinglayer::primitive2d::Primitive2DReference aEmbed( + new drawinglayer::primitive2d::TransformPrimitive2D( + aTranslateGridOffset, + maPrimitive2DSequence)); + + const_cast< OverlayObject* >(this)->maPrimitive2DSequence = drawinglayer::primitive2d::Primitive2DContainer { aEmbed }; + } } return getPrimitive2DSequence(); @@ -170,6 +187,18 @@ namespace sdr } } + void OverlayObject::setOffset(const basegfx::B2DVector& rOffset) + { + if(rOffset != maOffset) + { + // remember new value + maOffset = rOffset; + + // register change (after change) + objectChange(); + } + } + void OverlayObject::Trigger(sal_uInt32 /*nTime*/) { // default does not register again diff --git a/svx/source/sdr/overlay/overlayselection.cxx b/svx/source/sdr/overlay/overlayselection.cxx index 5d22203a4e4e..a1fa52810eb2 100644 --- a/svx/source/sdr/overlay/overlayselection.cxx +++ b/svx/source/sdr/overlay/overlayselection.cxx @@ -196,7 +196,7 @@ namespace sdr || nNewTransparence != mnLastTransparence) { // conditions of last local decomposition have changed, delete - const_cast< OverlaySelection* >(this)->setPrimitive2DSequence(drawinglayer::primitive2d::Primitive2DContainer()); + const_cast< OverlaySelection* >(this)->resetPrimitive2DSequence(); } } diff --git a/svx/source/svdraw/sdrpagewindow.cxx b/svx/source/svdraw/sdrpagewindow.cxx index c722fa883e49..80369f6dbd66 100644 --- a/svx/source/svdraw/sdrpagewindow.cxx +++ b/svx/source/svdraw/sdrpagewindow.cxx @@ -32,7 +32,7 @@ #include <svx/svdview.hxx> #include <svx/svdpagv.hxx> #include <svx/sdrpaintwindow.hxx> -#include <sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/contact/objectcontactofpageview.hxx> #include <svx/sdr/contact/displayinfo.hxx> #include <svx/fmview.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> @@ -43,7 +43,7 @@ using namespace ::com::sun::star; struct SdrPageWindow::Impl { // #110094# ObjectContact section - mutable sdr::contact::ObjectContactOfPageView* mpObjectContact; + mutable sdr::contact::ObjectContact* mpObjectContact; // the SdrPageView this window belongs to SdrPageView& mrPageView; @@ -456,8 +456,11 @@ void SdrPageWindow::InvalidatePageWindow(const basegfx::B2DRange& rRange) const sdr::contact::ObjectContact& SdrPageWindow::GetObjectContact() const { if (!mpImpl->mpObjectContact) - mpImpl->mpObjectContact = new sdr::contact::ObjectContactOfPageView( - const_cast<SdrPageWindow&>(*this), "svx::svdraw::SdrPageWindow mpObjectContact" ); + { + mpImpl->mpObjectContact = GetPageView().GetView().createViewSpecificObjectContact( + const_cast<SdrPageWindow&>(*this), + "svx::svdraw::SdrPageWindow mpObjectContact"); + } return *mpImpl->mpObjectContact; } @@ -465,8 +468,11 @@ const sdr::contact::ObjectContact& SdrPageWindow::GetObjectContact() const sdr::contact::ObjectContact& SdrPageWindow::GetObjectContact() { if (!mpImpl->mpObjectContact) - mpImpl->mpObjectContact = new sdr::contact::ObjectContactOfPageView( - *this, "svx::svdraw::SdrPageWindow mpObjectContact" ); + { + mpImpl->mpObjectContact = GetPageView().GetView().createViewSpecificObjectContact( + *this, + "svx::svdraw::SdrPageWindow mpObjectContact" ); + } return *mpImpl->mpObjectContact; } diff --git a/svx/source/svdraw/svdcrtv.cxx b/svx/source/svdraw/svdcrtv.cxx index 5578cb193198..911481038d79 100644 --- a/svx/source/svdraw/svdcrtv.cxx +++ b/svx/source/svdraw/svdcrtv.cxx @@ -641,6 +641,31 @@ bool SdrCreateView::EndCreateObj(SdrCreateCmd eCmd) if(!bSceneIntoScene) { + // Here an interactively created SdrObject gets added, so + // take into account that interaction created an object in + // model coordinates. If we have e.g. a GirdOffset, this is a + // little bit tricky - we have an object in model coordinates, + // so the fetched offset is at the wrong point in principle + // since we need to 'substract' the offset here to get to + // 'real' model coordinates. But we have nothing better here, + // so go for it. + // The 2nd a little tricky thing is that this will early-create + // a ViewObjectContact for the new SdrObject, but these VOCs + // are anyways layouted for being create-on-demand. This will + // be adapted/replaced corretly later on. + // This *should* be the right place for getting all interactively + // created objects, see InsertObjectAtView below that calls + // CreateUndoNewObject. + basegfx::B2DVector aGridOffset(0.0, 0.0); + if(getPossibleGridOffsetForSdrObject(aGridOffset, pObj, pCreatePV)) + { + const Size aOffset( + basegfx::fround(-aGridOffset.getX()), + basegfx::fround(-aGridOffset.getY())); + + pObj->NbcMove(aOffset); + } + // do the same as before InsertObjectAtView(pObj, *pCreatePV); } @@ -802,12 +827,8 @@ void SdrCreateView::ShowCreateObj(/*OutputDevice* pOut, sal_Bool bFull*/) } else { - ::basegfx::B2DPolyPolygon aPoly = pCurrentCreate->TakeCreatePoly(maDragStat); - Point aGridOff = pCurrentCreate->GetGridOffset(); - // Hack for calc, transform position of create placeholder - // object according to current zoom so as objects relative - // position to grid appears stable - aPoly.transform( basegfx::utils::createTranslateB2DHomMatrix( aGridOff.X(), aGridOff.Y() ) ); + const ::basegfx::B2DPolyPolygon aPoly(pCurrentCreate->TakeCreatePoly(maDragStat)); + mpCreateViewExtraData->CreateAndShowOverlay(*this, nullptr, aPoly); } diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx index 2c89ca4aabcb..13ee857e655f 100644 --- a/svx/source/svdraw/svddrgmt.cxx +++ b/svx/source/svdraw/svddrgmt.cxx @@ -135,11 +135,12 @@ drawinglayer::primitive2d::Primitive2DContainer SdrDragEntryPolyPolygon::createP } -SdrDragEntrySdrObject::SdrDragEntrySdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool bModify) +SdrDragEntrySdrObject::SdrDragEntrySdrObject( + const SdrObject& rOriginal, + bool bModify) : SdrDragEntry(), maOriginal(rOriginal), mpClone(nullptr), - mrObjectContact(rObjectContact), mbModify(bModify) { // add SdrObject parts to transparent overlay stuff @@ -185,16 +186,9 @@ drawinglayer::primitive2d::Primitive2DContainer SdrDragEntrySdrObject::createPri pSource = mpClone; } - // get VOC and Primitive2DContainer - sdr::contact::ViewContact& rVC = pSource->GetViewContact(); - sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(mrObjectContact); - sdr::contact::DisplayInfo aDisplayInfo; - - // Do not use the last ViewPort set at the OC from the last ProcessDisplay(), - // here we want the complete primitive sequence without visibility clippings - mrObjectContact.resetViewPort(); - - return rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo); + // use the view-independent primitive representation (without + // evtl. GridOffset, that may be applied to the DragEntry individually) + return pSource->GetViewContact().getViewIndependentPrimitive2DContainer(); } @@ -338,11 +332,46 @@ void SdrDragMethod::createSdrDragEntries() } } -void SdrDragMethod::createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact) +void SdrDragMethod::createSdrDragEntryForSdrObject(const SdrObject& rOriginal) { // add full object drag; Clone() at the object has to work // for this - addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntrySdrObject(rOriginal, rObjectContact, true/*bModify*/))); + addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntrySdrObject(rOriginal, true/*bModify*/))); +} + +void SdrDragMethod::insertNewlyCreatedOverlayObjectForSdrDragMethod( + std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject, + const sdr::contact::ObjectContact& rObjectContact, + sdr::overlay::OverlayManager& rOverlayManager) +{ + // check if we have an OverlayObject + if(!pOverlayObject) + { + return; + } + + // add to OverlayManager + rOverlayManager.add(*pOverlayObject); + + // Add GridOffset for non-linear ViewToDevice transformation (calc) + if(rObjectContact.supportsGridOffsets()) + { + const basegfx::B2DRange& rNewRange(pOverlayObject->getBaseRange()); + + if(!rNewRange.isEmpty()) + { + basegfx::B2DVector aOffset(0.0, 0.0); + rObjectContact.calculateGridOffsetForB2DRange(aOffset, rNewRange); + + if(!aOffset.equalZero()) + { + pOverlayObject->setOffset(aOffset); + } + } + } + + // add to local OverlayObjectList - ownership change (!) + maOverlayObjectList.append(std::move(pOverlayObject)); } void SdrDragMethod::createSdrDragEntries_SolidDrag() @@ -364,7 +393,6 @@ void SdrDragMethod::createSdrDragEntries_SolidDrag() { if(pPV->PageWindowCount()) { - sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact(); SdrObjListIter aIter(*pObject); while(aIter.IsMore()) @@ -386,7 +414,7 @@ void SdrDragMethod::createSdrDragEntries_SolidDrag() { // add full object drag; Clone() at the object has to work // for this - createSdrDragEntryForSdrObject(*pCandidate, rOC); + createSdrDragEntryForSdrObject(*pCandidate); } if(bAddWireframe) @@ -654,7 +682,9 @@ void SdrDragMethod::CancelSdrDrag() typedef std::map< const SdrObject*, SdrObject* > SdrObjectAndCloneMap; -void SdrDragMethod::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager) +void SdrDragMethod::CreateOverlayGeometry( + sdr::overlay::OverlayManager& rOverlayManager, + const sdr::contact::ObjectContact& rObjectContact) { // create SdrDragEntries on demand if(maSdrDragEntries.empty()) @@ -764,9 +794,14 @@ void SdrDragMethod::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlay if(!aResult.empty()) { - std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new sdr::overlay::OverlayPrimitive2DSequenceObject(aResult)); - rOverlayManager.add(*pNewOverlayObject); - addToOverlayObjectList(std::move(pNewOverlayObject)); + std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject( + new sdr::overlay::OverlayPrimitive2DSequenceObject( + aResult)); + + insertNewlyCreatedOverlayObjectForSdrDragMethod( + std::move(pNewOverlayObject), + rObjectContact, + rOverlayManager); } if(!aResultTransparent.empty()) @@ -774,9 +809,14 @@ void SdrDragMethod::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlay drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aResultTransparent, 0.5)); aResultTransparent = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparencePrimitive2D }; - std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new sdr::overlay::OverlayPrimitive2DSequenceObject(aResultTransparent)); - rOverlayManager.add(*pNewOverlayObject); - addToOverlayObjectList(std::move(pNewOverlayObject)); + std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject( + new sdr::overlay::OverlayPrimitive2DSequenceObject( + aResultTransparent)); + + insertNewlyCreatedOverlayObjectForSdrDragMethod( + std::move(pNewOverlayObject), + rObjectContact, + rOverlayManager); } } @@ -788,11 +828,17 @@ void SdrDragMethod::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlay const basegfx::B2DPoint aTopLeft(aActionRectangle.Left(), aActionRectangle.Top()); const basegfx::B2DPoint aBottomRight(aActionRectangle.Right(), aActionRectangle.Bottom()); - std::unique_ptr<sdr::overlay::OverlayRollingRectangleStriped> pNew(new sdr::overlay::OverlayRollingRectangleStriped( - aTopLeft, aBottomRight, true, false)); + std::unique_ptr<sdr::overlay::OverlayRollingRectangleStriped> pNew( + new sdr::overlay::OverlayRollingRectangleStriped( + aTopLeft, + aBottomRight, + true, + false)); - rOverlayManager.add(*pNew); - addToOverlayObjectList(std::move(pNew)); + insertNewlyCreatedOverlayObjectForSdrDragMethod( + std::move(pNew), + rObjectContact, + rOverlayManager); } } @@ -1159,8 +1205,7 @@ void SdrDragObjOwn::createSdrDragEntries() if(pPV && pPV->PageWindowCount()) { - sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact(); - addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntrySdrObject(*mpClone, rOC, false))); + addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntrySdrObject(*mpClone, false))); // potentially no wireframe needed, full drag works bAddWireframe = false; @@ -1417,19 +1462,15 @@ Pointer SdrDragObjOwn::GetSdrDragPointer() const } -void SdrDragMove::createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact) +void SdrDragMove::createSdrDragEntryForSdrObject(const SdrObject& rOriginal) { - // for SdrDragMove, use current Primitive2DContainer of SdrObject visualization - // in given ObjectContact directly - sdr::contact::ViewContact& rVC = rOriginal.GetViewContact(); - sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rObjectContact); - sdr::contact::DisplayInfo aDisplayInfo; + // use the view-independent primitive representation (without + // evtl. GridOffset, that may be applied to the DragEntry individually) + addSdrDragEntry( + std::unique_ptr<SdrDragEntry>( + new SdrDragEntryPrimitive2DSequence( + rOriginal.GetViewContact().getViewIndependentPrimitive2DContainer()))); - // Do not use the last ViewPort set at the OC from the last ProcessDisplay(), - // here we want the complete primitive sequence without visible clippings - rObjectContact.resetViewPort(); - - addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPrimitive2DSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo)))); } void SdrDragMove::applyCurrentTransformationToSdrObject(SdrObject& rTarget) @@ -1766,8 +1807,7 @@ bool SdrDragResize::BeginSdrDrag() if (pRefHdl!=nullptr && !getSdrDragView().IsResizeAtCenter()) { - // Calc hack to adjust for calc grid - DragStat().SetRef1(pRefHdl->GetPos() - getSdrDragView().GetGridOffset()); + DragStat().SetRef1(pRefHdl->GetPos()); } else { diff --git a/svx/source/svdraw/svddrgv.cxx b/svx/source/svdraw/svddrgv.cxx index 20f14af9c5ce..31132a5bbdef 100644 --- a/svx/source/svdraw/svddrgv.cxx +++ b/svx/source/svdraw/svddrgv.cxx @@ -40,6 +40,7 @@ #include <svx/polypolygoneditor.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> #include <svx/sdr/overlay/overlaymanager.hxx> +#include <svx/sdrpagewindow.hxx> using namespace sdr; @@ -220,6 +221,19 @@ bool SdrDragView::BegDragObj(const Point& rPnt, OutputDevice* pOut, SdrHdl* pHdl } Point aPnt(rPnt); + basegfx::B2DVector aGridOffset(0.0, 0.0); + + // Coordinate maybe affected by GridOffset, so we may need to + // adapt to Model-coordinates here + if(getPossibleGridOffsetForPosition( + aGridOffset, + basegfx::B2DPoint(aPnt.X(), aPnt.Y()), + GetSdrPageView())) + { + aPnt.AdjustX(basegfx::fround(-aGridOffset.getX())); + aPnt.AdjustY(basegfx::fround(-aGridOffset.getY())); + } + if(pHdl == nullptr || pHdl->GetKind() == SdrHdlKind::Move || pHdl->GetKind() == SdrHdlKind::MirrorAxis @@ -508,6 +522,19 @@ void SdrDragView::MovDragObj(const Point& rPnt) if (mpCurrentSdrDragMethod) { Point aPnt(rPnt); + basegfx::B2DVector aGridOffset(0.0, 0.0); + + // Coordinate maybe affected by GridOffset, so we may need to + // adapt to Model-coordinates here + if(getPossibleGridOffsetForPosition( + aGridOffset, + basegfx::B2DPoint(aPnt.X(), aPnt.Y()), + GetSdrPageView())) + { + aPnt.AdjustX(basegfx::fround(-aGridOffset.getX())); + aPnt.AdjustY(basegfx::fround(-aGridOffset.getY())); + } + ImpLimitToWorkArea(aPnt); mpCurrentSdrDragMethod->MoveSdrDrag(aPnt); // this call already makes a Hide()/Show combination } @@ -780,17 +807,35 @@ void SdrDragView::ShowDragObj() { if(mpCurrentSdrDragMethod && !maDragStat.IsShown()) { - for(sal_uInt32 a(0); a < PaintWindowCount(); a++) + // Changed for the GridOffset stuff: No longer iterate over + // SdrPaintWindow(s), but now over SdrPageWindow(s), so doing the + // same as the SdrHdl visualizations (see ::CreateB2dIAObject) do. + // This is needed to get access to a ObjectContact which is needed + // to evtl. process that GridOffset in CreateOverlayGeometry + SdrPageView* pPageView(GetSdrPageView()); + + if(nullptr != pPageView) { - SdrPaintWindow* pCandidate = GetPaintWindow(a); - const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager = pCandidate->GetOverlayManager(); - - if (xOverlayManager.is()) + for(sal_uInt32 a(0); a < pPageView->PageWindowCount(); a++) { - mpCurrentSdrDragMethod->CreateOverlayGeometry(*xOverlayManager); + const SdrPageWindow& rPageWindow(*pPageView->GetPageWindow(a)); + const SdrPaintWindow& rPaintWindow(rPageWindow.GetPaintWindow()); - // #i101679# Force changed overlay to be shown - xOverlayManager->flush(); + if(rPaintWindow.OutputToWindow()) + { + const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager( + rPaintWindow.GetOverlayManager()); + + if(xOverlayManager.is()) + { + mpCurrentSdrDragMethod->CreateOverlayGeometry( + *xOverlayManager.get(), + rPageWindow.GetObjectContact()); + + // #i101679# Force changed overlay to be shown + xOverlayManager->flush(); + } + } } } diff --git a/svx/source/svdraw/svdedtv1.cxx b/svx/source/svdraw/svdedtv1.cxx index 960dd2c58269..1acf37cd3771 100644 --- a/svx/source/svdraw/svdedtv1.cxx +++ b/svx/source/svdraw/svdedtv1.cxx @@ -1259,8 +1259,6 @@ SfxItemSet SdrEditView::GetGeoAttrFromMarked() const { SfxItemSet aMarkAttr(GetAttrFromMarked(false)); // because of AutoGrowHeight and corner radius tools::Rectangle aRect(GetMarkedObjRect()); - // restore position to that before calc hack - aRect -= GetGridOffset(); if(GetSdrPageView()) { diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx index 0f7361bbd6d8..66a409c8cfae 100644 --- a/svx/source/svdraw/svdedxv.cxx +++ b/svx/source/svdraw/svdedxv.cxx @@ -261,13 +261,20 @@ void SdrObjEditView::ModelHasChanged() tools::Rectangle aEditArea1; tools::Rectangle aMinArea1; pTextObj->TakeTextEditArea(&aPaperMin1,&aPaperMax1,&aEditArea1,&aMinArea1); - Point aPvOfs(pTextObj->GetTextEditOffset()); - // Hack for calc, transform position of edit object according - // to current zoom so as objects relative position to grid - // appears stable - aEditArea1 += pTextObj->GetGridOffset(); - aMinArea1 += pTextObj->GetGridOffset(); + + // add possible GridOffset to up-to-now view-independent EditAreas + basegfx::B2DVector aGridOffset(0.0, 0.0); + if(getPossibleGridOffsetForSdrObject(aGridOffset, pTextObj, GetSdrPageView())) + { + const Point aOffset( + basegfx::fround(aGridOffset.getX()), + basegfx::fround(aGridOffset.getY())); + + aEditArea1 += aOffset; + aMinArea1 += aOffset; + } + aEditArea1.Move(aPvOfs.X(),aPvOfs.Y()); aMinArea1.Move(aPvOfs.X(),aPvOfs.Y()); tools::Rectangle aNewArea(aMinArea1); @@ -494,7 +501,7 @@ namespace if (!maRange.equal(maLastRange) || maLastTextPrimitives != maTextPrimitives) { // conditions of last local decomposition have changed, delete to force new evaluation - const_cast<TextEditOverlayObject*>(this)->setPrimitive2DSequence(drawinglayer::primitive2d::Primitive2DContainer()); + const_cast<TextEditOverlayObject*>(this)->resetPrimitive2DSequence(); } } @@ -1148,14 +1155,20 @@ bool SdrObjEditView::SdrBeginTextEdit( aTextEditArea = aTextRect; - // Hack for calc, transform position of edit object according - // to current zoom so as objects relative position to grid - // appears stable + // add possible GridOffset to up-to-now view-independent EditAreas + basegfx::B2DVector aGridOffset(0.0, 0.0); + if(getPossibleGridOffsetForSdrObject(aGridOffset, pTextObj, pPV)) + { + const Point aOffset( + basegfx::fround(aGridOffset.getX()), + basegfx::fround(aGridOffset.getY())); + + aTextEditArea += aOffset; + aMinTextEditArea += aOffset; + } Point aPvOfs(pTextObj->GetTextEditOffset()); - aTextEditArea += pTextObj->GetGridOffset(); aTextEditArea.Move(aPvOfs.X(),aPvOfs.Y()); - aMinTextEditArea += pTextObj->GetGridOffset(); aMinTextEditArea.Move(aPvOfs.X(),aPvOfs.Y()); pTextEditCursorBuffer=pWin->GetCursor(); diff --git a/svx/source/svdraw/svdhdl.cxx b/svx/source/svdraw/svdhdl.cxx index 93621e714802..0a51a0a580ef 100644 --- a/svx/source/svdraw/svdhdl.cxx +++ b/svx/source/svdraw/svdhdl.cxx @@ -56,6 +56,8 @@ #include <svx/sdr/overlay/overlaypolypolygon.hxx> #include <vcl/lazydelete.hxx> #include <vcl/BitmapTools.hxx> +#include <svx/sdr/contact/objectcontact.hxx> +#include <svx/sdr/contact/viewcontact.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> @@ -612,12 +614,12 @@ void SdrHdl::CreateB2dIAObject() aPosition, eColIndex, eKindOfMarker, aMoveOutsideOffset); } + // OVERLAYMANAGER - if (pNewOverlayObject) - { - xManager->add(*pNewOverlayObject); - maOverlayGroup.append(std::move(pNewOverlayObject)); - } + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNewOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -1070,6 +1072,39 @@ BitmapEx SdrHdl::createGluePointBitmap() return ImpGetBitmapEx(BitmapMarkerKind::Glue_Deselected, BitmapColorIndex::LightGreen); } +void SdrHdl::insertNewlyCreatedOverlayObjectForSdrHdl( + std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject, + const sdr::contact::ObjectContact& rObjectContact, + sdr::overlay::OverlayManager& rOverlayManager) +{ + // check if we have an OverlayObject + if(!pOverlayObject) + { + return; + } + + // Add GridOffset for non-linear ViewToDevice transformation (calc) + if(nullptr != GetObj() && rObjectContact.supportsGridOffsets()) + { + basegfx::B2DVector aOffset(0.0, 0.0); + const sdr::contact::ViewObjectContact& rVOC(GetObj()->GetViewContact().GetViewObjectContact( + const_cast<sdr::contact::ObjectContact&>(rObjectContact))); + + rObjectContact.calculateGridOffsetForViewOjectContact(aOffset, rVOC); + + if(!aOffset.equalZero()) + { + pOverlayObject->setOffset(aOffset); + } + } + + // add to OverlayManager + rOverlayManager.add(*pOverlayObject); + + // add to local OverlayObjectList - ownership change (!) + maOverlayGroup.append(std::move(pOverlayObject)); +} + SdrHdlColor::SdrHdlColor(const Point& rRef, Color aCol, const Size& rSize, bool bLum) : SdrHdl(rRef, SdrHdlKind::Color), aMarkerSize(rSize), @@ -1121,8 +1156,10 @@ void SdrHdlColor::CreateB2dIAObject() )); // OVERLAYMANAGER - xManager->add(*pNewOverlayObject); - maOverlayGroup.append(std::move(pNewOverlayObject)); + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNewOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -1280,8 +1317,12 @@ void SdrHdlGradient::CreateB2dIAObject() )); pNewOverlayObject->setBaseColor(IsGradient() ? COL_BLACK : COL_BLUE); - xManager->add(*pNewOverlayObject); - maOverlayGroup.append(std::move(pNewOverlayObject)); + + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNewOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); // arrowhead Point aLeft(aMidPoint.X() + static_cast<sal_Int32>(aPerpend.getX() * fHalfArrowWidth), @@ -1301,8 +1342,11 @@ void SdrHdlGradient::CreateB2dIAObject() IsGradient() ? COL_BLACK : COL_BLUE )); - xManager->add(*pNewOverlayObject); - maOverlayGroup.append(std::move(pNewOverlayObject)); + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNewOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -1425,12 +1469,14 @@ void SdrHdlLine::CreateB2dIAObject() aPosition2 )); - // OVERLAYMANAGER // color(?) pNewOverlayObject->setBaseColor(COL_LIGHTRED); - xManager->add(*pNewOverlayObject); - maOverlayGroup.append(std::move(pNewOverlayObject)); + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNewOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -1482,15 +1528,18 @@ void SdrHdlBezWgt::CreateB2dIAObject() aPosition1, aPosition2 )); - // OVERLAYMANAGER + // line part is not hittable pNewOverlayObject->setHittable(false); // color(?) pNewOverlayObject->setBaseColor(COL_LIGHTBLUE); - xManager->add(*pNewOverlayObject); - maOverlayGroup.append(std::move(pNewOverlayObject)); + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNewOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -1532,11 +1581,13 @@ void E3dVolumeMarker::CreateB2dIAObject() sdr::overlay::OverlayPolyPolygonStripedAndFilled( aWireframePoly)); - // OVERLAYMANAGER pNewOverlayObject->setBaseColor(COL_BLACK); - xManager->add(*pNewOverlayObject); - maOverlayGroup.append(std::move(pNewOverlayObject)); + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNewOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -1597,11 +1648,10 @@ void ImpEdgeHdl::CreateB2dIAObject() eKindOfMarker)); // OVERLAYMANAGER - if (pNewOverlayObject) - { - xManager->add(*pNewOverlayObject); - maOverlayGroup.append(std::move(pNewOverlayObject)); - } + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNewOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -1713,11 +1763,10 @@ void ImpMeasureHdl::CreateB2dIAObject() eKindOfMarker)); // OVERLAYMANAGER - if (pNewOverlayObject) - { - xManager->add(*pNewOverlayObject); - maOverlayGroup.append(std::move(pNewOverlayObject)); - } + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNewOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -1784,10 +1833,13 @@ void ImpTextframeHdl::CreateB2dIAObject() nRotationAngle * -F_PI18000, true)); // allow animation; the Handle is not shown at text edit time - // OVERLAYMANAGER pNewOverlayObject->setHittable(false); - xManager->add(*pNewOverlayObject); - maOverlayGroup.append(std::move(pNewOverlayObject)); + + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNewOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -2395,8 +2447,10 @@ void SdrCropHdl::CreateB2dIAObject() } // OVERLAYMANAGER - xManager->add(*pOverlayObject); - maOverlayGroup.append(std::move(pOverlayObject)); + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -2608,8 +2662,11 @@ void SdrCropViewHdl::CreateB2dIAObject() // only informative object, no hit pNew->setHittable(false); - xManager->add(*pNew); - maOverlayGroup.append(std::move(pNew)); + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNew), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx index bbad824d3267..8a55f973873d 100644 --- a/svx/source/svdraw/svdmrkv.cxx +++ b/svx/source/svdraw/svdmrkv.cxx @@ -43,6 +43,7 @@ #include <svx/svdovirt.hxx> #include <sdr/overlay/overlayrollingrectangle.hxx> #include <svx/sdr/overlay/overlaymanager.hxx> +#include <svx/sdr/contact/viewcontact.hxx> #include <svx/sdrpaintwindow.hxx> #include <svx/sdrpagewindow.hxx> #include <svx/sdrhittesthelper.hxx> @@ -675,11 +676,6 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell) } } - // apply calc offset to marked object rect - // ( necessary for handles to be displayed in - // correct position ) - Point aGridOff = GetGridOffset(); - // There can be multiple mark views, but we're only interested in the one that has a window associated. const bool bTiledRendering = comphelper::LibreOfficeKit::isActive() && GetFirstOutputDevice() && GetFirstOutputDevice()->GetOutDevType() == OUTDEV_WINDOW; @@ -804,20 +800,13 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell) if (bFrmHdl) { if(!aRect.IsEmpty()) - { // otherwise nothing is found + { + // otherwise nothing is found + const size_t nSiz0(maHdlList.GetHdlCount()); + if( bSingleTextObjMark ) { - const size_t nSiz0=maHdlList.GetHdlCount(); mpMarkedObj->AddToHdlList(maHdlList); - const size_t nSiz1=maHdlList.GetHdlCount(); - for (size_t i=nSiz0; i<nSiz1; ++i) - { - SdrHdl* pHdl=maHdlList.GetHdl(i); - pHdl->SetObj(mpMarkedObj); - pHdl->SetPos( pHdl->GetPos() + aGridOff ); - pHdl->SetPageView(mpMarkedPV); - pHdl->SetObjHdlNum(sal_uInt16(i-nSiz0)); - } } else { @@ -876,6 +865,20 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell) } } } + + const size_t nSiz1(maHdlList.GetHdlCount()); + + // moved setting the missing parameters at SdrHdl here from the + // single loop above (bSingleTextObjMark), this was missing all + // the time. Setting SdrObject is now required to correctly get + // the View-Dependent evtl. GridOffset adapted + for (size_t i=nSiz0; i<nSiz1; ++i) + { + SdrHdl* pHdl=maHdlList.GetHdl(i); + pHdl->SetObj(mpMarkedObj); + pHdl->SetPageView(mpMarkedPV); + pHdl->SetObjHdlNum(sal_uInt16(i-nSiz0)); + } } } else @@ -888,7 +891,19 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell) // Default addCropHandles from SdrObject does nothing. When pMarkedObj is SdrGrafObj, previous // behaviour occurs (code in svx/source/svdraw/svdograf.cxx). When pMarkedObj is SwVirtFlyDrawObj // writer takes the responsibility of adding handles (code in sw/source/core/draw/dflyobj.cxx) + const size_t nSiz0(maHdlList.GetHdlCount()); mpMarkedObj->addCropHandles(maHdlList); + const size_t nSiz1(maHdlList.GetHdlCount()); + + // Was missing: Set infos at SdrCropHdl + for (size_t i=nSiz0; i<nSiz1; ++i) + { + SdrHdl* pHdl=maHdlList.GetHdl(i); + pHdl->SetObj(mpMarkedObj); + pHdl->SetPageView(mpMarkedPV); + pHdl->SetObjHdlNum(sal_uInt16(i-nSiz0)); + } + bDone = true; } @@ -907,7 +922,6 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell) for (size_t i=nSiz0; i<nSiz1; ++i) { SdrHdl* pHdl=maHdlList.GetHdl(i); - pHdl->SetPos( pHdl->GetPos() + aGridOff ); pHdl->SetObj(pObj); pHdl->SetPageView(pPV); pHdl->SetObjHdlNum(sal_uInt16(i-nSiz0)); @@ -1695,6 +1709,83 @@ void SdrMarkView::SetMarkHdlSizePixel(sal_uInt16 nSiz) } } +bool SdrMarkView::getPossibleGridOffsetForSdrObject( + basegfx::B2DVector& rOffset, + const SdrObject* pObj, + const SdrPageView* pPV) const +{ + if(nullptr == pObj || nullptr == pPV) + { + return false; + } + + const OutputDevice* pOutputDevice(GetFirstOutputDevice()); + + if(nullptr == pOutputDevice) + { + return false; + } + + const SdrPageWindow* pSdrPageWindow(pPV->FindPageWindow(*pOutputDevice)); + + if(nullptr == pSdrPageWindow) + { + return false; + } + + const sdr::contact::ObjectContact& rObjectContact(pSdrPageWindow->GetObjectContact()); + + if(!rObjectContact.supportsGridOffsets()) + { + return false; + } + + basegfx::B2DVector aOffset(0.0, 0.0); + const sdr::contact::ViewObjectContact& rVOC(pObj->GetViewContact().GetViewObjectContact( + const_cast<sdr::contact::ObjectContact&>(rObjectContact))); + + rObjectContact.calculateGridOffsetForViewOjectContact(rOffset, rVOC); + + return !rOffset.equalZero(); +} + +bool SdrMarkView::getPossibleGridOffsetForPosition( + basegfx::B2DVector& rOffset, + const basegfx::B2DPoint& rPoint, + const SdrPageView* pPV) const +{ + if(nullptr == pPV) + { + return false; + } + + const OutputDevice* pOutputDevice(GetFirstOutputDevice()); + + if(nullptr == pOutputDevice) + { + return false; + } + + const SdrPageWindow* pSdrPageWindow(pPV->FindPageWindow(*pOutputDevice)); + + if(nullptr == pSdrPageWindow) + { + return false; + } + + const sdr::contact::ObjectContact& rObjectContact(pSdrPageWindow->GetObjectContact()); + + if(!rObjectContact.supportsGridOffsets()) + { + return false; + } + + basegfx::B2DVector aOffset(0.0, 0.0); + rObjectContact.calculateGridOffsetForB2DRange(rOffset, basegfx::B2DRange(rPoint)); + + return !rOffset.equalZero(); +} + SdrObject* SdrMarkView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay) const { if(((nOptions & SdrSearchOptions::IMPISMASTER) && pObj->IsNotVisibleAsMaster()) || (!pObj->IsVisible())) @@ -1708,8 +1799,16 @@ SdrObject* SdrMarkView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nT const bool bTXT(dynamic_cast<const SdrTextObj*>( pObj) != nullptr && static_cast<SdrTextObj*>(pObj)->IsTextFrame()); SdrObject* pRet=nullptr; tools::Rectangle aRect(pObj->GetCurrentBoundRect()); - // hack for calc grid sync - aRect += pObj->GetGridOffset(); + + // add possible GridOffset to up-to-now view-independent BountRect data + basegfx::B2DVector aGridOffset(0.0, 0.0); + if(getPossibleGridOffsetForSdrObject(aGridOffset, pObj, pPV)) + { + aRect += Point( + basegfx::fround(aGridOffset.getX()), + basegfx::fround(aGridOffset.getY())); + } + sal_uInt16 nTol2(nTol); // double tolerance for OLE, text frames and objects in @@ -2009,6 +2108,7 @@ void SdrMarkView::AdjustMarkHdl(SfxViewShell* pOtherShell) SetMarkHandles(pOtherShell); } +// BoundRect in model coordinates, no GridOffset added tools::Rectangle SdrMarkView::GetMarkedObjBoundRect() const { tools::Rectangle aRect; @@ -2016,49 +2116,28 @@ tools::Rectangle SdrMarkView::GetMarkedObjBoundRect() const SdrMark* pM=GetSdrMarkByIndex(nm); SdrObject* pO=pM->GetMarkedSdrObj(); tools::Rectangle aR1(pO->GetCurrentBoundRect()); - // Ensure marked area includes the calc offset - // ( if applicable ) to sync to grid - aR1 += pO->GetGridOffset(); if (aRect.IsEmpty()) aRect=aR1; else aRect.Union(aR1); } return aRect; } -Point SdrMarkView::GetGridOffset() const -{ - Point aOffset; - // calculate the area occupied by the union of each marked object - // ( synced to grid ) and compare to the same unsynced area to calculate - // the offset. Hopefully that's the sensible thing to do - const tools::Rectangle& aGroupSyncedRect = GetMarkedObjRect(); - aOffset = aGroupSyncedRect.TopLeft() - maMarkedObjRectNoOffset.TopLeft(); - return aOffset; -} - +// ObjRect in model coordinates, no GridOffset added const tools::Rectangle& SdrMarkView::GetMarkedObjRect() const { if (mbMarkedObjRectDirty) { const_cast<SdrMarkView*>(this)->mbMarkedObjRectDirty=false; tools::Rectangle aRect; - tools::Rectangle aRect2; for (size_t nm=0; nm<GetMarkedObjectCount(); ++nm) { SdrMark* pM=GetSdrMarkByIndex(nm); SdrObject* pO = pM->GetMarkedSdrObj(); if (!pO) continue; tools::Rectangle aR1(pO->GetSnapRect()); - // apply calc offset to marked object rect - // ( necessary for handles to be displayed in - // correct position ) - if (aRect2.IsEmpty()) aRect2=aR1; - else aRect2.Union( aR1 ); - aR1 += pO->GetGridOffset(); if (aRect.IsEmpty()) aRect=aR1; else aRect.Union(aR1); } const_cast<SdrMarkView*>(this)->maMarkedObjRect=aRect; - const_cast<SdrMarkView*>(this)->maMarkedObjRectNoOffset=aRect2; } return maMarkedObjRect; } diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx index cb104cba5358..7706cfebd826 100644 --- a/svx/source/svdraw/svdobj.cxx +++ b/svx/source/svdraw/svdobj.cxx @@ -890,6 +890,8 @@ void SdrObject::RecalcBoundRect() // central new method which will calculate the BoundRect using primitive geometry if(aOutRect.IsEmpty()) { + // Use view-independent data - we do not want any connections + // to e.g. GridOffset in SdrObject-level const drawinglayer::primitive2d::Primitive2DContainer xPrimitives(GetViewContact().getViewIndependentPrimitive2DContainer()); if(!xPrimitives.empty()) @@ -905,7 +907,6 @@ void SdrObject::RecalcBoundRect() static_cast<long>(floor(aRange.getMinY())), static_cast<long>(ceil(aRange.getMaxX())), static_cast<long>(ceil(aRange.getMaxY()))); - aOutRect -= GetGridOffset(); // don't include grid offset return; } } @@ -1022,8 +1023,6 @@ SdrObject& SdrObject::operator=(const SdrObject& rObj) pGrabBagItem.reset(); if (rObj.pGrabBagItem!=nullptr) pGrabBagItem.reset(static_cast< SfxGrabBagItem* >( rObj.pGrabBagItem->Clone() )); - - aGridOffset = rObj.aGridOffset; return *this; } @@ -1706,7 +1705,6 @@ bool SdrObject::HasTextEdit() const bool SdrObject::Equals(const SdrObject& rOtherObj) const { return (aAnchor.X() == rOtherObj.aAnchor.X() && aAnchor.Y() == rOtherObj.aAnchor.Y() && - aGridOffset.X() == rOtherObj.aGridOffset.X() && aGridOffset.Y() == rOtherObj.aGridOffset.Y() && nOrdNum == rOtherObj.nOrdNum && mnNavigationPosition == rOtherObj.mnNavigationPosition && mbSupportTextIndentingOnLineWidthChange == rOtherObj.mbSupportTextIndentingOnLineWidthChange && mbLineIsOutsideGeometry == rOtherObj.mbLineIsOutsideGeometry && bMarkProt == rOtherObj.bMarkProt && diff --git a/svx/source/svdraw/svdorect.cxx b/svx/source/svdraw/svdorect.cxx index d9b74ea3aaa9..348ef3738842 100644 --- a/svx/source/svdraw/svdorect.cxx +++ b/svx/source/svdraw/svdorect.cxx @@ -316,9 +316,7 @@ void SdrRectObj::AddToHdlList(SdrHdlList& rHdlList) const if(IsTextFrame()) { OSL_ENSURE(!IsTextEditActive(), "Do not use a ImpTextframeHdl for highlighting text in active text edit, this will collide with EditEngine paints (!)"); - // hack for calc grid sync to ensure the hatched area - // for a textbox is displayed at correct position - std::unique_ptr<SdrHdl> pH(new ImpTextframeHdl(maRect + GetGridOffset())); + std::unique_ptr<SdrHdl> pH(new ImpTextframeHdl(maRect)); pH->SetObj(const_cast<SdrRectObj*>(this)); pH->SetRotationAngle(aGeo.nRotationAngle); rHdlList.AddHdl(std::move(pH)); diff --git a/svx/source/svdraw/svdpagv.cxx b/svx/source/svdraw/svdpagv.cxx index ed73fadf7acd..c180fe9b459e 100644 --- a/svx/source/svdraw/svdpagv.cxx +++ b/svx/source/svdraw/svdpagv.cxx @@ -35,7 +35,7 @@ #include <svx/svdtypes.hxx> #include <svx/svdoole2.hxx> -#include <sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/contact/objectcontactofpageview.hxx> #include <svx/sdr/contact/viewobjectcontactredirector.hxx> #include <svx/fmview.hxx> diff --git a/svx/source/svdraw/svdview.cxx b/svx/source/svdraw/svdview.cxx index c68bbe443a72..0cee85fe96c3 100644 --- a/svx/source/svdraw/svdview.cxx +++ b/svx/source/svdraw/svdview.cxx @@ -51,6 +51,7 @@ #include <svx/sdr/contact/viewcontact.hxx> #include <drawinglayer/processor2d/contourextractor2d.hxx> #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx> +#include <svx/sdr/contact/objectcontactofpageview.hxx> #include <sal/log.hxx> @@ -1470,5 +1471,12 @@ void SdrView::SetMasterPagePaintCaching(bool bOn) } } +// Default ObjectContact is ObjectContactOfPageView +sdr::contact::ObjectContact* SdrView::createViewSpecificObjectContact( + SdrPageWindow& rPageWindow, + const sal_Char* pDebugName) const +{ + return new sdr::contact::ObjectContactOfPageView(rPageWindow, pDebugName); +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/table/tablehandles.cxx b/svx/source/table/tablehandles.cxx index accbad2739d0..650180b23d3f 100644 --- a/svx/source/table/tablehandles.cxx +++ b/svx/source/table/tablehandles.cxx @@ -172,8 +172,12 @@ void TableEdgeHdl::CreateB2dIAObject() { // create overlay object for visible parts std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject(new OverlayTableEdge(aVisible, true)); - xManager->add(*pOverlayObject); - maOverlayGroup.append(std::move(pOverlayObject)); + + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } if(aInvisible.count()) @@ -182,8 +186,12 @@ void TableEdgeHdl::CreateB2dIAObject() // a standard HitTest using the primitives from that overlay object // (see OverlayTableEdge implementation) std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject(new OverlayTableEdge(aInvisible, false)); - xManager->add(*pOverlayObject); - maOverlayGroup.append(std::move(pOverlayObject)); + + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } @@ -289,8 +297,12 @@ void TableBorderHdl::CreateB2dIAObject() new sdr::overlay::OverlayRectangle(aRange.getMinimum(), aRange.getMaximum(), aHilightColor, fTransparence, fWidth, 0.0, 0.0, bAnimate)); - xManager->add(*pOverlayObject); - maOverlayGroup.append(std::move(pOverlayObject)); + + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } |