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

Armin Le Grand Armin.Le.Grand at cib.de
Fri Oct 6 14:39:06 UTC 2017


Rebased ref, commits from common ancestor:
commit 95196bd1977364224103b6ff37383f9f27180993
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Thu Oct 5 22:00:35 2017 +0200

    RotGrfFlyFrame: Clang error fix
    
    Change-Id: Ifae68d4d5a17446f01c97ce2e94cd0419217259e

diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx
index f437c4274f06..55e05d73e57f 100644
--- a/sw/source/core/draw/dview.cxx
+++ b/sw/source/core/draw/dview.cxx
@@ -829,11 +829,7 @@ void SwDrawView::CheckPossibilities()
                 pFrame = pFly->GetAnchorFrame();
                 if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() )
                 {
-                    // 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 SwContentFrame* pCntFr(static_cast<const SwContentFrame*>(pFly->Lower()));
                     const SwOLENode* pOLENd = pCntFr->GetNode()->GetOLENode();
                     const SwGrfNode* pGrfNd = pCntFr->GetNode()->GetGrfNode();
 
commit d288152b288e5bcd843053c32104509c3cb69235
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 26936aff2e5c..e26fb922f5b6 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 79ebc50726c1..8d0e22a22179 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 3348579bd508..a00528f61af8 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 f5f3f269f866..b2dd3a2fc6c8 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 7c9f54e35bd8..d7145be8f93a 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 6a21d0eb9d71..29e5e4a94715 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,64 @@ 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(static_cast<const SwContentFrame*>(pFlyFrame->Lower()));
+
+        if(nullptr != pCntFr)
+        {
+            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 +536,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 +985,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 +1000,7 @@ sal_uInt16 SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame() const
             const SwAttrSet& rSet = pGrfNd->GetSwAttrSet();
             const SwRotationGrf& rRotation = rSet.GetRotationGrf();
 
+            rSize = rRotation.GetUnrotatedSize();
             nRetval = rRotation.GetValue();
         }
     }
@@ -951,25 +1013,19 @@ SdrObject* SwVirtFlyDrawObj::getFullDragClone() const
     // call parent
     SdrObject* pRetval = SdrVirtObj::getFullDragClone();
 
-    if(pRetval)
+    if(pRetval && ContainsSwGrfNode())
     {
         // RotGrfFlyFrame: Add transformation to placeholder object
-        const sal_uInt16 nRotation(SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame());
-
-        if(0 != nRotation)
-        {
-            const double fRotate(static_cast< double >(-nRotation) * (M_PI/1800.0));
-            const tools::Rectangle aTmpOutRect(GetFlyFrame()->Frame().SVRect());
-            const basegfx::B2DRange aTargetRange(
-                aTmpOutRect.Left(), aTmpOutRect.Top(),
-                aTmpOutRect.Right(), aTmpOutRect.Bottom());
-            const basegfx::B2DHomMatrix aTargetTransform(
-                basegfx::utils::createRotateAroundCenterKeepAspectRatioStayInsideRange(
-                    aTargetRange,
-                    fRotate));
+        Size aSize;
+        const sal_uInt16 nRotation(SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame(aSize));
+        const double fRotate(static_cast< double >(-nRotation) * (M_PI/1800.0));
+        const basegfx::B2DRange aTargetRange(getInnerBound());
+        const basegfx::B2DHomMatrix aTargetTransform(
+            basegfx::utils::createRotateAroundCenterKeepAspectRatioStayInsideRange(
+                aTargetRange,
+                fRotate));
 
-            pRetval->TRSetBaseGeometry(aTargetTransform, basegfx::B2DPolyPolygon());
-        }
+        pRetval->TRSetBaseGeometry(aTargetTransform, basegfx::B2DPolyPolygon());
     }
 
     return pRetval;
@@ -987,7 +1043,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::utils::createRotateAroundCenterKeepAspectRatioStayInsideRange(
diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx
index 5bf7304acf39..f437c4274f06 100644
--- a/sw/source/core/draw/dview.cxx
+++ b/sw/source/core/draw/dview.cxx
@@ -44,6 +44,7 @@
 #include "doc.hxx"
 #include "mdiexp.hxx"
 #include <ndole.hxx>
+#include <ndgrf.hxx>
 #include <fmtanchr.hxx>
 #include "shellres.hxx"
 #include <IDocumentUndoRedo.hxx>
@@ -814,6 +815,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 +829,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 +858,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 +892,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 5ed4bdae28a8..27893c02fae6 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:
diff --git a/sw/uiconfig/swriter/toolbar/graphicobjectbar.xml b/sw/uiconfig/swriter/toolbar/graphicobjectbar.xml
index c1ba2219af1b..6494546daebd 100644
--- a/sw/uiconfig/swriter/toolbar/graphicobjectbar.xml
+++ b/sw/uiconfig/swriter/toolbar/graphicobjectbar.xml
@@ -28,6 +28,7 @@
  <toolbar:toolbaritem xlink:href=".uno:FlipHorizontal"/>
  <toolbar:toolbaritem xlink:href=".uno:RotateLeft"/>
  <toolbar:toolbaritem xlink:href=".uno:RotateRight"/>
+ <toolbar:toolbaritem xlink:href=".uno:ToggleObjectRotateMode"/>
  <toolbar:toolbaritem xlink:href=".uno:Rotate180" toolbar:visible="false"/>
  <toolbar:toolbaritem xlink:href=".uno:RotateReset" toolbar:visible="false"/>
  <toolbar:toolbarseparator/>
commit 425e7775035ad1945db23aba2e0e2057b2e5179a
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Fri Sep 29 12:35:44 2017 +0200

    RotGrfFlyFrame: Corrected position for CropHandles
    
    Position was taken from OuterBound FlyFrame, even in current
    master which is wrong. There can be a distance defined between
    InnerBound and OuterBound that has to be taken into account
    
    Change-Id: Id88f99c0b218bd26fa1daa5e8215eced00c0baa6

diff --git a/sw/source/core/draw/dflyobj.cxx b/sw/source/core/draw/dflyobj.cxx
index 358085bd2760..6a21d0eb9d71 100644
--- a/sw/source/core/draw/dflyobj.cxx
+++ b/sw/source/core/draw/dflyobj.cxx
@@ -48,6 +48,7 @@
 #include "pagefrm.hxx"
 #include "rootfrm.hxx"
 #include "wrtsh.hxx"
+#include <ndgrf.hxx>
 
 #include <svx/sdr/properties/defaultproperties.hxx>
 #include <basegfx/range/b2drange.hxx>
@@ -958,10 +959,10 @@ SdrObject* SwVirtFlyDrawObj::getFullDragClone() const
         if(0 != nRotation)
         {
             const double fRotate(static_cast< double >(-nRotation) * (M_PI/1800.0));
-            const tools::Rectangle aOutRect(GetFlyFrame()->Frame().SVRect());
+            const tools::Rectangle aTmpOutRect(GetFlyFrame()->Frame().SVRect());
             const basegfx::B2DRange aTargetRange(
-                aOutRect.Left(), aOutRect.Top(),
-                aOutRect.Right(), aOutRect.Bottom());
+                aTmpOutRect.Left(), aTmpOutRect.Top(),
+                aTmpOutRect.Right(), aTmpOutRect.Bottom());
             const basegfx::B2DHomMatrix aTargetTransform(
                 basegfx::utils::createRotateAroundCenterKeepAspectRatioStayInsideRange(
                     aTargetRange,
@@ -979,10 +980,10 @@ void SwVirtFlyDrawObj::addCropHandles(SdrHdlList& rTarget) const
     // RotGrfFlyFrame: Adapt to possible rotated Graphic contained in FlyFrame
     if(GetFlyFrame()->Frame().HasArea())
     {
-        const tools::Rectangle aOutRect(GetFlyFrame()->Frame().SVRect());
-        const basegfx::B2DRange aTargetRange(
-            aOutRect.Left(), aOutRect.Top(),
-            aOutRect.Right(), aOutRect.Bottom());
+        // Use InnerBound, OuterBound (same as GetFlyFrame()->Frame().SVRect())
+        // may have a distance to InnerBound which needs to be taken into acocunt.
+        // The Graphic is mapped to InnerBound, as is the rotated Graphic.
+        const basegfx::B2DRange aTargetRange(getInnerBound());
 
         if(!aTargetRange.isEmpty())
         {
diff --git a/sw/uiconfig/swriter/toolbar/graphicobjectbar.xml b/sw/uiconfig/swriter/toolbar/graphicobjectbar.xml
index 172d8b4d52b5..c1ba2219af1b 100644
--- a/sw/uiconfig/swriter/toolbar/graphicobjectbar.xml
+++ b/sw/uiconfig/swriter/toolbar/graphicobjectbar.xml
@@ -29,7 +29,7 @@
  <toolbar:toolbaritem xlink:href=".uno:RotateLeft"/>
  <toolbar:toolbaritem xlink:href=".uno:RotateRight"/>
  <toolbar:toolbaritem xlink:href=".uno:Rotate180" toolbar:visible="false"/>
- <toolbar:toolbaritem xlink:href=".uno:RotateReset"/>
+ <toolbar:toolbaritem xlink:href=".uno:RotateReset" toolbar:visible="false"/>
  <toolbar:toolbarseparator/>
  <toolbar:toolbaritem xlink:href=".uno:GrafTransparence"/>
  <toolbar:toolbarseparator/>
diff --git a/sw/uiconfig/swxform/toolbar/graphicobjectbar.xml b/sw/uiconfig/swxform/toolbar/graphicobjectbar.xml
index 6e2c6a2b4823..19662053bc76 100644
--- a/sw/uiconfig/swxform/toolbar/graphicobjectbar.xml
+++ b/sw/uiconfig/swxform/toolbar/graphicobjectbar.xml
@@ -30,8 +30,8 @@
  <toolbar:toolbaritem xlink:href=".uno:FlipHorizontal"/>
  <toolbar:toolbaritem xlink:href=".uno:RotateLeft"/>
  <toolbar:toolbaritem xlink:href=".uno:RotateRight"/>
- <toolbar:toolbaritem xlink:href=".uno:Rotate180"/>
- <toolbar:toolbaritem xlink:href=".uno:RotateReset"/>
+ <toolbar:toolbaritem xlink:href=".uno:Rotate180" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:RotateReset" toolbar:visible="false"/>
  <toolbar:toolbaritem xlink:href=".uno:Crop"/>
  <toolbar:toolbarseparator/>
  <toolbar:toolbaritem xlink:href=".uno:FrameDialog"/>


More information about the Libreoffice-commits mailing list