diff options
68 files changed, 1043 insertions, 475 deletions
diff --git a/chart2/source/controller/main/DragMethod_RotateDiagram.cxx b/chart2/source/controller/main/DragMethod_RotateDiagram.cxx index 87415cdcaee2..88572d961d4e 100644 --- a/chart2/source/controller/main/DragMethod_RotateDiagram.cxx +++ b/chart2/source/controller/main/DragMethod_RotateDiagram.cxx @@ -172,7 +172,9 @@ bool DragMethod_RotateDiagram::EndSdrDrag(bool /*bCopy*/) return true; } -void DragMethod_RotateDiagram::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager) +void DragMethod_RotateDiagram::CreateOverlayGeometry( + sdr::overlay::OverlayManager& rOverlayManager, + const sdr::contact::ObjectContact& rObjectContact) { ::basegfx::B3DHomMatrix aCurrentTransform; aCurrentTransform.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, @@ -212,10 +214,14 @@ void DragMethod_RotateDiagram::CreateOverlayGeometry(sdr::overlay::OverlayManage // transform to 2D view coordinates aPolyPolygon.transform(rVCScene.getObjectTransformation()); - std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled( - aPolyPolygon)); - rOverlayManager.add(*pNew); - addToOverlayObjectList(std::move(pNew)); + std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew( + new sdr::overlay::OverlayPolyPolygonStripedAndFilled( + aPolyPolygon)); + + insertNewlyCreatedOverlayObjectForSdrDragMethod( + std::move(pNew), + rObjectContact, + rOverlayManager); } } } //namespace chart diff --git a/chart2/source/controller/main/DragMethod_RotateDiagram.hxx b/chart2/source/controller/main/DragMethod_RotateDiagram.hxx index 863e7559f3b3..b2698bf85b18 100644 --- a/chart2/source/controller/main/DragMethod_RotateDiagram.hxx +++ b/chart2/source/controller/main/DragMethod_RotateDiagram.hxx @@ -53,7 +53,9 @@ public: virtual void MoveSdrDrag(const Point& rPnt) override; virtual bool EndSdrDrag(bool bCopy) override; - virtual void CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager) override; + virtual void CreateOverlayGeometry( + sdr::overlay::OverlayManager& rOverlayManager, + const sdr::contact::ObjectContact& rObjectContact) override; private: E3dScene* m_pScene; diff --git a/include/svx/sdr/contact/objectcontact.hxx b/include/svx/sdr/contact/objectcontact.hxx index d305d61b007d..dd1606e380fd 100644 --- a/include/svx/sdr/contact/objectcontact.hxx +++ b/include/svx/sdr/contact/objectcontact.hxx @@ -163,6 +163,16 @@ public: // wanted (like in such cases) this method is used. It will reuse the current // ViewInformation2D, but clear the ViewPort (no ViewPort means all is visible) void resetViewPort(); + + // interface to support GridOffset for non-linear ViewToDevice transformation (calc) + virtual bool supportsGridOffsets() const; + virtual void calculateGridOffsetForViewOjectContact( + basegfx::B2DVector& rTarget, + const ViewObjectContact& rClient) const; + virtual void calculateGridOffsetForB2DRange( + basegfx::B2DVector& rTarget, + const basegfx::B2DRange& rB2DRange) const; + void resetAllGridOffsets(); }; }} diff --git a/svx/inc/sdr/contact/objectcontactofpageview.hxx b/include/svx/sdr/contact/objectcontactofpageview.hxx index 4fb0bef53898..020b454cce87 100644 --- a/svx/inc/sdr/contact/objectcontactofpageview.hxx +++ b/include/svx/sdr/contact/objectcontactofpageview.hxx @@ -30,7 +30,7 @@ namespace sdr { namespace contact { - class ObjectContactOfPageView final : public ObjectContact, public Idle + class SVX_DLLPUBLIC ObjectContactOfPageView : public ObjectContact, public Idle { // the owner of this ObjectContactOfPageView. Set from constructor and not // to be changed in any way. diff --git a/include/svx/sdr/contact/viewobjectcontact.hxx b/include/svx/sdr/contact/viewobjectcontact.hxx index ce17890ee93d..a6d929c6c203 100644 --- a/include/svx/sdr/contact/viewobjectcontact.hxx +++ b/include/svx/sdr/contact/viewobjectcontact.hxx @@ -58,6 +58,9 @@ private: // the PrimitiveAnimation if Primitive2DContainer contains animations std::unique_ptr<sdr::animation::PrimitiveAnimation> mpPrimitiveAnimation; + // possible on-demand calculated GridOffset for non-linear ViewToDevice transformation (calc) + basegfx::B2DVector maGridOffset; + // This bool gets set when the object gets invalidated by ActionChanged() and // can be used from the OC to late-invalidates bool mbLazyInvalidate : 1; @@ -124,6 +127,10 @@ public: // just process the sub-hierarchy, used as tooling from getPrimitive2DSequenceHierarchy drawinglayer::primitive2d::Primitive2DContainer getPrimitive2DSequenceSubHierarchy(DisplayInfo& rDisplayInfo) const; + + // interface to support GridOffset for non-linear ViewToDevice transformation (calc) + const basegfx::B2DVector& getGridOffset() const; + void resetGridOffset(); }; }} diff --git a/include/svx/sdr/overlay/overlayobject.hxx b/include/svx/sdr/overlay/overlayobject.hxx index a506d336cac5..147081956319 100644 --- a/include/svx/sdr/overlay/overlayobject.hxx +++ b/include/svx/sdr/overlay/overlayobject.hxx @@ -65,14 +65,25 @@ namespace sdr OverlayManager* mpOverlayManager; // Primitive2DContainer of the OverlayObject - drawinglayer::primitive2d::Primitive2DContainer maPrimitive2DSequence; + drawinglayer::primitive2d::Primitive2DContainer maPrimitive2DSequence; + + // Possible Offset added to the geometry (automatically in + // createOverlayObjectPrimitive2DSequence()). Usually zero, may + // be used e.g. from calc when GridOffset is needed + basegfx::B2DVector maOffset; protected: // access methods to maPrimitive2DSequence. The usage of this methods may allow // later thread-safe stuff to be added if needed. Only to be used by getPrimitive2DSequence() // implementations for buffering the last decomposition. + // Resetting is allowed e.g. in ::getOverlayObjectPrimitive2DSequence() implementations + // if the conditions have changed to force a re-creation in calling the base implementation. + // The only allowed setter of maPrimitive2DSequence is + // OverlayObject::getOverlayObjectPrimitive2DSequence() which should be called by calling + // the base implementation in derived functions. That one will use the result of + // createOverlayObjectPrimitive2DSequence() to provide the geometry. const drawinglayer::primitive2d::Primitive2DContainer& getPrimitive2DSequence() const { return maPrimitive2DSequence; } - void setPrimitive2DSequence(const drawinglayer::primitive2d::Primitive2DContainer& rNew) { maPrimitive2DSequence = rNew; } + void resetPrimitive2DSequence() { maPrimitive2DSequence.clear(); } // the creation method for Primitive2DContainer. Called when getPrimitive2DSequence() // sees that maPrimitive2DSequence is empty. Needs to be supported by all @@ -146,6 +157,10 @@ namespace sdr const Color& getBaseColor() const { return maBaseColor; } void setBaseColor(Color aNew); + // access to Offset + const basegfx::B2DVector& getOffset() const { return maOffset; } + void setOffset(const basegfx::B2DVector& rOffset); + // execute event from base class sdr::animation::Event. Default // implementation does nothing and does not create a new event. virtual void Trigger(sal_uInt32 nTime) override; diff --git a/include/svx/svddrgmt.hxx b/include/svx/svddrgmt.hxx index 0013da3284e3..3e1a13d6a3d3 100644 --- a/include/svx/svddrgmt.hxx +++ b/include/svx/svddrgmt.hxx @@ -66,11 +66,12 @@ class SdrDragEntrySdrObject : public SdrDragEntry private: const SdrObject& maOriginal; SdrObject* mpClone; - sdr::contact::ObjectContact& mrObjectContact; bool const mbModify; public: - SdrDragEntrySdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool bModify); + SdrDragEntrySdrObject( + const SdrObject& rOriginal, + bool bModify); virtual ~SdrDragEntrySdrObject() override; // #i54102# Split createPrimitive2DSequenceInCurrentState in prepareCurrentState and processing, @@ -127,10 +128,19 @@ protected: void clearSdrDragEntries(); void addSdrDragEntry(std::unique_ptr<SdrDragEntry> pNew); virtual void createSdrDragEntries(); - virtual void createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact); - - // access for derivated classes to maOverlayObjectList (passes ownership) - void addToOverlayObjectList(std::unique_ptr<sdr::overlay::OverlayObject> pNew) { maOverlayObjectList.append(std::move(pNew)); } + virtual void createSdrDragEntryForSdrObject(const SdrObject& rOriginal); + + // Helper to support inserting a new OverlayObject. It will do all + // necessary stuff involved with that: + // - add GridOffset for non-linear ViewToDevice transformation (calc) + // - add to OverlayManager + // - add to local OverlayObjectList - ownership change (!) + // It is centralized here (and protected) to avoid that new usages/ + // implementations forget one of these needed steps. + void insertNewlyCreatedOverlayObjectForSdrDragMethod( + std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject, + const sdr::contact::ObjectContact& rObjectContact, + sdr::overlay::OverlayManager& rOverlayManager); // access for derivated classes to mrSdrDragView SdrDragView& getSdrDragView() { return mrSdrDragView; } @@ -192,7 +202,9 @@ public: virtual void CancelSdrDrag(); virtual Pointer GetSdrDragPointer() const=0; - virtual void CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager); + virtual void CreateOverlayGeometry( + sdr::overlay::OverlayManager& rOverlayManager, + const sdr::contact::ObjectContact& rObjectContact); void destroyOverlayGeometry(); virtual basegfx::B2DHomMatrix getCurrentTransformation(); @@ -225,7 +237,7 @@ private: void ImpCheckSnap(const Point& rPt); protected: - virtual void createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact) override; + virtual void createSdrDragEntryForSdrObject(const SdrObject& rOriginal) override; public: SdrDragMove(SdrDragView& rNewView); diff --git a/include/svx/svdhdl.hxx b/include/svx/svdhdl.hxx index 5760d642a3f7..caf95813973d 100644 --- a/include/svx/svdhdl.hxx +++ b/include/svx/svdhdl.hxx @@ -41,6 +41,10 @@ class SdrObject; class SdrPageView; class MouseEvent; +namespace sdr { namespace contact { + class ObjectContact; +}} + // Every object must be able to create its handles. They will be fetched on // selection, registered at the View and made visible. // When a handle is touched by the mouse (IsHit()), from the view the matching mouse pointer @@ -171,6 +175,18 @@ protected: Point aMoveOutsideOffset = Point()); static BitmapMarkerKind GetNextBigger(BitmapMarkerKind eKnd); + // Helper to support inserting a new OverlayObject. It will do all + // necessary stuff involved with that: + // - add GridOffset for non-linear ViewToDevice transformation (calc) + // - add to OverlayManager + // - add to local OverlayObjectList - ownership change (!) + // It is centralized here (and protected) to avoid that new usages/ + // implementations forget one of these needed steps. + void insertNewlyCreatedOverlayObjectForSdrHdl( + std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject, + const sdr::contact::ObjectContact& rObjectContact, + sdr::overlay::OverlayManager& rOverlayManager); + public: SdrHdl(); explicit SdrHdl(const Point& rPnt, SdrHdlKind eNewKind); diff --git a/include/svx/svdmrkv.hxx b/include/svx/svdmrkv.hxx index fd9d2399e910..83eefb9dd54f 100644 --- a/include/svx/svdmrkv.hxx +++ b/include/svx/svdmrkv.hxx @@ -105,7 +105,6 @@ protected: sdr::ViewSelection maSdrViewSelection; tools::Rectangle maMarkedObjRect; - tools::Rectangle maMarkedObjRectNoOffset; tools::Rectangle maMarkedPointsRect; tools::Rectangle maMarkedGluePointsRect; @@ -126,6 +125,18 @@ protected: // flag to completely disable handles at the view bool mbMarkHandlesHidden : 1; + // Helper to get a possible GridOffset from SdrObject + bool getPossibleGridOffsetForSdrObject( + basegfx::B2DVector& rOffset, + const SdrObject* pObj, + const SdrPageView* pPV) const; + + // Helper to get a possible GridOffset from Position + bool getPossibleGridOffsetForPosition( + basegfx::B2DVector& rOffset, + const basegfx::B2DPoint& rPoint, + const SdrPageView* pPV) const; + private: SVX_DLLPRIVATE void ImpClearVars(); SVX_DLLPRIVATE void ImpSetPointsRects() const; @@ -398,7 +409,6 @@ public: const tools::Rectangle& GetMarkedGluePointsRect() const; // Enclosing rectangle of all marked glue points const tools::Rectangle& GetAllMarkedRect() const { return GetMarkedObjRect(); } tools::Rectangle GetAllMarkedBoundRect() const { return GetMarkedObjBoundRect(); } - Point GetGridOffset() const; // Will be always called, if the list of marked objects might be changed. // If you override this method, be sure that you call the diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx index 2a1507ac6f7b..db1f4d1acf1a 100644 --- a/include/svx/svdobj.hxx +++ b/include/svx/svdobj.hxx @@ -382,9 +382,6 @@ public: sal_Int16 GetRelativeWidthRelation() const; const double* GetRelativeHeight() const; sal_Int16 GetRelativeHeightRelation() const; - // evil calc grid/shape drawlayer syncing - const Point& GetGridOffset() const { return aGridOffset; } - void SetGridOffset( const Point& rGridOffset ){ aGridOffset = rGridOffset; } /// @param bNotMyself = true: set only ObjList to dirty, don't mark this object as dirty. /// @@ -998,7 +995,6 @@ protected: private: struct Impl; std::unique_ptr<Impl> mpImpl; - Point aGridOffset; // hack (Calc) SdrObjList* mpParentOfSdrObject; // list that includes this object sal_uInt32 nOrdNum; // order number of the object in the list std::unique_ptr<SfxGrabBagItem> pGrabBagItem; // holds the GrabBagItem property diff --git a/include/svx/svdview.hxx b/include/svx/svdview.hxx index a4708917de00..677ba9b70fc2 100644 --- a/include/svx/svdview.hxx +++ b/include/svx/svdview.hxx @@ -50,6 +50,7 @@ // SdrView View class SvxURLField; +namespace sdr { namespace contact { class ObjectContact; }} enum class SdrViewContext { Standard, @@ -234,6 +235,12 @@ public: SvtAccessibilityOptions& getAccessibilityOptions() { return maAccessibilityOptions;} virtual void onAccessibilityOptionsChanged(); + + // Do not create ObjectContact locally, but offer a call to allow override + // and to create own derivations of ObjectContact + virtual sdr::contact::ObjectContact* createViewSpecificObjectContact( + SdrPageWindow& rPageWindow, + const sal_Char* pDebugName) const; }; // First of all the app creates a SdrModel. diff --git a/sc/inc/drwlayer.hxx b/sc/inc/drwlayer.hxx index 738ee08b6b37..143868c0e6ce 100644 --- a/sc/inc/drwlayer.hxx +++ b/sc/inc/drwlayer.hxx @@ -176,8 +176,15 @@ public: static void SetPageAnchored( SdrObject& ); static void SetCellAnchored( SdrObject&, const ScDrawObjData &rAnchor ); static void SetVisualCellAnchored( SdrObject&, const ScDrawObjData &rAnchor ); + // Updates rAnchor based on position of rObj - static void GetCellAnchorFromPosition( const SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bUseLogicRect = true, bool bHiddenAsZero = true ); + static void GetCellAnchorFromPosition( + const tools::Rectangle &rRectangle, + ScDrawObjData &rAnchor, + const ScDocument &rDoc, + SCTAB nTab, + bool bHiddenAsZero = true); + static void SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument &rDoc, SCTAB nTab, bool bResizeWithCell ); static void UpdateCellAnchorFromPositionEnd( const SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bUseLogicRect = true ); static ScAnchorType GetAnchorType( const SdrObject& ); diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx index 540e320d1999..d7dc576c407d 100644 --- a/sc/source/core/data/drwlayer.cxx +++ b/sc/source/core/data/drwlayer.cxx @@ -995,7 +995,14 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati // Ok, here is more nastiness, from xml the Anchor is in terms of the LogicRect which is the // untransformed unrotated shape, here we swap out that initial anchor and from now on use // an Anchor based on the SnapRect ( which is what you see on the screen ) - ScDrawLayer::GetCellAnchorFromPosition( *pObj, rData, *pDoc, nTab1, false, false ); + const tools::Rectangle aObjRect(pObj->GetSnapRect()); + ScDrawLayer::GetCellAnchorFromPosition( + aObjRect, + rData, + *pDoc, + nTab1, + false); + // reset shape to true 'maybe affected by hidden rows/cols' size calculated previously pObj->SetLogicRect(rNoRotatedAnchor.getShapeRect()); } @@ -2015,13 +2022,25 @@ void ScDrawLayer::SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument ScDrawObjData aAnchor; // set anchor in terms of the visual ( SnapRect ) // object ( e.g. for when object is rotated ) - GetCellAnchorFromPosition( rObj, aAnchor, rDoc, nTab, false ); + const tools::Rectangle aObjRect(rObj.GetSnapRect()); + GetCellAnchorFromPosition( + aObjRect, + aAnchor, + rDoc, + nTab); + aAnchor.mbResizeWithCell = bResizeWithCell; SetCellAnchored( rObj, aAnchor ); // - keep also an anchor in terms of the Logic ( untransformed ) object // because that's what we stored ( and still do ) to xml ScDrawObjData aVisAnchor; - GetCellAnchorFromPosition( rObj, aVisAnchor, rDoc, nTab ); + const tools::Rectangle aObjRect2(rObj.GetLogicRect()); + GetCellAnchorFromPosition( + aObjRect2, + aVisAnchor, + rDoc, + nTab); + aVisAnchor.mbResizeWithCell = bResizeWithCell; SetVisualCellAnchored( rObj, aVisAnchor ); // absolutely necessary to set flag that in order to prevent ScDrawLayer::RecalcPos @@ -2032,31 +2051,34 @@ void ScDrawLayer::SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument } } -void ScDrawLayer::GetCellAnchorFromPosition( const SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bUseLogicRect, bool bHiddenAsZero ) +void ScDrawLayer::GetCellAnchorFromPosition( + const tools::Rectangle &rObjRect, + ScDrawObjData &rAnchor, + const ScDocument &rDoc, + SCTAB nTab, + bool bHiddenAsZero) { - tools::Rectangle aObjRect( bUseLogicRect ? rObj.GetLogicRect() : rObj.GetSnapRect() ); - ScRange aRange = rDoc.GetRange( nTab, aObjRect, bHiddenAsZero ); + ScRange aRange = rDoc.GetRange( nTab, rObjRect, bHiddenAsZero ); tools::Rectangle aCellRect; rAnchor.maStart = aRange.aStart; aCellRect = rDoc.GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab(), bHiddenAsZero ); - rAnchor.maStartOffset.setY( aObjRect.Top()-aCellRect.Top() ); + rAnchor.maStartOffset.setY( rObjRect.Top()-aCellRect.Top() ); if (!rDoc.IsNegativePage(nTab)) - rAnchor.maStartOffset.setX( aObjRect.Left()-aCellRect.Left() ); + rAnchor.maStartOffset.setX( rObjRect.Left()-aCellRect.Left() ); else - rAnchor.maStartOffset.setX( aCellRect.Right()-aObjRect.Right() ); + rAnchor.maStartOffset.setX( aCellRect.Right()-rObjRect.Right() ); rAnchor.maEnd = aRange.aEnd; aCellRect = rDoc.GetMMRect( aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab(), bHiddenAsZero ); - rAnchor.maEndOffset.setY( aObjRect.Bottom()-aCellRect.Top() ); + rAnchor.maEndOffset.setY( rObjRect.Bottom()-aCellRect.Top() ); if (!rDoc.IsNegativePage(nTab)) - rAnchor.maEndOffset.setX( aObjRect.Right()-aCellRect.Left() ); + rAnchor.maEndOffset.setX( rObjRect.Right()-aCellRect.Left() ); else - rAnchor.maEndOffset.setX( aCellRect.Right()-aObjRect.Left() ); - + rAnchor.maEndOffset.setX( aCellRect.Right()-rObjRect.Left() ); } void ScDrawLayer::UpdateCellAnchorFromPositionEnd( const SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bUseLogicRect ) diff --git a/sc/source/ui/drawfunc/fuconarc.cxx b/sc/source/ui/drawfunc/fuconarc.cxx index 6d22c749bf89..8fde47db67e0 100644 --- a/sc/source/ui/drawfunc/fuconarc.cxx +++ b/sc/source/ui/drawfunc/fuconarc.cxx @@ -46,14 +46,8 @@ bool FuConstArc::MouseButtonDown( const MouseEvent& rMEvt ) if ( rMEvt.IsLeft() && !pView->IsAction() ) { Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); - // Hack to align object to nearest grid position where object - // would be anchored ( if it were cell anchored ) - // Get grid offset for current position ( note: aPnt is - // also adjusted ) - Point aGridOff = CurrentGridSyncOffsetAndPos( aPnt ); pWindow->CaptureMouse(); pView->BegCreateObj( aPnt ); - pView->GetCreateObj()->SetGridOffset( aGridOff ); bReturn = true; } return bReturn; diff --git a/sc/source/ui/drawfunc/fuconcustomshape.cxx b/sc/source/ui/drawfunc/fuconcustomshape.cxx index c2169a1863a2..23eebb22b5e9 100644 --- a/sc/source/ui/drawfunc/fuconcustomshape.cxx +++ b/sc/source/ui/drawfunc/fuconcustomshape.cxx @@ -61,12 +61,6 @@ bool FuConstCustomShape::MouseButtonDown(const MouseEvent& rMEvt) if ( rMEvt.IsLeft() && !pView->IsAction() ) { Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); - // Hack to align object to nearest grid position where object - // would be anchored ( if it were cell anchored ) - // Get grid offset for current position ( note: aPnt is - // also adjusted ) - Point aGridOff = CurrentGridSyncOffsetAndPos( aPnt ); - pWindow->CaptureMouse(); pView->BegCreateObj(aPnt); @@ -79,7 +73,6 @@ bool FuConstCustomShape::MouseButtonDown(const MouseEvent& rMEvt) bForceNoFillStyle = true; if ( bForceNoFillStyle ) pObj->SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) ); - pObj->SetGridOffset( aGridOff ); } bReturn = true; diff --git a/sc/source/ui/drawfunc/fuconrec.cxx b/sc/source/ui/drawfunc/fuconrec.cxx index d87a2b4456e3..a77bda2ec917 100644 --- a/sc/source/ui/drawfunc/fuconrec.cxx +++ b/sc/source/ui/drawfunc/fuconrec.cxx @@ -92,11 +92,6 @@ bool FuConstRectangle::MouseButtonDown(const MouseEvent& rMEvt) if ( rMEvt.IsLeft() && !pView->IsAction() ) { Point aPos( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); - // Hack to align object to nearest grid position where object - // would be anchored ( if it were cell anchored ) - // Get grid offset for current position ( note: aPnt is - // also adjusted ) - Point aGridOff = CurrentGridSyncOffsetAndPos( aPos ); pWindow->CaptureMouse(); if ( pView->GetCurrentObjIdentifier() == OBJ_CAPTION ) @@ -118,9 +113,6 @@ bool FuConstRectangle::MouseButtonDown(const MouseEvent& rMEvt) SetLineEnds(aAttr, *pObj, aSfxRequest.GetSlot()); pObj->SetMergedItemSet(aAttr); } - - if ( bReturn ) - pView->GetCreateObj()->SetGridOffset( aGridOff ); } return bReturn; } diff --git a/sc/source/ui/drawfunc/fuconstr.cxx b/sc/source/ui/drawfunc/fuconstr.cxx index df5bb72581fd..e6f61bd3d38d 100644 --- a/sc/source/ui/drawfunc/fuconstr.cxx +++ b/sc/source/ui/drawfunc/fuconstr.cxx @@ -46,47 +46,6 @@ FuConstruct::~FuConstruct() { } -// Calculate and return offset at current zoom. rInOutPos is adjusted by -// the calculated offset. rInOutPos now points to the position than when -// scaled to 100% actually would be at the position you see at the current zoom -// ( relative to the grid ) note: units are expected to be in 100th mm -Point FuConstruct::CurrentGridSyncOffsetAndPos( Point& rInOutPos ) -{ - Point aRetGridOff; - ScViewData& rViewData = rViewShell.GetViewData(); - ScDocument* pDoc = rViewData.GetDocument(); - if ( pDoc ) - { - // rInOutPos might not be where you think it is if there is zoom - // involved. Lets calculate where aPos would be at 100% zoom - // that's the actual correct position for the object (when you - // restore the zoom. - bool bNegative = pDoc->IsNegativePage(pView->GetTab()); - tools::Rectangle aObjRect( rInOutPos, rInOutPos ); - ScRange aRange = pDoc->GetRange( pView->GetTab(), aObjRect ); - ScAddress aOldStt = aRange.aStart; - Point aOldPos( pDoc->GetColOffset( aOldStt.Col(), aOldStt.Tab() ), pDoc->GetRowOffset( aOldStt.Row(), aOldStt.Tab() ) ); - aOldPos.setX( sc::TwipsToHMM( aOldPos.X() ) ); - aOldPos.setY( sc::TwipsToHMM( aOldPos.Y() ) ); - ScSplitPos eWhich = rViewData.GetActivePart(); - ScGridWindow* pGridWin = rViewData.GetActiveWin(); - // and equiv screen pos - Point aScreenPos = rViewShell.GetViewData().GetScrPos( aOldStt.Col(), aOldStt.Row(), eWhich, true ); - MapMode aDrawMode = pGridWin->GetDrawMapMode(); - Point aCurPosHmm = pGridWin->PixelToLogic(aScreenPos, aDrawMode ); - Point aOff = ( rInOutPos - aCurPosHmm ); - rInOutPos = aOldPos + aOff; - aRetGridOff = aCurPosHmm - aOldPos; - // fdo#64011 fix the X position when the sheet are RTL - if ( bNegative ) - { - aRetGridOff.setX( aCurPosHmm.getX() + aOldPos.getX() ); - rInOutPos.setX( aOff.getX() - aOldPos.getX() ); - } - } - return aRetGridOff; -} - bool FuConstruct::MouseButtonDown(const MouseEvent& rMEvt) { // remember button state for creation of own MouseEvents @@ -144,12 +103,6 @@ bool FuConstruct::MouseMove(const MouseEvent& rMEvt) Point aPix(rMEvt.GetPosPixel()); Point aPnt( pWindow->PixelToLogic(aPix) ); - // if object is being created then more than likely the mouse - // position has been 'adjusted' for the current zoom, need to - // restore the mouse position here to ensure resize works as expected - if ( pView->GetCreateObj() ) - aPnt -= pView->GetCreateObj()->GetGridOffset(); - if ( pView->IsAction() ) { ForceScroll(aPix); diff --git a/sc/source/ui/drawfunc/fuconuno.cxx b/sc/source/ui/drawfunc/fuconuno.cxx index ba0c0b58cc8c..3fe103ac2aa4 100644 --- a/sc/source/ui/drawfunc/fuconuno.cxx +++ b/sc/source/ui/drawfunc/fuconuno.cxx @@ -50,15 +50,8 @@ bool FuConstUnoControl::MouseButtonDown(const MouseEvent& rMEvt) if ( rMEvt.IsLeft() && !pView->IsAction() ) { Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); - // Hack to align object to nearest grid position where object - // would be anchored ( if it were cell anchored ) - // Get grid offset for current position ( note: aPnt is - // also adjusted ) - Point aGridOff = CurrentGridSyncOffsetAndPos( aPnt ); - pWindow->CaptureMouse(); pView->BegCreateObj(aPnt); - pView->GetCreateObj()->SetGridOffset( aGridOff ); bReturn = true; } return bReturn; diff --git a/sc/source/ui/drawfunc/futext.cxx b/sc/source/ui/drawfunc/futext.cxx index 13a38a90e612..ae3290911a26 100644 --- a/sc/source/ui/drawfunc/futext.cxx +++ b/sc/source/ui/drawfunc/futext.cxx @@ -295,15 +295,7 @@ bool FuText::MouseButtonDown(const MouseEvent& rMEvt) if (bStraightEnter)//Hack for that silly idea that creating text fields is inside the text routine { // create object - // Hack to align object to nearest grid position where object - // would be anchored ( if it were cell anchored ) - // Get grid offset for current position ( note: aPnt is - // also adjusted ) - Point aGridOff = CurrentGridSyncOffsetAndPos( aMDPos ); - - bool bRet = pView->BegCreateObj(aMDPos); - if ( bRet ) - pView->GetCreateObj()->SetGridOffset( aGridOff ); + pView->BegCreateObj(aMDPos); } else if (SdrObject* pObj = pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK)) { @@ -355,11 +347,6 @@ bool FuText::MouseMove(const MouseEvent& rMEvt) Point aPix(rMEvt.GetPosPixel()); Point aPnt(pWindow->PixelToLogic(aPix)); - // if object is being created then more than likely the mouse - // position has been 'adjusted' for the current zoom, need to - // restore the mouse position here to ensure resize works as expected - if ( pView->GetCreateObj() ) - aPnt -= pView->GetCreateObj()->GetGridOffset(); if ( pView->MouseMove(rMEvt, pWindow) ) return true; // event handled from SdrView diff --git a/sc/source/ui/inc/drawview.hxx b/sc/source/ui/inc/drawview.hxx index ce2af6a66b58..5a79b95cc60a 100644 --- a/sc/source/ui/inc/drawview.hxx +++ b/sc/source/ui/inc/drawview.hxx @@ -155,10 +155,25 @@ public: const OUString& rFilter); static void CheckOle( const SdrMarkList& rMarkList, bool& rAnyOle, bool& rOneOle ); + void SyncForGrid( SdrObject* pObj ); + bool calculateGridOffsetForSdrObject( + SdrObject& rSdrObject, + basegfx::B2DVector& rTarget) const; + bool calculateGridOffsetForB2DRange( + const basegfx::B2DRange& rB2DRange, + basegfx::B2DVector& rTarget) const; + void resetGridOffsetsForAllSdrPageViews(); + /// See SdrMarkView::GetSfxViewShell(). SfxViewShell* GetSfxViewShell() const override; + + // Do not create ObjectContact locally, but offer a call to allow override + // and to create own derivations of ObjectContact + virtual sdr::contact::ObjectContact* createViewSpecificObjectContact( + SdrPageWindow& rPageWindow, + const sal_Char* pDebugName) const override; }; extern Point aDragStartDiff; diff --git a/sc/source/ui/inc/fuconstr.hxx b/sc/source/ui/inc/fuconstr.hxx index 2dd8f6a514cd..e87a32092b26 100644 --- a/sc/source/ui/inc/fuconstr.hxx +++ b/sc/source/ui/inc/fuconstr.hxx @@ -37,10 +37,6 @@ public: virtual bool MouseButtonDown(const MouseEvent& rMEvt) override; bool SimpleMouseButtonUp(const MouseEvent& rMEvt); - - // Returns grid sync offset for rInOutPos, additionally adjusts rInOutPos - // by the offset - Point CurrentGridSyncOffsetAndPos( Point& rInOutPos); }; #endif // _SD_FUCONSTR_HXX diff --git a/sc/source/ui/inc/notemark.hxx b/sc/source/ui/inc/notemark.hxx index 45a09ed114db..ee682ad55853 100644 --- a/sc/source/ui/inc/notemark.hxx +++ b/sc/source/ui/inc/notemark.hxx @@ -49,7 +49,6 @@ private: bool const m_bByKeyboard; tools::Rectangle m_aRect; - ScDrawView* m_pDrawView; std::unique_ptr<SdrModel> m_pModel; std::shared_ptr< SdrCaptionObj > m_xObject; bool m_bVisible; @@ -58,7 +57,7 @@ private: public: ScNoteMarker( vcl::Window* pWin, vcl::Window* pRight, vcl::Window* pBottom, vcl::Window* pDiagonal, ScDocument* pD, const ScAddress& aPos, const OUString& rUser, - const MapMode& rMap, bool bLeftEdge, bool bForce, bool bKeyboard, ScDrawView * pDrawView); + const MapMode& rMap, bool bLeftEdge, bool bForce, bool bKeyboard); ~ScNoteMarker(); void Draw(); diff --git a/sc/source/ui/view/drawview.cxx b/sc/source/ui/view/drawview.cxx index 3882c0d73842..28af22f58c34 100644 --- a/sc/source/ui/view/drawview.cxx +++ b/sc/source/ui/view/drawview.cxx @@ -38,6 +38,10 @@ #include <comphelper/lok.hxx> #include <sfx2/lokhelper.hxx> #include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <svx/sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/contact/viewobjectcontact.hxx> +#include <svx/sdr/contact/viewcontact.hxx> +#include <svx/sdrpagewindow.hxx> #include <drawview.hxx> #include <global.hxx> @@ -322,8 +326,13 @@ void ScDrawView::RecalcScale() if (nEndRow<20) nEndRow = 20; - ScDrawUtil::CalcScale( pDoc, nTab, 0,0, nEndCol,nEndRow, pDev,aZoomX,aZoomY,nPPTX,nPPTY, - aScaleX,aScaleY ); + ScDrawUtil::CalcScale( + pDoc, nTab, 0, 0, nEndCol, nEndRow, pDev, aZoomX, aZoomY, nPPTX, nPPTY, + aScaleX, aScaleY); + + // clear all evtl existing GridOffset vectors + resetGridOffsetsForAllSdrPageViews(); + SdrPageView* pPV = GetSdrPageView(); if ( pViewData && pPV ) { @@ -939,7 +948,12 @@ void ScDrawView::SyncForGrid( SdrObject* pObj ) // synthesise an anchor ( but don't attach it to // the object as we want to maintain page anchoring ) ScDrawObjData aAnchor; - ScDrawLayer::GetCellAnchorFromPosition( *pObj, aAnchor, *pDoc, GetTab() ); + const tools::Rectangle aObjRect(pObj->GetLogicRect()); + ScDrawLayer::GetCellAnchorFromPosition( + aObjRect, + aAnchor, + *pDoc, + GetTab()); aOldStt = aAnchor.maStart; } MapMode aDrawMode = pGridWin->GetDrawMapMode(); @@ -954,10 +968,138 @@ void ScDrawView::SyncForGrid( SdrObject* pObj ) // fdo#63878 Fix the X position for RTL Sheet if( pDoc->IsNegativePage( GetTab() ) ) aGridOff.setX( aCurPosHmm.getX() + aOldPos.getX() ); - pObj->SetGridOffset( aGridOff ); } } +void ScDrawView::resetGridOffsetsForAllSdrPageViews() +{ + SdrPageView* pPageView(GetSdrPageView()); + + if(nullptr != pPageView) + { + for(sal_uInt32 a(0); a < pPageView->PageWindowCount(); a++) + { + SdrPageWindow* pPageWindow(pPageView->GetPageWindow(a)); + assert(pPageWindow && "SdrView::SetMasterPagePaintCaching: Corrupt SdrPageWindow list (!)"); + + if(nullptr != pPageWindow) + { + sdr::contact::ObjectContact& rObjectContact(pPageWindow->GetObjectContact()); + + if(rObjectContact.supportsGridOffsets()) + { + rObjectContact.resetAllGridOffsets(); + } + } + } + } +} + +bool ScDrawView::calculateGridOffsetForSdrObject( + SdrObject& rSdrObject, + basegfx::B2DVector& rTarget) const +{ + ScGridWindow* pGridWin(pViewData->GetActiveWin()); + + if(nullptr == pGridWin) + { + return false; + } + + ScDrawObjData* pData(ScDrawLayer::GetObjData(&rSdrObject)); + ScAddress aOldStt; + + if(nullptr != pData && pData->maStart.IsValid()) + { + aOldStt = pData->maStart; + } + else + { + // Page anchored object so... + // synthesise an anchor ( but don't attach it to + // the object as we want to maintain page anchoring ) + ScDrawObjData aAnchor; + const tools::Rectangle aObjRect(rSdrObject.GetLogicRect()); + ScDrawLayer::GetCellAnchorFromPosition( + aObjRect, + aAnchor, + *pDoc, + GetTab()); + aOldStt = aAnchor.maStart; + } + + MapMode aDrawMode = pGridWin->GetDrawMapMode(); + + // find pos anchor position + Point aOldPos(pDoc->GetColOffset(aOldStt.Col(), aOldStt.Tab()), pDoc->GetRowOffset(aOldStt.Row(), aOldStt.Tab())); + aOldPos.setX(sc::TwipsToHMM(aOldPos.X())); + aOldPos.setY(sc::TwipsToHMM(aOldPos.Y())); + + // find position of same point on the screen ( e.g. grid ) + ScSplitPos eWhich(pViewData->GetActivePart()); + Point aCurPos(pViewData->GetScrPos(aOldStt.Col(), aOldStt.Row(), eWhich, true)); + Point aCurPosHmm(pGridWin->PixelToLogic(aCurPos, aDrawMode)); + Point aGridOff(aCurPosHmm - aOldPos); + + // fdo#63878 Fix the X position for RTL Sheet + if(pDoc->IsNegativePage(GetTab())) + { + aGridOff.setX(aCurPosHmm.getX() + aOldPos.getX()); + } + + rTarget.setX(aGridOff.X()); + rTarget.setY(aGridOff.Y()); + return true; +} + +bool ScDrawView::calculateGridOffsetForB2DRange( + const basegfx::B2DRange& rB2DRange, + basegfx::B2DVector& rTarget) const +{ + ScGridWindow* pGridWin(pViewData->GetActiveWin()); + + if(nullptr == pGridWin || rB2DRange.isEmpty()) + { + return false; + } + + // No SdrObject, so synthesise an anchor ( but don't attach it to + // the object as we want to maintain page anchoring ) + ScDrawObjData aAnchor; + const tools::Rectangle aRectangle( + basegfx::fround(rB2DRange.getMinX()), basegfx::fround(rB2DRange.getMinY()), + basegfx::fround(rB2DRange.getMaxX()), basegfx::fround(rB2DRange.getMaxY())); + ScDrawLayer::GetCellAnchorFromPosition( + aRectangle, + aAnchor, + *pDoc, + GetTab()); + ScAddress aOldStt(aAnchor.maStart); + + MapMode aDrawMode = pGridWin->GetDrawMapMode(); + + // find pos anchor position + Point aOldPos(pDoc->GetColOffset(aOldStt.Col(), aOldStt.Tab()), pDoc->GetRowOffset(aOldStt.Row(), aOldStt.Tab())); + aOldPos.setX(sc::TwipsToHMM(aOldPos.X())); + aOldPos.setY(sc::TwipsToHMM(aOldPos.Y())); + + // find position of same point on the screen ( e.g. grid ) + ScSplitPos eWhich(pViewData->GetActivePart()); + Point aCurPos(pViewData->GetScrPos(aOldStt.Col(), aOldStt.Row(), eWhich, true)); + Point aCurPosHmm(pGridWin->PixelToLogic(aCurPos, aDrawMode)); + Point aGridOff(aCurPosHmm - aOldPos); + + // fdo#63878 Fix the X position for RTL Sheet + if(pDoc->IsNegativePage(GetTab())) + { + aGridOff.setX(aCurPosHmm.getX() + aOldPos.getX()); + } + + rTarget.setX(aGridOff.X()); + rTarget.setY(aGridOff.Y()); + return true; +} + // support enhanced text edit for draw objects SdrUndoManager* ScDrawView::getSdrUndoManagerForEnhancedTextEdit() const { @@ -1001,4 +1143,87 @@ SdrObject* ScDrawView::ApplyGraphicToObject( return nullptr; } +// Own derivation of ObjectContact to allow on-demand calculation of +// GridOffset for non-linear ViewToDevice transformation (calc) +namespace sdr +{ + namespace contact + { + class ObjectContactOfScDrawView final : public ObjectContactOfPageView + { + private: + // The ScDrawView to work on + const ScDrawView& mrScDrawView; + + public: + explicit ObjectContactOfScDrawView( + const ScDrawView& rScDrawView, + SdrPageWindow& rPageWindow, + const sal_Char* pDebugName); + + virtual bool supportsGridOffsets() const override; + virtual void calculateGridOffsetForViewOjectContact( + basegfx::B2DVector& rTarget, + const ViewObjectContact& rClient) const override; + virtual void calculateGridOffsetForB2DRange( + basegfx::B2DVector& rTarget, + const basegfx::B2DRange& rB2DRange) const override; + }; + + ObjectContactOfScDrawView::ObjectContactOfScDrawView( + const ScDrawView& rScDrawView, + SdrPageWindow& rPageWindow, + const sal_Char* pDebugName) + : ObjectContactOfPageView(rPageWindow, pDebugName), + mrScDrawView(rScDrawView) + { + } + + bool ObjectContactOfScDrawView::supportsGridOffsets() const + { + // yes - we support it + return true; + } + + void ObjectContactOfScDrawView::calculateGridOffsetForViewOjectContact( + basegfx::B2DVector& rTarget, + const ViewObjectContact& rClient) const + { + // Here the on-demand calculation happens. Try to access the SdrObject involved + SdrObject* pTargetSdrObject(rClient.GetViewContact().TryToGetSdrObject()); + + if(nullptr != pTargetSdrObject) + { + mrScDrawView.calculateGridOffsetForSdrObject( + *pTargetSdrObject, + rTarget); + } + } + + void ObjectContactOfScDrawView::calculateGridOffsetForB2DRange( + basegfx::B2DVector& rTarget, + const basegfx::B2DRange& rB2DRange) const + { + // Here the on-demand calculation happens. Try to access the SdrObject involved + if(!rB2DRange.isEmpty()) + { + mrScDrawView.calculateGridOffsetForB2DRange( + rB2DRange, + rTarget); + } + } + } +} + +// Create own derivation of ObjectContact for calc +sdr::contact::ObjectContact* ScDrawView::createViewSpecificObjectContact( + SdrPageWindow& rPageWindow, + const sal_Char* pDebugName) const +{ + return new sdr::contact::ObjectContactOfScDrawView( + *this, + rPageWindow, + pDebugName); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/gridwin3.cxx b/sc/source/ui/view/gridwin3.cxx index c2ea2346cb86..4faefae92ead 100644 --- a/sc/source/ui/view/gridwin3.cxx +++ b/sc/source/ui/view/gridwin3.cxx @@ -332,10 +332,6 @@ void ScGridWindow::UpdateStatusPosSize() pDrView->TakeActionRect( aRect ); if ( !aRect.IsEmpty() ) { - // mouse position will have been adjusted for offset - // at current position and zoom, restore that adjustment here - // so status shows correct value - aRect -= pDrView->GetGridOffset(); pPV->LogicToPagePos(aRect); aSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) ); aSet.Put( SvxSizeItem( SID_ATTR_SIZE, @@ -348,10 +344,6 @@ void ScGridWindow::UpdateStatusPosSize() if ( pDrView->AreObjectsMarked() ) // selected objects { tools::Rectangle aRect = pDrView->GetAllMarkedRect(); - // mouse position will have been adjusted for offset - // at current position and zoom, restore that adjustment here - // so status shows correct value - aRect -= pDrView->GetGridOffset(); pPV->LogicToPagePos(aRect); aSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) ); aSet.Put( SvxSizeItem( SID_ATTR_SIZE, diff --git a/sc/source/ui/view/gridwin5.cxx b/sc/source/ui/view/gridwin5.cxx index bcaa4c789c78..40f3bd722019 100644 --- a/sc/source/ui/view/gridwin5.cxx +++ b/sc/source/ui/view/gridwin5.cxx @@ -208,7 +208,7 @@ bool ScGridWindow::ShowNoteMarker( SCCOL nPosX, SCROW nPosY, bool bKeyboard ) mpNoteMarker.reset(new ScNoteMarker(pLeft, pRight, pBottom, pDiagonal, pDoc, aCellPos, aTrackText, - aMapMode, bLeftEdge, bFast, bKeyboard, pViewData->GetScDrawView())); + aMapMode, bLeftEdge, bFast, bKeyboard)); } bDone = true; // something is shown (old or new) diff --git a/sc/source/ui/view/notemark.cxx b/sc/source/ui/view/notemark.cxx index 6e789537de82..49901c9dff11 100644 --- a/sc/source/ui/view/notemark.cxx +++ b/sc/source/ui/view/notemark.cxx @@ -36,7 +36,7 @@ ScNoteMarker::ScNoteMarker( vcl::Window* pWin, vcl::Window* pRight, vcl::Window* pBottom, vcl::Window* pDiagonal, ScDocument* pD, const ScAddress& aPos, const OUString& rUser, - const MapMode& rMap, bool bLeftEdge, bool bForce, bool bKeyboard, ScDrawView *pDrawViewP) : + const MapMode& rMap, bool bLeftEdge, bool bForce, bool bKeyboard) : m_pWindow( pWin ), m_pRightWin( pRight ), m_pBottomWin( pBottom ), @@ -47,7 +47,6 @@ ScNoteMarker::ScNoteMarker( vcl::Window* pWin, vcl::Window* pRight, vcl::Window* m_aMapMode( rMap ), m_bLeft( bLeftEdge ), m_bByKeyboard( bKeyboard ), - m_pDrawView ( pDrawViewP ), m_bVisible( false ) { Size aSizePixel = m_pWindow->GetOutputSizePixel(); @@ -98,15 +97,14 @@ IMPL_LINK_NOARG(ScNoteMarker, TimeHdl, Timer *, void) m_xObject = ScNoteUtil::CreateTempCaption( *m_pDoc, m_aDocPos, *pPage, m_aUserText, m_aVisRect, m_bLeft ); if( m_xObject ) { - if (m_pDrawView) - m_pDrawView->SyncForGrid(m_xObject.get()); + // Here, SyncForGrid and GetGridOffset was used with the comment: + // // Need to include grid offset: GetCurrentBoundRect is removing it + // // but we need to know actual rect position + // This is no longer true - SdrObject::RecalcBoundRect() uses the + // GetViewContact().getViewIndependentPrimitive2DContainer()) call + // that now by default adds the eventually needed GridOffset. Thus + // I have removed that adaption stuff. m_aRect = m_xObject->GetCurrentBoundRect(); - - // Need to include grid offset: GetCurrentBoundRect is removing it - // but we need to know actual rect position - m_aRect += m_xObject->GetGridOffset(); - - assert(m_pDrawView && "this ended up with a wrong rectangle"); } // Insert page so that the model recognise it and also deleted diff --git a/sd/source/ui/animations/motionpathtag.cxx b/sd/source/ui/animations/motionpathtag.cxx index 47e2f5d98f1d..7ca7fc925361 100644 --- a/sd/source/ui/animations/motionpathtag.cxx +++ b/sd/source/ui/animations/motionpathtag.cxx @@ -290,8 +290,11 @@ void SdPathHdl::CreateB2dIAObject() const drawinglayer::primitive2d::Primitive2DContainer& aSequence = rVC.getViewIndependentPrimitive2DContainer(); std::unique_ptr<sdr::overlay::OverlayObject> pNew(new sdr::overlay::OverlayPrimitive2DSequenceObject(aSequence)); - xManager->add(*pNew); - maOverlayGroup.append(std::move(pNew)); + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pNew), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } diff --git a/sd/source/ui/annotations/annotationtag.cxx b/sd/source/ui/annotations/annotationtag.cxx index 9a27599411e6..9a58a17baeb9 100644 --- a/sd/source/ui/annotations/annotationtag.cxx +++ b/sd/source/ui/annotations/annotationtag.cxx @@ -225,8 +225,11 @@ void AnnotationHdl::CreateB2dIAObject() pOverlayObject.reset(new sdr::overlay::OverlayBitmapEx( aPosition, aBitmapEx, 0, 0 )); } - xManager->add(*pOverlayObject); - maOverlayGroup.append(std::move(pOverlayObject)); + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } diff --git a/sd/source/ui/view/viewoverlaymanager.cxx b/sd/source/ui/view/viewoverlaymanager.cxx index 0174c2ba27c1..2f1c148c5c37 100644 --- a/sd/source/ui/view/viewoverlaymanager.cxx +++ b/sd/source/ui/view/viewoverlaymanager.cxx @@ -34,6 +34,7 @@ #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx> #include <svx/sdr/overlay/overlaybitmapex.hxx> #include <svx/sdr/overlay/overlaymanager.hxx> +#include <svx/sdr/contact/objectcontact.hxx> #include <svx/svxids.hrc> #include <view/viewoverlaymanager.hxx> @@ -248,8 +249,12 @@ void ImageButtonHdl::CreateB2dIAObject() { std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject( new sdr::overlay::OverlayBitmapEx( aPosition, aBitmapEx, 0, 0 )); - xManager->add(*pOverlayObject); - maOverlayGroup.append(std::move(pOverlayObject)); + + // OVERLAYMANAGER + insertNewlyCreatedOverlayObjectForSdrHdl( + std::move(pOverlayObject), + rPageWindow.GetObjectContact(), + *xManager.get()); } } } diff --git a/solenv/clang-format/blacklist b/solenv/clang-format/blacklist index 28b397163878..d0e0cc780461 100644 --- a/solenv/clang-format/blacklist +++ b/solenv/clang-format/blacklist @@ -7316,6 +7316,7 @@ include/svx/sdr/attribute/sdrtextattribute.hxx include/svx/sdr/contact/displayinfo.hxx include/svx/sdr/contact/objectcontact.hxx include/svx/sdr/contact/objectcontactofobjlistpainter.hxx +include/svx/sdr/contact/objectcontactofpageview.hxx include/svx/sdr/contact/viewcontact.hxx include/svx/sdr/contact/viewcontactofe3d.hxx include/svx/sdr/contact/viewcontactofe3dscene.hxx @@ -14028,7 +14029,6 @@ svx/inc/pch/precompiled_svxcore.cxx svx/inc/pch/precompiled_svxcore.hxx svx/inc/sdr/attribute/sdrfilltextattribute.hxx svx/inc/sdr/attribute/sdrformtextoutlineattribute.hxx -svx/inc/sdr/contact/objectcontactofpageview.hxx svx/inc/sdr/contact/viewcontactofe3dcube.hxx svx/inc/sdr/contact/viewcontactofe3dextrude.hxx svx/inc/sdr/contact/viewcontactofe3dlathe.hxx 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/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()); } } } |