[Libreoffice-commits] core.git: Branch 'feature/RotGrfFlyFrame' - basegfx/source include/svx svx/source sw/inc sw/sdi sw/source

Armin Le Grand Armin.Le.Grand at cib.de
Wed Oct 4 15:48:13 UTC 2017


 basegfx/source/matrix/b2dhommatrixtools.cxx |    3 -
 include/svx/svdobj.hxx                      |    4 +
 include/svx/svdovirt.hxx                    |    3 +
 include/svx/svxids.hrc                      |    2 
 svx/source/svdraw/svddrgmt.cxx              |   18 ++++--
 svx/source/svdraw/svdmrkv.cxx               |   79 +++++++++++++++++++++-------
 svx/source/svdraw/svdobj.cxx                |    6 ++
 svx/source/svdraw/svdovirt.cxx              |    6 ++
 sw/inc/fesh.hxx                             |    3 +
 sw/sdi/grfsh.sdi                            |    9 +++
 sw/source/core/draw/dflyobj.cxx             |   68 ++++++++++++++++++++++--
 sw/source/core/draw/dview.cxx               |   27 ++++++++-
 sw/source/core/frmedt/feshview.cxx          |   23 ++++++++
 sw/source/core/inc/dflyobj.hxx              |    8 ++
 sw/source/uibase/frmdlg/frmmgr.cxx          |    4 -
 sw/source/uibase/shells/grfsh.cxx           |   38 +++++++++++++
 16 files changed, 267 insertions(+), 34 deletions(-)

New commits:
commit c414e361421bb6acab99da4ee44710295315de4a
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Oct 4 17:44:24 2017 +0200

    RotGrfFlyFrame: Added interactive rotation mode
    
    The FlyFrames containing a graphic now support an
    interactive rotation mode. Added a rotation icon to the
    Toolbar close to right/left 90degree rotation. When
    activated, works as similar to draw object mode as
    possible. Shear and move of the rotation center is
    deactivated since not supported. It uses as much of the
    existing interaction stuff as possible.
    
    Change-Id: Ia1a4e5c064d8576b114c3fcf3a96ccb42c9372bb

diff --git a/basegfx/source/matrix/b2dhommatrixtools.cxx b/basegfx/source/matrix/b2dhommatrixtools.cxx
index 013bb7d23703..a2cdedf77b03 100644
--- a/basegfx/source/matrix/b2dhommatrixtools.cxx
+++ b/basegfx/source/matrix/b2dhommatrixtools.cxx
@@ -364,7 +364,8 @@ namespace basegfx
         {
             basegfx::B2DHomMatrix aRetval;
 
-            // RotGrfFlyFrame: Take rotation into account. Rotation is in 10th degrees
+            // RotGrfFlyFrame: Create a transformation that maps the range inside of itself
+            // so that it fits, takes as much space as possible and keeps the aspect ratio
             if(0.0 != fRotate)
             {
                 // Fit rotated graphic to center of available space, keeping page ratio:
diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx
index 3d7ded0a7fe9..cd6953312565 100644
--- a/include/svx/svdobj.hxx
+++ b/include/svx/svdobj.hxx
@@ -410,6 +410,10 @@ public:
     void SingleObjectPainter(OutputDevice& rOut) const;
     bool LineGeometryUsageIsNecessary() const;
 
+    // RotGrfFlyFrame: If true, this SdrObject supports only limited rotation, that
+    // means no change of the rotation point (only centered) and no shear allowed
+    virtual bool HasLimitedRotation() const;
+
     // Returns a copy of the object. Every inherited class must reimplement this (in class Foo
     // it should be sufficient to do "virtual Foo* Clone() const { return CloneHelper< Foo >(); }".
     // Note that this function uses operator= internally.
diff --git a/include/svx/svdovirt.hxx b/include/svx/svdovirt.hxx
index a6223975572d..c6d626e1305f 100644
--- a/include/svx/svdovirt.hxx
+++ b/include/svx/svdovirt.hxx
@@ -68,6 +68,9 @@ public:
     virtual OUString TakeObjNameSingul() const override;
     virtual OUString TakeObjNamePlural() const override;
 
+    // RotGrfFlyFrame: If true, this SdrObject supports only limited rotation
+    virtual bool HasLimitedRotation() const override;
+
     virtual basegfx::B2DPolyPolygon TakeXorPoly() const override;
     virtual sal_uInt32 GetHdlCount() const override;
     virtual SdrHdl* GetHdl(sal_uInt32 nHdlNum) const override;
diff --git a/include/svx/svxids.hrc b/include/svx/svxids.hrc
index 1c25b7e0b550..12fc7909cc3c 100644
--- a/include/svx/svxids.hrc
+++ b/include/svx/svxids.hrc
@@ -919,7 +919,7 @@
 #define SID_ROTATE_GRAPHIC_LEFT                         ( SID_SVX_START + 1121 )
 #define SID_ROTATE_GRAPHIC_RIGHT                        ( SID_SVX_START + 1122 )
 #define SID_ROTATE_GRAPHIC_180                          ( SID_SVX_START + 1123 )
-#define SID_ROTATE_GRAPHIC_RESET                        ( SID_SVX_START + 1092 ) /* RotGrfFlyFrame: new slot */
+#define SID_ROTATE_GRAPHIC_RESET                        ( SID_SVX_START + 1092 ) /* RotGrfFlyFrame: */
 
 // new slots for panels
 #define SID_ATTR_FILL_TRANSPARENCE                      ( SID_SVX_START + 1124 )
diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx
index d7913114e7f0..dc1126fea867 100644
--- a/svx/source/svdraw/svddrgmt.cxx
+++ b/svx/source/svdraw/svddrgmt.cxx
@@ -2097,18 +2097,28 @@ bool SdrDragRotate::BeginSdrDrag()
 {
     SdrHdl* pH=GetHdlList().GetHdl(SdrHdlKind::Ref1);
 
-    if (pH!=nullptr)
+    if (nullptr != pH)
     {
         Show();
         DragStat().Ref1()=pH->GetPos();
         nAngle0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
         return true;
     }
-    else
+
+    // RotGrfFlyFrame: Support rotation around center *without* Ref1 (normally
+    // the rotation point)
+    const tools::Rectangle aLocalMarkRect(getSdrDragView().GetMarkedObjRect());
+
+    if(!aLocalMarkRect.IsEmpty())
     {
-        OSL_FAIL("SdrDragRotate::BeginSdrDrag(): No reference point handle found.");
-        return false;
+        Show();
+        DragStat().Ref1() = aLocalMarkRect.Center();
+        nAngle0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
+        return true;
     }
+
+    OSL_FAIL("SdrDragRotate::BeginSdrDrag(): No reference point handle found.");
+    return false;
 }
 
 basegfx::B2DHomMatrix SdrDragRotate::getCurrentTransformation()
diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx
index 73a79d4bb983..61286258cc0f 100644
--- a/svx/source/svdraw/svdmrkv.cxx
+++ b/svx/source/svdraw/svdmrkv.cxx
@@ -658,14 +658,22 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell)
         const size_t nMarkCount=GetMarkedObjectCount();
         bool bStdDrag=meDragMode==SdrDragMode::Move;
         bool bSingleTextObjMark=false;
+        bool bLimitedRotation(false);
 
         if (nMarkCount==1)
         {
             mpMarkedObj=GetMarkedObjectByIndex(0);
-            bSingleTextObjMark =
-                mpMarkedObj &&
-                dynamic_cast<const SdrTextObj*>( mpMarkedObj) !=  nullptr &&
-                static_cast<SdrTextObj*>(mpMarkedObj)->IsTextFrame();
+
+            if(nullptr != mpMarkedObj)
+            {
+                bSingleTextObjMark =
+                    mpMarkedObj &&
+                    dynamic_cast<const SdrTextObj*>( mpMarkedObj) !=  nullptr &&
+                    static_cast<SdrTextObj*>(mpMarkedObj)->IsTextFrame();
+
+                // RotGrfFlyFrame: we may have limited rotation
+                bLimitedRotation = SdrDragMode::Rotate == meDragMode && mpMarkedObj->HasLimitedRotation();
+            }
         }
 
         bool bFrmHdl=ImpIsFrameHandles();
@@ -831,27 +839,59 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell)
                 }
                 else
                 {
-                    bool bWdt0=aRect.Left()==aRect.Right();
-                    bool bHgt0=aRect.Top()==aRect.Bottom();
+                    const bool bWdt0(aRect.Left() == aRect.Right());
+                    const bool bHgt0(aRect.Top() == aRect.Bottom());
+
                     if (bWdt0 && bHgt0)
                     {
-                        maHdlList.AddHdl(new SdrHdl(aRect.TopLeft(),SdrHdlKind::UpperLeft));
+                        maHdlList.AddHdl(new SdrHdl(aRect.TopLeft(), SdrHdlKind::UpperLeft));
                     }
                     else if (!bStdDrag && (bWdt0 || bHgt0))
                     {
-                        maHdlList.AddHdl(new SdrHdl(aRect.TopLeft()    ,SdrHdlKind::UpperLeft));
-                        maHdlList.AddHdl(new SdrHdl(aRect.BottomRight(),SdrHdlKind::LowerRight));
+                        maHdlList.AddHdl(new SdrHdl(aRect.TopLeft(), SdrHdlKind::UpperLeft));
+                        maHdlList.AddHdl(new SdrHdl(aRect.BottomRight(), SdrHdlKind::LowerRight));
                     }
                     else
                     {
-                        if (!bWdt0 && !bHgt0) maHdlList.AddHdl(new SdrHdl(aRect.TopLeft()     ,SdrHdlKind::UpperLeft));
-                        if (          !bHgt0) maHdlList.AddHdl(new SdrHdl(aRect.TopCenter()   ,SdrHdlKind::Upper));
-                        if (!bWdt0 && !bHgt0) maHdlList.AddHdl(new SdrHdl(aRect.TopRight()    ,SdrHdlKind::UpperRight));
-                        if (!bWdt0          ) maHdlList.AddHdl(new SdrHdl(aRect.LeftCenter()  ,SdrHdlKind::Left ));
-                        if (!bWdt0          ) maHdlList.AddHdl(new SdrHdl(aRect.RightCenter() ,SdrHdlKind::Right));
-                        if (!bWdt0 && !bHgt0) maHdlList.AddHdl(new SdrHdl(aRect.BottomLeft()  ,SdrHdlKind::LowerLeft));
-                        if (          !bHgt0) maHdlList.AddHdl(new SdrHdl(aRect.BottomCenter(),SdrHdlKind::Lower));
-                        if (!bWdt0 && !bHgt0) maHdlList.AddHdl(new SdrHdl(aRect.BottomRight() ,SdrHdlKind::LowerRight));
+                        if (!bWdt0 && !bHgt0)
+                        {
+                            maHdlList.AddHdl(new SdrHdl(aRect.TopLeft(), SdrHdlKind::UpperLeft));
+                        }
+
+                        if (!bLimitedRotation && !bHgt0)
+                        {
+                            maHdlList.AddHdl(new SdrHdl(aRect.TopCenter(), SdrHdlKind::Upper));
+                        }
+
+                        if (!bWdt0 && !bHgt0)
+                        {
+                            maHdlList.AddHdl(new SdrHdl(aRect.TopRight(), SdrHdlKind::UpperRight));
+                        }
+
+                        if (!bLimitedRotation && !bWdt0)
+                        {
+                            maHdlList.AddHdl(new SdrHdl(aRect.LeftCenter(), SdrHdlKind::Left ));
+                        }
+
+                        if (!bLimitedRotation && !bWdt0)
+                        {
+                            maHdlList.AddHdl(new SdrHdl(aRect.RightCenter(), SdrHdlKind::Right));
+                        }
+
+                        if (!bWdt0 && !bHgt0)
+                        {
+                            maHdlList.AddHdl(new SdrHdl(aRect.BottomLeft(), SdrHdlKind::LowerLeft));
+                        }
+
+                        if (!bLimitedRotation && !bHgt0)
+                        {
+                            maHdlList.AddHdl(new SdrHdl(aRect.BottomCenter(), SdrHdlKind::Lower));
+                        }
+
+                        if (!bWdt0 && !bHgt0)
+                        {
+                            maHdlList.AddHdl(new SdrHdl(aRect.BottomRight(), SdrHdlKind::LowerRight));
+                        }
                     }
                 }
             }
@@ -945,7 +985,10 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell)
         }
 
         // rotation point/axis of reflection
-        AddDragModeHdl(meDragMode);
+        if(!bLimitedRotation)
+        {
+            AddDragModeHdl(meDragMode);
+        }
 
         // sort handles
         maHdlList.Sort();
diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx
index e1257be84517..c829f4e8d75a 100644
--- a/svx/source/svdraw/svdobj.cxx
+++ b/svx/source/svdraw/svdobj.cxx
@@ -931,6 +931,12 @@ bool SdrObject::LineGeometryUsageIsNecessary() const
     return (eXLS != drawing::LineStyle_NONE);
 }
 
+bool SdrObject::HasLimitedRotation() const
+{
+    // RotGrfFlyFrame: Default is false, support full rotation
+    return false;
+}
+
 SdrObject* SdrObject::Clone() const
 {
     return CloneHelper< SdrObject >();
diff --git a/svx/source/svdraw/svdovirt.cxx b/svx/source/svdraw/svdovirt.cxx
index cbd89c4b69d5..dec33db72d2b 100644
--- a/svx/source/svdraw/svdovirt.cxx
+++ b/svx/source/svdraw/svdovirt.cxx
@@ -166,6 +166,12 @@ OUString SdrVirtObj::TakeObjNamePlural() const
     return sName.makeStringAndClear();
 }
 
+bool SdrVirtObj::HasLimitedRotation() const
+{
+    // RotGrfFlyFrame: If true, this SdrObject supports only limited rotation
+    return rRefObj.HasLimitedRotation();
+}
+
 basegfx::B2DPolyPolygon SdrVirtObj::TakeXorPoly() const
 {
     basegfx::B2DPolyPolygon aPolyPolygon(rRefObj.TakeXorPoly());
diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx
index 0775d14cd852..1141a4ea9812 100644
--- a/sw/inc/fesh.hxx
+++ b/sw/inc/fesh.hxx
@@ -505,6 +505,9 @@ public:
     // Start cropping the selected image
     void StartCropImage();
 
+    // RotGrfFlyFrame: check if RotationMode is possibe
+    bool IsRotationOfSwGrfNodePossible() const;
+
     size_t IsObjSelected() const;   ///< @return object count, but doesn't count the objects in groups.
     bool IsObjSelected( const SdrObject& rObj ) const;
     bool IsObjSameLevelWithMarked(const SdrObject* pObj) const;
diff --git a/sw/sdi/grfsh.sdi b/sw/sdi/grfsh.sdi
index 956a0c82b443..8451eae60eba 100644
--- a/sw/sdi/grfsh.sdi
+++ b/sw/sdi/grfsh.sdi
@@ -24,5 +24,14 @@ shell SwGrfShell : SwBaseShell
 
 {
     import TextGraphic;
+
+    // RotGrfFlyFrame: need SID_OBJECT_ROTATE for FlyFrames with graphic
+    SID_OBJECT_ROTATE
+    [
+        Export = FALSE;
+        ExecMethod = Execute ;
+        StateMethod = GetAttrState ;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
 }
 
diff --git a/sw/source/core/draw/dflyobj.cxx b/sw/source/core/draw/dflyobj.cxx
index 32b59b036178..59380eb52939 100644
--- a/sw/source/core/draw/dflyobj.cxx
+++ b/sw/source/core/draw/dflyobj.cxx
@@ -49,6 +49,7 @@
 #include "rootfrm.hxx"
 #include "wrtsh.hxx"
 #include <ndgrf.hxx>
+#include <frmmgr.hxx>
 
 #include <svx/sdr/properties/defaultproperties.hxx>
 #include <basegfx/range/b2drange.hxx>
@@ -354,6 +355,60 @@ basegfx::B2DRange SwVirtFlyDrawObj::getInnerBound() const
     return aInnerRange;
 }
 
+bool SwVirtFlyDrawObj::ContainsSwGrfNode() const
+{
+    // RotGrfFlyFrame: Check if this is a SwGrfNode
+    const SwFlyFrame* pFlyFrame(GetFlyFrame());
+
+    if(nullptr != pFlyFrame && pFlyFrame->Lower() && pFlyFrame->Lower()->IsNoTextFrame())
+    {
+        const SwContentFrame* pCntFr = const_cast<SwContentFrame*>(static_cast<const SwContentFrame*>(pFlyFrame->Lower()));
+        const SwGrfNode* pGrfNd(pCntFr->GetNode()->GetGrfNode());
+
+        return nullptr != pGrfNd;
+    }
+
+    return false;
+}
+
+bool SwVirtFlyDrawObj::HasLimitedRotation() const
+{
+    // RotGrfFlyFrame: If true, this SdrObject supports only limited rotation.
+    // This is the case for SwGrfNode instances
+    return ContainsSwGrfNode();
+}
+
+void SwVirtFlyDrawObj::Rotate(const Point& rRef, long nAngle, double sn, double cs)
+{
+    if(ContainsSwGrfNode())
+    {
+        // RotGrfFlyFrame: Here is where the positively completed rotate interaction is executed.
+        // Rotation is in 1/100th degree and may be signed (!)
+        nAngle /= 10;
+
+        while(nAngle < 0)
+        {
+            nAngle += 3600;
+        }
+
+        if(0 != nAngle)
+        {
+            // RotGrfFlyFrame: Add transformation to placeholder object
+            Size aSize;
+            const sal_uInt16 nOldRot(SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame(aSize));
+            SwWrtShell *pSh = dynamic_cast<SwWrtShell*>( GetFlyFrame()->getRootFrame()->GetCurrShell() );
+            SwFlyFrameAttrMgr aMgr(false, pSh, Frmmgr_Type::NONE);
+
+            aMgr.SetRotation(nOldRot, (nOldRot + static_cast<sal_uInt16>(nAngle)) % 3600, aSize);
+        }
+    }
+    else
+    {
+        // call parent
+        SdrVirtObj::Rotate(rRef, nAngle, sn, cs);
+    }
+}
+
 sdr::contact::ViewContact* SwVirtFlyDrawObj::CreateObjectSpecificViewContact()
 {
     // need an own ViewContact (VC) to allow creation of a specialized primitive
@@ -477,7 +532,9 @@ void SwVirtFlyDrawObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
     rInfo.bMoveAllowed =
     rInfo.bResizeFreeAllowed = rInfo.bResizePropAllowed = true;
 
-    rInfo.bRotateFreeAllowed = rInfo.bRotate90Allowed =
+    // RotGrfFlyFrame: Some rotation may be allowed
+    rInfo.bRotateFreeAllowed = rInfo.bRotate90Allowed = HasLimitedRotation();
+
     rInfo.bMirrorFreeAllowed = rInfo.bMirror45Allowed =
     rInfo.bMirror90Allowed   = rInfo.bShearAllowed    =
     rInfo.bCanConvToPath     = rInfo.bCanConvToPoly   =
@@ -924,7 +981,7 @@ void SwVirtFlyDrawObj::Crop(const Point& rRef, const Fraction& xFact, const Frac
 }
 
 // RotGrfFlyFrame: Helper to access possible rotation of Graphic contained in FlyFrame
-sal_uInt16 SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame() const
+sal_uInt16 SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame(Size& rSize) const
 {
     sal_uInt16 nRetval(0);
     const SwNoTextFrame* pNoTx = dynamic_cast< const SwNoTextFrame* >(GetFlyFrame()->Lower());
@@ -939,6 +996,7 @@ sal_uInt16 SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame() const
             const SwAttrSet& rSet = pGrfNd->GetSwAttrSet();
             const SwRotationGrf& rRotation = rSet.GetRotationGrf();
 
+            rSize = rRotation.GetUnrotatedSize();
             nRetval = rRotation.GetValue();
         }
     }
@@ -954,7 +1012,8 @@ SdrObject* SwVirtFlyDrawObj::getFullDragClone() const
     if(pRetval)
     {
         // RotGrfFlyFrame: Add transformation to placeholder object
-        const sal_uInt16 nRotation(SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame());
+        Size aSize;
+        const sal_uInt16 nRotation(SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame(aSize));
 
         if(0 != nRotation)
         {
@@ -987,7 +1046,8 @@ void SwVirtFlyDrawObj::addCropHandles(SdrHdlList& rTarget) const
 
         if(!aTargetRange.isEmpty())
         {
-            const sal_uInt16 nRotation(SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame());
+            Size aSize;
+            const sal_uInt16 nRotation(SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame(aSize));
             const double fRotate(static_cast< double >(-nRotation) * (M_PI/1800.0));
             const basegfx::B2DHomMatrix aTargetTransform(
                 basegfx::tools::createRotateAroundCenterKeepAspectRatioStayInsideRange(
diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx
index 5bf7304acf39..2572783c9928 100644
--- a/sw/source/core/draw/dview.cxx
+++ b/sw/source/core/draw/dview.cxx
@@ -814,6 +814,8 @@ void SwDrawView::CheckPossibilities()
     const SdrMarkList &rMrkList = GetMarkedObjectList();
     bool bProtect = false;
     bool bSzProtect = false;
+    bool bRotate(false);
+
     for ( size_t i = 0; !bProtect && i < rMrkList.GetMarkCount(); ++i )
     {
         const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
@@ -826,10 +828,18 @@ void SwDrawView::CheckPossibilities()
                 pFrame = pFly->GetAnchorFrame();
                 if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() )
                 {
-                    SwOLENode *pNd = const_cast<SwContentFrame*>(static_cast<const SwContentFrame*>(pFly->Lower()))->GetNode()->GetOLENode();
-                    if ( pNd )
+                    // SwNoTextNode& rNoTNd = const_cast<SwNoTextNode&>(*static_cast<const SwNoTextNode*>((static_cast<const SwContentFrame*>(pFly->Lower()))->GetNode()));
+                    // SwGrfNode* pGrfNd = rNoTNd.GetGrfNode();
+                    // SwOLENode* pOLENd = rNoTNd.GetOLENode();
+
+                    const SwContentFrame* pCntFr = const_cast<SwContentFrame*>(static_cast<const SwContentFrame*>(pFly->Lower()));
+                    const SwOLENode* pOLENd = pCntFr->GetNode()->GetOLENode();
+                    const SwGrfNode* pGrfNd = pCntFr->GetNode()->GetGrfNode();
+
+                    if ( pOLENd )
                     {
-                        uno::Reference < embed::XEmbeddedObject > xObj = pNd->GetOLEObj().GetOleRef();
+                        const uno::Reference < embed::XEmbeddedObject > xObj = const_cast< SwOLEObj& >(pOLENd->GetOLEObj()).GetOleRef();
+
                         if ( xObj.is() )
                         {
                             // --> improvement for the future, when more
@@ -847,6 +857,13 @@ void SwDrawView::CheckPossibilities()
                                 bMoveProtect = true;
                         }
                     }
+                    else if(pGrfNd)
+                    {
+                        // RotGrfFlyFrame: GraphicNode allows rotation(s). The loop ew are in stops
+                        // as soon as bMoveProtect is set, but since rotation is valid only with
+                        // a single object selected this makes no difference
+                        bRotate = true;
+                    }
                 }
             }
         }
@@ -874,6 +891,10 @@ void SwDrawView::CheckPossibilities()
     }
     bMoveProtect    |= bProtect;
     bResizeProtect  |= bProtect || bSzProtect;
+
+    // RotGrfFlyFrame: allow rotation when SwGrfNode is selected and not size protected
+    bRotateFreeAllowed |= bRotate && !bProtect;
+    bRotate90Allowed |= bRotateFreeAllowed;
 }
 
 /// replace marked <SwDrawVirtObj>-objects by its reference object for delete marked objects.
diff --git a/sw/source/core/frmedt/feshview.cxx b/sw/source/core/frmedt/feshview.cxx
index a7838151adff..5fd1addda398 100644
--- a/sw/source/core/frmedt/feshview.cxx
+++ b/sw/source/core/frmedt/feshview.cxx
@@ -1161,6 +1161,29 @@ bool SwFEShell::IsObjSelected( const SdrObject& rObj ) const
         return Imp()->GetDrawView()->IsObjMarked( &rObj );
 }
 
+bool SwFEShell::IsRotationOfSwGrfNodePossible() const
+{
+    // RotGrfFlyFrame: check if RotationMode is possibe
+    const SdrView *pSdrView = Imp()->GetDrawView();
+
+    if(pSdrView)
+    {
+        const SdrMarkList& rList(pSdrView->GetMarkedObjectList());
+
+        if(1 == rList.GetMarkCount())
+        {
+            const SwVirtFlyDrawObj* pVirtFlyDraw(dynamic_cast< const SwVirtFlyDrawObj* >(rList.GetMark(0)->GetMarkedSdrObj()));
+
+            if(nullptr != pVirtFlyDraw)
+            {
+                return pVirtFlyDraw->ContainsSwGrfNode();
+            }
+        }
+    }
+
+    return false;
+}
+
 bool SwFEShell::IsObjSameLevelWithMarked(const SdrObject* pObj) const
 {
     if (pObj)
diff --git a/sw/source/core/inc/dflyobj.hxx b/sw/source/core/inc/dflyobj.hxx
index 528edc8aff39..8766b7980ebc 100644
--- a/sw/source/core/inc/dflyobj.hxx
+++ b/sw/source/core/inc/dflyobj.hxx
@@ -60,7 +60,7 @@ private:
 
     // RotGrfFlyFrame: Helper to acces sthe rotation angle (in 10th degrees, left-handed)
     // of a GraphicFrame
-    sal_uInt16 getPossibleRotationFromFraphicFrame() const;
+    sal_uInt16 getPossibleRotationFromFraphicFrame(Size& rSize) const;
 
 protected:
     // AW: Need own sdr::contact::ViewContact since AnchorPos from parent is
@@ -77,6 +77,8 @@ public:
     basegfx::B2DRange getOuterBound() const;
     basegfx::B2DRange getInnerBound() const;
 
+    // RotGrfFlyFrame: Check if this is a SwGrfNode
+    bool ContainsSwGrfNode() const;
 
     SwVirtFlyDrawObj(SdrObject& rNew, SwFlyFrame* pFly);
     virtual ~SwVirtFlyDrawObj() override;
@@ -105,6 +107,7 @@ public:
                                     const Fraction& yFact, bool bUnsetRelative = true) override;
     virtual       void       Crop(const Point& rRef, const Fraction& xFact, const Fraction& yFact) override;
     virtual       void       addCropHandles(SdrHdlList& rTarget) const override;
+    virtual       void       Rotate(const Point& rRef, long nAngle, double sn, double cs) override;
 
     // FullDrag support
     virtual SdrObject* getFullDragClone() const override;
@@ -122,6 +125,9 @@ public:
     virtual bool       HasMacro() const override;
     virtual SdrObject* CheckMacroHit       (const SdrObjMacroHitRec& rRec) const override;
     virtual Pointer    GetMacroPointer     (const SdrObjMacroHitRec& rRec) const override;
+
+    // RotGrfFlyFrame: If true, this SdrObject supports only limited rotation.
+    virtual bool HasLimitedRotation() const override;
 };
 
 #endif
diff --git a/sw/source/uibase/frmdlg/frmmgr.cxx b/sw/source/uibase/frmdlg/frmmgr.cxx
index b4956cfae92b..a08f441f948b 100644
--- a/sw/source/uibase/frmdlg/frmmgr.cxx
+++ b/sw/source/uibase/frmdlg/frmmgr.cxx
@@ -577,9 +577,9 @@ void SwFlyFrameAttrMgr::SetHeightSizeType( SwFrameSize eType )
 void SwFlyFrameAttrMgr::SetRotation(sal_uInt16 nOld, sal_uInt16 nNew, const Size& rUnrotatedSize)
 {
     // RotGrfFlyFrame: Central handling of real change of rotation here, all adaptions use this.
-    // Adaption of pos/size may be wanted in the future. Already tried to keep last SIze in
+    // Adaption of pos/size may be wanted in the future. Already tried to keep last Size in
     // UnrotatedSize in the SwRotationGrf Item, but this will lead to various problems. Also tried
-    // to use m_aSet.Put(...) as in other methods (also read methods for Rotation/UnrotatedSize) but
+    // to use m_aSet.Put(...) as in other methods (also tried read methods for Rotation/UnrotatedSize) but
     // somehow the needed ID (RES_GRFATR_ROTATION) is *not* in the SfxItemSet of the Frame, so for
     // now set directly. Undo/Redo is preserved by AttributeChange
     if(nOld != nNew)
diff --git a/sw/source/uibase/shells/grfsh.cxx b/sw/source/uibase/shells/grfsh.cxx
index 29251d3dc5b2..01fc01acb9c3 100644
--- a/sw/source/uibase/shells/grfsh.cxx
+++ b/sw/source/uibase/shells/grfsh.cxx
@@ -123,6 +123,27 @@ void SwGrfShell::Execute(SfxRequest &rReq)
     sal_uInt16 nSlot = rReq.GetSlot();
     switch(nSlot)
     {
+        case SID_OBJECT_ROTATE:
+        {
+            // RotGrfFlyFrame: start rotation when possible
+            SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+
+            if(rSh.IsRotationOfSwGrfNodePossible() && pSdrView->IsRotateAllowed())
+            {
+                if(GetView().IsDrawRotate())
+                {
+                    rSh.SetDragMode(SdrDragMode::Move);
+                }
+                else
+                {
+                    rSh.SetDragMode(SdrDragMode::Rotate);
+                }
+
+                GetView().FlipDrawRotate();
+            }
+        }
+        break;
+
         case SID_TWAIN_TRANSFER:
         {
             GetView().ExecuteScan( rReq );
@@ -721,6 +742,23 @@ void SwGrfShell::GetAttrState(SfxItemSet &rSet)
         bool bDisable = bParentCntProt;
         switch( nWhich )
         {
+        case SID_OBJECT_ROTATE:
+        {
+            // RotGrfFlyFrame: steer rotation state
+            const bool bIsRotate(GetView().IsDrawRotate());
+            SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
+
+            if(!bIsRotate && !pSdrView->IsRotateAllowed())
+            {
+                rSet.DisableItem(nWhich);
+            }
+            else
+            {
+                rSet.Put(SfxBoolItem(nWhich, bIsRotate));
+            }
+
+            break;
+        }
         case SID_INSERT_GRAPHIC:
         case FN_FORMAT_GRAFIC_DLG:
         case SID_TWAIN_TRANSFER:


More information about the Libreoffice-commits mailing list